Java tutorial
/* * Copyright (c) 2012-2014 Veniamin Isaias. * * This file is part of web4thejob. * * Web4thejob 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 any later version. * * Web4thejob 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 web4thejob. If not, see <http://www.gnu.org/licenses/>. */ package org.web4thejob.orm; import org.hibernate.SessionFactory; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.internal.SessionFactoryImpl; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.metadata.ClassMetadata; import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.LazyInitializer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils.FieldCallback; import org.web4thejob.context.ContextUtil; import org.web4thejob.orm.annotation.*; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.*; /** * @author Veniamin Isaias * @since 1.0.0 */ /* package */class MetaReaderServiceImpl implements MetaReaderService { // ------------------------------ FIELDS ------------------------------ static final Map<String, EntityMetadata> metaCache = new HashMap<String, EntityMetadata>(); static final Map<String, Map<String, Map<String, AnnotationMetadata<? extends Annotation>>>> annoCache = new HashMap<String, Map<String, Map<String, AnnotationMetadata<? extends Annotation>>>>(); @Autowired private SessionFactory sessionFactory; // ------------------------ INTERFACE METHODS ------------------------ // --------------------- Interface MetaReaderService --------------------- @Override @SuppressWarnings("unchecked") public <E extends Entity> E deproxyEntity(E entity) { final E proxy = entity; if (proxy instanceof HibernateProxy) { { if (((HibernateProxy) proxy).getHibernateLazyInitializer().isUninitialized()) { final E impl = ContextUtil.getTransactionWrapper().execute(new TransactionCallback<E>() { @Override public E doInTransaction(TransactionStatus status) { final LazyInitializer lazy = ((HibernateProxy) proxy).getHibernateLazyInitializer(); lazy.setSession((SessionImplementor) sessionFactory.getCurrentSession()); lazy.initialize(); final Object impl = lazy.getImplementation(); lazy.unsetSession(); return (E) impl; } }); return impl; } else { return (E) ((HibernateProxy) proxy).getHibernateLazyInitializer().getImplementation(); } } } return entity; } @Override @SuppressWarnings({ "unchecked", "rawtypes" }) public <E extends Entity, A extends Annotation> Collection<AnnotationMetadata<A>> getAnnotationMetadata( Class<E> entityType, Class<A> annotationType) { final Map<String, Map<String, AnnotationMetadata<? extends Annotation>>> map = annoCache .get(entityType.getName()); if (map != null && map.containsKey(annotationType.getName())) { List<AnnotationMetadata<A>> metadatas = new ArrayList<AnnotationMetadata<A>>(); for (AnnotationMetadata a : map.get(annotationType.getName()).values()) { metadatas.add(a); } return metadatas; } return Collections.emptyList(); } @Override public EntityMetadata getEntityMetadata(Class<? extends Entity> entityType) { return getEntityMetadata(entityType.getName()); } @Override public EntityMetadata getEntityMetadata(String entityType) { return metaCache.get(entityType); } @Override public PropertyMetadata getPropertyMetadata(Class<? extends Entity> entityType, String property) { return getEntityMetadata(entityType).getPropertyMetadata(property); } @Override public PropertyMetadata getPropertyMetadata(String entityType, String property) { return getEntityMetadata(entityType).getPropertyMetadata(property); } @Override public PathMetadata getPropertyPath(Class<? extends Entity> entityType, Path path) { return new PathMetadataImpl(entityType, path); } @Override public PathMetadata getPropertyPath(Class<? extends Entity> entityType, String[] path) { return new PathMetadataImpl(entityType, path); } @Override public PathMetadata getPropertyPath(Class<? extends Entity> entityType, List<PropertyMetadata> path) { String[] steps = new String[path.size()]; int index = 0; for (PropertyMetadata item : path) { steps[index] = item.getName(); index++; } return new PathMetadataImpl(entityType, steps); } @Override public PathMetadata getPropertyPath(PropertyMetadata propertyMetadata) { return new PathMetadataImpl(propertyMetadata.getEntityMetadata().getEntityType(), new Path(propertyMetadata.getName())); } @Override @SuppressWarnings("unchecked") public <E extends Entity> E newInstance(Class<? extends Entity> entityType) { try { if (entityType.isInterface()) { entityType = getEntityMetadata(entityType).getMappedClass(); } return (E) ReflectHelper.getDefaultConstructor(entityType).newInstance((Object[]) null); } catch (final Exception e) { e.printStackTrace(); return null; } } @Override public void refreshMetaCache() { ((SessionFactoryImpl) sessionFactory).registerEntityNameResolver(EntityNameResolverImpl.INSTANCE); annoCache.clear(); for (final ClassMetadata classMetadata : sessionFactory.getAllClassMetadata().values()) { final AnnotationReader reader = new AnnotationReader(classMetadata.getEntityName()); ReflectionUtils.doWithFields(classMetadata.getMappedClass(), reader); if (reader.map.size() > 0) { annoCache.put(classMetadata.getEntityName(), reader.map); } } metaCache.clear(); //first pass for (final ClassMetadata classMetadata : sessionFactory.getAllClassMetadata().values()) { if (!metaCache.containsKey(classMetadata.getEntityName())) { metaCache.put(classMetadata.getEntityName(), new EntityMetadataImpl(classMetadata)); } } //second pass for (EntityMetadata entityMetadata : metaCache.values()) { ((EntityMetadataImpl) entityMetadata).initUniqueKeyConstraints(); } } @Override public Collection<EntityMetadata> getEntityMetadatas() { List<EntityMetadata> metadatas = new ArrayList<EntityMetadata>(metaCache.values()); Collections.sort(metadatas, new Comparator<EntityMetadata>() { @Override public int compare(EntityMetadata o1, EntityMetadata o2) { return (o1.getSchema() + o1.getFriendlyName()).compareTo(o2.getSchema() + o2.getFriendlyName()); } }); return Collections.unmodifiableCollection(metadatas); } // -------------------------- OTHER METHODS -------------------------- @SuppressWarnings("unchecked") private Class<? extends Entity> getEntityType(String entityName) { try { return (Class<? extends Entity>) Class.forName(entityName); } catch (Exception e) { e.printStackTrace(); throw new IllegalArgumentException(entityName + " is not a valid Entity implementation"); } } // -------------------------- INNER CLASSES -------------------------- private class AnnotationReader implements FieldCallback { public final Map<String, Map<String, AnnotationMetadata<? extends Annotation>>> map = new HashMap<String, Map<String, AnnotationMetadata<? extends Annotation>>>(); private final String declaringType; public AnnotationReader(String declaringType) { this.declaringType = declaringType; } private <A extends Annotation> void appendMetadata(Class<A> annotationType, AnnotationMetadata<A> metadata) { if (!map.containsKey(annotationType.getName())) { map.put(annotationType.getName(), new HashMap<String, AnnotationMetadata<? extends Annotation>>()); } map.get(annotationType.getName()).put(metadata.getName(), metadata); } @Override public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { if (field.isAnnotationPresent(InsertTimeHolder.class)) { appendMetadata(InsertTimeHolder.class, new AnnotationMetadataImpl<InsertTimeHolder>( getEntityType(declaringType), field, field.getAnnotation(InsertTimeHolder.class))); } if (field.isAnnotationPresent(UpdateTimeHolder.class)) { appendMetadata(UpdateTimeHolder.class, new AnnotationMetadataImpl<UpdateTimeHolder>( getEntityType(declaringType), field, field.getAnnotation(UpdateTimeHolder.class))); } if (field.isAnnotationPresent(StatusHolder.class)) { appendMetadata(StatusHolder.class, new AnnotationMetadataImpl<StatusHolder>( getEntityType(declaringType), field, field.getAnnotation(StatusHolder.class))); } if (field.isAnnotationPresent(PropertyViewer.class)) { appendMetadata(PropertyViewer.class, new AnnotationMetadataImpl<PropertyViewer>( getEntityType(declaringType), field, field.getAnnotation(PropertyViewer.class))); } if (field.isAnnotationPresent(PropertyEditor.class)) { appendMetadata(PropertyEditor.class, new AnnotationMetadataImpl<PropertyEditor>( getEntityType(declaringType), field, field.getAnnotation(PropertyEditor.class))); } if (field.isAnnotationPresent(Encrypted.class)) { appendMetadata(Encrypted.class, new AnnotationMetadataImpl<Encrypted>(getEntityType(declaringType), field, field.getAnnotation(Encrypted.class))); } if (field.isAnnotationPresent(UserIdHolder.class)) { appendMetadata(UserIdHolder.class, new AnnotationMetadataImpl<UserIdHolder>( getEntityType(declaringType), field, field.getAnnotation(UserIdHolder.class))); } if (field.isAnnotationPresent(HtmlHolder.class)) { appendMetadata(HtmlHolder.class, new AnnotationMetadataImpl<HtmlHolder>( getEntityType(declaringType), field, field.getAnnotation(HtmlHolder.class))); } if (field.isAnnotationPresent(EmailHolder.class)) { appendMetadata(EmailHolder.class, new AnnotationMetadataImpl<EmailHolder>( getEntityType(declaringType), field, field.getAnnotation(EmailHolder.class))); } if (field.isAnnotationPresent(DefaultHolder.class)) { appendMetadata(DefaultHolder.class, new AnnotationMetadataImpl<DefaultHolder>( getEntityType(declaringType), field, field.getAnnotation(DefaultHolder.class))); } if (field.isAnnotationPresent(ColorHolder.class)) { appendMetadata(ColorHolder.class, new AnnotationMetadataImpl<ColorHolder>( getEntityType(declaringType), field, field.getAnnotation(ColorHolder.class))); } if (field.isAnnotationPresent(UrlHolder.class)) { appendMetadata(UrlHolder.class, new AnnotationMetadataImpl<UrlHolder>(getEntityType(declaringType), field, field.getAnnotation(UrlHolder.class))); } if (field.isAnnotationPresent(MediaHolder.class)) { appendMetadata(MediaHolder.class, new AnnotationMetadataImpl<MediaHolder>( getEntityType(declaringType), field, field.getAnnotation(MediaHolder.class))); } if (field.isAnnotationPresent(ImageHolder.class)) { appendMetadata(ImageHolder.class, new AnnotationMetadataImpl<ImageHolder>( getEntityType(declaringType), field, field.getAnnotation(ImageHolder.class))); } if (field.isAnnotationPresent(EntityTypeHolder.class)) { appendMetadata(EntityTypeHolder.class, new AnnotationMetadataImpl<EntityTypeHolder>( getEntityType(declaringType), field, field.getAnnotation(EntityTypeHolder.class))); } if (field.isAnnotationPresent(PanelHolder.class)) { appendMetadata(PanelHolder.class, new AnnotationMetadataImpl<PanelHolder>( getEntityType(declaringType), field, field.getAnnotation(PanelHolder.class))); } if (field.isAnnotationPresent(ControllerHolder.class)) { appendMetadata(ControllerHolder.class, new AnnotationMetadataImpl<ControllerHolder>( getEntityType(declaringType), field, field.getAnnotation(ControllerHolder.class))); } if (field.isAnnotationPresent(QueryHolder.class)) { appendMetadata(QueryHolder.class, new AnnotationMetadataImpl<QueryHolder>( getEntityType(declaringType), field, field.getAnnotation(QueryHolder.class))); } if (field.isAnnotationPresent(EntityHierarchyHolder.class)) { appendMetadata(EntityHierarchyHolder.class, new AnnotationMetadataImpl<EntityHierarchyHolder>( getEntityType(declaringType), field, field.getAnnotation(EntityHierarchyHolder.class))); } } } }