001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.compass.gps.device.jpa.entities;
018:
019: import java.util.ArrayList;
020: import java.util.Map;
021: import javax.persistence.EntityManagerFactory;
022:
023: import org.apache.commons.logging.Log;
024: import org.apache.commons.logging.LogFactory;
025: import org.compass.core.mapping.ResourceMapping;
026: import org.compass.gps.device.jpa.JpaGpsDevice;
027: import org.compass.gps.device.jpa.JpaGpsDeviceException;
028: import org.compass.gps.device.jpa.queryprovider.HibernateJpaQueryProvider;
029: import org.compass.gps.spi.CompassGpsInterfaceDevice;
030: import org.hibernate.EntityMode;
031: import org.hibernate.SessionFactory;
032: import org.hibernate.ejb.HibernateEntityManagerFactory;
033: import org.hibernate.metadata.ClassMetadata;
034: import org.hibernate.persister.entity.AbstractEntityPersister;
035:
036: /**
037: * A specilized version that works with Hibernate. This class should be used instead of
038: * {@link DefaultJpaEntitiesLocator} since it works with both hbm files and annotatios.
039: *
040: * @author kimchy
041: */
042: public class HibernateJpaEntitiesLocator implements JpaEntitiesLocator {
043:
044: protected Log log = LogFactory.getLog(getClass());
045:
046: public EntityInformation[] locate(
047: EntityManagerFactory entityManagerFactory,
048: JpaGpsDevice device) throws JpaGpsDeviceException {
049:
050: CompassGpsInterfaceDevice gps = (CompassGpsInterfaceDevice) device
051: .getGps();
052:
053: HibernateEntityManagerFactory hibernateEntityManagerFactory = (HibernateEntityManagerFactory) entityManagerFactory;
054: SessionFactory sessionFactory = hibernateEntityManagerFactory
055: .getSessionFactory();
056:
057: ArrayList<EntityInformation> entitiesList = new ArrayList<EntityInformation>();
058:
059: Map allClassMetaData = sessionFactory.getAllClassMetadata();
060: for (Object o : allClassMetaData.keySet()) {
061: String entityname = (String) o;
062: if (!gps.hasMappingForEntityForIndex((entityname))) {
063: if (log.isDebugEnabled()) {
064: log
065: .debug("Entity ["
066: + entityname
067: + "] does not have compass mapping, filtering it out");
068: }
069: continue;
070: }
071:
072: ClassMetadata classMetadata = (ClassMetadata) allClassMetaData
073: .get(entityname);
074: if (shouldFilter(entityname, classMetadata,
075: allClassMetaData, device)) {
076: continue;
077: }
078: Class<?> clazz = classMetadata
079: .getMappedClass(EntityMode.POJO);
080: ResourceMapping resourceMapping = gps
081: .getMappingForEntityForIndex(entityname);
082: EntityInformation entityInformation = new EntityInformation(
083: clazz, entityname, new HibernateJpaQueryProvider(
084: clazz, entityname), resourceMapping
085: .getSubIndexHash().getSubIndexes());
086: entitiesList.add(entityInformation);
087: if (log.isDebugEnabled()) {
088: log
089: .debug("Entity [" + entityname
090: + "] will be indexed");
091: }
092: }
093: return entitiesList.toArray(new EntityInformation[entitiesList
094: .size()]);
095: }
096:
097: /**
098: * Returns <code>true</code> if the entity name needs to be filtered.
099: *
100: * <p>Implementation filteres out inherited hibernate mappings, since the select query
101: * for the base class will cover any inherited classes as well.
102: *
103: * <p>Note, that this method is called after it has been verified that the class has
104: * Compass mappings (either directly, or indirectly by an interface or a super class).
105: *
106: * @param entityname The name of the entity
107: * @param classMetadata The Hibernate class meta data.
108: * @param device The Jpa Gps device
109: * @return <code>true</code> if the entity should be filtered out, <code>false</code> if not.
110: */
111: protected boolean shouldFilter(String entityname,
112: ClassMetadata classMetadata, Map allClassMetaData,
113: JpaGpsDevice device) {
114: Class<?> clazz = classMetadata.getMappedClass(EntityMode.POJO);
115: // if it is inherited, do not add it to the classes to index, since the "from [entity]"
116: // query for the base class will return results for this class as well
117: if (classMetadata.isInherited()) {
118: String super ClassEntityName = ((AbstractEntityPersister) classMetadata)
119: .getMappedSuperclass();
120: ClassMetadata super ClassMetadata = (ClassMetadata) allClassMetaData
121: .get(super ClassEntityName);
122: Class super Class = super ClassMetadata
123: .getMappedClass(EntityMode.POJO);
124: // only filter out classes that their super class has compass mappings
125: if (super Class != null
126: && ((CompassGpsInterfaceDevice) device.getGps())
127: .hasMappingForEntityForIndex(super Class)) {
128: if (log.isDebugEnabled()) {
129: log
130: .debug("Entity ["
131: + entityname
132: + "] is inherited and super class ["
133: + super Class
134: + "] has compass mapping, filtering it out");
135: }
136: return true;
137: }
138: }
139: return false;
140: }
141: }
|