/* * * This is a simple Content Management System (CMS) * Copyright (C) 2011 Imran M Yousuf (imyousuf@smartitengineering.com) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.smartitengineering.cms.maven.dto.generator.plugin; import com.google.inject.AbstractModule; import com.google.inject.Inject; import com.google.inject.PrivateModule; import com.google.inject.Singleton; import com.google.inject.TypeLiteral; import com.google.inject.multibindings.MapBinder; import com.google.inject.name.Names; import com.smartitengineering.cms.api.content.CompositeFieldValue; import com.smartitengineering.cms.api.content.Content; import com.smartitengineering.cms.api.content.ContentId; import com.smartitengineering.cms.api.content.Field; import com.smartitengineering.cms.api.content.FieldValue; import com.smartitengineering.cms.api.content.MutableCompositeFieldValue; import com.smartitengineering.cms.api.content.MutableField; import com.smartitengineering.cms.api.content.MutableFieldValue; import com.smartitengineering.cms.api.factory.SmartContentAPI; import com.smartitengineering.cms.api.factory.content.ContentLoader; import com.smartitengineering.cms.api.factory.content.WriteableContent; import com.smartitengineering.cms.api.impl.type.ContentTypeImpl; import com.smartitengineering.cms.api.impl.workspace.WorkspaceIdImpl; import com.smartitengineering.cms.api.type.CollectionDataType; import com.smartitengineering.cms.api.type.CompositeDataType; import com.smartitengineering.cms.api.type.ContentDataType; import com.smartitengineering.cms.api.type.ContentType; import com.smartitengineering.cms.api.type.ContentType.DefinitionType; import com.smartitengineering.cms.api.type.ContentTypeId; import com.smartitengineering.cms.api.type.EnumDataType; import com.smartitengineering.cms.api.type.FieldDef; import com.smartitengineering.cms.api.type.FieldValueType; import com.smartitengineering.cms.api.type.MutableContentType; import com.smartitengineering.cms.api.workspace.WorkspaceId; import com.smartitengineering.cms.repo.dao.impl.AbstractRepoAdapterHelper; import com.smartitengineering.cms.repo.dao.impl.AbstractRepositoryDomain; import com.smartitengineering.cms.repo.dao.impl.ExtendedReadDao; import com.smartitengineering.cms.repo.dao.impl.Initializer; import com.smartitengineering.cms.repo.dao.impl.RepositoryDaoImpl; import com.smartitengineering.cms.repo.dao.impl.tx.CommonTxDao; import com.smartitengineering.cms.repo.dao.impl.tx.TransactionImplModule; import com.smartitengineering.cms.repo.dao.impl.tx.Transactionable; import com.smartitengineering.cms.type.xml.XMLParserIntrospector; import com.smartitengineering.cms.type.xml.XmlParser; import com.smartitengineering.dao.common.CommonDao; import com.smartitengineering.dao.common.CommonReadDao; import com.smartitengineering.dao.common.CommonWriteDao; import com.smartitengineering.domain.PersistentDTO; import com.smartitengineering.util.bean.adapter.AbstractAdapterHelper; import com.smartitengineering.util.bean.adapter.GenericAdapter; import com.smartitengineering.util.bean.adapter.GenericAdapterImpl; import com.sun.codemodel.ClassType; import com.sun.codemodel.JBlock; import com.sun.codemodel.JClass; import com.sun.codemodel.JClassAlreadyExistsException; import com.sun.codemodel.JCodeModel; import com.sun.codemodel.JConditional; import com.sun.codemodel.JDefinedClass; import com.sun.codemodel.JExpr; import com.sun.codemodel.JExpression; import com.sun.codemodel.JFieldVar; import com.sun.codemodel.JForLoop; import com.sun.codemodel.JInvocation; import com.sun.codemodel.JMethod; import com.sun.codemodel.JMod; import com.sun.codemodel.JType; import com.sun.codemodel.JVar; import com.sun.codemodel.JWhileLoop; import nu.xom.Element; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import java.io.File; import java.io.FileInputStream; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.apache.maven.project.MavenProject; /** * Goal which touches a timestamp file. Configure any one of contentTypesResourceConfig, contentTypeResourceConfig and * contentTypeResource. Not configuring any one of them or more than one would result runtime exception. * * @goal generate * * @phase generate-sources */ public class PojoGeneratorMojo extends AbstractMojo { /** * Location of the file. * @parameter expression="${generated.sources.directory}" * @required */ private File outputDirectory; /** * A collection of content types for generating POJOs for beans in multiple workspaces. Content types could either be * a file or a classpath resource. If either is missing it would result a classpath exception * @parameter */ private List<String> contentTypes; /** * A content type file * @parameter */ private File contentTypeResource; /** * Default package for aggregating modules * @parameter * @required */ private String packageForGuiceMasterModule; /** * The workspace id for the specified content type resource. It will be used to DI in the adapter and DAO Impl * @parameter * @required */ private String workspaceId; /** * The Maven project instance for the executing project. * * @parameter expression="${project}" * @required */ private MavenProject project; /** * The content type files from classpath to use for initialization * * @parameter */ private List<String> typeFiles; /** * Whether transaction is enabled for this piece of generated code or not. By default its false to be backward * compatible. * @parameter expression="false" */ private boolean transactionEnabled; /** * Whether a transaction with isolated=false is allowed or not. By default its not allowed. * @parameter expression="false" */ private boolean nonIsolatedTransactionAllowed; public void execute() throws MojoExecutionException { File f = outputDirectory; if (!f.exists()) { f.mkdirs(); } if ((contentTypes == null || contentTypes.isEmpty()) && contentTypeResource == null) { throw new MojoExecutionException("Parameters not specified properly. Any one and only one of " + "contentTypesResourceConfig, contentTypeResourceConfig and contentTypeResource must be specified!"); } if (StringUtils.isBlank(packageForGuiceMasterModule)) { throw new MojoExecutionException("Parameter 'packageForGuiceMasterModule' can not be blank"); } JCodeModel codeModel = new JCodeModel(); Set<MutableContentType> types = new LinkedHashSet<MutableContentType>(); if (StringUtils.isBlank(workspaceId) || workspaceId.split(":").length != 2) { throw new MojoExecutionException("Workspace ID not specified or is not in format 'namespace:name'"); } final String wIds[] = workspaceId.split(":"); if (contentTypeResource != null) { if (!contentTypeResource.exists() || !contentTypeResource.isFile()) { throw new MojoExecutionException("'contentTypeResource' file either does not exist or is not a file: " + (contentTypeResource == null ? null : contentTypeResource.getAbsolutePath())); } final WorkspaceIdImpl dummyIdImpl = new WorkspaceIdImpl(); dummyIdImpl.setGlobalNamespace(wIds[0]); dummyIdImpl.setName(wIds[1]); types.addAll(parseContentType(dummyIdImpl, contentTypeResource)); } else { for (String contentTypeRsrc : contentTypes) { final String value = contentTypeRsrc; if (StringUtils.isBlank(value)) { throw new MojoExecutionException("'contentTypesResourceConfig' can not have empty resource config"); } File file = new File(value); if (file.exists() && file.isFile()) { WorkspaceIdImpl idImpl = new WorkspaceIdImpl(); idImpl.setGlobalNamespace(wIds[0]); idImpl.setName(wIds[1]); types.addAll(parseContentType(idImpl, file)); } else { throw new MojoExecutionException("'contentTypesResourceConfig' can not have a resource config that is neither" + "a file nor a classpath resoruce: " + value); } } } try { generateCode(codeModel, types); codeModel.build(outputDirectory); project.addCompileSourceRoot(outputDirectory.getAbsolutePath()); } catch (Exception ex) { throw new MojoExecutionException(ex.getMessage(), ex); } } protected void generateIoCClasses(JCodeModel codeModel, Set<MutableContentType> types, Map<ContentTypeId, JDefinedClass> classes, Map<ContentTypeId, JDefinedClass> helpers, Map<ContentTypeId, JDefinedClass> modules) throws JClassAlreadyExistsException { // Create helpers and google guice module for concrete type definitions JClass privateModuleClass = codeModel.ref(PrivateModule.class); // Initialize common classes for Google Guice bindings JClass typeLiteral = codeModel.ref(TypeLiteral.class); JClass commonDao = codeModel.ref(CommonDao.class); JClass commonReadDao = codeModel.ref(CommonReadDao.class); JClass extendedReadDao = codeModel.ref(ExtendedReadDao.class); JClass commonWriteDao = codeModel.ref(CommonWriteDao.class); JClass commonDaoImpl = codeModel.ref(RepositoryDaoImpl.class); JClass commonTxDao = codeModel.ref(CommonTxDao.class); JClass transactionableAnn = codeModel.ref(Transactionable.class); JClass genericAdapter = codeModel.ref(GenericAdapter.class).narrow(Content.class); JClass classRef = codeModel.ref(Class.class); JClass genericAdapterImpl = codeModel.ref(GenericAdapterImpl.class).narrow(Content.class); JClass abstractHelper = codeModel.ref(AbstractAdapterHelper.class).narrow(Content.class); JClass singletonScope = codeModel.ref(Singleton.class); String[] wId = workspaceId.split(":"); for (MutableContentType type : types) { if (type.getDefinitionType().equals(DefinitionType.CONCRETE_TYPE)) { final ContentTypeId contentTypeID = type.getContentTypeID(); JDefinedClass definedClass = classes.get(contentTypeID); final JDefinedClass helperClass = generateHelper(type, codeModel, classes, types); helpers.put(contentTypeID, helperClass); { final String moduleClassName = new StringBuilder(contentTypeID.getNamespace()).append(".guice.").append(contentTypeID. getName()).append("Module").toString(); final JDefinedClass moduleClass = codeModel._class(moduleClassName); modules.put(contentTypeID, moduleClass); moduleClass._extends(privateModuleClass); JMethod configureMethod = moduleClass.method(JMod.PUBLIC, JCodeModel.boxToPrimitive.get(Void.class), "configure"); JBlock block = configureMethod.body(); final JDefinedClass commonDaoType; final JDefinedClass daoImplType; final JDefinedClass txDaoImplType; final JDefinedClass readDaoType; final JDefinedClass writeDaoType; { final JClass narrowedCommonDaoTypeLiteral = typeLiteral.narrow(commonDao.narrow(definedClass).narrow( String.class)); commonDaoType = moduleClass._class(new StringBuilder(type.getContentTypeID().getName()).append( "CommonDaoType").toString()); commonDaoType._extends(narrowedCommonDaoTypeLiteral); } { final JClass narrowedReadTypeLiteral = typeLiteral.narrow(commonReadDao.narrow(definedClass).narrow( String.class)); readDaoType = moduleClass._class(new StringBuilder(type.getContentTypeID().getName()).append("ReadDaoType"). toString()); readDaoType._extends(narrowedReadTypeLiteral); block.add(JExpr.invoke("bind").arg(JExpr._new(readDaoType)).invoke("to").arg(JExpr._new(commonDaoType)). invoke("in").arg(singletonScope.dotclass())); block.add(JExpr.invoke("binder").invoke("expose").arg(JExpr._new(readDaoType))); } { final JClass narrowedWriteTypeLiteral = typeLiteral.narrow(commonWriteDao.narrow(definedClass)); writeDaoType = moduleClass._class(new StringBuilder(type.getContentTypeID().getName()).append("WriteDaoType"). toString()); writeDaoType._extends(narrowedWriteTypeLiteral); block.add(JExpr.invoke("bind").arg(JExpr._new(writeDaoType)).invoke("to").arg(JExpr._new(commonDaoType)). invoke("in").arg(singletonScope.dotclass())); block.add(JExpr.invoke("binder").invoke("expose").arg(JExpr._new(writeDaoType))); } { final JClass narrowedDaoImplTypeLiteral = typeLiteral.narrow(commonDaoImpl.narrow(definedClass)); final JClass narrowedCommonTxDaoTypeLiteral = typeLiteral.narrow(commonTxDao.narrow(definedClass)); final JClass beanClass = classRef.narrow(definedClass); JDefinedClass classType = moduleClass._class(new StringBuilder(type.getContentTypeID().getName()).append( "ClassType").toString()); classType._extends(typeLiteral.narrow(beanClass)); daoImplType = moduleClass._class(new StringBuilder(type.getContentTypeID().getName()).append("DaoImplType"). toString()); daoImplType._extends(narrowedDaoImplTypeLiteral); txDaoImplType = moduleClass._class(new StringBuilder(type.getContentTypeID().getName()).append( "CommonTxDaoType").toString()); txDaoImplType._extends(narrowedCommonTxDaoTypeLiteral); block.add(JExpr.invoke("bind").arg(JExpr._new(classType)).invoke("toInstance").arg(definedClass.dotclass())); if (transactionEnabled) { block.add(JExpr.invoke("bind").arg(JExpr._new(commonDaoType)).invoke("to").arg(JExpr._new(txDaoImplType))); block.add(JExpr.invoke("bind").arg(JExpr._new(readDaoType)).invoke("annotatedWith").arg(transactionableAnn. dotclass()).invoke("to").arg(JExpr._new(daoImplType))); block.add(JExpr.invoke("bind").arg(JExpr._new(writeDaoType)).invoke("annotatedWith").arg(transactionableAnn. dotclass()).invoke("to").arg(JExpr._new(daoImplType))); } else { block.add(JExpr.invoke("bind").arg(JExpr._new(commonDaoType)).invoke("to").arg(JExpr._new(daoImplType))); } block.add(JExpr.invoke("binder").invoke("expose").arg(JExpr._new(commonDaoType))); } { final JClass narrowedReadTypeLiteral = typeLiteral.narrow(extendedReadDao.narrow(definedClass).narrow( String.class)); final JDefinedClass extReadDaoType = moduleClass._class(new StringBuilder(type.getContentTypeID().getName()). append("ExtReadDaoType").toString()); extReadDaoType._extends(narrowedReadTypeLiteral); block.add(JExpr.invoke("bind").arg(JExpr._new(extReadDaoType)).invoke("to").arg(JExpr._new(daoImplType)). invoke("in").arg(singletonScope.dotclass())); block.add(JExpr.invoke("binder").invoke("expose").arg(JExpr._new(extReadDaoType))); } { JClass lGenericAdapter = genericAdapter.narrow(definedClass); JClass lGenericAdapterImpl = genericAdapterImpl.narrow(definedClass); JClass lAbstractHelper = abstractHelper.narrow(definedClass); final JDefinedClass adapterHelperType = moduleClass._class(new StringBuilder( type.getContentTypeID().getName()).append("AdapterType").toString()); adapterHelperType._extends(typeLiteral.narrow(lGenericAdapter)); final JDefinedClass adapterImplType = moduleClass._class(new StringBuilder(type.getContentTypeID().getName()). append("AdapterImplType").toString()); adapterImplType._extends(typeLiteral.narrow(lGenericAdapterImpl)); final JDefinedClass abstractHelperType = moduleClass._class(new StringBuilder(type.getContentTypeID(). getName()).append("AdapterHelperType").toString()); abstractHelperType._extends(typeLiteral.narrow(lAbstractHelper)); final JDefinedClass helperType = moduleClass._class(new StringBuilder(type.getContentTypeID().getName()). append("AdapterHelperImplType").toString()); helperType._extends(typeLiteral.narrow(helperClass)); block.add(JExpr.invoke("bind").arg(JExpr._new(adapterHelperType)).invoke("to").arg(JExpr._new( adapterImplType)).invoke("in").arg(singletonScope.dotclass())); block.add(JExpr.invoke("bind").arg(JExpr._new(abstractHelperType)).invoke("to").arg(JExpr._new(helperType)). invoke("in").arg(singletonScope.dotclass())); } //String TypeLiteral final JDefinedClass stringType; { final JClass narrowedReadTypeLiteral = typeLiteral.narrow(String.class); stringType = moduleClass._class("StringType"); stringType._extends(narrowedReadTypeLiteral); } //Traverse fields to make their DIs { Collection<FieldDef> defs = getAllFields(type, types).values(); generateAssociationIoCForFields(defs, codeModel, stringType, typeLiteral, moduleClass, block, types, classes, type.getContentTypeID().getName(), new HashSet<ContentTypeId>()); } } } } generateMasterModule(modules, codeModel, wId); } protected Set<FieldDef> getAllComposedFields(CompositeDataType compositeDataType, Set<? extends ContentType> types) { Set<FieldDef> compositeFields = new LinkedHashSet<FieldDef>(); if (compositeDataType.getEmbeddedContentType() != null) { ContentType currentType = getType(types, compositeDataType.getEmbeddedContentType().getTypeDef()); if (currentType != null) { compositeFields.addAll(getAllFields(currentType, types).values()); } } compositeFields.addAll(compositeDataType.getOwnComposition()); return compositeFields; } protected Map<String, FieldDef> getAllFields(ContentType currentType, Set<? extends ContentType> types) { Map<String, FieldDef> defs = new LinkedHashMap<String, FieldDef>(); boolean hasMore = true; while (hasMore) { Map<String, FieldDef> ownFields = currentType.getOwnFieldDefs(); for (Entry<String, FieldDef> ownField : ownFields.entrySet()) { if (!defs.containsKey(ownField.getKey())) { defs.put(ownField.getKey(), ownField.getValue()); } } if (currentType.getParent() != null) { final ContentTypeId parent = currentType.getParent(); currentType = getType(types, parent); hasMore = currentType != null; } else { hasMore = false; } } return defs; } protected ContentType getType(Set<? extends ContentType> types, final ContentTypeId id) { for (ContentType type : types) { if (type.getContentTypeID().equals(id)) { return type; } } return null; } protected JFieldVar initializeDao(ContentTypeId typeId, JDefinedClass helperClass, JCodeModel model, Map<ContentTypeId, JDefinedClass> classes) { final JDefinedClass typeDef = classes.get(typeId); final String varClassName = typeDef.name(); String readDaoName = new StringBuilder(new StringBuilder().append( ("" + varClassName.charAt(0)).toLowerCase()).append(varClassName.substring(1)).toString()).append( "ReadDaos").toString(); JFieldVar readDaoVar = helperClass.fields().get(readDaoName); if (readDaoVar == null) { readDaoVar = helperClass.field(JMod.PRIVATE, model.ref(Map.class).narrow(String.class).narrow(model.ref( CommonReadDao.class).narrow(typeDef.wildcard()).narrow( String.class)), readDaoName); readDaoVar.annotate(Inject.class); } return readDaoVar; } protected Collection<MutableContentType> parseContentType(final WorkspaceId id, File file) throws MojoExecutionException { try { final XmlParser parser = new XmlParser(id, new FileInputStream(file), new XMLParserIntrospector() { public MutableContentType createMutableContentType() { return new ContentTypeImpl(); } public void processMutableContentType(MutableContentType type, Element element) { } }); return parser.parse(); } catch (Exception ex) { throw new MojoExecutionException(ex.getMessage(), ex); } } protected void generateCode(JCodeModel codeModel, Set<MutableContentType> types) throws Exception { Map<ContentTypeId, JDefinedClass> classes = new LinkedHashMap<ContentTypeId, JDefinedClass>(); Map<ContentTypeId, JDefinedClass> helpers = new LinkedHashMap<ContentTypeId, JDefinedClass>(); Map<ContentTypeId, JDefinedClass> modules = new LinkedHashMap<ContentTypeId, JDefinedClass>(); // Create the classes for (MutableContentType type : types) { final ContentTypeId contentTypeID = type.getContentTypeID(); classes.put(contentTypeID, generateClassForType(type, codeModel)); } // Set parent content types as appropriate for (MutableContentType type : types) { final JDefinedClass typeClass = classes.get(type.getContentTypeID()); if (type.getParent() != null) { final JClass parentClass = classes.get(type.getParent()); typeClass._extends(parentClass); } } // Create members and their accessors for (MutableContentType type : types) { generateFields(type.getOwnFieldDefs().values(), classes.get(type.getContentTypeID()), classes, codeModel); } generateIoCClasses(codeModel, types, classes, helpers, modules); } protected JDefinedClass generateHelper(final ContentType contentType, JCodeModel codeModel, Map<ContentTypeId, JDefinedClass> classes, Set<? extends ContentType> types) throws JClassAlreadyExistsException { ContentTypeId contentTypeID = contentType.getContentTypeID(); final JDefinedClass definedClass = classes.get(contentTypeID); final JClass parentClass = codeModel.ref(AbstractRepoAdapterHelper.class); final JDefinedClass helperClass; final String helperClassName = new StringBuilder(contentTypeID.getNamespace()).append(".helpers.").append(contentTypeID. getName()).append("Helper").toString(); helperClass = codeModel._class(helperClassName); helperClass._extends(parentClass.narrow(definedClass)); ContentType currentType = contentType; Map<String, FieldDef> defs = getAllFields(currentType, types); { JMethod forwardConversion = helperClass.method(JMod.PROTECTED, JCodeModel.boxToPrimitive.get(Void.class), "mergeContentIntoBean"); JVar content = forwardConversion.param(Content.class, "fromBean"); JVar toBean = forwardConversion.param(definedClass, "toBean"); JBlock block = forwardConversion.body(); generateForwardBlocks(defs.values(), block, content, toBean, codeModel, definedClass, helperClass, classes, types, ""); } { JMethod reverseConversion = helperClass.method(JMod.PROTECTED, JCodeModel.boxToPrimitive.get(Void.class), "mergeBeanIntoContent"); JVar fromBean = reverseConversion.param(definedClass, "fromBean"); JVar wContent = reverseConversion.param(WriteableContent.class, "toBean"); JBlock block = reverseConversion.body(); JInvocation staticInvoke = codeModel.ref(SmartContentAPI.class).staticInvoke("getInstance"); block._if(staticInvoke.eq(JExpr._null()))._then()._throw(JExpr._new(codeModel.ref(IllegalStateException.class)). arg("Smart Content API can not be null!")); JVar contentLoader = block.decl(JMod.FINAL, codeModel.ref(ContentLoader.class), "contentLoader", staticInvoke.invoke("getContentLoader")); JVar fieldDefs = block.decl(codeModel.ref(Map.class).narrow(String.class).narrow(FieldDef.class), "fieldDefs", wContent.invoke("getContentDefinition").invoke("getFieldDefs")); generateReverseBlocks(defs.values(), block, fromBean, wContent, contentLoader, fieldDefs, codeModel, definedClass, classes, types, ""); } { JMethod instanceCreation = helperClass.method(JMod.PROTECTED, definedClass, "newTInstance"); JBlock block = instanceCreation.body(); block._return(JExpr._new(definedClass)); } return helperClass; } protected JDefinedClass generateClassForType(MutableContentType type, JCodeModel codeModel) throws JClassAlreadyExistsException { ContentTypeId typeId = type.getContentTypeID(); int mod = JMod.PUBLIC; final DefinitionType defType = type.getDefinitionType(); if (defType.equals(ContentType.DefinitionType.ABSTRACT_COMPONENT)) { // Extend nothing mod = mod | JMod.ABSTRACT; } else if (defType.equals(ContentType.DefinitionType.ABSTRACT_TYPE)) { mod = mod | JMod.ABSTRACT; } JDefinedClass definedClass = codeModel._class(mod, new StringBuilder(typeId.getNamespace()).append('.').append(typeId. getName()).toString(), ClassType.CLASS); if (defType.equals(ContentType.DefinitionType.ABSTRACT_TYPE) || defType.equals( ContentType.DefinitionType.CONCRETE_TYPE)) { JClass clazz = codeModel.ref(AbstractRepositoryDomain.class); definedClass._extends(clazz.narrow(definedClass)); } return definedClass; } protected void generateFields(Collection<FieldDef> fields, JDefinedClass definedClass, Map<ContentTypeId, JDefinedClass> classes, JCodeModel codeModel) throws JClassAlreadyExistsException, ClassNotFoundException { for (FieldDef def : fields) { final Class fieldClass; final JType jType; final String name = def.getName(); final String getterSetterSuffix = new StringBuilder().append(("" + name.charAt(0)).toUpperCase()).append(name. substring(1)).toString(); switch (def.getValueDef().getType()) { case BOOLEAN: fieldClass = Boolean.class; jType = null; break; case STRING: fieldClass = String.class; jType = null; break; case CONTENT: ContentDataType contentDataType = (ContentDataType) def.getValueDef(); fieldClass = null; final ContentTypeId typeDef = contentDataType.getTypeDef(); jType = classes.get(typeDef); break; case DATE_TIME: fieldClass = Date.class; jType = null; break; case INTEGER: fieldClass = Integer.class; jType = null; break; case DOUBLE: fieldClass = Double.class; jType = null; break; case LONG: fieldClass = Long.class; jType = null; break; case OTHER: fieldClass = byte[].class; jType = null; break; case ENUM: { JDefinedClass enumClass = definedClass._enum(JMod.PUBLIC | JMod.STATIC, getterSetterSuffix); EnumDataType enumDataType = (EnumDataType) def.getValueDef(); Collection<String> choices = enumDataType.getChoices(); for (String choice : choices) { enumClass.enumConstant(choice); } fieldClass = null; jType = enumClass; break; } case COLLECTION: fieldClass = null; final JClass itemType; CollectionDataType collectionDataType = (CollectionDataType) def.getValueDef(); switch (collectionDataType.getItemDataType().getType()) { case BOOLEAN: itemType = codeModel.ref(Boolean.class); break; case STRING: itemType = codeModel.ref(String.class); break; case CONTENT: itemType = classes.get(((ContentDataType) collectionDataType.getItemDataType()).getTypeDef()); break; case DATE_TIME: itemType = codeModel.ref(Date.class); break; case INTEGER: itemType = codeModel.ref(Integer.class); break; case DOUBLE: itemType = codeModel.ref(Double.class); break; case LONG: itemType = codeModel.ref(Long.class); break; case OTHER: itemType = codeModel.ref(byte[].class); break; case ENUM: { JDefinedClass enumClass = definedClass._enum(JMod.PUBLIC | JMod.STATIC, getterSetterSuffix); EnumDataType enumDataType = (EnumDataType) collectionDataType.getItemDataType(); Collection<String> choices = enumDataType.getChoices(); for (String choice : choices) { enumClass.enumConstant(choice); } itemType = enumClass; break; } case COMPOSITE: { CompositeDataType compositeDataType = (CompositeDataType) collectionDataType.getItemDataType(); ContentDataType composedOfContent = compositeDataType.getEmbeddedContentType(); final JDefinedClass composedOfClass; if (composedOfContent != null) { composedOfClass = classes.get(composedOfContent.getTypeDef()); } else { composedOfClass = null; } if (compositeDataType.getOwnComposition() != null && !compositeDataType.getOwnComposition().isEmpty()) { JDefinedClass compositeFieldClass = definedClass._class(JMod.STATIC | JMod.PUBLIC, getterSetterSuffix); if (composedOfContent != null) { compositeFieldClass._extends(composedOfClass); } generateFields(compositeDataType.getOwnComposition(), compositeFieldClass, classes, codeModel); itemType = compositeFieldClass; } else if (composedOfContent != null) { itemType = composedOfClass; } else { itemType = codeModel.ref(Object.class); } break; } default: itemType = codeModel.ref(Object.class); } jType = codeModel.ref(Collection.class).narrow(itemType); break; case COMPOSITE: { CompositeDataType compositeDataType = (CompositeDataType) def.getValueDef(); ContentDataType composedOfContent = compositeDataType.getEmbeddedContentType(); if (compositeDataType.getOwnComposition() != null && !compositeDataType.getOwnComposition().isEmpty()) { fieldClass = null; JDefinedClass compositeFieldClass = definedClass._class(JMod.STATIC | JMod.PUBLIC, getterSetterSuffix); if (composedOfContent != null) { compositeFieldClass._extends(classes.get(composedOfContent.getTypeDef())); } generateFields(compositeDataType.getOwnComposition(), compositeFieldClass, classes, codeModel); jType = compositeFieldClass; } else if (composedOfContent != null) { fieldClass = null; jType = classes.get(composedOfContent.getTypeDef()); } else { fieldClass = Object.class; jType = null; } break; } default: fieldClass = Object.class; jType = null; } final String getterName = new StringBuilder("get").append(getterSetterSuffix).toString(); final String setterName = new StringBuilder("set").append(getterSetterSuffix).toString(); final JFieldVar fieldVar; final JMethod getterMethod; final JMethod setterMethod; final JVar paramVar; final JFieldVar propConstant = definedClass.field(JMod.PUBLIC | JMod.FINAL | JMod.STATIC, String.class, new StringBuilder("PROPERTY").append('_').append(name. toUpperCase()).toString(), JExpr.lit(name)); if (jType == null) { fieldVar = definedClass.field(JMod.PROTECTED, fieldClass, name); getterMethod = definedClass.method(JMod.PUBLIC, fieldClass, getterName); setterMethod = definedClass.method(JMod.PUBLIC, JCodeModel.boxToPrimitive.get(Void.class), setterName); paramVar = setterMethod.param(fieldClass, name); } else { fieldVar = definedClass.field(JMod.PROTECTED, jType, name); getterMethod = definedClass.method(JMod.PUBLIC, jType, getterName); setterMethod = definedClass.method(JMod.PUBLIC, JCodeModel.boxToPrimitive.get(Void.class), setterName); paramVar = setterMethod.param(jType, name); } final JBlock getterBlock = getterMethod.body(); getterBlock._return(fieldVar); JBlock setterBlock = setterMethod.body(); setterBlock.assign(JExpr._this().ref(fieldVar), paramVar); } } protected void generateForwardBlocks(Collection<FieldDef> values, JBlock block, JVar from, JVar toBean, JCodeModel model, JDefinedClass currentClass, JDefinedClass helperClass, Map<ContentTypeId, JDefinedClass> classes, Set<? extends ContentType> types, String prefix) { final JClass contentIdRef = model.ref(ContentId.class); for (FieldDef def : values) { final String name = def.getName(); final String varName = getVarName(prefix, name); final String fieldVar = new StringBuilder(varName).append("Field").toString(); JVar field = block.decl(model.ref(Field.class), fieldVar, from.invoke("getField").arg(name)); JConditional conditional = block._if(field.ne(JExpr._null())); JBlock valBlock = conditional._then(); switch (def.getValueDef().getType()) { case BOOLEAN: setField(valBlock, model, field, name, toBean, Boolean.class, prefix); break; case STRING: setField(valBlock, model, field, name, toBean, String.class, prefix); break; case ENUM: { final String getterSetterSuffix = new StringBuilder().append(("" + name.charAt(0)).toUpperCase()).append(name. substring(1)).toString(); final String setterName = new StringBuilder("set").append(getterSetterSuffix).toString(); final String fieldValVar = getVarName(prefix, new StringBuilder(name).append("Val").toString()); JClass enumClass = ((JClass) currentClass.fields().get(name).type()); JVar fieldVal = block.decl(model.ref(FieldValue.class).narrow(String.class), fieldValVar, field.invoke( "getValue")); JConditional valCond = block._if(fieldVal.ne(JExpr._null())); JBlock setBlock = valCond._then(); setBlock.add(toBean.invoke(setterName).arg(enumClass.staticInvoke("valueOf").arg(fieldVal.invoke("getValue")))); break; } case DATE_TIME: setField(valBlock, model, field, name, toBean, Date.class, prefix); break; case INTEGER: setField(valBlock, model, field, name, toBean, Integer.class, prefix); break; case DOUBLE: setField(valBlock, model, field, name, toBean, Double.class, prefix); break; case LONG: setField(valBlock, model, field, name, toBean, Long.class, prefix); break; case OTHER: setField(valBlock, model, field, name, toBean, byte[].class, prefix); break; case CONTENT: { ContentDataType contentDataType = (ContentDataType) def.getValueDef(); final JDefinedClass typeDef = classes.get(contentDataType.getTypeDef()); if (typeDef != null) { JFieldVar readDaoVar = initializeDao(contentDataType.getTypeDef(), helperClass, model, classes); if (readDaoVar != null) { final String getterSetterSuffix = new StringBuilder().append(("" + name.charAt(0)).toUpperCase()).append(name. substring(1)).toString(); final String setterName = new StringBuilder("set").append(getterSetterSuffix).toString(); final String fieldValVar = new StringBuilder(varName).append("Val").toString(); JVar fieldVal = valBlock.decl(model.ref(FieldValue.class).narrow(contentIdRef), fieldValVar, field.invoke("getValue")); JConditional valCond = valBlock._if(fieldVal.ne(JExpr._null())); JBlock setBlock = valCond._then(); final JVar contentIdVal = setBlock.decl(contentIdRef, getVarName(prefix, "contentIdVal"), fieldVal.invoke( "getValue")); JConditional idValCond = setBlock._if(contentIdVal.ne(JExpr._null())); JBlock typeDaoBlock = idValCond._then(); String readDaoName = new StringBuilder(new StringBuilder().append( ("" + typeDef.name().charAt(0)).toLowerCase()).append(typeDef.name().substring(1)).toString()).append( "ReadDao").toString(); JVar typeDao = typeDaoBlock.decl(model.ref(CommonReadDao.class).narrow(typeDef.wildcard()).narrow( String.class), readDaoName, readDaoVar.invoke("get").arg(contentIdVal.invoke("getContent").invoke( "getContentDefinition").invoke("toString"))); JConditional daoValCond = typeDaoBlock._if(typeDao.ne(JExpr._null())); daoValCond._then().add(toBean.invoke(setterName).arg(typeDao.invoke("getById").arg( contentIdVal.invoke("toString")))); } } break; } case COMPOSITE: { CompositeDataType compositeDataType = (CompositeDataType) def.getValueDef(); Set<FieldDef> compositeFields = getAllComposedFields(compositeDataType, types); JClass compFieldVal = model.ref(FieldValue.class).narrow(model.ref(Collection.class).narrow(Field.class)); final JVar fieldVal = valBlock.decl(compFieldVal, new StringBuilder(varName).append("FieldVal").toString(), field.invoke("getValue")); JDefinedClass compositeDefinition = findClass(compositeDataType, currentClass, classes, name); JDefinedClass newCompositeDefintion = findConcreteClass(compositeDefinition, classes); if (compositeDefinition != null && newCompositeDefintion != null) { JBlock validCompVal = valBlock._if(fieldVal.ne(JExpr._null()))._then(); final JVar compositeToBean = validCompVal.decl(compositeDefinition, varName, JExpr._new( newCompositeDefintion)); final JClass ref = model.ref(CompositeFieldValue.class); JVar compositeFromBean = validCompVal.decl(ref, new StringBuilder(varName).append("Val").toString(), JExpr. cast(ref, fieldVal)); String compPrefix = new StringBuilder(varName).append('_').toString(); generateForwardBlocks(compositeFields, validCompVal, compositeFromBean, compositeToBean, model, compositeDefinition, helperClass, classes, types, compPrefix); final String getterSetterSuffix = new StringBuilder().append(("" + name.charAt(0)).toUpperCase()).append(name. substring(1)).toString(); final String setterName = new StringBuilder("set").append(getterSetterSuffix).toString(); validCompVal.add(toBean.invoke(setterName).arg(compositeToBean)); } break; } case COLLECTION: CollectionDataType collectionDataType = (CollectionDataType) def.getValueDef(); switch (collectionDataType.getItemDataType().getType()) { case BOOLEAN: setCollectionField(valBlock, model, field, Boolean.class, name, toBean, prefix); break; case STRING: setCollectionField(valBlock, model, field, String.class, name, toBean, prefix); break; case ENUM: { JClass itClass = (JClass) ((JClass) currentClass.fields().get(name).type()).getTypeParameters().get(0); JVar resultVal = valBlock.decl(model.ref(Collection.class).narrow(itClass), getVarName(prefix, "beanList"), JExpr._new(model.ref(ArrayList.class).narrow(itClass))); final JClass narrowedCollection = model.ref(Collection.class).narrow(FieldValue.class); JVar fieldVal = valBlock.decl(model.ref(FieldValue.class).narrow(narrowedCollection), getVarName(prefix, "fieldVal"), field.invoke("getValue")); JConditional collectionValCond = valBlock._if(fieldVal.ne(JExpr._null())); JBlock validValBlock = collectionValCond._then(); JVar collectionVal = validValBlock.decl(narrowedCollection, getVarName(prefix, "collectionVal"), fieldVal. invoke( "getValue")); JConditional validCollectionCond = validValBlock._if(collectionVal.ne(JExpr._null()).cand(collectionVal. invoke( "isEmpty").not())); JBlock iterateBlock = validCollectionCond._then(); JVar iterator = iterateBlock.decl(model.ref(Iterator.class).narrow(FieldValue.class), getVarName(prefix, "iterator"), collectionVal.invoke("iterator")); JWhileLoop loop = iterateBlock._while(iterator.invoke("hasNext")); JBlock loopBlock = loop.body(); JVar val = loopBlock.decl(model.ref(FieldValue.class).narrow(String.class), getVarName(prefix, "val"), iterator.invoke("next")); JConditional singleValCond = loopBlock._if(val.ne(JExpr._null())); singleValCond._then().add(resultVal.invoke("add").arg(itClass.staticInvoke("valueOf").arg(val.invoke( "getValue")))); final String getterSetterSuffix = new StringBuilder().append(("" + name.charAt(0)).toUpperCase()).append(name. substring(1)).toString(); final String setterName = new StringBuilder("set").append(getterSetterSuffix).toString(); valBlock.add(toBean.invoke(setterName).arg(resultVal)); break; } case DATE_TIME: setCollectionField(valBlock, model, field, Date.class, name, toBean, prefix); break; case INTEGER: setCollectionField(valBlock, model, field, Integer.class, name, toBean, prefix); break; case DOUBLE: setCollectionField(valBlock, model, field, Double.class, name, toBean, prefix); break; case LONG: setCollectionField(valBlock, model, field, Long.class, name, toBean, prefix); break; case OTHER: setCollectionField(valBlock, model, field, byte[].class, name, toBean, prefix); break; case CONTENT: { ContentDataType contentDataType = (ContentDataType) collectionDataType.getItemDataType(); final JDefinedClass typeDef = classes.get(contentDataType.getTypeDef()); if (typeDef != null) { JFieldVar readDaoVar = initializeDao(contentDataType.getTypeDef(), helperClass, model, classes); if (readDaoVar != null) { JVar resultVal = valBlock.decl(model.ref(Collection.class).narrow(typeDef), getVarName(prefix, "beanList"), JExpr._new(model.ref(ArrayList.class).narrow(typeDef))); final JClass narrowedCollection = model.ref(Collection.class).narrow(FieldValue.class); JVar fieldVal = valBlock.decl(model.ref(FieldValue.class).narrow(narrowedCollection), getVarName(prefix, "fieldVal"), field.invoke("getValue")); JConditional collectionValCond = valBlock._if(fieldVal.ne(JExpr._null())); JBlock validValBlock = collectionValCond._then(); JVar collectionVal = validValBlock.decl(narrowedCollection, getVarName(prefix, "collectionVal"), fieldVal.invoke("getValue")); JConditional validCollectionCond = validValBlock._if(collectionVal.ne(JExpr._null()).cand(collectionVal. invoke("isEmpty").not())); JBlock iterateBlock = validCollectionCond._then(); JVar iterator = iterateBlock.decl(model.ref(Iterator.class).narrow(FieldValue.class), getVarName(prefix, "iterator"), collectionVal.invoke("iterator")); JWhileLoop loop = iterateBlock._while(iterator.invoke("hasNext")); JBlock loopBlock = loop.body(); JVar val = loopBlock.decl(model.ref(FieldValue.class).narrow(contentIdRef), getVarName(prefix, "val"), iterator.invoke("next")); JConditional singleValCond = loopBlock._if(val.ne(JExpr._null())); final JBlock _then = singleValCond._then(); final JVar contentIdVal = _then.decl(contentIdRef, getVarName(prefix, "contentIdVal"), val.invoke("getValue")); JConditional idValCond = _then._if(contentIdVal.ne(JExpr._null())); JBlock typeDaoBlock = idValCond._then(); String readDaoName = new StringBuilder(new StringBuilder().append( ("" + typeDef.name().charAt(0)).toLowerCase()).append(typeDef.name().substring(1)).toString()). append( "ReadDao").toString(); JVar typeDao = typeDaoBlock.decl(model.ref(CommonReadDao.class).narrow(typeDef.wildcard()).narrow( String.class), readDaoName, readDaoVar.invoke("get").arg(contentIdVal.invoke("getContent").invoke( "getContentDefinition").invoke("getContentTypeID").invoke("toString"))); JConditional daoValCond = typeDaoBlock._if(typeDao.ne(JExpr._null())); daoValCond._then().add(resultVal.invoke("add").arg(typeDao.invoke("getById").arg( contentIdVal.invoke("toString")))); final String getterSetterSuffix = new StringBuilder().append(("" + name.charAt(0)).toUpperCase()). append(name.substring(1)).toString(); final String setterName = new StringBuilder("set").append(getterSetterSuffix).toString(); valBlock.add(toBean.invoke(setterName).arg(resultVal)); } } break; } case COMPOSITE: { CompositeDataType compositeDataType = (CompositeDataType) collectionDataType.getItemDataType(); Set<FieldDef> compositeFields = new LinkedHashSet<FieldDef>(); if (compositeDataType.getEmbeddedContentType() != null) { ContentType currentType = getType(types, compositeDataType.getEmbeddedContentType().getTypeDef()); if (currentType != null) { compositeFields.addAll(getAllFields(currentType, types).values()); } } compositeFields.addAll(compositeDataType.getOwnComposition()); JDefinedClass compositeDefinition = findClass(compositeDataType, currentClass, classes, name); JDefinedClass newCompositeDefintion = findConcreteClass(compositeDefinition, classes); if (compositeDefinition != null && newCompositeDefintion != null) { JVar resultVal = valBlock.decl(model.ref(Collection.class).narrow(newCompositeDefintion), getVarName(prefix, "beanList"), JExpr._new(model.ref(ArrayList.class).narrow(newCompositeDefintion))); final JClass narrowedCollection = model.ref(Collection.class).narrow(FieldValue.class); JVar fieldVal = valBlock.decl(model.ref(FieldValue.class).narrow(narrowedCollection), getVarName(prefix, "fieldVal"), field.invoke("getValue")); JConditional collectionValCond = valBlock._if(fieldVal.ne(JExpr._null())); JBlock validValBlock = collectionValCond._then(); JVar collectionVal = validValBlock.decl(narrowedCollection, getVarName(prefix, "collectionVal"), fieldVal.invoke("getValue")); JConditional validCollectionCond = validValBlock._if(collectionVal.ne(JExpr._null()).cand(collectionVal. invoke("isEmpty").not())); JBlock iterateBlock = validCollectionCond._then(); JVar iterator = iterateBlock.decl(model.ref(Iterator.class).narrow(FieldValue.class), getVarName(prefix, "iterator"), collectionVal.invoke("iterator")); JWhileLoop loop = iterateBlock._while(iterator.invoke("hasNext")); JBlock loopBlock = loop.body(); JVar val = loopBlock.decl(model.ref(FieldValue.class).narrow(model.ref(Collection.class).narrow( Field.class)), getVarName(prefix, "val"), iterator.invoke("next")); final JBlock _then = loopBlock; JBlock validCompVal = _then._if(val.ne(JExpr._null()))._then(); final JVar compositeToBean = validCompVal.decl(compositeDefinition, varName, JExpr._new( newCompositeDefintion)); final JClass ref = model.ref(CompositeFieldValue.class); JVar compositeFromBean = validCompVal.decl(ref, new StringBuilder(varName).append("Val").toString(), JExpr.cast(ref, val)); String compPrefix = new StringBuilder(varName).append('_').toString(); generateForwardBlocks(compositeFields, validCompVal, compositeFromBean, compositeToBean, model, compositeDefinition, helperClass, classes, types, compPrefix); final String getterSetterSuffix = new StringBuilder().append(("" + name.charAt(0)).toUpperCase()).append(name. substring(1)).toString(); final String setterName = new StringBuilder("set").append(getterSetterSuffix).toString(); validCompVal.add(resultVal.invoke("add").arg(compositeToBean)); valBlock.add(toBean.invoke(setterName).arg(resultVal)); } } } break; default: } } } protected void setCollectionField(JBlock valBlock, JCodeModel model, JVar field, final Class narrowClass, final String name, JVar toBean, String prefix) { final JVar collectionVal = addToCollection(valBlock, model, field, narrowClass, prefix); final String getterSetterSuffix = new StringBuilder().append(("" + name.charAt(0)).toUpperCase()).append(name. substring(1)).toString(); final String setterName = new StringBuilder("set").append(getterSetterSuffix).toString(); valBlock.add(toBean.invoke(setterName).arg(collectionVal)); } protected String getVarName(String prefix, String literal) { return new StringBuilder(prefix).append(literal).toString(); } protected JVar addToCollection(JBlock valBlock, JCodeModel model, JVar field, final Class narrowClass, String prefix) { JVar resultVal = valBlock.decl(model.ref(Collection.class).narrow(narrowClass), getVarName(prefix, "beanList"), JExpr._new(model.ref(ArrayList.class).narrow(narrowClass))); final JClass narrowedCollection = model.ref(Collection.class).narrow(FieldValue.class); JVar fieldVal = valBlock.decl(model.ref(FieldValue.class).narrow(narrowedCollection), getVarName(prefix, "fieldVal"), field.invoke("getValue")); JConditional collectionValCond = valBlock._if(fieldVal.ne(JExpr._null())); JBlock validValBlock = collectionValCond._then(); JVar collectionVal = validValBlock.decl(narrowedCollection, getVarName(prefix, "collectionVal"), fieldVal.invoke( "getValue")); JConditional validCollectionCond = validValBlock._if(collectionVal.ne(JExpr._null()).cand(collectionVal.invoke( "isEmpty").not())); JBlock iterateBlock = validCollectionCond._then(); JVar iterator = iterateBlock.decl(model.ref(Iterator.class).narrow(FieldValue.class), getVarName(prefix, "iterator"), collectionVal.invoke("iterator")); JWhileLoop loop = iterateBlock._while(iterator.invoke("hasNext")); JBlock loopBlock = loop.body(); JVar val = loopBlock.decl(model.ref(FieldValue.class).narrow(narrowClass), getVarName(prefix, "val"), iterator. invoke("next")); JConditional singleValCond = loopBlock._if(val.ne(JExpr._null())); singleValCond._then().add(resultVal.invoke("add").arg(val.invoke("getValue"))); return resultVal; } protected void setField(JBlock block, JCodeModel model, JVar field, final String name, JVar toBean, Class valType, String prefix) { final String getterSetterSuffix = new StringBuilder().append(("" + name.charAt(0)).toUpperCase()).append(name. substring(1)).toString(); final String setterName = new StringBuilder("set").append(getterSetterSuffix).toString(); final String fieldValVar = getVarName(prefix, new StringBuilder(name).append("Val").toString()); JVar fieldVal = block.decl(model.ref(FieldValue.class).narrow(valType), fieldValVar, field.invoke("getValue")); JConditional valCond = block._if(fieldVal.ne(JExpr._null())); JBlock setBlock = valCond._then(); setBlock.add(toBean.invoke(setterName).arg(fieldVal.invoke("getValue"))); } protected void addField(JBlock block, JCodeModel model, JVar field, final String name, JVar toBean, Class valType, String prefix) { final String setterName = "add"; final String fieldValVar = getVarName(prefix, new StringBuilder(name).append("Val").toString()); JVar fieldVal = block.decl(model.ref(FieldValue.class).narrow(valType), fieldValVar, field.invoke("getValue")); JConditional valCond = block._if(fieldVal.ne(JExpr._null())); JBlock setBlock = valCond._then(); setBlock.add(toBean.invoke(setterName).arg(fieldVal.invoke("getValue"))); } protected JDefinedClass findClass(CompositeDataType compositeDataType, JDefinedClass currentClass, Map<ContentTypeId, JDefinedClass> classes, String fieldName) { final String getterSetterSuffix = new StringBuilder().append(("" + fieldName.charAt(0)).toUpperCase()).append(fieldName. substring(1)).toString(); JDefinedClass jType = null; ContentDataType composedOfContent = compositeDataType.getEmbeddedContentType(); if (compositeDataType.getOwnComposition() != null && !compositeDataType.getOwnComposition().isEmpty()) { Iterator<JDefinedClass> compositeFieldClasses = currentClass.classes(); while (compositeFieldClasses.hasNext()) { JDefinedClass innerClass = compositeFieldClasses.next(); if (innerClass.name().equals(getterSetterSuffix)) { jType = innerClass; } } } else if (composedOfContent != null) { jType = classes.get(composedOfContent.getTypeDef()); } return jType; } protected JDefinedClass findConcreteClass(JDefinedClass compositeDefinition, Map<ContentTypeId, JDefinedClass> classes) { if (compositeDefinition.isAbstract()) { for (JDefinedClass clazz : classes.values()) { if (!clazz.isAbstract() && compositeDefinition.isAssignableFrom(clazz)) { return clazz; } else { JDefinedClass inInnerClass = findConcreteInInnerClass(compositeDefinition, clazz); if (inInnerClass != null) { return inInnerClass; } } } return null; } else { return compositeDefinition; } } protected JDefinedClass findConcreteInInnerClass(JDefinedClass compositeDefinition, JDefinedClass clazz) { final Iterator<JDefinedClass> classes = clazz.classes(); while (classes.hasNext()) { JDefinedClass innerClass = classes.next(); if (compositeDefinition.isAssignableFrom(innerClass)) { return innerClass; } else { JDefinedClass inInnerClass = findConcreteInInnerClass(compositeDefinition, innerClass); if (inInnerClass != null) { return inInnerClass; } } } return null; } protected void generateReverseBlocks(Collection<FieldDef> values, JBlock block, JVar fromBean, JVar wContent, JVar contentLoader, JVar fieldDefs, JCodeModel model, JDefinedClass currentClass, Map<ContentTypeId, JDefinedClass> classes, Set<? extends ContentType> types, String prefix) { for (FieldDef def : values) { final String name = def.getName(); final String getterSetterSuffix = new StringBuilder().append(("" + name.charAt(0)).toUpperCase()).append(name. substring(1)).toString(); final String getterName = new StringBuilder("get").append(getterSetterSuffix).toString(); switch (def.getValueDef().getType()) { case BOOLEAN: { final String methodName = "createBooleanFieldValue"; final Class valClass = Boolean.class; setSimpleField(block, fromBean, wContent, getterName, fieldDefs, name, model, contentLoader, valClass, methodName, prefix); break; } case STRING: { final String methodName = "createStringFieldValue"; final Class valClass = String.class; setSimpleField(block, fromBean, wContent, getterName, fieldDefs, name, model, contentLoader, valClass, methodName, prefix); break; } case ENUM: { final String methodName = "createStringFieldValue"; final Class valClass = String.class; JBlock nonNullBlock = block._if(fromBean.invoke(getterName).ne(JExpr._null()).cand(fieldDefs.invoke("get").arg( name).ne(JExpr._null())))._then(); JVar mutableField = nonNullBlock.decl(model.ref(MutableField.class), getVarName(prefix, "mutableField"), contentLoader.invoke("createMutableField").arg(JExpr._null()).arg(fieldDefs. invoke("get").arg(name))); JVar mutableFieldValue = nonNullBlock.decl(model.ref(MutableFieldValue.class).narrow(valClass), getVarName(prefix, "fieldVal"), contentLoader.invoke(methodName)); nonNullBlock.add(mutableFieldValue.invoke("setValue").arg(fromBean.invoke(getterName).invoke("name"))); nonNullBlock.add(mutableField.invoke("setValue").arg(mutableFieldValue)); nonNullBlock.add(wContent.invoke("setField").arg(mutableField)); break; } case DATE_TIME: { final String methodName = "createDateTimeFieldValue"; final Class valClass = Date.class; setSimpleField(block, fromBean, wContent, getterName, fieldDefs, name, model, contentLoader, valClass, methodName, prefix); break; } case INTEGER: { final String methodName = "createIntegerFieldValue"; final Class valClass = Number.class; setSimpleField(block, fromBean, wContent, getterName, fieldDefs, name, model, contentLoader, valClass, methodName, prefix); break; } case DOUBLE: { final String methodName = "createDoubleFieldValue"; final Class valClass = Number.class; setSimpleField(block, fromBean, wContent, getterName, fieldDefs, name, model, contentLoader, valClass, methodName, prefix); break; } case LONG: { final String methodName = "createLongFieldValue"; final Class valClass = Number.class; setSimpleField(block, fromBean, wContent, getterName, fieldDefs, name, model, contentLoader, valClass, methodName, prefix); break; } case OTHER: { final String methodName = "createOtherFieldValue"; final Class valClass = byte[].class; setSimpleField(block, fromBean, wContent, getterName, fieldDefs, name, model, contentLoader, valClass, methodName, prefix); break; } case CONTENT: { JBlock nonNullBlock = block._if(fromBean.invoke(getterName).ne(JExpr._null()).cand(fieldDefs.invoke("get").arg( name).ne(JExpr._null()).cand(fromBean.invoke(getterName).invoke("getId").ne(JExpr._null()))))._then(); JVar mutableField = nonNullBlock.decl(model.ref(MutableField.class), getVarName(prefix, "mutableField"), contentLoader.invoke("createMutableField").arg(JExpr._null()). arg(fieldDefs.invoke("get").arg(name))); JVar mutableFieldValue = nonNullBlock.decl(model.ref(MutableFieldValue.class).narrow(ContentId.class), getVarName(prefix, "fieldVal"), contentLoader.invoke("createContentFieldValue")); nonNullBlock.add(mutableFieldValue.invoke("setValue").arg(JExpr._super().invoke("getContentId").arg(fromBean. invoke(getterName).invoke("getId")).arg(fromBean.invoke(getterName).invoke("getWorkspaceId")))); nonNullBlock.add(mutableField.invoke("setValue").arg(mutableFieldValue)); nonNullBlock.add(wContent.invoke("setField").arg(mutableField)); break; } case COMPOSITE: { CompositeDataType compositeDataType = (CompositeDataType) def.getValueDef(); JBlock nonNullBlock = block._if(fromBean.invoke(getterName).ne(JExpr._null()).cand(fieldDefs.invoke("get").arg( name).ne(JExpr._null())))._then(); JDefinedClass clazz = findClass(compositeDataType, currentClass, classes, name); JVar input = nonNullBlock.decl(clazz, getVarName(prefix, "compositeField"), fromBean.invoke(getterName)); final JInvocation defArg = fieldDefs.invoke("get").arg(name); JVar fieldDef = nonNullBlock.decl(model.ref(FieldDef.class), getVarName(prefix, "def"), defArg); JVar compositeFieldDefs = nonNullBlock.decl( model.ref(Map.class).narrow(String.class).narrow(FieldDef.class), getVarName(prefix, "compositeFieldDefs"), JExpr.invoke(JExpr.cast(model.ref(CompositeDataType.class), fieldDef.invoke("getValueDef")), "getComposedFieldDefs")); JVar mutableField = nonNullBlock.decl(model.ref(MutableField.class), getVarName(prefix, "mutableField"), contentLoader.invoke("createMutableField").arg(JExpr._null()).arg(fieldDef)); JVar mutableFieldValue = nonNullBlock.decl(model.ref(MutableCompositeFieldValue.class), getVarName(prefix, "fieldVal"), contentLoader.invoke("createCompositeFieldValue")); Collection<FieldDef> defs = getAllComposedFields(compositeDataType, types); generateReverseBlocks(defs, nonNullBlock, input, mutableFieldValue, contentLoader, compositeFieldDefs, model, clazz, classes, types, new StringBuilder(prefix).append(name).append('_').toString()); nonNullBlock.add(mutableField.invoke("setValue").arg(mutableFieldValue)); nonNullBlock.add(wContent.invoke("setField").arg(mutableField)); break; } case COLLECTION: CollectionDataType collectionDataType = (CollectionDataType) def.getValueDef(); switch (collectionDataType.getItemDataType().getType()) { case BOOLEAN: { final String methodName = "createBooleanFieldValue"; final Class valClass = Boolean.class; setSimpleMultiField(block, fromBean, wContent, getterName, fieldDefs, name, model, contentLoader, valClass, methodName, prefix); break; } case STRING: { final String methodName = "createStringFieldValue"; final Class valClass = String.class; setSimpleMultiField(block, fromBean, wContent, getterName, fieldDefs, name, model, contentLoader, valClass, methodName, prefix); break; } case ENUM: { final String methodName = "createStringFieldValue"; final Class valClass = String.class; JBlock nonNullBlock = block._if(fromBean.invoke(getterName).ne(JExpr._null()).cand(fieldDefs.invoke("get"). arg( name).ne(JExpr._null())))._then(); JVar mutableField = nonNullBlock.decl(model.ref(MutableField.class), getVarName(prefix, "mutableField"), contentLoader.invoke("createMutableField").arg(JExpr._null()).arg(fieldDefs. invoke("get").arg(name))); JVar mutableFieldValue = nonNullBlock.decl(model.ref(MutableFieldValue.class).narrow(model.ref( Collection.class). narrow(model.ref(FieldValue.class))), getVarName(prefix, "fieldVals"), contentLoader.invoke( "createCollectionFieldValue")); nonNullBlock.add(mutableField.invoke("setValue").arg(mutableFieldValue)); nonNullBlock.add(wContent.invoke("setField").arg(mutableField)); JVar collection = nonNullBlock.decl(model.ref(Collection.class).narrow(model.ref(FieldValue.class)), getVarName( prefix, "collectionVar"), JExpr._new(model.ref(ArrayList.class).narrow(FieldValue.class))); nonNullBlock.add(mutableFieldValue.invoke("setValue").arg(collection)); final JForLoop forLoop = nonNullBlock._for(); JType itClass = ((JClass) currentClass.fields().get(name).type()).getTypeParameters().get(0); JVar iterator_item = forLoop.init(model.ref(Iterator.class).narrow(itClass), getVarName(prefix, "i"), fromBean.invoke(getterName).invoke("iterator")); forLoop.test(iterator_item.invoke("hasNext")); final JBlock forBody = forLoop.body(); JVar mutableItemFieldValue = forBody.decl(model.ref(MutableFieldValue.class).narrow(valClass), getVarName(prefix, "fieldVal"), contentLoader.invoke(methodName)); forBody.add(mutableItemFieldValue.invoke("setValue").arg(iterator_item.invoke("next").invoke("name"))); forBody.add(collection.invoke("add").arg(mutableItemFieldValue)); break; } case DATE_TIME: { final String methodName = "createDateTimeFieldValue"; final Class valClass = Date.class; setSimpleMultiField(block, fromBean, wContent, getterName, fieldDefs, name, model, contentLoader, valClass, methodName, prefix); break; } case INTEGER: { final String methodName = "createIntegerFieldValue"; final Class valClass = Number.class; setSimpleMultiField(block, fromBean, wContent, getterName, fieldDefs, name, model, contentLoader, valClass, methodName, prefix); break; } case DOUBLE: { final String methodName = "createDoubleFieldValue"; final Class valClass = Number.class; setSimpleMultiField(block, fromBean, wContent, getterName, fieldDefs, name, model, contentLoader, valClass, methodName, prefix); break; } case LONG: { final String methodName = "createLongFieldValue"; final Class valClass = Number.class; setSimpleMultiField(block, fromBean, wContent, getterName, fieldDefs, name, model, contentLoader, valClass, methodName, prefix); break; } case OTHER: { final String methodName = "createOtherFieldValue"; final Class valClass = byte[].class; setSimpleMultiField(block, fromBean, wContent, getterName, fieldDefs, name, model, contentLoader, valClass, methodName, prefix); break; } case CONTENT: { JBlock nonNullBlock = block._if(fromBean.invoke(getterName).ne(JExpr._null()).cand(fieldDefs.invoke("get"). arg( name).ne(JExpr._null())))._then(); JVar mutableField = nonNullBlock.decl(model.ref(MutableField.class), getVarName(prefix, "mutableField"), contentLoader.invoke("createMutableField").arg(JExpr._null()).arg(fieldDefs. invoke("get").arg(name))); JVar mutableFieldValue = nonNullBlock.decl(model.ref(MutableFieldValue.class).narrow(model.ref( Collection.class).narrow(model.ref(FieldValue.class))), getVarName(prefix, "fieldVals"), contentLoader.invoke("createCollectionFieldValue")); nonNullBlock.add(mutableField.invoke("setValue").arg(mutableFieldValue)); nonNullBlock.add(wContent.invoke("setField").arg(mutableField)); JVar collection = nonNullBlock.decl(model.ref(Collection.class).narrow(model.ref(FieldValue.class)), getVarName(prefix, "collectionVar"), JExpr._new(model.ref( ArrayList.class).narrow(FieldValue.class))); nonNullBlock.add(mutableFieldValue.invoke("setValue").arg(collection)); final JForLoop forLoop = nonNullBlock._for(); final JClass narrowedDomain = model.ref(AbstractRepositoryDomain.class).narrow(model.ref( PersistentDTO.class).narrow(model.ref(PersistentDTO.class).wildcard()).narrow(String.class).narrow( Long.class).wildcard()); JVar iterator_item = forLoop.init(model.ref(Iterator.class).narrow(narrowedDomain.wildcard()), getVarName( prefix, "i"), fromBean.invoke(getterName).invoke("iterator")); forLoop.test(iterator_item.invoke("hasNext")); final JBlock forBody = forLoop.body(); JVar nextVal = forBody.decl(narrowedDomain, getVarName(prefix, "domain"), iterator_item.invoke( "next")); JVar mutableItemFieldValue = forBody.decl(model.ref(MutableFieldValue.class).narrow(ContentId.class), getVarName(prefix, "fieldVal"), contentLoader.invoke("createContentFieldValue")); forBody.add(mutableItemFieldValue.invoke("setValue").arg(JExpr._super().invoke("getContentId").arg(nextVal. invoke("getId")).arg(nextVal.invoke("getWorkspaceId")))); forBody.add(collection.invoke("add").arg(mutableItemFieldValue)); break; } case COMPOSITE: { CompositeDataType compositeDataType = (CompositeDataType) collectionDataType.getItemDataType(); JBlock nonNullBlock = block._if(fromBean.invoke(getterName).ne(JExpr._null()).cand(fieldDefs.invoke("get"). arg(name).ne(JExpr._null())))._then(); JDefinedClass clazz = findClass(compositeDataType, currentClass, classes, name); final JInvocation defArg = fieldDefs.invoke("get").arg(name); JVar fieldDef = nonNullBlock.decl(model.ref(FieldDef.class), getVarName(prefix, "def"), defArg); JVar compositeFieldDefs = nonNullBlock.decl(model.ref(Map.class).narrow(String.class).narrow( FieldDef.class), getVarName(prefix, "compositeFieldDefs"), JExpr.invoke(JExpr.cast(model.ref(CompositeDataType.class), JExpr.invoke(JExpr.cast(model.ref( CollectionDataType.class), fieldDef.invoke("getValueDef")), "getItemDataType")), "getComposedFieldDefs")); JVar mutableField = nonNullBlock.decl(model.ref(MutableField.class), getVarName(prefix, "mutableField"), contentLoader.invoke("createMutableField").arg(JExpr._null()).arg( fieldDef)); JVar mutableFieldValue = nonNullBlock.decl(model.ref(MutableFieldValue.class).narrow(model.ref( Collection.class).narrow(model.ref(FieldValue.class))), getVarName(prefix, "fieldVals"), contentLoader.invoke("createCollectionFieldValue")); nonNullBlock.add(mutableField.invoke("setValue").arg(mutableFieldValue)); nonNullBlock.add(wContent.invoke("setField").arg(mutableField)); JVar collection = nonNullBlock.decl(model.ref(Collection.class).narrow(model.ref(FieldValue.class)), getVarName(prefix, "collectionVar"), JExpr._new(model.ref( ArrayList.class).narrow(FieldValue.class))); nonNullBlock.add(mutableFieldValue.invoke("setValue").arg(collection)); final JForLoop forLoop = nonNullBlock._for(); final JClass narrowedDomain = clazz; JVar iterator_item = forLoop.init(model.ref(Iterator.class).narrow(narrowedDomain), getVarName( prefix, "i"), fromBean.invoke(getterName).invoke("iterator")); forLoop.test(iterator_item.invoke("hasNext")); final JBlock forBody = forLoop.body(); JVar nextVal = forBody.decl(narrowedDomain, getVarName(prefix, "domain"), iterator_item.invoke( "next")); JVar mutableItemFieldValue = forBody.decl(model.ref(MutableCompositeFieldValue.class), getVarName(prefix, "fieldVal"), contentLoader.invoke("createCompositeFieldValue")); Collection<FieldDef> defs = getAllComposedFields(compositeDataType, types); generateReverseBlocks(defs, forBody, nextVal, mutableItemFieldValue, contentLoader, compositeFieldDefs, model, clazz, classes, types, new StringBuilder(prefix).append(name).append('_').toString()); forBody.add(collection.invoke("add").arg(mutableItemFieldValue)); } } break; default: } } } protected void setSimpleField(JBlock block, JVar fromBean, JVar wContent, final String getterName, JVar fieldDefs, final String name, JCodeModel model, JVar contentLoader, final Class valClass, final String methodName, String prefix) { JBlock nonNullBlock = block._if(fromBean.invoke(getterName).ne(JExpr._null()).cand(fieldDefs.invoke("get").arg( name).ne(JExpr._null())))._then(); JVar mutableField = nonNullBlock.decl(model.ref(MutableField.class), getVarName(prefix, "mutableField"), contentLoader.invoke("createMutableField").arg(JExpr._null()).arg(fieldDefs. invoke("get").arg(name))); JVar mutableFieldValue = nonNullBlock.decl(model.ref(MutableFieldValue.class).narrow(valClass), getVarName(prefix, "fieldVal"), contentLoader.invoke(methodName)); nonNullBlock.add(mutableFieldValue.invoke("setValue").arg(fromBean.invoke(getterName))); nonNullBlock.add(mutableField.invoke("setValue").arg(mutableFieldValue)); nonNullBlock.add(wContent.invoke("setField").arg(mutableField)); } protected void setSimpleMultiField(JBlock block, JVar fromBean, JVar wContent, final String getterName, JVar fieldDefs, final String name, JCodeModel model, JVar contentLoader, final Class valClass, final String methodName, String prefix) { JBlock nonNullBlock = block._if(fromBean.invoke(getterName).ne(JExpr._null()).cand(fieldDefs.invoke("get").arg( name).ne(JExpr._null())))._then(); JVar mutableField = nonNullBlock.decl(model.ref(MutableField.class), getVarName(prefix, "mutableField"), contentLoader.invoke("createMutableField").arg(JExpr._null()).arg(fieldDefs. invoke("get").arg(name))); JVar mutableFieldValue = nonNullBlock.decl(model.ref(MutableFieldValue.class).narrow(model.ref(Collection.class). narrow(model.ref(FieldValue.class))), getVarName(prefix, "fieldVals"), contentLoader.invoke( "createCollectionFieldValue")); nonNullBlock.add(mutableField.invoke("setValue").arg(mutableFieldValue)); nonNullBlock.add(wContent.invoke("setField").arg(mutableField)); JVar collection = nonNullBlock.decl(model.ref(Collection.class).narrow(model.ref(FieldValue.class)), getVarName( prefix, "collectionVar"), JExpr._new(model.ref(ArrayList.class).narrow(FieldValue.class))); nonNullBlock.add(mutableFieldValue.invoke("setValue").arg(collection)); final JForLoop forLoop = nonNullBlock._for(); JVar iterator_item = forLoop.init(model.ref(Iterator.class).narrow(model.ref(valClass).wildcard()), getVarName( prefix, "i"), fromBean.invoke(getterName).invoke("iterator")); forLoop.test(iterator_item.invoke("hasNext")); final JBlock forBody = forLoop.body(); JVar mutableItemFieldValue = forBody.decl(model.ref(MutableFieldValue.class).narrow(valClass), getVarName(prefix, "fieldVal"), contentLoader.invoke(methodName)); forBody.add(mutableItemFieldValue.invoke("setValue").arg(iterator_item.invoke("next"))); forBody.add(collection.invoke("add").arg(mutableItemFieldValue)); } protected void generateMasterModule(Map<ContentTypeId, JDefinedClass> modules, JCodeModel codeModel, String[] wId) throws JClassAlreadyExistsException { final String moduleClassName = new StringBuilder(packageForGuiceMasterModule).append(".MasterModule").toString(); final JDefinedClass moduleClass = codeModel._class(moduleClassName); moduleClass._extends(codeModel.ref(AbstractModule.class)); JMethod configureMethod = moduleClass.method(JMod.PUBLIC, JCodeModel.boxToPrimitive.get(Void.class), "configure"); JClass namesClass = codeModel.ref(Names.class); JBlock block = configureMethod.body(); final JClass systemClass = codeModel.ref(System.class); final JClass stringClassType = codeModel.ref(String.class); JExpression stringClass = stringClassType.dotclass(); JVar workspaceNamespace = block.decl(stringClassType, "workspaceNamespace", systemClass.staticInvoke("getProperty").arg( "com.smartitengineering.cms.repo.workspace.namespace").arg(wId[0])); JVar workspaceName = block.decl(stringClassType, "workspaceName", systemClass.staticInvoke("getProperty").arg( "com.smartitengineering.cms.repo.workspace.name").arg(wId[1])); block.add(JExpr.invoke("bind").arg(stringClass).invoke("annotatedWith").arg(namesClass.staticInvoke("named"). arg("cmsWorkspaceNamespace")).invoke("toInstance").arg(workspaceNamespace)); block.add(JExpr.invoke("bind").arg(stringClass).invoke("annotatedWith").arg(namesClass.staticInvoke("named"). arg("cmsWorkspaceName")).invoke("toInstance").arg(workspaceName)); if (typeFiles != null && !typeFiles.isEmpty()) { { JClass typeLiteral = codeModel.ref(TypeLiteral.class); final JClass narrowedTypesLiteral = typeLiteral.narrow(codeModel.ref(List.class).narrow(String.class)); final JDefinedClass stringListType = moduleClass._class("InitializationContentTypes"); stringListType._extends(narrowedTypesLiteral); JVar typesList = block.decl(codeModel.ref(List.class).narrow(String.class), "contentTypes", JExpr._new(codeModel.ref(ArrayList.class).narrow(String.class))); for (String typeFile : typeFiles) { block.add(typesList.invoke("add").arg(typeFile)); } block.add(JExpr.invoke("bind").arg(JExpr._new(stringListType)).invoke( "annotatedWith").arg(namesClass.staticInvoke("named").arg("contentTypePath")).invoke("toInstance").arg( typesList)); JVar initVar = block.decl(codeModel.ref(Initializer.class), "initializer", JExpr._new(codeModel.ref(Initializer.class)).arg(workspaceNamespace).arg(workspaceName). arg(typesList)); block.add(initVar.invoke("init")); } } JClass workspaceIdClass = codeModel.ref(WorkspaceId.class); JClass apiClass = codeModel.ref(SmartContentAPI.class); final JInvocation workspaceApiInvocation = apiClass.staticInvoke("getInstance").invoke("getWorkspaceApi"). invoke("createWorkspaceId"); final JInvocation _new = workspaceApiInvocation.arg(workspaceNamespace).arg(workspaceName); block.add(JExpr.invoke("bind").arg(workspaceIdClass.dotclass()).invoke("toInstance").arg(_new)); for (JDefinedClass clazz : modules.values()) { block.invoke("install").arg(JExpr._new(clazz)); } if (transactionEnabled) { JClass booleanClass = codeModel.ref(Boolean.class); JClass bigBoolClass = codeModel.ref(Boolean.class); JClass txImplModuleClass = codeModel.ref(TransactionImplModule.class); block.add(JExpr.invoke("bind").arg(booleanClass.dotclass()).invoke("annotatedWith").arg(namesClass.staticInvoke( "named").arg("nonIsolatedLookupEnabled")).invoke("toInstance").arg(bigBoolClass.staticInvoke("parseBoolean"). arg(String.valueOf(nonIsolatedTransactionAllowed)))); block.invoke("install").arg(JExpr._new(txImplModuleClass)); } } private void generateAssociationIoCForFields(Collection<FieldDef> defs, JCodeModel model, JDefinedClass stringType, JClass typeLiteral, JDefinedClass moduleClass, JBlock block, Set<MutableContentType> types, Map<ContentTypeId, JDefinedClass> classes, String namePrefix, final Set<ContentTypeId> idsConfigdFor) throws JClassAlreadyExistsException { for (FieldDef def : defs) { final ContentDataType contentDataType; final String probablePrefix = new StringBuilder(namePrefix).append(def.getName().substring(0, 1).toUpperCase()). append(def.getName().substring(1)).toString(); switch (def.getValueDef().getType()) { case CONTENT: contentDataType = (ContentDataType) def.getValueDef(); break; case COLLECTION: CollectionDataType collectionDataType = (CollectionDataType) def.getValueDef(); if (collectionDataType.getItemDataType().getType().equals(FieldValueType.CONTENT)) { contentDataType = (ContentDataType) collectionDataType.getItemDataType(); } else if (collectionDataType.getItemDataType().getType().equals(FieldValueType.COMPOSITE)) { CompositeDataType compositeDataType = (CompositeDataType) collectionDataType.getItemDataType(); generateAssociationIoCForFields(getAllComposedFields(compositeDataType, types), model, stringType, typeLiteral, moduleClass, block, types, classes, probablePrefix, idsConfigdFor); contentDataType = null; } else { contentDataType = null; } break; case COMPOSITE: CompositeDataType compositeDataType = (CompositeDataType) def.getValueDef(); generateAssociationIoCForFields(getAllComposedFields(compositeDataType, types), model, stringType, typeLiteral, moduleClass, block, types, classes, probablePrefix, idsConfigdFor); default: contentDataType = null; break; } if (contentDataType != null && !idsConfigdFor.contains(contentDataType.getTypeDef())) { idsConfigdFor.add(contentDataType.getTypeDef()); JBlock mapBindingBlock = block.block(); JDefinedClass definedClass = classes.get(contentDataType.getTypeDef()); final JClass assocType = model.ref(CommonReadDao.class).narrow(definedClass.wildcard()).narrow(String.class); final JClass narrowedReadTypeLiteral = typeLiteral.narrow(assocType); final JDefinedClass assocDaoTypeLit = moduleClass._class(new StringBuilder(probablePrefix).append("DaoType"). toString()); assocDaoTypeLit._extends(narrowedReadTypeLiteral); JVar mapBinderVar = mapBindingBlock.decl(model.ref(MapBinder.class).narrow(String.class).narrow(assocType), "mapBinder", model.ref(MapBinder.class).staticInvoke("newMapBinder"). arg(JExpr._this().invoke("binder")).arg(JExpr._new(stringType)).arg(JExpr._new(assocDaoTypeLit))); Collection<ContentType> concreteInstances = findConcreteInstanceOf(contentDataType.getTypeDef(), types); for (ContentType concreteInstance : concreteInstances) { JDefinedClass concClass = classes.get(concreteInstance.getContentTypeID()); if (concClass == null) { continue; } final JClass concType = model.ref(CommonReadDao.class).narrow(concClass).narrow(String.class); final JClass narrowedConcReadTypeLiteral = typeLiteral.narrow(concType); final String name = concreteInstance.getContentTypeID().getName(); final JDefinedClass concDaoTypeLit = moduleClass._class(new StringBuilder(probablePrefix).append(name. substring(0, 1).toUpperCase()).append(name.substring(1)).append("DaoType"). toString()); concDaoTypeLit._extends(narrowedConcReadTypeLiteral); mapBindingBlock.add(mapBinderVar.invoke("addBinding").arg(JExpr.lit(concreteInstance.getContentTypeID(). toString())).invoke("to").arg(JExpr._new(concDaoTypeLit))); } } } } private Collection<ContentType> findConcreteInstanceOf(final ContentTypeId typeDef, final Collection<? extends ContentType> types) { if (types == null || typeDef == null || types.isEmpty()) { return Collections.emptyList(); } final List<ContentType> instanceOfTypes = new ArrayList<ContentType>(); final Map<ContentTypeId, ContentType> typeMap = new HashMap<ContentTypeId, ContentType>(); for (ContentType type : types) { typeMap.put(type.getContentTypeID(), type); } for (ContentType type : types) { if (type.getDefinitionType().equals(DefinitionType.CONCRETE_TYPE)) { boolean isInstanceOf = isInstanceOf(type, typeDef, typeMap); if (isInstanceOf) { instanceOfTypes.add(type); } } } return instanceOfTypes; } private boolean isInstanceOf(ContentType type, final ContentTypeId typeDef, Map<ContentTypeId, ContentType> types) { boolean isInstanceOf = false; if (type.getContentTypeID().equals(typeDef)) { isInstanceOf = true; } if (!isInstanceOf) { ContentTypeId parentId = type.getParent(); if (!isInstanceOf && parentId != null && types.get(parentId) != null) { isInstanceOf = isInstanceOf(types.get(parentId), typeDef, types); } } return isInstanceOf; } }