org.eclipse.persistence.jpa.rs.util.CollectionWrapperBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction f2b9fc5
/*
* Copyright (c) 2014, 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:
// Dmitry Kornilov - Initial implementation
package org.eclipse.persistence.jpa.rs.util;
import org.eclipse.persistence.dynamic.DynamicClassLoader;
import org.eclipse.persistence.internal.jpa.rs.metadata.model.LinkV2;
import org.eclipse.persistence.internal.jpa.rs.weaving.CollectionProxyClassWriter;
import org.eclipse.persistence.internal.jpa.rs.weaving.PersistenceWeavedRest;
import org.eclipse.persistence.jpa.rs.PersistenceContext;
import org.eclipse.persistence.jpa.rs.ReservedWords;
import org.eclipse.persistence.jpa.rs.exceptions.JPARSException;
import org.eclipse.persistence.jpa.rs.util.list.PageableCollection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Helper class used to create proxies for collections. Used in JPARS 2.0.
*
* @author Dmitry Kornilov
* @since EclipseLink 2.6.0
*/
public class CollectionWrapperBuilder {
private final PersistenceContext context;
/**
* Creates a new CollectionWrapperBuilder.
*
* @param context the persistence context.
*/
public CollectionWrapperBuilder(PersistenceContext context) {
this.context = context;
}
/**
* Builds proxies for collections containing in a given object. Replaces original collections with
* newly created proxies.
*
* @param object the object to wrap collections.
*/
public void wrapCollections(Object object) {
if (object instanceof PageableCollection) {
for (Object o : ((PageableCollection>) object).getItems()) {
wrapCollectionsForEntity(o);
}
} else {
wrapCollectionsForEntity(object);
}
}
private void wrapCollectionsForEntity(Object entity) {
if (!PersistenceWeavedRest.class.isAssignableFrom(entity.getClass())) {
return;
}
for (final Field field : entity.getClass().getDeclaredFields()) {
if (Collection.class.isAssignableFrom(field.getType())) {
// Get entity id
final String id = IdHelper.stringifyId(entity, entity.getClass().getSimpleName(), context);
// Generate links
final List links = new ArrayList<>(2);
final String href = HrefHelper.buildEntityFieldHref(context, entity.getClass().getSimpleName(), id, field.getName());
links.add(new LinkV2(ReservedWords.JPARS_REL_SELF, href));
links.add(new LinkV2(ReservedWords.JPARS_REL_CANONICAL, href));
// Get accessibility
boolean accessible = field.isAccessible();
if (!accessible) {
field.setAccessible(true);
}
// Make proxy
try {
// No proxy for weaved fields and null fields
if (!field.getName().startsWith("_") && field.get(entity) != null) {
CollectionProxy proxy = getRestCollectionProxy((Collection>) field.get(entity), entity.getClass().getName(), field.getName());
proxy.setLinks(links);
field.set(entity, field.getType().cast(proxy));
}
} catch (IllegalAccessException e) {
throw JPARSException.exceptionOccurred(e);
}
// Restore accessibility
if (!accessible) {
field.setAccessible(false);
}
}
}
}
private CollectionProxy getRestCollectionProxy(final Collection> toProxy, final String entityName, final String fieldname) {
try {
final DynamicClassLoader classLoader = (DynamicClassLoader)context.getServerSession().getDatasourcePlatform().getConversionManager().getLoader();
final CollectionProxyClassWriter writer = new CollectionProxyClassWriter(toProxy.getClass().getName(), entityName, fieldname);
final String proxyClassName = writer.getClassName();
if (classLoader.getClassWriter(proxyClassName) == null) {
classLoader.addClass(proxyClassName, writer);
}
final Class> referenceAdaptorClass = Class.forName(proxyClassName, true, classLoader);
final Class>[] argTypes = {Collection.class};
final Constructor> referenceAdaptorConstructor = referenceAdaptorClass.getDeclaredConstructor(argTypes);
final Object[] args = new Object[]{toProxy};
return (CollectionProxy)referenceAdaptorConstructor.newInstance(args);
} catch (Exception e) {
throw JPARSException.exceptionOccurred(e);
}
}
}