| /* |
| * Copyright (c) 2014, 2020 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.xmladapters; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| |
| import jakarta.xml.bind.annotation.adapters.XmlAdapter; |
| |
| import org.eclipse.persistence.descriptors.ClassDescriptor; |
| import org.eclipse.persistence.internal.jpa.rs.metadata.model.CollectionWrapper; |
| import org.eclipse.persistence.internal.jpa.rs.metadata.model.LinkV2; |
| import org.eclipse.persistence.internal.jpa.rs.weaving.PersistenceWeavedRest; |
| import org.eclipse.persistence.internal.sessions.AbstractSession; |
| 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.CollectionProxy; |
| import org.eclipse.persistence.jpa.rs.util.IdHelper; |
| import org.eclipse.persistence.mappings.DatabaseMapping; |
| |
| /** |
| * Collections adapter used in JPARS V2. Collections are wrapped into CollectionWrapper which has 'links'. |
| * @see CollectionWrapper |
| * |
| * @param <T> list generac type |
| * |
| * @author Dmitry Kornilov |
| * @since EclipseLink 2.6.0 |
| */ |
| public class RestCollectionAdapter<T extends PersistenceWeavedRest> extends XmlAdapter<CollectionWrapper<T>, Collection<T>> { |
| protected PersistenceContext context; |
| |
| public RestCollectionAdapter() { |
| super(); |
| } |
| |
| /** |
| * Instantiates a new RestCollectionAdapter. |
| * |
| * @param context persistent context |
| */ |
| public RestCollectionAdapter(PersistenceContext context) { |
| this.context = context; |
| } |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| public Collection<T> unmarshal(CollectionWrapper<T> v) throws Exception { |
| if (v == null) { |
| return null; |
| } |
| |
| final Collection<T> result = new ArrayList<T>(); |
| |
| // Check if links exist and items from there if it does |
| if (v.getLinks() != null && !v.getLinks().isEmpty()) { |
| for (final LinkV2 link : v.getLinks()) { |
| if (link.getRel().equals(ReservedWords.JPARS_REL_SELF) && link.getHref() != null) { |
| return loadItems(link.getHref()); |
| } |
| } |
| } |
| |
| if (v.getItems() != null) { |
| // Process each item (load from href, etc.) |
| final ReferenceAdapterV2<T> referenceAdapter = new ReferenceAdapterV2<T>(context); |
| for (T item : v.getItems()) { |
| if (context != null) { |
| result.add(referenceAdapter.unmarshal(item)); |
| } else { |
| result.add(item); |
| } |
| } |
| } |
| return result; |
| } |
| |
| @Override |
| public CollectionWrapper<T> marshal(Collection<T> v) throws Exception { |
| if (v == null || v.isEmpty()) { |
| return null; |
| } |
| |
| final CollectionWrapper<T> result = new CollectionWrapper<T>(); |
| |
| // Currently it returns only links. It will return items when 'expand' |
| // feature will be implemented. |
| //result.setItems(v); |
| |
| // Read links from the RestCollection wrapper |
| if (v instanceof CollectionProxy) { |
| CollectionProxy restCollection = (CollectionProxy)v; |
| result.setLinks(restCollection.getLinks()); |
| } |
| |
| return result; |
| } |
| |
| private Collection loadItems(String href) throws Exception { |
| String uri = href.replace("\\/", "/"); |
| uri = uri.substring(uri.indexOf("entity/")); |
| uri = uri.substring(uri.indexOf('/') + 1); |
| |
| final String[] uriItems = uri.split("/"); |
| final String entityType = uriItems[0]; |
| final String entityId = uriItems[1]; |
| final String attributeName = uriItems[2]; |
| |
| final ClassDescriptor descriptor = context.getDescriptor(entityType); |
| final Object id = IdHelper.buildId(context, descriptor.getAlias(), entityId); |
| |
| final T entity = getObjectById(entityType, id); |
| final DatabaseMapping attributeMapping = descriptor.getMappingForAttributeName(attributeName); |
| if ((attributeMapping == null) || (entity == null)) { |
| throw JPARSException.databaseMappingCouldNotBeFoundForEntityAttribute(attributeName, entityType, entityId, null); |
| } |
| |
| return (Collection) attributeMapping.getRealAttributeValueFromAttribute(attributeMapping.getAttributeValueFromObject(entity), entity, (AbstractSession)context.getServerSession()); |
| } |
| |
| @SuppressWarnings("unchecked") |
| private T getObjectById(String entityType, Object id) throws Exception { |
| final Object entity = context.find(null, entityType, id, null); |
| if (entity != null) { |
| return (T)entity; |
| } |
| // It is an error if the object referred by a link doesn't exist, so throw exception |
| throw JPARSException.objectReferredByLinkDoesNotExist(entityType, id); |
| } |
| } |