/* Copyright 2011-2014 Red Hat, Inc This file is part of PressGang CCMS. PressGang CCMS is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. PressGang CCMS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with PressGang CCMS. If not, see <http://www.gnu.org/licenses/>. */ package org.jboss.pressgang.ccms.server.rest.v1.factory.base; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaQuery; import java.util.List; import org.jboss.pressgang.ccms.filter.utils.JPAUtils; import org.jboss.pressgang.ccms.rest.v1.collections.base.RESTBaseCollectionItemV1; import org.jboss.pressgang.ccms.rest.v1.collections.base.RESTBaseCollectionV1; import org.jboss.pressgang.ccms.rest.v1.elements.base.RESTBaseElementV1; import org.jboss.pressgang.ccms.rest.v1.expansion.ExpandDataDetails; import org.jboss.pressgang.ccms.rest.v1.expansion.ExpandDataTrunk; import org.jboss.resteasy.spi.InternalServerErrorException; public class RESTElementCollectionFactory { /** * Create a Collection of REST Entities from a collection of Objects. * * @param clazz The Class of the Collection Object that should be returned by the method. * @param dataObjectFactory The factory to convert the database entity to a REST entity * @param objects A collection of objects. * @param dataType The type of data that is returned through the REST interface * @param parentExpand The parent objects expansion details * @param baseUrl The base of the url that was used to access this collection * @return a REST collection from a collection of database entities. */ public static <T extends RESTBaseElementV1<T>, U, V extends RESTBaseCollectionV1<T, W>, W extends RESTBaseCollectionItemV1<T, W>> V create( final Class<V> clazz, final RESTElementFactory<T, U> dataObjectFactory, final List<U> objects, final String dataType, final ExpandDataTrunk parentExpand, final String baseUrl) { return create(clazz, dataObjectFactory, objects, null, dataType, parentExpand, baseUrl); } /** * Create a Collection of REST Entities from a collection of Objects. * * @param clazz The Class of the Collection Object that should be returned by the method. * @param dataObjectFactory The factory to convert the database entity to a REST entity * @param objects A collection of objects. * @param expandName The name of the collection that we are working with * @param dataType The type of data that is returned through the REST interface * @param parentExpand The parent objects expansion details * @param baseUrl The base of the url that was used to access this collection * @return a REST collection from a collection of database entities. */ public static <T extends RESTBaseElementV1<T>, U, V extends RESTBaseCollectionV1<T, W>, W extends RESTBaseCollectionItemV1<T, W>> V create( final Class<V> clazz, final RESTElementFactory<T, U> dataObjectFactory, final List<U> objects, final String expandName, final String dataType, final ExpandDataTrunk parentExpand, final String baseUrl) { V retValue = null; try { retValue = clazz.newInstance(); } catch (final Exception ex) { throw new InternalServerErrorException(ex); } /* * either the entities collection needs to be set, or the revisions and parent */ if (objects == null) return retValue; retValue.setExpand(expandName); /* * Un-comment this to make it so that size is always shown. Don't forget to comment out line 62 below. */ // retValue.setSize(objects.size()); final ExpandDataTrunk expand = parentExpand != null ? parentExpand.get(expandName) : null; if (expand != null) { if (expand.getTrunk().getName().equals(expandName)) { assert baseUrl != null : "Parameter baseUrl can not be null if parameter expand is not null"; final ExpandDataDetails indexes = expand.getTrunk(); /* * Un-comment this to make it so that size is only shown when the expand is set. Don't forget to comment out * line 48 above. */ final int size = objects.size(); retValue.setSize(size); // Find the start reference for the response using the start and size of the entity list. int start = 0; if (indexes.getStart() != null) { final int startIndex = indexes.getStart(); if (startIndex < 0) { start = Math.max(0, size + startIndex); } else { start = Math.min(startIndex, size == 0 ? 0 : size - 1); } } // Find the end reference for the response using the start and size of the entity list. int end = size; if (indexes.getEnd() != null) { final int endIndex = indexes.getEnd(); if (endIndex < 0) { end = Math.max(0, size + endIndex + 1); } else { end = Math.min(endIndex, size); } } // Fix the start and end if the two overlap final int fixedStart = Math.min(start, end); final int fixedEnd = Math.max(start, end); retValue.setStartExpandIndex(fixedStart); retValue.setEndExpandIndex(fixedEnd); // Get the entities requested from the entity list and create the REST Entities. for (int i = fixedStart; i < fixedEnd; i++) { final U object = objects.get(i); // If the entity was found then create the REST Entity if (object != null) { final T restElement = dataObjectFactory.createRESTEntityFromObject(object, baseUrl, dataType, expand); // Add the item to the return value retValue.addItem(restElement); } } } } return retValue; } /** * Create a Collection of REST Entities from a collection of Database Entities. * * @param clazz The Class of the Collection Object that should be returned by the method. * @param dataObjectFactory The factory to convert the database entity to a REST entity * @param query The CriteriaQuery that holds the details on which entities to create the collection from. * @param expandName The name of the collection that we are working with * @param dataType The type of data that is returned through the REST interface * @param parentExpand The parent objects expansion details * @param baseUrl The base of the url that was used to access this collection * @param entityManager The EntityManager being used to provide data for the collection. * @return a REST collection from a collection of database entities. */ public static <T extends RESTBaseElementV1<T>, U, V extends RESTBaseCollectionV1<T, W>, W extends RESTBaseCollectionItemV1<T, W>> V create( final Class<V> clazz, final RESTElementFactory<T, U> dataObjectFactory, final CriteriaQuery<U> query, final String expandName, final String dataType, final ExpandDataTrunk parentExpand, final String baseUrl, final EntityManager entityManager) { V retValue = null; try { retValue = clazz.newInstance(); } catch (final Exception ex) { throw new InternalServerErrorException(ex); } /* * There must be a query otherwise just return */ if (query == null) return retValue; retValue.setExpand(expandName); /* * Un-comment this to make it so that size is always shown. Don't forget to comment out line 303 below. */ //final int size = JPAUtils.count(entityManager, query).intValue(); //retValue.setSize(size); final ExpandDataTrunk expand = parentExpand != null ? parentExpand.get(expandName) : null; if (expand != null) { if (expand.getTrunk().getName().equals(expandName)) { assert baseUrl != null : "Parameter baseUrl can not be null if parameter expand is not null"; final ExpandDataDetails indexes = expand.getTrunk(); /* * Un-comment this to make it so that size is only shown when the expand is set. Don't forget to comment out * line 287 above. */ final int size = JPAUtils.count(entityManager, query).intValue(); retValue.setSize(size); // Find the start reference for the response using the start and size of the entity list. int start = 0; if (indexes.getStart() != null) { final int startIndex = indexes.getStart(); if (startIndex < 0) { start = Math.max(0, size + startIndex); } else { start = Math.min(startIndex, size == 0 ? 0 : size - 1); } } // Find the end reference for the response using the start and size of the entity list. int end = size; if (indexes.getEnd() != null) { final int endIndex = indexes.getEnd(); if (endIndex < 0) { end = Math.max(0, size + endIndex + 1); } else { end = Math.min(endIndex, size); } } // Fix the start and end if the two overlap final int fixedStart = Math.min(start, end); final int fixedEnd = Math.max(start, end); retValue.setStartExpandIndex(fixedStart); retValue.setEndExpandIndex(fixedEnd); // Create the query final TypedQuery<U> query1 = entityManager.createQuery(query); // Set the start and the end query1.setFirstResult(fixedStart); query1.setMaxResults(fixedEnd - fixedStart); // Get the results final List<U> entities = query1.getResultList(); // Get the entities requested from the entity list and create the REST Entities. for (int i = 0; i < entities.size(); i++) { U dbEntity = entities.get(i); // If the entity was found then create the REST Entity if (dbEntity != null) { final T restEntity = dataObjectFactory.createRESTEntityFromObject(dbEntity, baseUrl, dataType, expand); // Add the item to the return value retValue.addItem(restEntity); } } } } return retValue; } }