| /* |
| * Copyright (c) 2013, 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: |
| // gonural - initial implementation |
| // 2014-09-01-2.6.0 Dmitry Kornilov |
| // - JPARS 2.0 fixes |
| package org.eclipse.persistence.jpa.rs.features.core.selflinks; |
| |
| import org.eclipse.persistence.descriptors.ClassDescriptor; |
| import org.eclipse.persistence.internal.jpa.rs.metadata.model.ItemLinks; |
| import org.eclipse.persistence.internal.jpa.rs.metadata.model.LinkV2; |
| import org.eclipse.persistence.internal.jpa.rs.weaving.PersistenceWeavedRest; |
| import org.eclipse.persistence.internal.queries.ReportItem; |
| 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.features.FeatureResponseBuilderImpl; |
| import org.eclipse.persistence.jpa.rs.features.ItemLinksBuilder; |
| import org.eclipse.persistence.jpa.rs.util.HrefHelper; |
| import org.eclipse.persistence.jpa.rs.util.IdHelper; |
| import org.eclipse.persistence.jpa.rs.util.list.ReadAllQueryResultCollection; |
| import org.eclipse.persistence.jpa.rs.util.list.ReportQueryResultCollection; |
| import org.eclipse.persistence.jpa.rs.util.list.ReportQueryResultListItem; |
| import org.eclipse.persistence.jpa.rs.util.list.SingleResultQueryResult; |
| |
| import jakarta.ws.rs.core.UriInfo; |
| import jakarta.xml.bind.JAXBElement; |
| import java.beans.BeanInfo; |
| import java.beans.IntrospectionException; |
| import java.beans.Introspector; |
| import java.beans.PropertyDescriptor; |
| import java.lang.reflect.Field; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * FeatureResponseBuilder implementation generating 'self' and 'canonical' links. Used in JPARS 2.0. |
| * |
| * @author gonural, Dmitry Kornilov |
| * @since EclipseList 2.6.0 |
| */ |
| @SuppressWarnings({ "unchecked"}) |
| public class SelfLinksResponseBuilder extends FeatureResponseBuilderImpl { |
| |
| @Override |
| public Object buildReadAllQueryResponse(PersistenceContext context, Map<String, Object> queryParams, List<Object> items, UriInfo uriInfo) { |
| return collectionResponse(context, items, uriInfo); |
| } |
| |
| @Override |
| public Object buildReportQueryResponse(PersistenceContext context, Map<String, Object> queryParams, List<Object[]> results, List<ReportItem> items, UriInfo uriInfo) { |
| ReportQueryResultCollection response = new ReportQueryResultCollection(); |
| for (Object result : results) { |
| ReportQueryResultListItem queryResultListItem = new ReportQueryResultListItem(); |
| List<JAXBElement<?>> jaxbFields = createShellJAXBElementList(items, result); |
| generateLinksInElementsList(context, jaxbFields); |
| queryResultListItem.setFields(jaxbFields); |
| response.addItem(queryResultListItem); |
| } |
| response.addLink(new LinkV2(ReservedWords.JPARS_REL_SELF, uriInfo.getRequestUri().toString())); |
| return response; |
| } |
| |
| @Override |
| public Object buildSingleResultQueryResponse(PersistenceContext context, Map<String, Object> queryParams, Object result, List<ReportItem> items, UriInfo uriInfo) { |
| final SingleResultQueryResult response = new SingleResultQueryResult(); |
| final List<JAXBElement<?>> fields = createShellJAXBElementList(items, result); |
| |
| // If there are entities in fields insert links there |
| generateLinksInElementsList(context, fields); |
| |
| response.setFields(fields); |
| response.addLink(new LinkV2(ReservedWords.JPARS_REL_SELF, uriInfo.getRequestUri().toString())); |
| return response; |
| } |
| |
| @Override |
| public Object buildAttributeResponse(PersistenceContext context, Map<String, Object> queryParams, String attribute, Object item, UriInfo uriInfo) { |
| if (item instanceof List) { |
| return collectionResponse(context, (List<Object>) item, uriInfo); |
| } |
| return item; |
| } |
| |
| @Override |
| public Object buildSingleEntityResponse(PersistenceContext context, Map<String, Object> queryParams, Object result, UriInfo uriInfo) { |
| if (result instanceof PersistenceWeavedRest) { |
| final PersistenceWeavedRest entity = (PersistenceWeavedRest)result; |
| final ClassDescriptor classDescriptor = context.getServerSession().getProject().getDescriptor(result.getClass()); |
| final String entityClassName = classDescriptor.getAlias(); |
| final String entityId = IdHelper.stringifyId(entity, entityClassName, context); |
| |
| final ItemLinksBuilder itemLinksBuilder = (new ItemLinksBuilder()) |
| .addSelf(uriInfo.getRequestUri().toString()) |
| .addCanonical(HrefHelper.buildEntityHref(context, entityClassName, entityId)); |
| |
| generateLinksForRelationships(context, entity); |
| entity._persistence_setLinks(itemLinksBuilder.build()); |
| return entity; |
| } |
| return result; |
| } |
| |
| private Object collectionResponse(PersistenceContext context, List<Object> results, UriInfo uriInfo) { |
| if ((results != null) && (!results.isEmpty())) { |
| final ReadAllQueryResultCollection response = new ReadAllQueryResultCollection(); |
| for (Object item : results) { |
| if (item instanceof PersistenceWeavedRest) { |
| final PersistenceWeavedRest entity = (PersistenceWeavedRest) item; |
| final ClassDescriptor classDescriptor = context.getServerSession().getProject().getDescriptor(item.getClass()); |
| final String entityClassName = classDescriptor.getAlias(); |
| final String entityId = IdHelper.stringifyId(entity, entityClassName, context); |
| |
| final String href = HrefHelper.buildEntityHref(context, entityClassName, entityId); |
| final ItemLinksBuilder itemLinksBuilder = (new ItemLinksBuilder()) |
| .addCanonical(href); |
| entity._persistence_setLinks(itemLinksBuilder.build()); |
| |
| generateLinksForRelationships(context, entity); |
| response.addItem(entity); |
| } else { |
| response.addItem(item); |
| } |
| } |
| |
| response.addLink(new LinkV2(ReservedWords.JPARS_REL_SELF, uriInfo.getRequestUri().toString())); |
| return response; |
| } |
| return results; |
| } |
| |
| private void generateLinksInElementsList(PersistenceContext context, List<JAXBElement<?>> fields) { |
| for (JAXBElement<?> field : fields) { |
| if (field.getValue() instanceof PersistenceWeavedRest) { |
| final PersistenceWeavedRest entity = (PersistenceWeavedRest) field.getValue(); |
| final ClassDescriptor classDescriptor = context.getServerSession().getProject().getDescriptor(entity.getClass()); |
| final String entityClassName = classDescriptor.getAlias(); |
| final String entityId = IdHelper.stringifyId(entity, entityClassName, context); |
| |
| // No links for embedded objects |
| if (!classDescriptor.isAggregateDescriptor()) { |
| final String href = HrefHelper.buildEntityHref(context, entityClassName, entityId); |
| final ItemLinksBuilder itemLinksBuilder = (new ItemLinksBuilder()) |
| .addSelf(href) |
| .addCanonical(href); |
| entity._persistence_setLinks(itemLinksBuilder.build()); |
| } |
| } |
| } |
| } |
| |
| private void generateLinksForRelationships(PersistenceContext context, PersistenceWeavedRest entity) { |
| final ClassDescriptor classDescriptor = context.getServerSession().getProject().getDescriptor(entity.getClass()); |
| final String entityClassName = classDescriptor.getAlias(); |
| final String entityId = IdHelper.stringifyId(entity, entityClassName, context); |
| |
| for (final Field field : entity.getClass().getDeclaredFields()) { |
| if (PersistenceWeavedRest.class.isAssignableFrom(field.getType())) { |
| final PersistenceWeavedRest obj = (PersistenceWeavedRest) callGetterForProperty(entity, field.getName()); |
| if (obj != null) { |
| final String fieldClassName = context.getJAXBDescriptorForClass(field.getType()).getAlias(); |
| final String fieldId = IdHelper.stringifyId(obj, fieldClassName, context); |
| |
| final ItemLinks links = (new ItemLinksBuilder()) |
| .addSelf(HrefHelper.buildEntityFieldHref(context, entityClassName, entityId, field.getName())) |
| .addCanonical(HrefHelper.buildEntityHref(context, fieldClassName, fieldId)) |
| .build(); |
| |
| obj._persistence_setLinks(links); |
| } |
| } |
| } |
| } |
| |
| private Object callGetterForProperty(Object bean, String propertyName) { |
| try { |
| final BeanInfo info = Introspector.getBeanInfo(bean.getClass(), Object.class); |
| final PropertyDescriptor[] props = info.getPropertyDescriptors(); |
| for (PropertyDescriptor pd : props) { |
| if (propertyName.equals(pd.getName())) { |
| return pd.getReadMethod().invoke(bean); |
| } |
| } |
| } catch (InvocationTargetException| IntrospectionException | IllegalAccessException e) { |
| throw JPARSException.exceptionOccurred(e); |
| } |
| |
| return null; |
| } |
| } |