com.amalto.core.storage.hibernate.EntityFinder.java Source code

Java tutorial

Introduction

Here is the source code for com.amalto.core.storage.hibernate.EntityFinder.java

Source

/*
 * Copyright (C) 2006-2016 Talend Inc. - www.talend.com
 *
 * This source code is available under agreement available at
 * %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
 *
 * You should have received a copy of the agreement
 * along with this program; if not, write to Talend SA
 * 9 rue Pages 92150 Suresnes, France
 */

package com.amalto.core.storage.hibernate;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Blob;
import java.sql.Clob;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

import org.apache.commons.collections.set.ListOrderedSet;
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.search.Explanation;
import org.apache.lucene.search.Sort;
import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.Query;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Restrictions;
import org.hibernate.search.FullTextQuery;
import org.hibernate.search.filter.FullTextFilter;
import org.hibernate.search.query.DatabaseRetrievalMethod;
import org.hibernate.search.query.ObjectLookupMethod;
import org.hibernate.search.query.engine.spi.FacetManager;
import org.hibernate.search.spatial.Coordinates;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.Type;
import org.talend.mdm.commmon.metadata.ComplexTypeMetadata;
import org.talend.mdm.commmon.metadata.InboundReferences;
import org.talend.mdm.commmon.metadata.ReferenceFieldMetadata;

public class EntityFinder {

    private EntityFinder() {
    }

    /**
     * Starting from <code>wrapper</code>, goes up the containment tree using references introspection in metadata.
     * @param wrapper A {@link Wrapper} instance (so an object managed by {@link HibernateStorage}.
     * @param storage A {@link HibernateStorage} instance. It will be used to compute references from the internal
     *                data model.
     * @param session A Hibernate {@link Session}.
     * @return The top level (aka the Wrapper instance that represent a MDM entity).
     */
    public static Wrapper findEntity(Wrapper wrapper, HibernateStorage storage, Session session) {
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        if (!(contextClassLoader instanceof StorageClassLoader)) {
            throw new IllegalStateException("Expects method to be called in the context of a storage operation.");
        }
        StorageClassLoader classLoader = (StorageClassLoader) contextClassLoader;
        ComplexTypeMetadata wrapperType = classLoader.getTypeFromClass(wrapper.getClass());
        if (wrapperType == null) {
            throw new IllegalArgumentException(
                    "Wrapper '" + wrapper.getClass().getName() + "' isn't known in current storage.");
        }
        if (wrapperType.isInstantiable()) {
            return wrapper;
        }
        InboundReferences incomingReferences = new InboundReferences(wrapperType);
        InternalRepository internalRepository = storage.getTypeEnhancer();
        Set<ReferenceFieldMetadata> references = internalRepository.getInternalRepository()
                .accept(incomingReferences);
        if (references.isEmpty()) {
            throw new IllegalStateException("Cannot find container type for '" + wrapperType.getName() + "'.");
        }
        String keyFieldName = wrapperType.getKeyFields().iterator().next().getName();
        Object id = wrapper.get(keyFieldName);
        for (ReferenceFieldMetadata reference : references) {
            ComplexTypeMetadata containingType = reference.getContainingType();
            Class<? extends Wrapper> clazz = classLoader.getClassFromType(containingType);
            Criteria criteria = session.createCriteria(clazz, "a0"); //$NON-NLS-1$
            criteria.createAlias("a0." + reference.getName(), "a1", CriteriaSpecification.INNER_JOIN); //$NON-NLS-1$
            criteria.add(Restrictions.eq("a1." + keyFieldName, id)); //$NON-NLS-1$
            List list = criteria.list();
            if (!list.isEmpty()) {
                Wrapper container = (Wrapper) list.get(0);
                if (list.size() > 1) {
                    Object previousItem = list.get(0);
                    for (int i = 1; i < list.size(); i++) {
                        Object currentItem = list.get(i);
                        if (!previousItem.equals(currentItem)) {
                            throw new IllegalStateException("Expected contained instance to have only one owner.");
                        }
                        previousItem = currentItem;
                    }
                }
                return findEntity(container, storage, session);
            }
        }
        return null;
    }

    /**
     * Wraps a {@link FullTextQuery} so it returns only "top level" Hibernate objects (iso. of possible technical objects).
     * This method ensures all methods that returns results will return expected results.
     *
     * @see org.hibernate.Query#scroll()
     * @param query The full text query to wrap.
     * @param storage The {@link HibernateStorage} implementation used to perform the query.
     * @param session A open, read for immediate usage Hibernate {@link Session}.
     * @return A wrapper that implements and supports all methods of {@link FullTextQuery}.
     */
    public static FullTextQuery wrap(FullTextQuery query, HibernateStorage storage, Session session,
            List<ComplexTypeMetadata> types) {
        return new QueryWrapper(query, storage, session, types);
    }

    private static class ScrollableResultsWrapper implements ScrollableResults {
        private final ScrollableResults scrollableResults;

        private final HibernateStorage storage;

        private final Session session;

        public ScrollableResultsWrapper(ScrollableResults scrollableResults, HibernateStorage storage,
                Session session) {
            this.scrollableResults = scrollableResults;
            this.storage = storage;
            this.session = session;
        }

        @Override
        public boolean next() throws HibernateException {
            return scrollableResults.next();
        }

        @Override
        public boolean previous() throws HibernateException {
            return scrollableResults.previous();
        }

        @Override
        public boolean scroll(int i) throws HibernateException {
            return scrollableResults.scroll(i);
        }

        @Override
        public boolean last() throws HibernateException {
            return scrollableResults.last();
        }

        @Override
        public boolean first() throws HibernateException {
            return scrollableResults.first();
        }

        @Override
        public void beforeFirst() throws HibernateException {
            scrollableResults.beforeFirst();
        }

        @Override
        public void afterLast() throws HibernateException {
            scrollableResults.afterLast();
        }

        @Override
        public boolean isFirst() throws HibernateException {
            return scrollableResults.isFirst();
        }

        @Override
        public boolean isLast() throws HibernateException {
            return scrollableResults.isLast();
        }

        @Override
        public void close() throws HibernateException {
            scrollableResults.close();
        }

        @Override
        public Object[] get() throws HibernateException {
            Object[] objects = scrollableResults.get();
            Object[] entities = new Object[objects.length];
            int i = 0;
            for (Object object : objects) {
                entities[i++] = EntityFinder.findEntity((Wrapper) object, storage, session);
            }
            return entities;
        }

        @Override
        public Object get(int i) throws HibernateException {
            return EntityFinder.findEntity((Wrapper) scrollableResults.get(i), storage, session);
        }

        @Override
        public Type getType(int i) {
            return scrollableResults.getType(i);
        }

        @Override
        public Integer getInteger(int col) throws HibernateException {
            return scrollableResults.getInteger(col);
        }

        @Override
        public Long getLong(int col) throws HibernateException {
            return scrollableResults.getLong(col);
        }

        @Override
        public Float getFloat(int col) throws HibernateException {
            return scrollableResults.getFloat(col);
        }

        @Override
        public Boolean getBoolean(int col) throws HibernateException {
            return scrollableResults.getBoolean(col);
        }

        @Override
        public Double getDouble(int col) throws HibernateException {
            return scrollableResults.getDouble(col);
        }

        @Override
        public Short getShort(int col) throws HibernateException {
            return scrollableResults.getShort(col);
        }

        @Override
        public Byte getByte(int col) throws HibernateException {
            return scrollableResults.getByte(col);
        }

        @Override
        public Character getCharacter(int col) throws HibernateException {
            return scrollableResults.getCharacter(col);
        }

        @Override
        public byte[] getBinary(int col) throws HibernateException {
            return scrollableResults.getBinary(col);
        }

        @Override
        public String getText(int col) throws HibernateException {
            return scrollableResults.getText(col);
        }

        @Override
        public Blob getBlob(int col) throws HibernateException {
            return scrollableResults.getBlob(col);
        }

        @Override
        public Clob getClob(int col) throws HibernateException {
            return scrollableResults.getClob(col);
        }

        @Override
        public String getString(int col) throws HibernateException {
            return scrollableResults.getString(col);
        }

        @Override
        public BigDecimal getBigDecimal(int col) throws HibernateException {
            return scrollableResults.getBigDecimal(col);
        }

        @Override
        public BigInteger getBigInteger(int col) throws HibernateException {
            return scrollableResults.getBigInteger(col);
        }

        @Override
        public Date getDate(int col) throws HibernateException {
            return scrollableResults.getDate(col);
        }

        @Override
        public Locale getLocale(int col) throws HibernateException {
            return scrollableResults.getLocale(col);
        }

        @Override
        public Calendar getCalendar(int col) throws HibernateException {
            return scrollableResults.getCalendar(col);
        }

        @Override
        public TimeZone getTimeZone(int col) throws HibernateException {
            return scrollableResults.getTimeZone(col);
        }

        @Override
        public int getRowNumber() throws HibernateException {
            return scrollableResults.getRowNumber();
        }

        @Override
        public boolean setRowNumber(int rowNumber) throws HibernateException {
            return scrollableResults.setRowNumber(rowNumber);
        }
    }

    private static class IteratorWrapper implements Iterator {
        private final Iterator iterator;

        private final HibernateStorage storage;

        private final Session session;

        public IteratorWrapper(Iterator iterator, HibernateStorage storage, Session session) {
            this.iterator = iterator;
            this.storage = storage;
            this.session = session;
        }

        @Override
        public boolean hasNext() {
            return iterator.hasNext();
        }

        @Override
        public Object next() {
            return EntityFinder.findEntity((Wrapper) iterator.next(), storage, session);
        }

        @Override
        public void remove() {
            iterator.remove();
        }
    }

    private static class QueryWrapper implements FullTextQuery {

        private final FullTextQuery query;

        private final HibernateStorage storage;

        private final Session session;

        private List<String> entityClassName = new ArrayList<String>();

        public QueryWrapper(FullTextQuery query, HibernateStorage storage, Session session,
                List<ComplexTypeMetadata> types) {
            this.query = query;
            this.storage = storage;
            this.session = session;
            if (types != null && types.size() > 0) {
                for (ComplexTypeMetadata ctm : types) {
                    entityClassName.add(ClassCreator.getClassName(ctm.getName()));
                    if (ctm.getSubTypes() != null) {
                        for (ComplexTypeMetadata subType : ctm.getSubTypes()) {
                            entityClassName.add(ClassCreator.getClassName(subType.getName()));
                        }
                    }
                }
            }
        }

        @Override
        public String getQueryString() {
            return query.getQueryString();
        }

        @Override
        public Integer getMaxResults() {
            return query.getMaxResults();
        }

        @Override
        public Type[] getReturnTypes() throws HibernateException {
            return query.getReturnTypes();
        }

        @Override
        public String[] getReturnAliases() throws HibernateException {
            return query.getReturnAliases();
        }

        @Override
        public String[] getNamedParameters() throws HibernateException {
            return query.getNamedParameters();
        }

        @Override
        public Iterator iterate() throws HibernateException {
            Iterator iterator = query.iterate();
            return new IteratorWrapper(iterator, storage, session);
        }

        @Override
        public ScrollableResults scroll() throws HibernateException {
            ScrollableResults scrollableResults = query.scroll();
            return new ScrollableResultsWrapper(scrollableResults, storage, session);
        }

        @Override
        public ScrollableResults scroll(ScrollMode scrollMode) throws HibernateException {
            ScrollableResults scrollableResults = query.scroll(scrollMode);
            return new ScrollableResultsWrapper(scrollableResults, storage, session);
        }

        @Override
        public List list() throws HibernateException {
            List<Wrapper> list = query.list();
            Set<Wrapper> newSet = new ListOrderedSet();
            for (Object item : list) {
                Wrapper element = EntityFinder.findEntity((Wrapper) item, storage, session);
                if (element != null) {
                    if (entityClassName.size() > 0) {
                        if (this.entityClassName.contains(element.getClass().getName())) {
                            newSet.add(element);
                        }
                    } else {
                        newSet.add(element);
                    }
                }
            }
            return new ArrayList<Wrapper>(newSet);
        }

        @Override
        public Object uniqueResult() throws HibernateException {
            return query.uniqueResult();
        }

        @Override
        public int executeUpdate() throws HibernateException {
            return query.executeUpdate();
        }

        @Override
        public FullTextQuery setMaxResults(int maxResults) {
            return query.setMaxResults(maxResults);
        }

        @Override
        public Integer getFirstResult() {
            return query.getFirstResult();
        }

        @Override
        public FullTextQuery setFirstResult(int firstResult) {
            return query.setFirstResult(firstResult);
        }

        @Override
        public boolean isReadOnly() {
            return query.isReadOnly();
        }

        @Override
        public Query setReadOnly(boolean readOnly) {
            return query.setReadOnly(readOnly);
        }

        @Override
        public LockOptions getLockOptions() {
            return query.getLockOptions();
        }

        @Override
        public Query setCacheable(boolean cacheable) {
            return query.setCacheable(cacheable);
        }

        @Override
        public String getCacheRegion() {
            return query.getCacheRegion();
        }

        @Override
        public Query setCacheRegion(String cacheRegion) {
            return query.setCacheRegion(cacheRegion);
        }

        @Override
        public Integer getTimeout() {
            return query.getTimeout();
        }

        @Override
        public Query setTimeout(int timeout) {
            return query.setTimeout(timeout);
        }

        @Override
        public Integer getFetchSize() {
            return query.getFetchSize();
        }

        @Override
        public FullTextQuery setFetchSize(int fetchSize) {
            return query.setFetchSize(fetchSize);
        }

        @Override
        public Query setLockOptions(LockOptions lockOptions) {
            return query.setLockOptions(lockOptions);
        }

        @Override
        public Query setLockMode(String alias, LockMode lockMode) {
            return query.setLockMode(alias, lockMode);
        }

        @Override
        public String getComment() {
            return query.getComment();
        }

        @Override
        public Query setComment(String comment) {
            return query.setComment(comment);
        }

        @Override
        public Query addQueryHint(String hint) {
            return query.addQueryHint(hint);
        }

        @Override
        public FlushMode getFlushMode() {
            return query.getFlushMode();
        }

        @Override
        public Query setFlushMode(FlushMode flushMode) {
            return query.setFlushMode(flushMode);
        }

        @Override
        public CacheMode getCacheMode() {
            return query.getCacheMode();
        }

        @Override
        public Query setCacheMode(CacheMode cacheMode) {
            return query.setCacheMode(cacheMode);
        }

        @Override
        public boolean isCacheable() {
            return query.isCacheable();
        }

        @Override
        public Query setParameter(int position, Object val, Type type) {
            return query.setParameter(position, val, type);
        }

        @Override
        public Query setParameter(String name, Object val, Type type) {
            return query.setParameter(name, val, type);
        }

        @Override
        public Query setParameter(int position, Object val) throws HibernateException {
            return query.setParameter(position, val);
        }

        @Override
        public Query setParameter(String name, Object val) throws HibernateException {
            return query.setParameter(name, val);
        }

        @Override
        public Query setParameters(Object[] values, Type[] types) throws HibernateException {
            return query.setParameters(values, types);
        }

        @Override
        public Query setParameterList(String name, Collection vals, Type type) throws HibernateException {
            return query.setParameterList(name, vals, type);
        }

        @Override
        public Query setParameterList(String name, Collection vals) throws HibernateException {
            return query.setParameterList(name, vals);
        }

        @Override
        public Query setParameterList(String name, Object[] vals, Type type) throws HibernateException {
            return query.setParameterList(name, vals, type);
        }

        @Override
        public Query setParameterList(String name, Object[] vals) throws HibernateException {
            return query.setParameterList(name, vals);
        }

        @Override
        public Query setProperties(Object bean) throws HibernateException {
            return query.setProperties(bean);
        }

        @Override
        public Query setProperties(Map bean) throws HibernateException {
            return query.setProperties(bean);
        }

        @Override
        public Query setString(int position, String val) {
            return query.setString(position, val);
        }

        @Override
        public Query setCharacter(int position, char val) {
            return query.setCharacter(position, val);
        }

        @Override
        public Query setBoolean(int position, boolean val) {
            return query.setBoolean(position, val);
        }

        @Override
        public Query setByte(int position, byte val) {
            return query.setByte(position, val);
        }

        @Override
        public Query setShort(int position, short val) {
            return query.setShort(position, val);
        }

        @Override
        public Query setInteger(int position, int val) {
            return query.setInteger(position, val);
        }

        @Override
        public Query setLong(int position, long val) {
            return query.setLong(position, val);
        }

        @Override
        public Query setFloat(int position, float val) {
            return query.setFloat(position, val);
        }

        @Override
        public Query setDouble(int position, double val) {
            return query.setDouble(position, val);
        }

        @Override
        public Query setBinary(int position, byte[] val) {
            return query.setBinary(position, val);
        }

        @Override
        public Query setText(int position, String val) {
            return query.setText(position, val);
        }

        @Override
        public Query setSerializable(int position, Serializable val) {
            return query.setSerializable(position, val);
        }

        @Override
        public Query setLocale(int position, Locale locale) {
            return query.setLocale(position, locale);
        }

        @Override
        public Query setBigDecimal(int position, BigDecimal number) {
            return query.setBigDecimal(position, number);
        }

        @Override
        public Query setBigInteger(int position, BigInteger number) {
            return query.setBigInteger(position, number);
        }

        @Override
        public Query setDate(int position, Date date) {
            return query.setDate(position, date);
        }

        @Override
        public Query setTime(int position, Date date) {
            return query.setTime(position, date);
        }

        @Override
        public Query setTimestamp(int position, Date date) {
            return query.setTimestamp(position, date);
        }

        @Override
        public Query setCalendar(int position, Calendar calendar) {
            return query.setCalendar(position, calendar);
        }

        @Override
        public Query setCalendarDate(int position, Calendar calendar) {
            return query.setCalendarDate(position, calendar);
        }

        @Override
        public Query setString(String name, String val) {
            return query.setString(name, val);
        }

        @Override
        public Query setCharacter(String name, char val) {
            return query.setCharacter(name, val);
        }

        @Override
        public Query setBoolean(String name, boolean val) {
            return query.setBoolean(name, val);
        }

        @Override
        public Query setByte(String name, byte val) {
            return query.setByte(name, val);
        }

        @Override
        public Query setShort(String name, short val) {
            return query.setShort(name, val);
        }

        @Override
        public Query setInteger(String name, int val) {
            return query.setInteger(name, val);
        }

        @Override
        public Query setLong(String name, long val) {
            return query.setLong(name, val);
        }

        @Override
        public Query setFloat(String name, float val) {
            return query.setFloat(name, val);
        }

        @Override
        public Query setDouble(String name, double val) {
            return query.setDouble(name, val);
        }

        @Override
        public Query setBinary(String name, byte[] val) {
            return query.setBinary(name, val);
        }

        @Override
        public Query setText(String name, String val) {
            return query.setText(name, val);
        }

        @Override
        public Query setSerializable(String name, Serializable val) {
            return query.setSerializable(name, val);
        }

        @Override
        public Query setLocale(String name, Locale locale) {
            return query.setLocale(name, locale);
        }

        @Override
        public Query setBigDecimal(String name, BigDecimal number) {
            return query.setBigDecimal(name, number);
        }

        @Override
        public Query setBigInteger(String name, BigInteger number) {
            return query.setBigInteger(name, number);
        }

        @Override
        public Query setDate(String name, Date date) {
            return query.setDate(name, date);
        }

        @Override
        public Query setTime(String name, Date date) {
            return query.setTime(name, date);
        }

        @Override
        public Query setTimestamp(String name, Date date) {
            return query.setTimestamp(name, date);
        }

        @Override
        public Query setCalendar(String name, Calendar calendar) {
            return query.setCalendar(name, calendar);
        }

        @Override
        public Query setCalendarDate(String name, Calendar calendar) {
            return query.setCalendarDate(name, calendar);
        }

        @Override
        public Query setEntity(int position, Object val) {
            return query.setEntity(position, val);
        }

        @Override
        public Query setEntity(String name, Object val) {
            return query.setEntity(name, val);
        }

        @Override
        public FullTextQuery setResultTransformer(ResultTransformer transformer) {
            return query.setResultTransformer(transformer);
        }

        @Override
        public <T> T unwrap(Class<T> tClass) {
            return query.unwrap(tClass);
        }

        @Override
        public FullTextQuery setTimeout(long timeout, TimeUnit timeUnit) {
            return query.setTimeout(timeout, timeUnit);
        }

        @Override
        public FullTextQuery limitExecutionTimeTo(long timeout, TimeUnit timeUnit) {
            return query.limitExecutionTimeTo(timeout, timeUnit);
        }

        @Override
        public boolean hasPartialResults() {
            return query.hasPartialResults();
        }

        @Override
        public FullTextQuery initializeObjectsWith(ObjectLookupMethod lookupMethod,
                DatabaseRetrievalMethod retrievalMethod) {
            return query.initializeObjectsWith(lookupMethod, retrievalMethod);
        }

        @Override
        public FullTextQuery setSort(Sort sort) {
            return query.setSort(sort);
        }

        @Override
        public FullTextQuery setFilter(org.apache.lucene.search.Filter filter) {
            return query.setFilter(filter);
        }

        @Override
        public int getResultSize() {
            return query.getResultSize();
        }

        @Override
        public FullTextQuery setCriteriaQuery(Criteria criteria) {
            return query.setCriteriaQuery(criteria);
        }

        @Override
        public FullTextQuery setProjection(String... strings) {
            return query.setProjection(strings);
        }

        @Override
        public FullTextQuery setSpatialParameters(double latitude, double longitude, String fieldName) {
            return query.setSpatialParameters(latitude, longitude, fieldName);
        }

        @Override
        public FullTextQuery setSpatialParameters(Coordinates center, String fieldName) {
            return query.setSpatialParameters(center, fieldName);
        }

        @Override
        public FullTextFilter enableFullTextFilter(String s) {
            return query.enableFullTextFilter(s);
        }

        @Override
        public void disableFullTextFilter(String s) {
            query.disableFullTextFilter(s);
        }

        @Override
        public FacetManager getFacetManager() {
            return query.getFacetManager();
        }

        @Override
        public Explanation explain(int i) {
            return query.explain(i);
        }
    }
}