http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientDataMapArtifact.java ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientDataMapArtifact.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientDataMapArtifact.java new file mode 100644 index 0000000..a9d1dfe --- /dev/null +++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientDataMapArtifact.java @@ -0,0 +1,50 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.gen; + +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.map.QueryDescriptor; +import org.apache.cayenne.util.Util; + +import java.util.Collection; + +public class ClientDataMapArtifact extends DataMapArtifact { + + public ClientDataMapArtifact(DataMap dataMap, Collection<QueryDescriptor> queries) { + super(dataMap, queries); + + } + + @Override + public String getQualifiedBaseClassName() { + + return dataMap.getDefaultClientSuperclass(); + } + + @Override + public String getQualifiedClassName() { + String clientPrefix = ""; + if (Util.nullSafeEquals(dataMap.getDefaultClientPackage(), dataMap.getDefaultPackage())) { + clientPrefix = "Client_"; + } + + return dataMap.getNameWithDefaultClientPackage(Util.underscoredToJava(clientPrefix + dataMap.getName(), true)); + } +} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientEntityArtifact.java ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientEntityArtifact.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientEntityArtifact.java new file mode 100644 index 0000000..d20a2d4 --- /dev/null +++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClientEntityArtifact.java @@ -0,0 +1,45 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.gen; + +import org.apache.cayenne.PersistentObject; +import org.apache.cayenne.map.ObjEntity; + +/** + * Client code generation artifact based on ObjEntity. + * + * @since 3.0 + */ +public class ClientEntityArtifact extends EntityArtifact { + + public ClientEntityArtifact(ObjEntity entity) { + super(entity); + } + + @Override + public String getQualifiedBaseClassName() { + return (entity.getClientSuperClassName() != null) ? entity + .getClientSuperClassName() : PersistentObject.class.getName(); + } + + @Override + public String getQualifiedClassName() { + return entity.getClientClassName(); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/java/org/apache/cayenne/gen/DataMapArtifact.java ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/DataMapArtifact.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/DataMapArtifact.java new file mode 100644 index 0000000..8e60495 --- /dev/null +++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/DataMapArtifact.java @@ -0,0 +1,137 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.gen; + +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.map.QueryDescriptor; +import org.apache.cayenne.util.Util; +import org.apache.velocity.VelocityContext; + +import java.util.Collection; +import java.util.LinkedList; + +/** + * {@link Artifact} facade for a DataMap. + * + * @since 3.0 + */ +public class DataMapArtifact implements Artifact { + + public static final String DATAMAP_UTILS_KEY = "dataMapUtils"; + + protected DataMap dataMap; + protected Collection<QueryDescriptor> selectQueries; + protected Collection<QueryDescriptor> sqlTemplateQueries; + protected Collection<QueryDescriptor> procedureQueries; + protected Collection<QueryDescriptor> ejbqlQueries; + protected Collection<String> queryNames; + + public DataMapArtifact(DataMap dataMap, Collection<QueryDescriptor> queries) { + this.dataMap = dataMap; + selectQueries = new LinkedList<>(); + sqlTemplateQueries = new LinkedList<>(); + procedureQueries = new LinkedList<>(); + ejbqlQueries = new LinkedList<>(); + queryNames = new LinkedList<>(); + addQueries(queries); + } + + public String getQualifiedBaseClassName() { + return Object.class.getName(); + } + + public String getQualifiedClassName() { + return dataMap.getNameWithDefaultPackage(Util.underscoredToJava(dataMap.getName(), true)); + } + + public Object getObject() { + return this; + } + + public void postInitContext(VelocityContext context) { + DataMapUtils dataMapUtils = new DataMapUtils(); + context.put(DATAMAP_UTILS_KEY, dataMapUtils); + } + + public TemplateType[] getTemplateTypes(ArtifactGenerationMode mode) { + switch (mode) { + case SINGLE_CLASS: + return new TemplateType[] { + TemplateType.DATAMAP_SINGLE_CLASS + }; + case GENERATION_GAP: + return new TemplateType[] { + TemplateType.DATAMAP_SUPERCLASS, TemplateType.DATAMAP_SUBCLASS + }; + default: + return new TemplateType[0]; + } + } + + private void addQueries(Collection<QueryDescriptor> queries) { + if (queries != null) { + for (QueryDescriptor query : queries) { + addQuery(query); + } + } + } + + private void addQuery(QueryDescriptor query) { + + switch (query.getType()) { + case QueryDescriptor.SELECT_QUERY: + selectQueries.add(query); + break; + case QueryDescriptor.PROCEDURE_QUERY: + procedureQueries.add(query); + break; + case QueryDescriptor.SQL_TEMPLATE: + sqlTemplateQueries.add(query); + break; + case QueryDescriptor.EJBQL_QUERY: + ejbqlQueries.add(query); + break; + } + + if (query.getName() != null && !"".equals(query.getName())) { + queryNames.add(query.getName()); + } + } + + public Collection<QueryDescriptor> getSelectQueries() { + return selectQueries; + } + + public boolean hasSelectQueries() { + return selectQueries.size() > 0; + } + + public boolean hasQueryNames() { + return !queryNames.isEmpty(); + } + + public Collection<String> getQueryNames() { + return queryNames; + } + + public DataMap getDataMap() { + return dataMap; + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/java/org/apache/cayenne/gen/DataMapUtils.java ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/DataMapUtils.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/DataMapUtils.java new file mode 100644 index 0000000..a0013cc --- /dev/null +++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/DataMapUtils.java @@ -0,0 +1,219 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.gen; + +import org.apache.cayenne.exp.Expression; +import org.apache.cayenne.exp.ExpressionException; +import org.apache.cayenne.exp.ExpressionParameter; +import org.apache.cayenne.exp.parser.ASTList; +import org.apache.cayenne.exp.parser.ASTObjPath; +import org.apache.cayenne.map.Entity; +import org.apache.cayenne.map.ObjAttribute; +import org.apache.cayenne.map.ObjEntity; +import org.apache.cayenne.map.ObjRelationship; +import org.apache.cayenne.map.PathComponent; +import org.apache.cayenne.map.QueryDescriptor; +import org.apache.cayenne.map.SelectQueryDescriptor; +import org.apache.cayenne.query.Ordering; +import org.apache.cayenne.util.CayenneMapEntry; +import org.apache.cayenne.util.Util; +import org.apache.commons.collections.set.ListOrderedSet; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Attributes and Methods for working with Queries. + * + * @since 3.0 + */ +public class DataMapUtils { + + Map<String, Map<String, String>> queriesMap = new HashMap<>(); + + /** + * Return valid method name based on query name (replace all illegal + * characters with underscore '_'). + * + * @param query + * @return Method name that perform query. + */ + public String getQueryMethodName(QueryDescriptor query) { + return Util.underscoredToJava(query.getName(), true); + } + + /** + * Get all parameter names that used in query qualifier. + * + * @param query + * @return Parameter names. + */ + public Collection getParameterNames(SelectQueryDescriptor query) { + + if (query.getQualifier() == null) { + return Collections.EMPTY_SET; + } + + Map<String, String> queryParameters = queriesMap.get(query.getName()); + + if (queryParameters == null) { + queryParameters = getParameterNames(query.getQualifier(), query.getRoot()); + queriesMap.put(query.getName(), queryParameters); + } + + return parseQualifier(query.getQualifier().toString()); + } + + public Boolean isValidParameterNames(SelectQueryDescriptor query) { + + if (query.getQualifier() == null) { + return true; + } + + Map<String, String> queryParameters = queriesMap.get(query.getName()); + + if (queryParameters == null) { + try { + queryParameters = getParameterNames(query.getQualifier(), query.getRoot()); + } catch (Exception e) { + // if we have wrong path in queryParameters return false. + return false; + } + } + + for (Ordering ordering : query.getOrderings()) { + // validate paths in ordering + String path = ordering.getSortSpecString(); + Iterator<CayenneMapEntry> it = ((ObjEntity) query.getRoot()).resolvePathComponents(path); + while (it.hasNext()) { + try { + it.next(); + } catch (ExpressionException e) { + // if we have wrong path in orderings return false. + return false; + } + } + } + + return true; + } + + /** + * Get list of parameter names in the same order as in qualifier. + * + * @param qualifierString + * to be parsed + * @return List of parameter names. + */ + private Set parseQualifier(String qualifierString) { + Set result = new ListOrderedSet(); + Pattern pattern = Pattern.compile("\\$[\\w]+"); + Matcher matcher = pattern.matcher(qualifierString); + while (matcher.find()) { + String name = matcher.group(); + result.add(Util.underscoredToJava(name.substring(1), false)); + } + + return result; + } + + public boolean hasParameters(SelectQueryDescriptor query) { + Map queryParameters = queriesMap.get(query.getName()); + + if (queryParameters == null) { + return false; + } + + return queryParameters.keySet().size() > 0; + + } + + /** + * Get type of parameter for given name. + * + * @param query + * @param name + * @return Parameter type. + */ + public String getParameterType(SelectQueryDescriptor query, String name) { + return queriesMap.get(query.getName()).get(name); + } + + private Map<String, String> getParameterNames(Expression expression, Object root) { + if (expression != null) { + Map<String, String> types = new HashMap<>(); + String typeName = ""; + List<String> names = new LinkedList<String>(); + + for (int i = 0; i < expression.getOperandCount(); i++) { + Object operand = expression.getOperand(i); + + if (operand instanceof Expression) { + types.putAll(getParameterNames((Expression) operand, root)); + } + + if (operand instanceof ASTObjPath) { + PathComponent<ObjAttribute, ObjRelationship> component = ((Entity) root).lastPathComponent( + (ASTObjPath) operand, null); + ObjAttribute attribute = component.getAttribute(); + if (attribute != null) { + typeName = attribute.getType(); + } else { + ObjRelationship relationship = component.getRelationship(); + if (relationship != null) { + typeName = ((ObjEntity) relationship.getTargetEntity()).getClassName(); + } else { + typeName = "Object"; + } + } + } + + if (operand instanceof ASTList) { + Object[] values = (Object[]) ((ASTList) operand).getOperand(0); + for (Object value : values) { + if (value instanceof ExpressionParameter) { + names.add(((ExpressionParameter) value).getName()); + } + } + } + + if (operand instanceof ExpressionParameter) { + names.add(((ExpressionParameter) operand).getName()); + } + + } + + for (String name : names) { + types.put(Util.underscoredToJava(name, false), typeName); + } + + return types; + } + return Collections.EMPTY_MAP; + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/java/org/apache/cayenne/gen/EmbeddableArtifact.java ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/EmbeddableArtifact.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/EmbeddableArtifact.java new file mode 100644 index 0000000..8e6ea43 --- /dev/null +++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/EmbeddableArtifact.java @@ -0,0 +1,68 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.gen; + +import org.apache.cayenne.map.Embeddable; +import org.apache.velocity.VelocityContext; + +/** + * {@link Artifact} facade for an {@link Embeddable}. + * + * @since 3.0 + */ +public class EmbeddableArtifact implements Artifact { + + protected Embeddable embeddable; + + public EmbeddableArtifact(Embeddable embeddable) { + this.embeddable = embeddable; + } + + public Object getObject() { + return embeddable; + } + + public String getQualifiedBaseClassName() { + return Object.class.getName(); + } + + public String getQualifiedClassName() { + return embeddable.getClassName(); + } + + public TemplateType[] getTemplateTypes(ArtifactGenerationMode mode) { + switch (mode) { + case SINGLE_CLASS: + return new TemplateType[] { + TemplateType.EMBEDDABLE_SINGLE_CLASS + }; + case GENERATION_GAP: + return new TemplateType[] { + TemplateType.EMBEDDABLE_SUPERCLASS, + TemplateType.EMBEDDABLE_SUBCLASS + }; + default: + return new TemplateType[0]; + } + } + + public void postInitContext(VelocityContext context) { + // noop - no special keys... + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/java/org/apache/cayenne/gen/EntityArtifact.java ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/EntityArtifact.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/EntityArtifact.java new file mode 100644 index 0000000..394304f --- /dev/null +++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/EntityArtifact.java @@ -0,0 +1,98 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.gen; + +import org.apache.cayenne.CayenneDataObject; +import org.apache.cayenne.map.ObjEntity; +import org.apache.velocity.VelocityContext; + +/** + * {@link Artifact} facade for an ObjEntity. + * + * @since 3.0 + */ +public class EntityArtifact implements Artifact { + + public static String ENTITY_UTILS_KEY = "entityUtils"; + + protected ObjEntity entity; + + public EntityArtifact(ObjEntity entity) { + this.entity = entity; + } + + /** + * Returns ObjEntity. + */ + public Object getObject() { + return entity; + } + + public String getQualifiedBaseClassName() { + return (entity.getSuperClassName() != null) + ? entity.getSuperClassName() + : CayenneDataObject.class.getName(); + } + + public String getQualifiedClassName() { + return entity.getClassName(); + } + + public TemplateType getSingleClassType() { + return TemplateType.ENTITY_SINGLE_CLASS; + } + + public TemplateType getSubclassType() { + return TemplateType.ENTITY_SUBCLASS; + } + + public TemplateType getSuperClassType() { + return TemplateType.ENTITY_SUPERCLASS; + } + + public TemplateType[] getTemplateTypes(ArtifactGenerationMode mode) { + switch (mode) { + case SINGLE_CLASS: + return new TemplateType[] { + TemplateType.ENTITY_SINGLE_CLASS + }; + case GENERATION_GAP: + return new TemplateType[] { + TemplateType.ENTITY_SUPERCLASS, TemplateType.ENTITY_SUBCLASS + }; + default: + return new TemplateType[0]; + } + } + + public void postInitContext(VelocityContext context) { + EntityUtils metadata = new EntityUtils( + entity.getDataMap(), + entity, + (String) context.get(BASE_CLASS_KEY), + (String) context.get(BASE_PACKAGE_KEY), + (String) context.get(SUPER_CLASS_KEY), + (String) context.get(SUPER_PACKAGE_KEY), + (String) context.get(SUB_CLASS_KEY), + (String) context.get(SUB_PACKAGE_KEY)); + + context.put(ENTITY_UTILS_KEY, metadata); + } + +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/java/org/apache/cayenne/gen/EntityUtils.java ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/EntityUtils.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/EntityUtils.java new file mode 100644 index 0000000..ecf2a3f --- /dev/null +++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/EntityUtils.java @@ -0,0 +1,274 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.gen; + +import java.util.Collection; + +import org.apache.cayenne.CayenneRuntimeException; +import org.apache.cayenne.ObjectId; +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.map.DbEntity; +import org.apache.cayenne.map.MappingNamespace; +import org.apache.cayenne.map.ObjAttribute; +import org.apache.cayenne.map.ObjEntity; +import org.apache.cayenne.map.ObjRelationship; +import org.apache.cayenne.map.Relationship; + +/** + * Attributes and Methods for working with ObjEntities. + * + * @since 1.2 + */ +public class EntityUtils { + + // template substitution values + protected String subClassName; + protected String superClassName; + protected String baseClassName; + protected String subPackageName; + protected String superPackageName; + protected String basePackageName; + + protected DataMap primaryDataMap; + protected ObjEntity objEntity; + + protected Collection<String> callbackNames; + + public EntityUtils(DataMap dataMap, ObjEntity objEntity, String fqnBaseClass, String fqnSuperClass, + String fqnSubClass) { + + StringUtils stringUtils = StringUtils.getInstance(); + + this.baseClassName = stringUtils.stripPackageName(fqnBaseClass); + this.basePackageName = stringUtils.stripClass(fqnBaseClass); + this.superClassName = stringUtils.stripPackageName(fqnSuperClass); + this.superPackageName = stringUtils.stripClass(fqnSuperClass); + this.subClassName = stringUtils.stripPackageName(fqnSubClass); + this.subPackageName = stringUtils.stripClass(fqnSubClass); + + this.primaryDataMap = dataMap; + + this.objEntity = objEntity; + this.callbackNames = objEntity.getCallbackMethods(); + } + + EntityUtils(DataMap dataMap, ObjEntity objEntity, String baseClassName, String basePackageName, + String superClassName, String superPackageName, String subClassName, String subPackageName) { + + this.baseClassName = baseClassName; + this.basePackageName = basePackageName; + this.superClassName = superClassName; + this.superPackageName = superPackageName; + this.subClassName = subClassName; + this.subPackageName = subPackageName; + + this.primaryDataMap = dataMap; + + this.objEntity = objEntity; + this.callbackNames = objEntity.getCallbackMethods(); + } + + /** + * @return Returns the primary DataMap. + * @since 1.2 + */ + public DataMap getPrimaryDataMap() { + return primaryDataMap; + } + + /** + * Returns the EntityResolver for this set of DataMaps. + * + * @since 1.2 + */ + public MappingNamespace getEntityResolver() { + return primaryDataMap.getNamespace(); + } + + /** + * Returns true if current ObjEntity is defined as abstract. + */ + public boolean isAbstract() { + return isAbstract(objEntity); + } + + /** + * Returns true if current ObjEntity is defined as abstract. + */ + public boolean isAbstract(ObjEntity anObjEntity) { + return anObjEntity != null && anObjEntity.isAbstract(); + } + + /** + * Returns true if current ObjEntity contains at least one toMany + * relationship. + */ + public boolean hasToManyRelationships() { + return hasToManyRelationships(objEntity); + } + + /** + * Returns true if an ObjEntity contains at least one toMany relationship. + */ + public boolean hasToManyRelationships(ObjEntity anObjEntity) { + if (anObjEntity == null) { + return false; + } + + for (Relationship r : anObjEntity.getRelationships()) { + if (r.isToMany()) { + return true; + } + } + + return false; + } + + /** + * Returns true if current ObjEntity contains at least one toMany + * relationship, ignoring those declared in superentities. + * + * @since 1.2 + */ + public boolean hasToManyDeclaredRelationships() { + return hasToManyDeclaredRelationships(objEntity); + } + + /** + * Returns true if an ObjEntity contains at least one toMany relationship, + * ignoring those declared in superentities. + * + * @since 1.2 + */ + public boolean hasToManyDeclaredRelationships(ObjEntity anObjEntity) { + if (anObjEntity == null) { + return false; + } + + for (Relationship r : anObjEntity.getDeclaredRelationships()) { + if (r.isToMany()) { + return true; + } + } + + return false; + } + + /** + * Returns true if current ObjEntity contains at least one toOne + * relationship. + */ + public boolean hasToOneRelationships() { + return hasToOneRelationships(objEntity); + } + + /** + * Returns true if an ObjEntity contains at least one toOne relationship. + */ + public boolean hasToOneRelationships(ObjEntity anObjEntity) { + if (anObjEntity == null) { + return false; + } + + for (Relationship r : anObjEntity.getRelationships()) { + if (!r.isToMany()) { + return true; + } + } + + return false; + } + + /** + * Returns true if current ObjEntity contains at least one toOne + * relationship, ignoring those declared in superentities. + */ + public boolean hasToOneDeclaredRelationships() { + return hasToOneDeclaredRelationships(objEntity); + } + + /** + * Returns true if an ObjEntity contains at least one toOne relationship, + * ignoring those declared in superentities. + */ + public boolean hasToOneDeclaredRelationships(ObjEntity anObjEntity) { + if (anObjEntity == null) { + return false; + } + + for (Relationship r : anObjEntity.getDeclaredRelationships()) { + if (!r.isToMany()) { + return true; + } + } + + return false; + } + + /** + * Returns the map key type for a collection relationship of type + * java.util.Map. + * + * @param relationship + * The relationship to look up type information for. + * @return The type of the attribute keyed on. + */ + public String getMapKeyType(final ObjRelationship relationship) { + + ObjEntity targetEntity = (ObjEntity) relationship.getTargetEntity(); + + // If the map key is null, then we're doing look-ups by actual object + // key. + if (relationship.getMapKey() == null) { + + // If it's a multi-column key, then the return type is always + // ObjectId. + DbEntity dbEntity = targetEntity.getDbEntity(); + if ((dbEntity != null) && (dbEntity.getPrimaryKeys().size() > 1)) { + return ObjectId.class.getName(); + } + + // If it's a single column key or no key exists at all, then we + // really don't + // know what the key type is, + // so default to Object. + return Object.class.getName(); + } + + // If the map key is a non-default attribute, then fetch the attribute + // and return + // its type. + ObjAttribute attribute = targetEntity.getAttribute(relationship.getMapKey()); + if (attribute == null) { + throw new CayenneRuntimeException("Invalid map key '" + relationship.getMapKey() + + "', no matching attribute found"); + } + + return attribute.getType(); + } + + /** + * @return the list of all callback names registered for the entity. + * @since 3.0 + */ + public Collection<String> getCallbackNames() { + return callbackNames; + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ImportUtils.java ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ImportUtils.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ImportUtils.java new file mode 100644 index 0000000..af40499 --- /dev/null +++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ImportUtils.java @@ -0,0 +1,266 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.gen; + +import org.apache.cayenne.util.Util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Methods for mangling strings. + * + */ +public class ImportUtils { + + public static final String importOrdering[] = new String[] { "java.", "javax.", "org.", "com." }; + + static final String primitives[] = new String[] { "long", "double", "byte", "boolean", "float", "short", "int", + "char" }; + + static final String primitiveClasses[] = new String[] { Long.class.getName(), Double.class.getName(), + Byte.class.getName(), Boolean.class.getName(), Float.class.getName(), Short.class.getName(), + Integer.class.getName(), Character.class.getName() }; + + static Map<String, String> classesForPrimitives = Util.toMap(primitives, primitiveClasses); + static Map<String, String> primitivesForClasses = Util.toMap(primitiveClasses, primitives); + + protected Map<String, String> importTypesMap = new HashMap<>(); + + // Types forced to be FQN + protected Map<String, String> reservedImportTypesMap = new HashMap<>(); + + protected String packageName; + + public ImportUtils() { + super(); + } + + protected boolean canRegisterType(String typeName) { + // Not sure why this would ever happen, but it did + if (null == typeName) + return false; + + StringUtils stringUtils = StringUtils.getInstance(); + String typeClassName = stringUtils.stripPackageName(typeName); + String typePackageName = stringUtils.stripClass(typeName); + + if (typePackageName.length() == 0) + return false; // disallow non-packaged types (primitives, probably) + if ("java.lang".equals(typePackageName)) + return false; + + // Can only have one type -- rest must use fqn + if (reservedImportTypesMap.containsKey(typeClassName)) + return false; + if (importTypesMap.containsKey(typeClassName)) + return false; + + return true; + } + + /** + * Reserve a fully-qualified data type class name so it cannot be used by + * another class. No import statements will be generated for reserved types. + * Typically, this is the fully-qualified class name of the class being + * generated. + * + * @param typeName + * FQ data type class name. + */ + public void addReservedType(String typeName) { + if (!canRegisterType(typeName)) + return; + + StringUtils stringUtils = StringUtils.getInstance(); + String typeClassName = stringUtils.stripPackageName(typeName); + + reservedImportTypesMap.put(typeClassName, typeName); + } + + /** + * Register a fully-qualified data type class name. For example, + * org.apache.cayenne.CayenneDataObject. + * + * @param typeName + * FQ data type class name. + */ + public void addType(String typeName) { + if (!canRegisterType(typeName)) + return; + + StringUtils stringUtils = StringUtils.getInstance(); + String typePackageName = stringUtils.stripClass(typeName); + String typeClassName = stringUtils.stripPackageName(typeName); + + if (typePackageName.equals(packageName)) + return; + + importTypesMap.put(typeClassName, typeName); + } + + /** + * Add the package name to use for this importUtil invocation. + * + * @param packageName + */ + public void setPackage(String packageName) { + this.packageName = packageName; + } + + /** + * Performs processing similar to <code>formatJavaType(String)</code>, with + * special handling of primitive types and their Java class counterparts. + * This method allows users to make a decision whether to use primitives or + * not, regardless of how type is mapped. + */ + public String formatJavaType(String typeName, boolean usePrimitives) { + if (usePrimitives) { + String primitive = primitivesForClasses.get(typeName); + return (primitive != null) ? primitive : formatJavaType(typeName); + } else { + String primitiveClass = classesForPrimitives.get(typeName); + return (primitiveClass != null) ? formatJavaType(primitiveClass) : formatJavaType(typeName); + } + } + + /** + * Removes registered package and non-reserved registered type name prefixes + * from java types + */ + public String formatJavaType(String typeName) { + if (typeName != null) { + StringUtils stringUtils = StringUtils.getInstance(); + String typeClassName = stringUtils.stripPackageName(typeName); + + if (!reservedImportTypesMap.containsKey(typeClassName)) { + if (importTypesMap.containsKey(typeClassName)) { + if (typeName.equals(importTypesMap.get(typeClassName))) + return typeClassName; + } + } + + String typePackageName = stringUtils.stripClass(typeName); + if ("java.lang".equals(typePackageName)) + return typeClassName; + if ((null != packageName) && (packageName.equals(typePackageName))) + return typeClassName; + } + + return typeName; + } + + /** + * @since 3.0 + */ + public String formatJavaTypeAsNonBooleanPrimitive(String type) { + String value = ImportUtils.classesForPrimitives.get(type); + return formatJavaType(value != null ? value : type); + } + + /** + * @since 3.0 + */ + public boolean isNonBooleanPrimitive(String type) { + return ImportUtils.classesForPrimitives.containsKey(type) && !isBoolean(type); + } + + /** + * @since 3.0 + */ + public boolean isBoolean(String type) { + return "boolean".equals(type); + } + + /** + * Generate package and list of import statements based on the registered + * types. + */ + public String generate() { + StringBuilder outputBuffer = new StringBuilder(); + + if (null != packageName) { + outputBuffer.append("package "); + outputBuffer.append(packageName); + + // Using UNIX line endings intentionally - generated Java files + // should look + // the same regardless of platform to prevent developer teams + // working on + // multiple OS's to override each other's work + outputBuffer.append(";\n\n"); + } + + List<String> typesList = new ArrayList<>(importTypesMap.values()); + Collections.sort(typesList, new Comparator<String>() { + + public int compare(String s1, String s2) { + + for (String ordering : importOrdering) { + if ((s1.startsWith(ordering)) && (!s2.startsWith(ordering))) { + return -1; + } + if ((!s1.startsWith(ordering)) && (s2.startsWith(ordering))) { + return 1; + } + } + + return s1.compareTo(s2); + } + }); + + String lastStringPrefix = null; + boolean firstIteration = true; + for (String typeName : typesList) { + + if (firstIteration) { + firstIteration = false; + } else { + outputBuffer.append('\n'); + } + // Output another newline if we're in a different root package. + // Find root package + String thisStringPrefix = typeName; + int dotIndex = typeName.indexOf('.'); + if (-1 != dotIndex) { + thisStringPrefix = typeName.substring(0, dotIndex); + } + // if this isn't the first import, + if (null != lastStringPrefix) { + // and it's different from the last import + if (false == thisStringPrefix.equals(lastStringPrefix)) { + // output a newline; force UNIX style per comment above + outputBuffer.append("\n"); + } + } + lastStringPrefix = thisStringPrefix; + + outputBuffer.append("import "); + outputBuffer.append(typeName); + outputBuffer.append(';'); + } + + return outputBuffer.toString(); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/java/org/apache/cayenne/gen/StringUtils.java ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/StringUtils.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/StringUtils.java new file mode 100644 index 0000000..778a09b --- /dev/null +++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/StringUtils.java @@ -0,0 +1,213 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.gen; + +import org.apache.cayenne.project.validation.NameValidationHelper; +import org.apache.cayenne.util.Util; + +/** + * Methods for mangling strings. + */ +public class StringUtils { + + private static StringUtils sharedInstance; + + public static StringUtils getInstance() { + if (null == sharedInstance) { + sharedInstance = new StringUtils(); + } + + return sharedInstance; + } + + /** + * Prepends underscore to variable name if necessary to remove conflict with reserved + * keywords. + */ + public String formatVariableName(String variableName) { + if (NameValidationHelper.getInstance().isReservedJavaKeyword(variableName)) { + return "_" + variableName; + } + else { + return variableName; + } + } + + /** + * Removes package name, leaving base name. + * + * @since 1.2 + */ + public String stripPackageName(String fullyQualifiedClassName) { + return Util.stripPackageName(fullyQualifiedClassName); + } + + /** + * Removes base name, leaving package name. + * + * @since 1.2 + */ + public String stripClass(String aString) { + if (aString == null || aString.length() == 0) + return aString; + + int lastDot = aString.lastIndexOf('.'); + + if (-1 == lastDot) + return ""; + + return aString.substring(0, lastDot); + } + + /** + * Capitalizes the first letter of the property name. + * + * @since 1.1 + */ + public String capitalized(String name) { + if (name == null || name.length() == 0) + return name; + + char c = Character.toUpperCase(name.charAt(0)); + return (name.length() == 1) ? Character.toString(c) : c + name.substring(1); + } + + /** + * Returns string with lowercased first letter + * + * @since 1.2 + */ + public static String uncapitalized(String aString) { + if (aString == null || aString.length() == 0) + return aString; + + char c = Character.toLowerCase(aString.charAt(0)); + return (aString.length() == 1) ? Character.toString(c) : c + aString.substring(1); + } + + /** + * Converts property name to Java constants naming convention. + * + * @since 1.1 + */ + public String capitalizedAsConstant(String name) { + if (name == null || name.length() == 0) + return name; + + // clear of non-java chars. While the method name implies that a passed identifier + // is pure Java, it is used to build pk columns names and such, so extra safety + // check is a good idea + name = Util.specialCharsToJava(name); + + char charArray[] = name.toCharArray(); + StringBuilder buffer = new StringBuilder(); + + for (int i = 0; i < charArray.length; i++) { + if ((Character.isUpperCase(charArray[i])) && (i != 0)) { + + char prevChar = charArray[i - 1]; + if ((Character.isLowerCase(prevChar))) { + buffer.append("_"); + } + } + + buffer.append(Character.toUpperCase(charArray[i])); + } + + return buffer.toString(); + } + + /** + * Converts entity or property name to a plural form. For example: + * <ul> + * <li>pluralize("Word") == "Words"</li> + * <li>pluralize("Status") == "Statuses"</li> + * <li>pluralize("Index") == "Indexes"</li> + * <li>pluralize("Factory") == "Factories"</li> + * </ul> + * <p> + * As of 3.1 this method is not used in bundled templates, and is present here for + * user templates convenience. + * + * @since 3.1 + */ + public String pluralize(String str) { + if (str == null || str.length() == 0) { + return str; + } + else if (str.endsWith("s") || str.endsWith("x")) { + return str + "es"; + } + else if (str.endsWith("y")) { + return str.substring(0, str.length() - 1) + "ies"; + } + else { + return str + "s"; + } + } + + /** + * <p> + * Strip generic definition from string + * </p> + * <p>For example: List>Integer< == List</p> + * @since 4.0 + */ + public String stripGeneric(String str) { + if(str == null) { + return null; + } + int start = str.indexOf('<'); + if(start == -1) { + return str; + } + int end = str.lastIndexOf('>'); + if(end == -1) { + return str; + } else if(end == str.length() - 1) { + return str.substring(0, start); + } + return str.substring(0, start) + str.substring(end+1); + } + + public String replaceWildcardInStringWithString(String wildcard, String pattern, String replacement) { + if (pattern == null || wildcard == null) { + return pattern; + } + + StringBuilder buffer = new StringBuilder(); + int lastPos = 0; + int wildCardPos = pattern.indexOf(wildcard); + while (wildCardPos != -1) { + if (lastPos != wildCardPos) { + buffer.append(pattern.substring(lastPos, wildCardPos)); + } + buffer.append(replacement); + lastPos += wildCardPos + wildcard.length(); + wildCardPos = pattern.indexOf(wildcard, lastPos); + } + + if (lastPos < pattern.length()) { + buffer.append(pattern.substring(lastPos)); + } + + return buffer.toString(); + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/java/org/apache/cayenne/gen/TemplateType.java ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/TemplateType.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/TemplateType.java new file mode 100644 index 0000000..109627e --- /dev/null +++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/TemplateType.java @@ -0,0 +1,55 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.gen; + +/** + * Defines class generation template types. + * + * @since 3.0 + */ +public enum TemplateType { + + ENTITY_SINGLE_CLASS(false), + + ENTITY_SUPERCLASS(true), + + ENTITY_SUBCLASS(false), + + EMBEDDABLE_SINGLE_CLASS(false), + + EMBEDDABLE_SUPERCLASS(true), + + EMBEDDABLE_SUBCLASS(false), + + DATAMAP_SINGLE_CLASS(false), + + DATAMAP_SUPERCLASS(true), + + DATAMAP_SUBCLASS(false); + + private boolean superclass; + + private TemplateType(boolean superclass) { + this.superclass = superclass; + } + + public boolean isSuperclass() { + return superclass; + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/java/org/apache/cayenne/gen/package.html ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/package.html b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/package.html new file mode 100644 index 0000000..69b8b7d --- /dev/null +++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/package.html @@ -0,0 +1,28 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<html> +<body> +Contains classes that provide Java source generation facility. +Source creation is based on a set of templates parsed +during generation process, using Jakarta Velocity template engine. + +<p><i>For more information see <a href="../../../../../../index.html" +target="_top">Cayenne User Guide.</a></i></p> +</body> +</html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java b/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java new file mode 100644 index 0000000..4d068d8 --- /dev/null +++ b/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorEntityFilterAction.java @@ -0,0 +1,85 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.tools; + +import org.apache.cayenne.dbsync.filter.NameFilter; +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.map.Embeddable; +import org.apache.cayenne.map.ObjEntity; + +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; + +/** + * Performs entity filtering to build a collection of entities that should be used in + * class generation. + * + * @since 3.0 + */ +class CayenneGeneratorEntityFilterAction { + + private NameFilter nameFilter; + private boolean client; + + Collection<Embeddable> getFilteredEmbeddables(DataMap mainDataMap) { + Collection<Embeddable> embeddables = new ArrayList<>(mainDataMap.getEmbeddables()); + + // filter out excluded entities... + Iterator<Embeddable> it = embeddables.iterator(); + + while (it.hasNext()) { + Embeddable e = it.next(); + + // note that unlike entity, embeddable is matched by class name as it doesn't + // have a symbolic name... + if (!nameFilter.isIncluded(e.getClassName())) { + it.remove(); + } + } + + return embeddables; + } + + Collection<ObjEntity> getFilteredEntities(DataMap mainDataMap) + throws MalformedURLException { + + Collection<ObjEntity> entities = new ArrayList<>(mainDataMap.getObjEntities()); + + // filter out excluded entities... + Iterator<ObjEntity> it = entities.iterator(); + while (it.hasNext()) { + ObjEntity e = it.next(); + if (e.isGeneric() || client && !e.isClientAllowed() || !nameFilter.isIncluded(e.getName())) { + it.remove(); + } + } + + return entities; + } + + void setClient(boolean client) { + this.client = client; + } + + public void setNameFilter(NameFilter nameFilter) { + this.nameFilter = nameFilter; + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMapLoaderAction.java ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMapLoaderAction.java b/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMapLoaderAction.java new file mode 100644 index 0000000..1a0a098 --- /dev/null +++ b/cayenne-cgen/src/main/java/org/apache/cayenne/tools/CayenneGeneratorMapLoaderAction.java @@ -0,0 +1,78 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ +package org.apache.cayenne.tools; + +import java.io.File; +import java.net.MalformedURLException; + +import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.map.EntityResolver; +import org.apache.cayenne.map.MapLoader; +import org.xml.sax.InputSource; + +/** + * Loads a DataMap and a shared entity namespace. + * + * @since 3.0 + */ +class CayenneGeneratorMapLoaderAction { + + private File mainDataMapFile; + private File[] additionalDataMapFiles; + private DataMap mainDataMap; + + DataMap getMainDataMap() throws MalformedURLException { + if (mainDataMap == null) { + MapLoader mapLoader = new MapLoader(); + + DataMap mainDataMap = loadDataMap(mapLoader, mainDataMapFile); + + if (additionalDataMapFiles != null) { + + EntityResolver entityResolver = new EntityResolver(); + entityResolver.addDataMap(mainDataMap); + mainDataMap.setNamespace(entityResolver); + + for (File additionalDataMapFile : additionalDataMapFiles) { + + DataMap dataMap = loadDataMap(mapLoader, additionalDataMapFile); + entityResolver.addDataMap(dataMap); + dataMap.setNamespace(entityResolver); + } + } + + this.mainDataMap = mainDataMap; + } + + return mainDataMap; + } + + protected DataMap loadDataMap(MapLoader mapLoader, File dataMapFile) throws MalformedURLException { + InputSource in = new InputSource(dataMapFile.toURI().toURL().toString()); + return mapLoader.loadDataMap(in); + } + + void setMainDataMapFile(File mainDataMapFile) { + this.mainDataMapFile = mainDataMapFile; + } + + void setAdditionalDataMapFiles(File[] additionalDataMapFiles) { + this.additionalDataMapFiles = additionalDataMapFiles; + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/resources/templates/v1_2/client-datamap-singleclass.vm ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/resources/templates/v1_2/client-datamap-singleclass.vm b/cayenne-cgen/src/main/resources/templates/v1_2/client-datamap-singleclass.vm new file mode 100644 index 0000000..d0c7f6c --- /dev/null +++ b/cayenne-cgen/src/main/resources/templates/v1_2/client-datamap-singleclass.vm @@ -0,0 +1,96 @@ +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you under the Apache License, Version 2.0 (the +## "License"); you may not use this file except in compliance +## with the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, +## software distributed under the License is distributed on an +## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +## KIND, either express or implied. See the License for the +## specific language governing permissions and limitations +## under the License. +## +##Terminology: +## Base class - super superclass of entity, ie, org.apache.cayenne.CayenneDataObject or MyBaseClass +## Super class - superclass of entity, ie, org.apache.cayenne.art.auto._Artist +## Sub class - class of entity, ie, org.apache.cayenne.art.Artist +## +## Classes available in template +## object (duplicated as 'objEntity') - the ObjEntity class: See org.apache.cayenne.map.ObjectEntity +## stringUtils - class for string "helper" functions: See org.apache.cayenne.gen.StringUtils +## dataMapUtils - class for query "helper" functions: See org.apache.cayenne.gen.DataMapUtils +## importUtils - class for import statement management: See org.apache.cayenne.gen.ImportUtils +## superClassName +## superPackageName +## subClassName +## subPackageName +## baseClassName +## basePackageName +## +## +${importUtils.setPackage($subPackageName)}## +${importUtils.addReservedType("${subPackageName}.${subClassName}")}## +${importUtils.addType("${basePackageName}.${baseClassName}")}## +${importUtils.addType('java.util.List')} +${importUtils.addType('java.util.Map')} +${importUtils.addType('java.util.HashMap')} +${importUtils.addType('org.apache.cayenne.ObjectContext')} +#foreach( $selectQuery in ${object.SelectQueries}) +${importUtils.addType(${selectQuery.Root.ClassName})} +#foreach( $parameter in ${dataMapUtils.getParameterNames(${selectQuery})}) +${importUtils.addType(${dataMapUtils.getParameterType(${selectQuery}, ${parameter})})} +#end +#end +${importUtils.generate()} + +/** + * This class was generated by Cayenne. + * It is probably a good idea to avoid changing this class manually, + * since it may be overwritten next time code is regenerated. + * If you need to make any customizations, please use subclass. + */ +public class ${subClassName} { +#if( ${object.hasQueryNames()}) +#foreach( $qname in ${object.QueryNames}) + + public static final String ${stringUtils.capitalizedAsConstant($qname)}_QUERYNAME = "$qname"; +#end +#end + +private static ${subClassName} instance; + + private ${subClassName}() {} + + public ${subClassName} getInstance() { + if( instance == null) { + instance = new ${subClassName}(); + } + return instance; + } + +#foreach( $selectQuery in ${object.SelectQueries}) + public List<${stringUtils.stripPackageName($selectQuery.Root.ClassName)}> perform${dataMapUtils.getQueryMethodName(${selectQuery})}(ObjectContext context #foreach( $parameter in ${dataMapUtils.getParameterNames(${selectQuery})}), ${stringUtils.stripPackageName(${dataMapUtils.getParameterType(${selectQuery}, ${parameter})})} ${parameter} #end) { + #if(${dataMapUtils.hasParameters($selectQuery)}) + String[] parameters = new String[] { + #foreach( $parameter in ${dataMapUtils.getParameterNames(${selectQuery})}) + "${parameter}", + #end + }; + + Object[] values = new Object[] { + #foreach( $parameter in ${dataMapUtils.getParameterNames(${selectQuery})}) + ${parameter}, + #end + }; + #end + + NamedQuery query = new NamedQuery("${selectQuery.Name}"#if(${dataMapUtils.hasParameters($selectQuery)}), parameters, values#end); + return context.performQuery(query); + } +#end +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/resources/templates/v1_2/client-datamap-subclass.vm ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/resources/templates/v1_2/client-datamap-subclass.vm b/cayenne-cgen/src/main/resources/templates/v1_2/client-datamap-subclass.vm new file mode 100644 index 0000000..f5e0474 --- /dev/null +++ b/cayenne-cgen/src/main/resources/templates/v1_2/client-datamap-subclass.vm @@ -0,0 +1,47 @@ +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you under the Apache License, Version 2.0 (the +## "License"); you may not use this file except in compliance +## with the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, +## software distributed under the License is distributed on an +## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +## KIND, either express or implied. See the License for the +## specific language governing permissions and limitations +## under the License. +## +##Terminology: +## Base class - super superclass of entity, ie, org.apache.cayenne.CayenneDataObject or MyBaseClass +## Super class - superclass of entity, ie, org.apache.cayenne.art.auto._Artist +## Sub class - class of entity, ie, org.apache.cayenne.art.Artist +## +## Classes available in template +## stringUtils - class for string "helper" functions: See org.apache.cayenne.gen.StringUtils +## dataMapUtils - class for query "helper" functions: See org.apache.cayenne.gen.dataMapUtils +## importUtils - class for import statement management: See org.apache.cayenne.gen.ImportUtils +## +## +${importUtils.setPackage($subPackageName)}## +${importUtils.addReservedType("${subPackageName}.${subClassName}")}## +${importUtils.addType("${superPackageName}.${superClassName}")}## +${importUtils.generate()} + +public class ${subClassName} extends ${superClassName} { + + private static ${subClassName} instance; + + private ${subClassName}() {} + + public static ${subClassName} getInstance() { + if(instance == null) { + instance = new ${subClassName}(); + } + + return instance; + } +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/resources/templates/v1_2/client-datamap-superclass.vm ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/resources/templates/v1_2/client-datamap-superclass.vm b/cayenne-cgen/src/main/resources/templates/v1_2/client-datamap-superclass.vm new file mode 100644 index 0000000..c196301 --- /dev/null +++ b/cayenne-cgen/src/main/resources/templates/v1_2/client-datamap-superclass.vm @@ -0,0 +1,83 @@ +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you under the Apache License, Version 2.0 (the +## "License"); you may not use this file except in compliance +## with the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, +## software distributed under the License is distributed on an +## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +## KIND, either express or implied. See the License for the +## specific language governing permissions and limitations +## under the License. +## +##Terminology: +## Base class - super superclass of entity, ie, org.apache.cayenne.CayenneDataObject or MyBaseClass +## Super class - superclass of entity, ie, org.apache.cayenne.art.auto._Artist +## Sub class - class of entity, ie, org.apache.cayenne.art.Artist +## +## Classes available in template +## stringUtils - class for string "helper" functions: See org.apache.cayenne.gen.StringUtils +## dataMapUtils - class for query "helper" functions: See org.apache.cayenne.gen.DataMapUtils +## importUtils - class for import statement management: See org.apache.cayenne.gen.ImportUtils +## superClassName +## superPackageName +## subClassName +## subPackageName +## baseClassName +## basePackageName +## +${importUtils.setPackage($superPackageName)}## +#if(${superPackageName})${importUtils.addReservedType("${superPackageName}.${superClassName}")}#end## +#if(${basePackageName})${importUtils.addType("${basePackageName}.${baseClassName}")}#end## +#if( ${object.hasSelectQueries()} ) +${importUtils.addType('java.util.List')}## +${importUtils.addType('org.apache.cayenne.ObjectContext')}## +${importUtils.addType('org.apache.cayenne.query.NamedQuery')}## +#foreach( $selectQuery in ${object.SelectQueries}) +${importUtils.addType(${selectQuery.Root.ClientClassName})}## +#foreach( $parameter in ${dataMapUtils.getParameterNames(${selectQuery})}) +${importUtils.addType(${dataMapUtils.getParameterType(${selectQuery}, ${parameter})})}## +#end +#end +#end +${importUtils.generate()} + +/** + * This class was generated by Cayenne. + * It is probably a good idea to avoid changing this class manually, + * since it may be overwritten next time code is regenerated. + * If you need to make any customizations, please use subclass. + */ +public class ${superClassName} { +#if( ${object.hasQueryNames()}) +#foreach( $qname in ${object.QueryNames}) + + public static final String ${stringUtils.capitalizedAsConstant($qname)}_QUERYNAME = "$qname"; +#end +#end +#foreach( $selectQuery in ${object.SelectQueries}) + + public List<${stringUtils.stripPackageName($selectQuery.Root.ClientClassName)}> perform${dataMapUtils.getQueryMethodName(${selectQuery})}(ObjectContext context #foreach( $parameter in ${dataMapUtils.getParameterNames(${selectQuery})}), ${stringUtils.stripPackageName(${dataMapUtils.getParameterType(${selectQuery}, ${parameter})})} ${parameter}#end) { +#if(${dataMapUtils.hasParameters($selectQuery)}) + String[] parameters = { +#foreach( $parameter in ${dataMapUtils.getParameterNames(${selectQuery})}) + "${parameter}", +#end + }; + + Object[] values = { +#foreach( $parameter in ${dataMapUtils.getParameterNames(${selectQuery})}) + ${parameter}, +#end + }; + +#end + return context.performQuery(new NamedQuery("${selectQuery.Name}"#if(${dataMapUtils.hasParameters($selectQuery)}), parameters, values#end)); + } +#end +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/resources/templates/v1_2/client-subclass.vm ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/resources/templates/v1_2/client-subclass.vm b/cayenne-cgen/src/main/resources/templates/v1_2/client-subclass.vm new file mode 100644 index 0000000..d28de85 --- /dev/null +++ b/cayenne-cgen/src/main/resources/templates/v1_2/client-subclass.vm @@ -0,0 +1,57 @@ +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you under the Apache License, Version 2.0 (the +## "License"); you may not use this file except in compliance +## with the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, +## software distributed under the License is distributed on an +## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +## KIND, either express or implied. See the License for the +## specific language governing permissions and limitations +## under the License. +## +## A default Cayenne template for a client-side subclass in a generated subclass/superclass pair. +## +## Terminology: +## Base class - super superclass of entity, ie, org.apache.cayenne.CayenneDataObject or MyBaseClass +## Super class - superclass of entity, ie, org.apache.cayenne.art.auto._Artist +## Sub class - class of entity, ie, org.apache.cayenne.art.Artist +## +## Classes available in template +## object (duplicated as 'objEntity') - the ObjEntity class: See org.apache.cayenne.map.ObjectEntity +## stringUtils - class for string "helper" functions: See org.apache.cayenne.gen.StringUtils +## entityUtils - class for entity "helper" functions: See org.apache.cayenne.gen.EntityUtils +## importUtils - class for import statement management: See org.apache.cayenne.gen.ImportUtils +## superClassName +## superPackageName +## subClassName +## subPackageName +## baseClassName +## basePackageName +## +${importUtils.setPackage($subPackageName)}## +${importUtils.addReservedType("${$subPackageName}.${subClassName}")}## +${importUtils.addType("${superPackageName}.${superClassName}")}## +${importUtils.generate()} + +/** + * A persistent class mapped as "${object.name}" Cayenne entity. + */ +public#if("true" == "${object.getIsAbstract()}") abstract#end class ${subClassName} extends ${superClassName} { + + private static final long serialVersionUID = 1L; + +##callback methods +#foreach( $cbname in ${entityUtils.callbackNames}) + @Override + protected void ${cbname}() { + //TODO: Implement ${cbname} + } + +#end +} http://git-wip-us.apache.org/repos/asf/cayenne/blob/c63b6be2/cayenne-cgen/src/main/resources/templates/v1_2/client-superclass.vm ---------------------------------------------------------------------- diff --git a/cayenne-cgen/src/main/resources/templates/v1_2/client-superclass.vm b/cayenne-cgen/src/main/resources/templates/v1_2/client-superclass.vm new file mode 100644 index 0000000..f8c9cbe --- /dev/null +++ b/cayenne-cgen/src/main/resources/templates/v1_2/client-superclass.vm @@ -0,0 +1,248 @@ +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you under the Apache License, Version 2.0 (the +## "License"); you may not use this file except in compliance +## with the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, +## software distributed under the License is distributed on an +## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +## KIND, either express or implied. See the License for the +## specific language governing permissions and limitations +## under the License. +## +##Terminology: +## Base class - super superclass of entity, ie, org.apache.cayenne.PersistentObject or MyBaseClass +## Super class - superclass of entity, ie, org.apache.cayenne.art.auto._Artist +## Sub class - class of entity, ie, org.apache.cayenne.art.Artist +## +## Classes available in template +## object (duplicated as 'objEntity') - the ObjEntity class: See org.apache.cayenne.map.ObjectEntity +## stringUtils - class for string "helper" functions: See org.apache.cayenne.gen.StringUtils +## entityUtils - class for entity "helper" functions: See org.apache.cayenne.gen.EntityUtils +## importUtils - class for import statement management: See org.apache.cayenne.gen.ImportUtils +## superClassName +## superPackageName +## subClassName +## subPackageName +## baseClassName +## basePackageName +## +## +${importUtils.setPackage($superPackageName)}## +${importUtils.addReservedType("${$superPackageName}.${superClassName}")}## +${importUtils.addType("${basePackageName}.${baseClassName}")}## +#if((${object.DeclaredAttributes} && !${object.DeclaredAttributes.isEmpty()}) || (${object.DeclaredRelationships} && !${object.DeclaredRelationships.isEmpty()})) +${importUtils.addType('org.apache.cayenne.exp.Property')}## +#end +#foreach( $attr in ${object.DeclaredAttributes} ) +$importUtils.addType(${attr.Type})## +#end +#foreach( $rel in ${object.DeclaredRelationships} ) +$importUtils.addType(${rel.TargetEntity.ClientClassName})## +#if(${rel.CollectionType}) +$importUtils.addType(${rel.CollectionType})## +#end +#end +#if( ${entityUtils.hasToOneDeclaredRelationships()} ) +${importUtils.addType('org.apache.cayenne.ValueHolder')}## +${importUtils.addType('org.apache.cayenne.util.PersistentObjectHolder')}## +#end +#if( ${entityUtils.hasToManyDeclaredRelationships()} ) +${importUtils.addType('org.apache.cayenne.util.PersistentObjectList')}## +#end +${importUtils.generate()} + +/** + * A generated persistent class mapped as "${object.name}" Cayenne entity. It is a good idea to + * avoid changing this class manually, since it will be overwritten next time code is + * regenerated. If you need to make any customizations, put them in a subclass. + */ +public abstract class ${superClassName} extends ${baseClassName} { + +## Create ivars names +#if( $createPropertyNames ) +#foreach( $attr in ${object.DeclaredAttributes} ) + public static final String ${stringUtils.capitalizedAsConstant($attr.Name)}_PROPERTY = "${attr.Name}"; +#end +#foreach( $rel in ${object.DeclaredRelationships} ) + public static final String ${stringUtils.capitalizedAsConstant($rel.Name)}_PROPERTY = "${rel.Name}"; +#end + +#end +## Create Properties +#foreach( $attr in ${object.DeclaredAttributes} ) + #set ( $type = "$importUtils.formatJavaType(${attr.Type}, false)" ) + public static final Property<$type> ${stringUtils.capitalizedAsConstant($attr.Name)} = Property.create("${attr.Name}", ${stringUtils.stripGeneric($type)}.class); +#end +#foreach( $rel in ${object.DeclaredRelationships} ) +#if( $rel.ToMany ) +#if ( ${rel.CollectionType} == "java.util.Map") + #set( $type = "$importUtils.formatJavaType($rel.CollectionType)<$importUtils.formatJavaType($entityUtils.getMapKeyType($rel)), $importUtils.formatJavaType($rel.TargetEntity.ClientClassName)>" ) + public static final Property<$type> ${stringUtils.capitalizedAsConstant($rel.Name)} = Property.create("${rel.Name}", ${stringUtils.stripGeneric($type)}.class); +#else + #set( $type = "$importUtils.formatJavaType($rel.CollectionType)<$importUtils.formatJavaType($rel.TargetEntity.ClientClassName)>" ) + public static final Property<$type> ${stringUtils.capitalizedAsConstant($rel.Name)} = Property.create("${rel.Name}", ${stringUtils.stripGeneric($type)}.class); +#end +#else + #set( $type = "$importUtils.formatJavaType(${rel.TargetEntity.ClassName})" ) + public static final Property<$type> ${stringUtils.capitalizedAsConstant($rel.Name)} = Property.create("${rel.Name}", ${stringUtils.stripGeneric($type)}.class); +#end +#end + +## Create ivars +#foreach( $attr in ${object.DeclaredAttributes} ) + protected $importUtils.formatJavaType(${attr.Type}) ${attr.Name}; +#end +#foreach( $rel in ${object.DeclaredRelationships} ) +#if( $rel.ToMany ) +#if ( ${rel.CollectionType} == "java.util.Map") + protected $importUtils.formatJavaType($rel.CollectionType)<$importUtils.formatJavaType($entityUtils.getMapKeyType($rel)), $importUtils.formatJavaType($rel.TargetEntity.ClientClassName)> ${rel.Name}; +#else + protected $importUtils.formatJavaType($rel.CollectionType)<$importUtils.formatJavaType($rel.TargetEntity.ClientClassName)> ${rel.Name}; +#end +#else + protected ValueHolder ${rel.Name}; +#end +#end + +## Create attribute set/get methods +#foreach( $attr in ${object.DeclaredAttributes} ) +#if ( $importUtils.isBoolean(${attr.Type}) ) + public boolean is${stringUtils.capitalized($attr.Name)}() { + if(objectContext != null) { + objectContext.prepareForAccess(this, "${attr.Name}", false); + } + + return ${attr.Name}; + } +#else + public $importUtils.formatJavaType(${attr.Type}) get${stringUtils.capitalized($attr.Name)}() { + if(objectContext != null) { + objectContext.prepareForAccess(this, "${attr.Name}", false); + } + + return ${attr.Name}; + } +#end +#if ("true" != "${object.isReadOnly()}") + public void set${stringUtils.capitalized($attr.Name)}($importUtils.formatJavaType(${attr.Type}) $stringUtils.formatVariableName(${attr.Name})) { + if(objectContext != null) { + objectContext.prepareForAccess(this, "${attr.Name}", false); + } + + Object oldValue = this.${stringUtils.formatVariableName($attr.Name)}; + // notify objectContext about simple property change + if(objectContext != null) { + objectContext.propertyChanged(this, "${attr.Name}", oldValue, $stringUtils.formatVariableName(${attr.Name})); + } + + this.${stringUtils.formatVariableName($attr.Name)} = ${stringUtils.formatVariableName($attr.Name)}; + } +#end + +#end +## +## +## Create list add/remove/get methods +#foreach( $rel in ${object.DeclaredRelationships} ) +#if( $rel.ToMany ) +#if ( ${rel.CollectionType} == "java.util.Map") + public $importUtils.formatJavaType($rel.CollectionType)<$importUtils.formatJavaType($entityUtils.getMapKeyType($rel)), $importUtils.formatJavaType($rel.TargetEntity.ClientClassName)> get${stringUtils.capitalized($rel.Name)}() { +#else + public $importUtils.formatJavaType($rel.CollectionType)<$importUtils.formatJavaType($rel.TargetEntity.ClientClassName)> get${stringUtils.capitalized($rel.Name)}() { +#end + if(objectContext != null) { + objectContext.prepareForAccess(this, "${rel.Name}", true); + } else if (this.$rel.Name == null) { +#if ( ${rel.CollectionType} == "java.util.Map") + throw new RuntimeException("Map relationships cannot be accessed for transient objects"); +#else + this.$rel.Name = new PersistentObjectList(this, "${rel.Name}"); +#end + } + + return ${rel.Name}; + } +#if ( ! $rel.ReadOnly ) +#if ( ${rel.CollectionType} == "java.util.Map") + public void addTo${stringUtils.capitalized($rel.Name)}($importUtils.formatJavaType(${rel.TargetEntity.ClientClassName}) object) { + if(objectContext != null) { + objectContext.prepareForAccess(this, "${rel.Name}", true); + } else if (this.$rel.Name == null) { + throw new RuntimeException("Map relationships cannot be accessed for transient objects"); + } + + this.${rel.Name}.put(getMapKey("${rel.Name}", object), object); + } + public void removeFrom${stringUtils.capitalized($rel.Name)}($importUtils.formatJavaType(${rel.TargetEntity.ClientClassName}) object) { + if(objectContext != null) { + objectContext.prepareForAccess(this, "${rel.Name}", true); + } else if (this.$rel.Name == null) { + throw new RuntimeException("Map relationships cannot be accessed for transient objects"); + } + + this.${rel.Name}.remove(getMapKey("${rel.Name}", object)); + } +#else + public void addTo${stringUtils.capitalized($rel.Name)}($importUtils.formatJavaType(${rel.TargetEntity.ClientClassName}) object) { + if(objectContext != null) { + objectContext.prepareForAccess(this, "${rel.Name}", true); + } else if (this.$rel.Name == null) { + this.$rel.Name = new PersistentObjectList(this, "${rel.Name}"); + } + + this.${rel.Name}.add(object); + } + public void removeFrom${stringUtils.capitalized($rel.Name)}($importUtils.formatJavaType(${rel.TargetEntity.ClientClassName}) object) { + if(objectContext != null) { + objectContext.prepareForAccess(this, "${rel.Name}", true); + } else if (this.$rel.Name == null) { + this.$rel.Name = new PersistentObjectList(this, "${rel.Name}"); + } + + this.${rel.Name}.remove(object); + } +#end +#end +#else + public $importUtils.formatJavaType(${rel.TargetEntity.ClientClassName}) get${stringUtils.capitalized($rel.Name)}() { + if(objectContext != null) { + objectContext.prepareForAccess(this, "${rel.Name}", true); + } else if (this.$rel.Name == null) { + this.$rel.Name = new PersistentObjectHolder(this, "$rel.Name"); + } + + return ($importUtils.formatJavaType(${rel.TargetEntity.ClientClassName})) ${rel.Name}.getValue(); + } +#if ( !${object.isReadOnly()} && !$rel.ReadOnly ) + public void set${stringUtils.capitalized($rel.Name)}(${importUtils.formatJavaType($rel.TargetEntity.ClientClassName)} $stringUtils.formatVariableName(${rel.Name})) { + if(objectContext != null) { + objectContext.prepareForAccess(this, "${rel.Name}", true); + } else if (this.$rel.Name == null) { + this.$rel.Name = new PersistentObjectHolder(this, "$rel.Name"); + } + + // note how we notify ObjectContext of change BEFORE the object is actually + // changed... this is needed to take a valid current snapshot + Object oldValue = this.${rel.Name}.getValueDirectly(); + if (objectContext != null) { + objectContext.propertyChanged(this, "$rel.Name", oldValue, $stringUtils.formatVariableName(${rel.Name})); + } + + this.${stringUtils.formatVariableName($rel.Name)}.setValue(${stringUtils.formatVariableName($rel.Name)}); + } +#end +#end + +#end +##callback methods +#foreach( $cbname in ${entityUtils.callbackNames}) + protected abstract void ${cbname}(); + +#end +}