com.github.shyiko.rook.target.hibernate4.fulltextindex.SynchronizationContext.java Source code

Java tutorial

Introduction

Here is the source code for com.github.shyiko.rook.target.hibernate4.fulltextindex.SynchronizationContext.java

Source

/*
 * Copyright 2013 Stanley Shyiko
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.shyiko.rook.target.hibernate4.fulltextindex;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.ToOne;
import org.hibernate.mapping.Value;
import org.hibernate.property.Getter;
import org.hibernate.search.annotations.ContainedIn;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.indexes.interceptor.DefaultEntityInterceptor;
import org.hibernate.search.indexes.interceptor.EntityIndexingInterceptor;

import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Member;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

/**
 * @author <a href="mailto:stanley.shyiko@gmail.com">Stanley Shyiko</a>
 */
public class SynchronizationContext {

    private final String schema;
    private final SessionFactory sessionFactory;

    private final Map<String, IndexingDirective> directivesByTable = new HashMap<String, IndexingDirective>();
    private final Map<Class, IndexingDirective> directivesByEntityClass = new HashMap<Class, IndexingDirective>();

    public SynchronizationContext(Configuration configuration, SessionFactory sessionFactory) {
        this.schema = ((SessionFactoryImplementor) sessionFactory).getJdbcServices().getExtractedMetaDataSupport()
                .getConnectionCatalogName().toLowerCase();
        this.sessionFactory = sessionFactory;
        loadIndexingDirectives(configuration);
    }

    public SessionFactoryImplementor getSessionFactory() {
        return (SessionFactoryImplementor) sessionFactory;
    }

    public Collection<IndexingDirective> getIndexingDirectives(String table) {
        IndexingDirective indexingTarget = directivesByTable.get(table.toLowerCase());
        return indexingTarget == null ? Collections.<IndexingDirective>emptyList() : Arrays.asList(indexingTarget);
    }

    public IndexingDirective getIndexingDirective(Class entityClass) {
        return directivesByEntityClass.get(entityClass);
    }

    @SuppressWarnings("unchecked")
    private void loadIndexingDirectives(Configuration configuration) {
        Map<String, IndexingDirective> directivesByEntityNameMap = new HashMap<String, IndexingDirective>();
        Collection<Property> allContainedInProperties = new ArrayList<Property>();
        for (Iterator<PersistentClass> classIterator = configuration.getClassMappings(); classIterator.hasNext();) {
            PersistentClass persistentClass = classIterator.next();
            boolean suppressSelfIndexing = true;
            Class mappedClass = persistentClass.getMappedClass();
            Indexed indexed = (Indexed) mappedClass.getAnnotation(Indexed.class);
            EntityIndexingInterceptor indexingInterceptor = null;
            if (indexed != null) {
                suppressSelfIndexing = false;
                Class<? extends EntityIndexingInterceptor> interceptorClass = indexed.interceptor();
                if (interceptorClass != DefaultEntityInterceptor.class) {
                    try {
                        indexingInterceptor = interceptorClass.newInstance();
                    } catch (InstantiationException e) {
                        throw new RuntimeException("Failed to instantiate " + interceptorClass, e);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException("Failed to instantiate " + interceptorClass, e);
                    }
                }
            }
            Collection<Property> containedInProperties = extractAnnotatedProperties(persistentClass,
                    ContainedIn.class);
            if (suppressSelfIndexing && containedInProperties.isEmpty()) {
                continue;
            }
            allContainedInProperties.addAll(containedInProperties);
            PrimaryKey primaryKey = new PrimaryKey(persistentClass);
            Collection<Reference> containers = new ArrayList<Reference>();
            for (Property property : containedInProperties) {
                containers.add(new Reference(property.getGetter(mappedClass)));
            }
            IndexingDirective indexingDirective = new IndexingDirective(primaryKey, suppressSelfIndexing,
                    indexingInterceptor, containers);
            Table table = persistentClass.getTable();
            directivesByTable.put(schema + "." + table.getName().toLowerCase(), indexingDirective);
            directivesByEntityClass.put(mappedClass, indexingDirective);
            directivesByEntityNameMap.put(persistentClass.getEntityName(), indexingDirective);
        }
        loadIndexingDirectivesForJoinTables(allContainedInProperties, directivesByEntityNameMap);
    }

    @SuppressWarnings("unchecked")
    private Collection<Property> extractAnnotatedProperties(PersistentClass persistentClass,
            Class<? extends Annotation> annotation) {
        Class mappedClass = persistentClass.getMappedClass();
        Collection<Property> properties = new ArrayList<Property>();
        for (Iterator<Property> propertyIterator = persistentClass.getPropertyIterator(); propertyIterator
                .hasNext();) {
            Property property = propertyIterator.next();
            Getter getter = property.getGetter(mappedClass);
            if (getter == null) {
                continue;
            }
            Member mappedClassMember = getter.getMember();
            boolean isRequestedAnnotationPresent = mappedClassMember instanceof AccessibleObject
                    && ((AccessibleObject) mappedClassMember).isAnnotationPresent(annotation);
            if (isRequestedAnnotationPresent) {
                properties.add(property);
            }
        }
        return properties;
    }

    private void loadIndexingDirectivesForJoinTables(Collection<Property> allContainedInProperties,
            Map<String, IndexingDirective> directivesByEntityNameMap) {
        for (Property property : allContainedInProperties) {
            Value value = property.getValue();
            if (value instanceof org.hibernate.mapping.Collection) {
                org.hibernate.mapping.Collection collection = (org.hibernate.mapping.Collection) value;
                Table collectionTable = collection.getCollectionTable();
                String tableName = schema + "." + collectionTable.getName().toLowerCase();
                if (directivesByTable.containsKey(tableName)) {
                    continue;
                }
                PrimaryKey primaryKey = resolveForeignPrimaryKey(collection, directivesByEntityNameMap);
                if (primaryKey == null) {
                    continue;
                }
                IndexingDirective containerIndexingDirective = directivesByEntityClass
                        .get(primaryKey.getEntityClass());
                directivesByTable.put(tableName,
                        new IndexingDirective(primaryKey, containerIndexingDirective.isSuppressSelfIndexing(),
                                containerIndexingDirective.getEntityIndexingInterceptor(),
                                containerIndexingDirective.getContainerReferences()));
            }
        }
    }

    @SuppressWarnings("unchecked")
    private PrimaryKey resolveForeignPrimaryKey(org.hibernate.mapping.Collection collection,
            Map<String, IndexingDirective> directivesByEntityNameMap) {
        Table collectionTable = collection.getCollectionTable();
        ToOne element = (ToOne) collection.getElement();
        IndexingDirective indexingDirective = directivesByEntityNameMap.get(element.getReferencedEntityName());
        if (indexingDirective == null) {
            return null;
        }
        Collection<String> targetPrimaryKeyColumnNames = new HashSet<String>();
        for (Iterator<Column> columnIterator = element.getColumnIterator(); columnIterator.hasNext();) {
            Column column = columnIterator.next();
            targetPrimaryKeyColumnNames.add(column.getName());
        }
        Map<String, Integer> columnIndexByNameMap = new HashMap<String, Integer>();
        int index = 0;
        for (Iterator<Column> columnIterator = collectionTable.getColumnIterator(); columnIterator.hasNext();) {
            Column column = columnIterator.next();
            if (targetPrimaryKeyColumnNames.contains(column.getName())) {
                columnIndexByNameMap.put(column.getName(), index);
            }
            index++;
        }
        return new PrimaryKey(indexingDirective.getPrimaryKey(), columnIndexByNameMap);
    }

}