| /* |
| * 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); |
| } |
| |
| } |