/* * This code is distributed under The GNU Lesser General Public License (LGPLv3) * Please visit GNU site for LGPLv3 http://www.gnu.org/copyleft/lesser.html * * Copyright Denis Pavlov 2009 * Web: http://www.genericdtoassembler.org * SVN: https://svn.code.sf.net/p/geda-genericdto/code/trunk/ * SVN (mirror): http://geda-genericdto.googlecode.com/svn/trunk/ */ package com.inspiresoftware.lib.dto.geda.assembler; import com.inspiresoftware.lib.dto.geda.adapter.BeanFactory; import com.inspiresoftware.lib.dto.geda.adapter.DtoToEntityMatcher; import com.inspiresoftware.lib.dto.geda.exception.*; import java.util.Collection; import java.util.HashMap; import java.util.Map; /** * Collection pipe meta contains information on the metadata of the pipe. * * @author DPavlov */ @SuppressWarnings("unchecked") public class CollectionPipeMetadata extends BasePipeMetadata implements com.inspiresoftware.lib.dto.geda.assembler.meta.CollectionPipeMetadata { private static final Map<Class, DtoToEntityMatcher> CACHE = new HashMap<Class, DtoToEntityMatcher>(); private final Class< ? extends Collection> dtoCollectionClass; private final String dtoCollectionClassKey; private final Class< ? extends Collection> entityCollectionClass; private final String entityCollectionClassKey; private final Class< ? > returnType; private final String returnTypeKey; private final DtoToEntityMatcher dtoToEntityMatcher; private final String dtoToEntityMatcherKey; /** * * @param dtoFieldName key for accessing field on DTO object * @param entityFieldName key for accessing field on Entity bean * @param dtoBeanKey key for constructing DTO bean * @param entityBeanKey key for constructing Entity bean * @param readOnly read only marker (true then write to entity is omitted) * @param dtoCollectionClass the dto collection class for creating new collection instance * @param dtoCollectionClassKey key for dto collection class fetched from beanFactory * @param entityCollectionClass the entity collection class for creating new collection instance * @param entityCollectionClassKey key for entity collection class fetched from beanFactory * @param returnType the generic type for entity collection item * @param returnTypeKey bean factory key for generic type for entity collection item * @param dtoToEntityMatcherClass matcher for synchronising collections * @param dtoToEntityMatcherKey key of matcher in the converters map * * @throws UnableToCreateInstanceException if unable to create item matcher */ public CollectionPipeMetadata(final String dtoFieldName, final String entityFieldName, final String dtoBeanKey, final String entityBeanKey, final boolean readOnly, final Class<? extends Collection> dtoCollectionClass, final String dtoCollectionClassKey, final Class<? extends Collection> entityCollectionClass, final String entityCollectionClassKey, final Class<?> returnType, final String returnTypeKey, final Class<? extends DtoToEntityMatcher> dtoToEntityMatcherClass, final String dtoToEntityMatcherKey) throws UnableToCreateInstanceException { super(dtoFieldName, entityFieldName, dtoBeanKey, entityBeanKey, readOnly); this.dtoCollectionClass = dtoCollectionClass; this.returnTypeKey = returnTypeKey != null && returnTypeKey.length() > 0 ? returnTypeKey : null; this.dtoCollectionClassKey = dtoCollectionClassKey != null && dtoCollectionClassKey.length() > 0 ? dtoCollectionClassKey : null; this.entityCollectionClass = entityCollectionClass; this.entityCollectionClassKey = entityCollectionClassKey != null && entityCollectionClassKey.length() > 0 ? entityCollectionClassKey : null; this.returnType = returnType; if (dtoToEntityMatcherKey == null || dtoToEntityMatcherKey.length() == 0) { if (CACHE.containsKey(dtoToEntityMatcherClass)) { this.dtoToEntityMatcher = CACHE.get(dtoToEntityMatcherClass); } else { this.dtoToEntityMatcher = newBeanForClass( dtoToEntityMatcherClass, "Unable to create matcher: {0} for: {1} - {2}", dtoToEntityMatcherClass, this.getDtoBeanKey(), this.getEntityBeanKey()); CACHE.put(dtoToEntityMatcherClass, this.dtoToEntityMatcher); } this.dtoToEntityMatcherKey = null; } else { this.dtoToEntityMatcher = null; this.dtoToEntityMatcherKey = dtoToEntityMatcherKey; } } /** {@inheritDoc} */ public Collection newDtoCollection(final BeanFactory beanFactory) throws UnableToCreateInstanceException, BeanFactoryNotFoundException { if (this.dtoCollectionClassKey != null) { return newCollection(this.dtoCollectionClassKey, beanFactory, true); } return newCollection(dtoCollectionClass, " Dto field: ", this.getDtoFieldName()); } /** {@inheritDoc} */ public Collection newEntityCollection(final BeanFactory beanFactory) throws UnableToCreateInstanceException, BeanFactoryNotFoundException { if (this.entityCollectionClassKey != null) { return newCollection(this.entityCollectionClassKey, beanFactory, false); } return newCollection(entityCollectionClass, " Entity field: ", this.getEntityFieldName()); } /** {@inheritDoc} */ public Class< ? > getReturnType(BeanFactory beanFactory) throws BeanFactoryUnableToLocateRepresentationException, BeanFactoryNotFoundException { if (this.returnTypeKey == null) { return returnType; } return getRepresentation(this.returnTypeKey, beanFactory, false); } /** {@inheritDoc} */ public DtoToEntityMatcher getDtoToEntityMatcher(final Map<String, Object> converters) throws DtoToEntityMatcherNotFoundException, NotDtoToEntityMatcherException { if (this.dtoToEntityMatcherKey == null) { return dtoToEntityMatcher; } if (converters == null) { throw new DtoToEntityMatcherNotFoundException(this.getDtoFieldName(), this.getEntityFieldName(), this.dtoToEntityMatcherKey); } final Object matcher = converters.get(this.dtoToEntityMatcherKey); if (matcher == null) { throw new DtoToEntityMatcherNotFoundException(this.getDtoFieldName(), this.getEntityFieldName(), this.dtoToEntityMatcherKey); } if (matcher instanceof DtoToEntityMatcher) { return (DtoToEntityMatcher) matcher; } throw new NotDtoToEntityMatcherException(this.getDtoFieldName(), this.getEntityFieldName(), this.dtoToEntityMatcherKey); } private Collection newCollection(final String clazzKey, final BeanFactory beanFactory, final boolean isDto) throws UnableToCreateInstanceException, BeanFactoryNotFoundException { if (beanFactory == null) { throw new BeanFactoryNotFoundException(this.getDtoFieldName(), clazzKey, isDto); } final Object coll = beanFactory.get(clazzKey); if (coll instanceof Collection) { return (Collection) coll; } throw new UnableToCreateInstanceException(clazzKey, " Collection" + (isDto ? " Dto" : " Entity") + " field: " + this.getDtoFieldName() + "@key:" + clazzKey + " (Check if beanFactory [" + beanFactory + "] returns a correct instance)", null); } private Collection newCollection(final Class< ? extends Collection> clazz, final String type, final String field) throws UnableToCreateInstanceException { return newBeanForClass(clazz, "Unable to create collection: {0} for {1} {2}", clazz, type, field); } private <T> T newBeanForClass(final Class<T> clazz, final String errMsg, final Object ... msgParams) throws UnableToCreateInstanceException { try { return clazz.newInstance(); } catch (Exception iex) { throw new UnableToCreateInstanceException(clazz.getCanonicalName(), String.format(errMsg, msgParams), iex); } } }