blob: e63933c1366fe5d7ceb791640e862e997266b06d [file] [log] [blame]
/*
* Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Blaise Doughan & Denise Smith = 2.1 - Initial contribution
package org.eclipse.persistence.internal.jaxb.many;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;
import org.eclipse.persistence.core.mappings.CoreAttributeAccessor;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.internal.core.queries.CoreContainerPolicy;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.mappings.AttributeAccessor;
/**
* AttributeAccessor used in conjunction with an XMLCompositeDirectCollectionMapping to enable
* support for mapping to arrays
*/
public class JAXBArrayAttributeAccessor extends AttributeAccessor {
private CoreAttributeAccessor nestedAccessor;
private CoreContainerPolicy containerPolicy;
private String componentClassName;
private Class<?> componentClass;
private String adaptedClassName;
private Class<? extends ManyValue> adaptedClass;
private ClassLoader classLoader;
public JAXBArrayAttributeAccessor(CoreAttributeAccessor nestedAccessor, CoreContainerPolicy containerPolicy, ClassLoader classLoader) {
this.nestedAccessor = nestedAccessor;
this.containerPolicy = containerPolicy;
this.classLoader = classLoader;
}
@Override
public Object getAttributeValueFromObject(Object object) throws DescriptorException {
Object arrayValue = nestedAccessor.getAttributeValueFromObject(object);
if (arrayValue == null) {
return null;
}
int length = Array.getLength(arrayValue);
Object results = containerPolicy.containerInstance(length);
if (null == adaptedClass) {
for (int x = 0; x < length; x++) {
containerPolicy.addInto(Array.get(arrayValue, x), results, null);
}
} else {
for (int x = 0; x < length; x++) {
try {
ManyValue manyValue = PrivilegedAccessHelper.newInstanceFromClass(adaptedClass);
manyValue.setItem(Array.get(arrayValue, x));
containerPolicy.addInto(manyValue, results, null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
return results;
}
@Override
public void setAttributeValueInObject(Object object, Object value) throws DescriptorException {
List listValue = (List) value;
if (null == listValue || listValue.isEmpty()) {
nestedAccessor.setAttributeValueInObject(object, null);
return;
}
int[] dims = new int[1];
int listValueSize = listValue.size();
dims[0] = listValueSize;
if (listValueSize > 0) {
Object firstItem = listValue.get(0);
if (firstItem instanceof ManyValue) {
dims = getDimensions(dims, ((ManyValue) firstItem).getItem());
}
}
Object arrayValue = Array.newInstance(componentClass, dims);
for (int i = 0; i < listValueSize; i++) {
Object next = listValue.get(i);
if (next instanceof ManyValue) {
next = ((ManyValue) next).getItem();
}
Array.set(arrayValue, i, next);
}
nestedAccessor.setAttributeValueInObject(object, arrayValue);
}
@Override
public void initializeAttributes(Class<?> theJavaClass) throws DescriptorException {
nestedAccessor.initializeAttributes(theJavaClass);
if (adaptedClass == null && adaptedClassName != null) {
try {
adaptedClass = PrivilegedAccessHelper.getClassForName(adaptedClassName, true, classLoader);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
if (componentClass == null && componentClassName != null) {
try {
componentClass = PrivilegedAccessHelper.getClassForName(componentClassName, true, classLoader);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
public void setAdaptedClass(Class<? extends ManyValue> adaptedClass) {
this.adaptedClass = adaptedClass;
}
public void setComponentClass(Class<?> componentClass) {
this.componentClass = componentClass;
}
public void setAdaptedClassName(String adaptedClassName) {
this.adaptedClassName = adaptedClassName;
}
public void setComponentClassName(String componentClassName) {
this.componentClassName = componentClassName;
}
private int[] getDimensions(int[] dimensions, Object array) {
int[] newDimensions = Arrays.copyOf(dimensions, dimensions.length + 1);
newDimensions[newDimensions.length - 1] = Array.getLength(array);
Object nestedArray = Array.get(array, 0);
if (nestedArray.getClass().isArray()) {
return getDimensions(newDimensions, nestedArray);
}
return newDimensions;
}
public void setNestedAccessor(AttributeAccessor a) {
this.nestedAccessor = a;
}
@Override
public void setIsWriteOnly(boolean aBoolean) {
super.setIsWriteOnly(aBoolean);
this.nestedAccessor.setIsWriteOnly(aBoolean);
}
@Override
public void setIsReadOnly(boolean aBoolean) {
super.setIsReadOnly(aBoolean);
this.nestedAccessor.setIsReadOnly(aBoolean);
}
}