blob: 31cb51cc7823c68fd0e7520a43a2978a538b854c [file] [log] [blame]
/*
* 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.ofbiz.entity.model;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.CopyOnWriteArrayList;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
import org.ofbiz.base.util.ObjectType;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilPlist;
import org.ofbiz.base.util.UtilTimer;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.base.util.UtilXml;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntity;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.config.model.Datasource;
import org.ofbiz.entity.config.model.EntityConfig;
import org.ofbiz.entity.jdbc.DatabaseUtil;
import org.ofbiz.entity.model.ModelIndex.Field;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* An object that models the <code>&lt;entity&gt;</code> element.
*
*/
public class ModelEntity implements Comparable<ModelEntity>, Serializable {
public static final String module = ModelEntity.class.getName();
/** The name of the time stamp field for locking/synchronization */
public static final String STAMP_FIELD = "lastUpdatedStamp";
public static final String STAMP_TX_FIELD = "lastUpdatedTxStamp";
public static final String CREATE_STAMP_FIELD = "createdStamp";
public static final String CREATE_STAMP_TX_FIELD = "createdTxStamp";
private ModelInfo modelInfo;
/** The ModelReader that created this Entity */
private final ModelReader modelReader;
/** The entity-name of the Entity */
protected String entityName = "";
/** The table-name of the Entity */
protected String tableName = "";
/** The package-name of the Entity */
protected String packageName = "";
/** The entity-name of the Entity that this Entity is dependent on, if empty then no dependency */
protected String dependentOn = "";
/** The sequence-bank-size of the Entity */
protected Integer sequenceBankSize = null;
/** Synchronization object used to control access to the ModelField collection objects.
* A single lock is used for all ModelField collections so collection updates are atomic. */
private final Object fieldsLock = new Object();
/** Model fields in the order they were defined. This list duplicates the values in fieldsMap, but
* we must keep the list in its original sequence for SQL DISTINCT operations to work properly. */
private final List<ModelField> fieldsList = new ArrayList<ModelField>();
private final Map<String, ModelField> fieldsMap = new HashMap<String, ModelField>();
/** A List of the Field objects for the Entity, one for each Primary Key */
private final ArrayList<ModelField> pks = new ArrayList<ModelField>();
/** A List of the Field objects for the Entity, one for each NON Primary Key */
private final ArrayList<ModelField> nopks = new ArrayList<ModelField>();
/** relations defining relationships between this entity and other entities */
protected CopyOnWriteArrayList<ModelRelation> relations = new CopyOnWriteArrayList<ModelRelation>();
/** indexes on fields/columns in this entity */
private CopyOnWriteArrayList<ModelIndex> indexes = new CopyOnWriteArrayList<ModelIndex>();
/** The reference of the dependentOn entity model */
protected ModelEntity specializationOfModelEntity = null;
/** The list of entities that are specialization of on this entity */
protected Map<String, ModelEntity> specializedEntities = new HashMap<String, ModelEntity>();
/** map of ModelViewEntities that references this model */
private final Set<String> viewEntities = new HashSet<String>();
/** An indicator to specify if this entity requires locking for updates */
protected boolean doLock = false;
/** Can be used to disable automatically creating update stamp fields and populating them on inserts and updates */
protected boolean noAutoStamp = false;
/** An indicator to specify if this entity is never cached.
* If true causes the delegator to not clear caches on write and to not get
* from cache on read showing a warning messages to that effect
*/
protected boolean neverCache = false;
protected boolean neverCheck = false;
protected boolean autoClearCache = true;
/** The location of this entity's definition */
protected String location = "";
// ===== CONSTRUCTORS =====
/** Default Constructor */
public ModelEntity() {
this.modelReader = null;
this.modelInfo = ModelInfo.DEFAULT;
}
protected ModelEntity(ModelReader reader) {
this.modelReader = reader;
this.modelInfo = ModelInfo.DEFAULT;
}
protected ModelEntity(ModelReader reader, ModelInfo modelInfo) {
this.modelReader = reader;
this.modelInfo = modelInfo;
}
/** XML Constructor */
protected ModelEntity(ModelReader reader, Element entityElement, ModelInfo modelInfo) {
this.modelReader = reader;
this.modelInfo = ModelInfo.createFromAttributes(modelInfo, entityElement);
}
/** XML Constructor */
public ModelEntity(ModelReader reader, Element entityElement, UtilTimer utilTimer, ModelInfo modelInfo) {
this.modelReader = reader;
this.modelInfo = ModelInfo.createFromAttributes(modelInfo, entityElement);
if (utilTimer != null) utilTimer.timerString(" createModelEntity: before general/basic info");
this.populateBasicInfo(entityElement);
if (utilTimer != null) utilTimer.timerString(" createModelEntity: before prim-keys");
List<String> pkFieldNames = new ArrayList<String>();
for (Element pkElement: UtilXml.childElementList(entityElement, "prim-key")) {
pkFieldNames.add(pkElement.getAttribute("field").intern());
}
if (utilTimer != null) utilTimer.timerString(" createModelEntity: before fields");
for (Element fieldElement: UtilXml.childElementList(entityElement, "field")) {
String fieldName = UtilXml.checkEmpty(fieldElement.getAttribute("name")).intern();
boolean isPk = pkFieldNames.contains(fieldName);
ModelField field = ModelField.create(this, fieldElement, isPk);
internalAddField(field, pkFieldNames);
}
// if applicable automatically add the STAMP_FIELD and STAMP_TX_FIELD fields
if ((this.doLock || !this.noAutoStamp) && !fieldsMap.containsKey(STAMP_FIELD)) {
ModelField newField = ModelField.create(this, "", STAMP_FIELD, "date-time", null, null, null, false, false, false, true, false, null);
internalAddField(newField, pkFieldNames);
}
if (!this.noAutoStamp && !fieldsMap.containsKey(STAMP_TX_FIELD)) {
ModelField newField = ModelField.create(this, "", STAMP_TX_FIELD, "date-time", null, null, null, false, false, false, true, false, null);
internalAddField(newField, pkFieldNames);
// also add an index for this field
String indexName = ModelUtil.shortenDbName(this.tableName + "_TXSTMP", 18);
Field indexField = new Field(STAMP_TX_FIELD, null);
ModelIndex txIndex = ModelIndex.create(this, null, indexName, UtilMisc.toList(indexField), false);
indexes.add(txIndex);
}
// if applicable automatically add the CREATE_STAMP_FIELD and CREATE_STAMP_TX_FIELD fields
if ((this.doLock || !this.noAutoStamp) && !fieldsMap.containsKey(CREATE_STAMP_FIELD)) {
ModelField newField = ModelField.create(this, "", CREATE_STAMP_FIELD, "date-time", null, null, null, false, false, false, true, false, null);
internalAddField(newField, pkFieldNames);
}
if (!this.noAutoStamp && !fieldsMap.containsKey(CREATE_STAMP_TX_FIELD)) {
ModelField newField = ModelField.create(this, "", CREATE_STAMP_TX_FIELD, "date-time", null, null, null, false, false, false, true, false, null);
internalAddField(newField, pkFieldNames);
// also add an index for this field
String indexName = ModelUtil.shortenDbName(this.tableName + "_TXCRTS", 18);
Field indexField = new Field(CREATE_STAMP_TX_FIELD, null);
ModelIndex txIndex = ModelIndex.create(this, null, indexName, UtilMisc.toList(indexField), false);
indexes.add(txIndex);
}
// Must be done last to preserve pk field sequence
for (String pkFieldName : pkFieldNames) {
ModelField pkField = fieldsMap.get(pkFieldName);
if (pkField == null) {
Debug.logWarning("Error in entity definition - primary key is invalid for entity " + this.getEntityName(), module);
} else {
pks.add(pkField);
}
}
pks.trimToSize();
nopks.trimToSize();
reader.incrementFieldCount(fieldsMap.size());
if (utilTimer != null) utilTimer.timerString(" createModelEntity: before relations");
this.populateRelated(reader, entityElement);
this.populateIndexes(entityElement);
}
/** DB Names Constructor */
public ModelEntity(String tableName, Map<String, DatabaseUtil.ColumnCheckInfo> colMap, ModelFieldTypeReader modelFieldTypeReader, boolean isCaseSensitive) {
// if there is a dot in the name, remove it and everything before it, should be the schema name
this.modelReader = null;
this.modelInfo = ModelInfo.DEFAULT;
this.tableName = tableName;
int dotIndex = this.tableName.indexOf(".");
if (dotIndex >= 0) {
this.tableName = this.tableName.substring(dotIndex + 1);
}
this.entityName = ModelUtil.dbNameToClassName(this.tableName);
for (Map.Entry<String, DatabaseUtil.ColumnCheckInfo> columnEntry : colMap.entrySet()) {
DatabaseUtil.ColumnCheckInfo ccInfo = columnEntry.getValue();
ModelField newField = ModelField.create(this, ccInfo, modelFieldTypeReader);
addField(newField);
}
}
protected void populateBasicInfo(Element entityElement) {
this.entityName = UtilXml.checkEmpty(entityElement.getAttribute("entity-name")).intern();
this.tableName = UtilXml.checkEmpty(entityElement.getAttribute("table-name"), ModelUtil.javaNameToDbName(this.entityName)).intern();
this.packageName = UtilXml.checkEmpty(entityElement.getAttribute("package-name")).intern();
this.dependentOn = UtilXml.checkEmpty(entityElement.getAttribute("dependent-on")).intern();
this.doLock = UtilXml.checkBoolean(entityElement.getAttribute("enable-lock"), false);
this.noAutoStamp = UtilXml.checkBoolean(entityElement.getAttribute("no-auto-stamp"), false);
this.neverCache = UtilXml.checkBoolean(entityElement.getAttribute("never-cache"), false);
this.neverCheck = UtilXml.checkBoolean(entityElement.getAttribute("never-check"), false);
this.autoClearCache = UtilXml.checkBoolean(entityElement.getAttribute("auto-clear-cache"), true);
String sequenceBankSizeStr = UtilXml.checkEmpty(entityElement.getAttribute("sequence-bank-size"));
if (UtilValidate.isNotEmpty(sequenceBankSizeStr)) {
try {
this.sequenceBankSize = Integer.valueOf(sequenceBankSizeStr);
} catch (NumberFormatException e) {
Debug.logError("Error parsing sequence-bank-size value [" + sequenceBankSizeStr + "] for entity [" + this.entityName + "]", module);
}
}
}
private void internalAddField(ModelField newField, List<String> pkFieldNames) {
if (!newField.getIsPk()) {
this.nopks.add(newField);
}
this.fieldsList.add(newField);
this.fieldsMap.put(newField.getName(), newField);
}
protected void populateRelated(ModelReader reader, Element entityElement) {
List<ModelRelation> tempList = new ArrayList<ModelRelation>(this.relations);
for (Element relationElement: UtilXml.childElementList(entityElement, "relation")) {
ModelRelation relation = reader.createRelation(this, relationElement);
if (relation != null) {
tempList.add(relation);
}
}
this.relations = new CopyOnWriteArrayList<ModelRelation>(tempList);
}
protected void populateIndexes(Element entityElement) {
List<ModelIndex> tempList = new ArrayList<ModelIndex>(this.indexes);
for (Element indexElement: UtilXml.childElementList(entityElement, "index")) {
ModelIndex index = ModelIndex.create(this, indexElement);
tempList.add(index);
}
this.indexes = new CopyOnWriteArrayList<ModelIndex>(tempList);
}
public boolean containsAllPkFieldNames(Set<String> fieldNames) {
Iterator<ModelField> pksIter = this.getPksIterator();
while (pksIter.hasNext()) {
ModelField pkField = pksIter.next();
if (!fieldNames.contains(pkField.getName())) {
return false;
}
}
return true;
}
public void addExtendEntity(ModelReader reader, Element extendEntityElement) {
if (extendEntityElement.hasAttribute("enable-lock")) {
this.doLock = UtilXml.checkBoolean(extendEntityElement.getAttribute("enable-lock"), false);
}
if (extendEntityElement.hasAttribute("no-auto-stamp")) {
this.noAutoStamp = UtilXml.checkBoolean(extendEntityElement.getAttribute("no-auto-stamp"), false);
}
if (extendEntityElement.hasAttribute("auto-clear-cache")) {
this.autoClearCache = UtilXml.checkBoolean(extendEntityElement.getAttribute("auto-clear-cache"), false);
}
if (extendEntityElement.hasAttribute("never-cache")) {
this.neverCache = UtilXml.checkBoolean(extendEntityElement.getAttribute("never-cache"), false);
}
if (extendEntityElement.hasAttribute("sequence-bank-size")) {
String sequenceBankSizeStr = UtilXml.checkEmpty(extendEntityElement.getAttribute("sequence-bank-size"));
if (UtilValidate.isNotEmpty(sequenceBankSizeStr)) {
try {
this.sequenceBankSize = Integer.valueOf(sequenceBankSizeStr);
} catch (NumberFormatException e) {
Debug.logError("Error parsing sequence-bank-size value [" + sequenceBankSizeStr + "] for entity [" + this.entityName + "]", module);
}
}
}
for (Element fieldElement : UtilXml.childElementList(extendEntityElement, "field")) {
ModelField newField = ModelField.create(this, fieldElement, false);
ModelField existingField = this.getField(newField.getName());
if (existingField != null) {
// override the existing field's attributes
// TODO: only overrides of type, colName, description and enable-audit-log are currently supported
String type = existingField.getType();
if (!newField.getType().isEmpty()) {
type = newField.getType();
}
String colName = existingField.getColName();
if (!newField.getColName().isEmpty()) {
colName = newField.getColName();
}
String description = existingField.getDescription();
if (!newField.getDescription().isEmpty()) {
description = newField.getDescription();
}
boolean enableAuditLog = existingField.getEnableAuditLog();
if (UtilValidate.isNotEmpty(fieldElement.getAttribute("enable-audit-log"))) {
enableAuditLog = "true".equals(fieldElement.getAttribute("enable-audit-log"));
}
newField = ModelField.create(this, description, existingField.getName(), type, colName, existingField.getColValue(), existingField.getFieldSet(),
existingField.getIsNotNull(), existingField.getIsPk(), existingField.getEncryptMethod(), existingField.getIsAutoCreatedInternal(),
enableAuditLog, existingField.getValidators());
}
// add to the entity as a new field
synchronized (fieldsLock) {
if (existingField != null) {
this.fieldsList.remove(existingField);
}
this.fieldsList.add(newField);
this.fieldsMap.put(newField.getName(), newField);
if (!newField.getIsPk()) {
if (existingField != null) {
this.nopks.remove(existingField);
}
this.nopks.add(newField);
} else {
if (existingField != null) {
this.pks.remove(existingField);
}
this.pks.add(newField);
}
}
}
this.modelInfo = ModelInfo.createFromAttributes(this.modelInfo, extendEntityElement);
this.populateRelated(reader, extendEntityElement);
this.populateIndexes(extendEntityElement);
this.dependentOn = UtilXml.checkEmpty(extendEntityElement.getAttribute("dependent-on")).intern();
}
// ===== GETTERS/SETTERS =====
public ModelReader getModelReader() {
return modelReader;
}
/** The entity-name of the Entity */
public String getEntityName() {
return this.entityName;
}
public void setEntityName(String entityName) {
this.entityName = entityName;
}
/** The plain table-name of the Entity without a schema name prefix */
public String getPlainTableName() {
return this.tableName;
}
/** The table-name of the Entity including a Schema name if specified in the datasource config */
public String getTableName(String helperName) {
return getTableName(EntityConfig.getDatasource(helperName));
}
/** The table-name of the Entity including a Schema name if specified in the datasource config */
public String getTableName(Datasource datasourceInfo) {
if (datasourceInfo != null && UtilValidate.isNotEmpty(datasourceInfo.getSchemaName())) {
return datasourceInfo.getSchemaName() + "." + this.tableName;
} else {
return this.tableName;
}
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
/** The package-name of the Entity */
public String getPackageName() {
return this.packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
/** The entity-name of the Entity that this Entity is dependent on, if empty then no dependency */
public String getDependentOn() {
return this.dependentOn;
}
public void setDependentOn(String dependentOn) {
this.dependentOn = dependentOn;
}
/** An indicator to specify if this entity is never cached.
* If true causes the delegator to not clear caches on write and to not get
* from cache on read showing a warning messages to that effect
*/
public boolean getNeverCache() {
return this.neverCache;
}
public void setNeverCache(boolean neverCache) {
this.neverCache = neverCache;
}
/**
* An indicator to specific if this entity should ignore automatic DB checks.
* This should be set when the entity is mapped to a database view to prevent
* warnings and attempts to modify the schema.
*/
public boolean getNeverCheck() {
return neverCheck;
}
public void setNeverCheck(boolean neverCheck) {
this.neverCheck = neverCheck;
}
public boolean getAutoClearCache() {
return this.autoClearCache;
}
public void setAutoClearCache(boolean autoClearCache) {
this.autoClearCache = autoClearCache;
}
public boolean getHasFieldWithAuditLog() {
for (ModelField mf : getFieldsUnmodifiable()) {
if (mf.getEnableAuditLog()) {
return true;
}
}
return false;
}
/* Get the location of this entity's definition */
public String getLocation() {
return this.location;
}
/* Set the location of this entity's definition */
public void setLocation(String location) {
this.location = location;
}
/** An indicator to specify if this entity requires locking for updates */
public boolean getDoLock() {
return this.doLock;
}
public void setDoLock(boolean doLock) {
this.doLock = doLock;
}
public boolean lock() {
if (doLock && isField(STAMP_FIELD)) {
return true;
} else {
doLock = false;
return false;
}
}
public Integer getSequenceBankSize() {
return this.sequenceBankSize;
}
public boolean isField(String fieldName) {
if (fieldName == null) return false;
synchronized (fieldsLock) {
return fieldsMap.containsKey(fieldName);
}
}
public boolean areFields(Collection<String> fieldNames) {
if (fieldNames == null) return false;
for (String fieldName: fieldNames) {
if (!isField(fieldName)) return false;
}
return true;
}
public int getPksSize() {
synchronized (fieldsLock) {
return this.pks.size();
}
}
public ModelField getOnlyPk() {
synchronized (fieldsLock) {
if (this.pks.size() == 1) {
return this.pks.get(0);
} else {
throw new IllegalArgumentException("Error in getOnlyPk, the [" + this.getEntityName() + "] entity has more than one pk!");
}
}
}
public Iterator<ModelField> getPksIterator() {
return getPkFields().iterator();
}
public List<ModelField> getPkFields() {
synchronized (fieldsLock) {
return new ArrayList<ModelField>(this.pks);
}
}
public List<ModelField> getPkFieldsUnmodifiable() {
return Collections.unmodifiableList(getPkFields());
}
public String getFirstPkFieldName() {
List<String> pkFieldNames = this.getPkFieldNames();
String idFieldName = null;
if (UtilValidate.isNotEmpty(pkFieldNames)) {
idFieldName = pkFieldNames.get(0);
}
return idFieldName;
}
public int getNopksSize() {
synchronized (fieldsLock) {
return this.nopks.size();
}
}
public Iterator<ModelField> getNopksIterator() {
return getNopksCopy().iterator();
}
public List<ModelField> getNopksCopy() {
synchronized (fieldsLock) {
return new ArrayList<ModelField>(this.nopks);
}
}
public int getFieldsSize() {
synchronized (fieldsLock) {
return this.fieldsList.size();
}
}
public Iterator<ModelField> getFieldsIterator() {
synchronized (fieldsLock) {
List<ModelField> newList = new ArrayList<ModelField>(this.fieldsList);
return newList.iterator();
}
}
public List<ModelField> getFieldsUnmodifiable() {
synchronized (fieldsLock) {
List<ModelField> newList = new ArrayList<ModelField>(this.fieldsList);
return Collections.unmodifiableList(newList);
}
}
/** The col-name of the Field, the alias of the field if this is on a view-entity */
public String getColNameOrAlias(String fieldName) {
ModelField modelField = this.getField(fieldName);
String fieldString = modelField.getColName();
return fieldString;
}
public ModelField getField(String fieldName) {
if (fieldName == null) return null;
synchronized (fieldsLock) {
return fieldsMap.get(fieldName);
}
}
public void addField(ModelField field) {
if (field == null)
return;
synchronized (fieldsLock) {
this.fieldsList.add(field);
fieldsMap.put(field.getName(), field);
if (field.getIsPk()) {
pks.add(field);
} else {
nopks.add(field);
}
}
}
public ModelField removeField(String fieldName) {
if (fieldName == null)
return null;
synchronized (fieldsLock) {
ModelField field = fieldsMap.remove(fieldName);
if (field != null) {
this.fieldsList.remove(field);
if (field.getIsPk()) {
pks.remove(field);
} else {
nopks.remove(field);
}
}
return field;
}
}
public List<String> getAllFieldNames() {
synchronized (fieldsLock) {
List<String> newList = new ArrayList<String>(fieldsMap.size());
newList.addAll(this.fieldsMap.keySet());
return newList;
}
}
public List<String> getPkFieldNames() {
return getFieldNamesFromFieldVector(getPkFields());
}
public List<String> getNoPkFieldNames() {
return getFieldNamesFromFieldVector(getNopksCopy());
}
private List<String> getFieldNamesFromFieldVector(List<ModelField> modelFields) {
List<String> nameList = new ArrayList<String>(modelFields.size());
for (ModelField field: modelFields) {
nameList.add(field.getName());
}
return nameList;
}
/**
* @return field names list, managed by entity-engine
*/
public List<String> getAutomaticFieldNames() {
List<String> nameList = new LinkedList<String>();
if (! this.noAutoStamp) {
nameList.add(STAMP_FIELD);
nameList.add(STAMP_TX_FIELD);
nameList.add(CREATE_STAMP_FIELD);
nameList.add(CREATE_STAMP_TX_FIELD);
}
return nameList;
}
public int getRelationsSize() {
return this.relations.size();
}
public int getRelationsOneSize() {
int numRels = 0;
Iterator<ModelRelation> relationsIter = this.getRelationsIterator();
while (relationsIter.hasNext()) {
ModelRelation modelRelation = relationsIter.next();
if ("one".equals(modelRelation.getType())) {
numRels++;
}
}
return numRels;
}
public ModelRelation getRelation(int index) {
return this.relations.get(index);
}
public Iterator<ModelRelation> getRelationsIterator() {
return this.relations.iterator();
}
public List<ModelRelation> getRelationsList(boolean includeOne, boolean includeOneNoFk, boolean includeMany) {
List<ModelRelation> relationsList = new LinkedList<ModelRelation>();
Iterator<ModelRelation> allIter = this.getRelationsIterator();
while (allIter.hasNext()) {
ModelRelation modelRelation = allIter.next();
if (includeOne && "one".equals(modelRelation.getType())) {
relationsList.add(modelRelation);
} else if (includeOneNoFk && "one-nofk".equals(modelRelation.getType())) {
relationsList.add(modelRelation);
} else if (includeMany && "many".equals(modelRelation.getType())) {
relationsList.add(modelRelation);
}
}
return relationsList;
}
public List<ModelRelation> getRelationsOneList() {
return getRelationsList(true, true, false);
}
public List<ModelRelation> getRelationsManyList() {
return getRelationsList(false, false, true);
}
public ModelRelation getRelation(String relationName) {
if (relationName == null) return null;
for (ModelRelation relation: relations) {
if (relationName.equals(relation.getTitle() + relation.getRelEntityName())) return relation;
}
return null;
}
public void addRelation(ModelRelation relation) {
this.relations.add(relation);
}
public ModelRelation removeRelation(int index) {
return this.relations.remove(index);
}
public int getIndexesSize() {
return this.indexes.size();
}
public ModelIndex getIndex(int index) {
return this.indexes.get(index);
}
public Iterator<ModelIndex> getIndexesIterator() {
return this.indexes.iterator();
}
public ModelIndex getIndex(String indexName) {
if (indexName == null) return null;
for (ModelIndex index: indexes) {
if (indexName.equals(index.getName())) return index;
}
return null;
}
public void addIndex(ModelIndex index) {
this.indexes.add(index);
}
public ModelIndex removeIndex(int index) {
return this.indexes.remove(index);
}
public int getViewEntitiesSize() {
synchronized (viewEntities) {
return this.viewEntities.size();
}
}
public Iterator<String> getViewConvertorsIterator() {
synchronized (viewEntities) {
return new HashSet<String>(this.viewEntities).iterator();
}
}
public void addViewEntity(ModelViewEntity view) {
synchronized (viewEntities) {
this.viewEntities.add(view.getEntityName());
}
}
public List<? extends Map<String, Object>> convertToViewValues(String viewEntityName, GenericEntity entity) {
if (entity == null || entity == GenericEntity.NULL_ENTITY || entity == GenericValue.NULL_VALUE) return UtilMisc.toList(entity);
ModelViewEntity view = (ModelViewEntity) entity.getDelegator().getModelEntity(viewEntityName);
return view.convert(getEntityName(), entity);
}
public boolean removeViewEntity(String viewEntityName) {
synchronized (viewEntities) {
return this.viewEntities.remove(viewEntityName);
}
}
public boolean removeViewEntity(ModelViewEntity viewEntity) {
return removeViewEntity(viewEntity.getEntityName());
}
public String nameString(List<ModelField> flds) {
return nameString(flds, ", ", "");
}
public String nameString(List<ModelField> flds, String separator, String afterLast) {
StringBuilder returnString = new StringBuilder();
if (flds.size() < 1) {
return "";
}
int i = 0;
for (; i < flds.size() - 1; i++) {
returnString.append(flds.get(i).getName());
returnString.append(separator);
}
returnString.append(flds.get(i).getName());
returnString.append(afterLast);
return returnString.toString();
}
public String typeNameString(ModelField... flds) {
return typeNameString(Arrays.asList(flds));
}
public String typeNameString(List<ModelField> flds) {
StringBuilder returnString = new StringBuilder();
if (flds.size() < 1) {
return "";
}
int i = 0;
for (; i < flds.size() - 1; i++) {
ModelField curField = flds.get(i);
returnString.append(curField.getType());
returnString.append(" ");
returnString.append(curField.getName());
returnString.append(", ");
}
ModelField curField = flds.get(i);
returnString.append(curField.getType());
returnString.append(" ");
returnString.append(curField.getName());
return returnString.toString();
}
public String fieldNameString() {
return fieldNameString(", ", "");
}
public String fieldNameString(String separator, String afterLast) {
return nameString(getFieldsUnmodifiable(), separator, afterLast);
}
public String fieldTypeNameString() {
return typeNameString(getFieldsUnmodifiable());
}
public String primKeyClassNameString() {
return typeNameString(getPkFields());
}
public String pkNameString() {
return pkNameString(", ", "");
}
public String pkNameString(String separator, String afterLast) {
return nameString(getPkFields(), separator, afterLast);
}
public String nonPkNullList() {
return fieldsStringList(getFieldsUnmodifiable(), "null", ", ", false, true);
}
@Deprecated
public String fieldsStringList(String eachString, String separator, ModelField... flds) {
return fieldsStringList(Arrays.asList(flds), eachString, separator, false, false);
}
public StringBuilder fieldsStringList(StringBuilder sb, String eachString, String separator, ModelField... flds) {
return fieldsStringList(Arrays.asList(flds), sb, eachString, separator, false, false);
}
@Deprecated
public String fieldsStringList(List<ModelField> flds, String eachString, String separator) {
return fieldsStringList(flds, eachString, separator, false, false);
}
public StringBuilder fieldsStringList(List<ModelField> flds, StringBuilder sb, String eachString, String separator) {
return fieldsStringList(flds, sb, eachString, separator, false, false);
}
@Deprecated
public String fieldsStringList(String eachString, String separator, boolean appendIndex, ModelField... flds) {
return fieldsStringList(Arrays.asList(flds), eachString, separator, appendIndex, false);
}
public StringBuilder fieldsStringList(StringBuilder sb, String eachString, String separator, boolean appendIndex, ModelField... flds) {
return fieldsStringList(Arrays.asList(flds), sb, eachString, separator, appendIndex, false);
}
@Deprecated
public String fieldsStringList(List<ModelField> flds, String eachString, String separator, boolean appendIndex) {
return fieldsStringList(flds, eachString, separator, appendIndex, false);
}
public StringBuilder fieldsStringList(List<ModelField> flds, StringBuilder sb, String eachString, String separator, boolean appendIndex) {
return fieldsStringList(flds, sb, eachString, separator, appendIndex, false);
}
@Deprecated
public String fieldsStringList(String eachString, String separator, boolean appendIndex, boolean onlyNonPK, ModelField... flds) {
return fieldsStringList(Arrays.asList(flds), eachString, separator, appendIndex, onlyNonPK);
}
public StringBuilder fieldsStringList(StringBuilder sb, String eachString, String separator, boolean appendIndex, boolean onlyNonPK, ModelField... flds) {
return fieldsStringList(Arrays.asList(flds), sb, eachString, separator, appendIndex, onlyNonPK);
}
@Deprecated
public String fieldsStringList(List<ModelField> flds, String eachString, String separator, boolean appendIndex, boolean onlyNonPK) {
return fieldsStringList(flds, new StringBuilder(), eachString, separator, appendIndex, onlyNonPK).toString();
}
public StringBuilder fieldsStringList(List<ModelField> flds, StringBuilder sb, String eachString, String separator, boolean appendIndex, boolean onlyNonPK) {
if (flds.size() < 1) {
return sb;
}
int i = 0;
for (; i < flds.size(); i++) {
if (onlyNonPK && flds.get(i).getIsPk()) continue;
sb.append(eachString);
if (appendIndex) sb.append(i + 1);
if (i < flds.size() - 1) sb.append(separator);
}
return sb;
}
@Deprecated
public String colNameString(ModelField... flds) {
return colNameString(new StringBuilder(), "", flds).toString();
}
public StringBuilder colNameString(StringBuilder sb, String prefix, ModelField... flds) {
return colNameString(Arrays.asList(flds), sb, prefix);
}
@Deprecated
public String colNameString(List<ModelField> flds) {
return colNameString(flds, new StringBuilder(), "", ", ", "", false).toString();
}
public StringBuilder colNameString(List<ModelField> flds, StringBuilder sb, String prefix) {
return colNameString(flds, sb, prefix, ", ", "", false);
}
@Deprecated
public String colNameString(String separator, String afterLast, boolean alias, ModelField... flds) {
return colNameString(Arrays.asList(flds), new StringBuilder(), "", separator, afterLast, alias).toString();
}
public StringBuilder colNameString(StringBuilder sb, String prefix, String separator, String afterLast, boolean alias, ModelField... flds) {
return colNameString(Arrays.asList(flds), sb, prefix, separator, afterLast, alias);
}
@Deprecated
public String colNameString(List<ModelField> flds, String separator, String afterLast, boolean alias) {
return colNameString(flds, new StringBuilder(), "", separator, afterLast, alias).toString();
}
public StringBuilder colNameString(List<ModelField> flds, StringBuilder sb, String prefix, String separator, String afterLast, boolean alias) {
if (flds.size() < 1) {
return sb;
}
sb.append(prefix);
Iterator<ModelField> fldsIt = flds.iterator();
while (fldsIt.hasNext()) {
ModelField field = fldsIt.next();
sb.append(field.getColName());
if (fldsIt.hasNext()) {
sb.append(separator);
}
}
sb.append(afterLast);
return sb;
}
public String classNameString(ModelField... flds) {
return classNameString(Arrays.asList(flds));
}
public String classNameString(List<ModelField> flds) {
return classNameString(flds, ", ", "");
}
public String classNameString(String separator, String afterLast, ModelField... flds) {
return classNameString(Arrays.asList(flds), separator, afterLast);
}
public String classNameString(List<ModelField> flds, String separator, String afterLast) {
StringBuilder returnString = new StringBuilder();
if (flds.size() < 1) {
return "";
}
int i = 0;
for (; i < flds.size() - 1; i++) {
returnString.append(ModelUtil.upperFirstChar(flds.get(i).getName()));
returnString.append(separator);
}
returnString.append(ModelUtil.upperFirstChar(flds.get(i).getName()));
returnString.append(afterLast);
return returnString.toString();
}
public String finderQueryString(ModelField... flds) {
return finderQueryString(Arrays.asList(flds));
}
public String finderQueryString(List<ModelField> flds) {
StringBuilder returnString = new StringBuilder();
if (flds.size() < 1) {
return "";
}
int i = 0;
for (; i < flds.size() - 1; i++) {
returnString.append(flds.get(i).getColName());
returnString.append(" like {");
returnString.append(i);
returnString.append("} AND ");
}
returnString.append(flds.get(i).getColName());
returnString.append(" like {");
returnString.append(i);
returnString.append("}");
return returnString.toString();
}
public String httpArgList(ModelField... flds) {
return httpArgList(Arrays.asList(flds));
}
public String httpArgList(List<ModelField> flds) {
StringBuilder returnString = new StringBuilder();
if (flds.size() < 1) {
return "";
}
int i = 0;
for (; i < flds.size() - 1; i++) {
returnString.append("\"");
returnString.append(tableName);
returnString.append("_");
returnString.append(flds.get(i).getColName());
returnString.append("=\" + ");
returnString.append(flds.get(i).getName());
returnString.append(" + \"&\" + ");
}
returnString.append("\"");
returnString.append(tableName);
returnString.append("_");
returnString.append(flds.get(i).getColName());
returnString.append("=\" + ");
returnString.append(flds.get(i).getName());
return returnString.toString();
}
public String httpArgListFromClass(ModelField... flds) {
return httpArgListFromClass(Arrays.asList(flds));
}
public String httpArgListFromClass(List<ModelField> flds) {
StringBuilder returnString = new StringBuilder();
if (flds.size() < 1) {
return "";
}
int i = 0;
for (; i < flds.size() - 1; i++) {
returnString.append("\"");
returnString.append(tableName);
returnString.append("_");
returnString.append(flds.get(i).getColName());
returnString.append("=\" + ");
returnString.append(ModelUtil.lowerFirstChar(entityName));
returnString.append(".get");
returnString.append(ModelUtil.upperFirstChar(flds.get(i).getName()));
returnString.append("() + \"&\" + ");
}
returnString.append("\"");
returnString.append(tableName);
returnString.append("_");
returnString.append(flds.get(i).getColName());
returnString.append("=\" + ");
returnString.append(ModelUtil.lowerFirstChar(entityName));
returnString.append(".get");
returnString.append(ModelUtil.upperFirstChar(flds.get(i).getName()));
returnString.append("()");
return returnString.toString();
}
public String httpArgListFromClass(String entityNameSuffix, ModelField... flds) {
return httpArgListFromClass(Arrays.asList(flds), entityNameSuffix);
}
public String httpArgListFromClass(List<ModelField> flds, String entityNameSuffix) {
StringBuilder returnString = new StringBuilder();
if (flds.size() < 1) {
return "";
}
int i = 0;
for (; i < flds.size() - 1; i++) {
returnString.append("\"");
returnString.append(tableName);
returnString.append("_");
returnString.append(flds.get(i).getColName());
returnString.append("=\" + ");
returnString.append(ModelUtil.lowerFirstChar(entityName));
returnString.append(entityNameSuffix);
returnString.append(".get");
returnString.append(ModelUtil.upperFirstChar(flds.get(i).getName()));
returnString.append("() + \"&\" + ");
}
returnString.append("\"");
returnString.append(tableName);
returnString.append("_");
returnString.append(flds.get(i).getColName());
returnString.append("=\" + ");
returnString.append(ModelUtil.lowerFirstChar(entityName));
returnString.append(entityNameSuffix);
returnString.append(".get");
returnString.append(ModelUtil.upperFirstChar(flds.get(i).getName()));
returnString.append("()");
return returnString.toString();
}
public String httpRelationArgList(ModelRelation relation, ModelField... flds) {
return httpRelationArgList(Arrays.asList(flds), relation);
}
public String httpRelationArgList(List<ModelField> flds, ModelRelation relation) {
StringBuilder returnString = new StringBuilder();
if (flds.size() < 1) {
return "";
}
int i = 0;
for (; i < flds.size() - 1; i++) {
ModelKeyMap keyMap = relation.findKeyMapByRelated(flds.get(i).getName());
if (keyMap != null) {
returnString.append("\"");
returnString.append(tableName);
returnString.append("_");
returnString.append(flds.get(i).getColName());
returnString.append("=\" + ");
returnString.append(ModelUtil.lowerFirstChar(relation.getModelEntity().entityName));
returnString.append(".get");
returnString.append(ModelUtil.upperFirstChar(keyMap.getFieldName()));
returnString.append("() + \"&\" + ");
} else {
Debug.logWarning("-- -- ENTITYGEN ERROR:httpRelationArgList: Related Key in Key Map not found for name: " + flds.get(i).getName() + " related entity: " + relation.getRelEntityName() + " main entity: " + relation.getModelEntity().entityName + " type: " + relation.getType(), module);
}
}
ModelKeyMap keyMap = relation.findKeyMapByRelated(flds.get(i).getName());
if (keyMap != null) {
returnString.append("\"");
returnString.append(tableName);
returnString.append("_");
returnString.append(flds.get(i).getColName());
returnString.append("=\" + ");
returnString.append(ModelUtil.lowerFirstChar(relation.getModelEntity().entityName));
returnString.append(".get");
returnString.append(ModelUtil.upperFirstChar(keyMap.getFieldName()));
returnString.append("()");
} else {
Debug.logWarning("-- -- ENTITYGEN ERROR:httpRelationArgList: Related Key in Key Map not found for name: " + flds.get(i).getName() + " related entity: " + relation.getRelEntityName() + " main entity: " + relation.getModelEntity().entityName + " type: " + relation.getType(), module);
}
return returnString.toString();
}
/*
public String httpRelationArgList(ModelRelation relation) {
String returnString = "";
if (relation.keyMaps.size() < 1) { return ""; }
int i = 0;
for (; i < relation.keyMaps.size() - 1; i++) {
ModelKeyMap keyMap = (ModelKeyMap)relation.keyMaps.get(i);
if (keyMap != null)
returnString = returnString + "\"" + tableName + "_" + keyMap.relColName + "=\" + " + ModelUtil.lowerFirstChar(relation.mainEntity.entityName) + ".get" + ModelUtil.upperFirstChar(keyMap.fieldName) + "() + \"&\" + ";
}
ModelKeyMap keyMap = (ModelKeyMap)relation.keyMaps.get(i);
returnString = returnString + "\"" + tableName + "_" + keyMap.relColName + "=\" + " + ModelUtil.lowerFirstChar(relation.mainEntity.entityName) + ".get" + ModelUtil.upperFirstChar(keyMap.fieldName) + "()";
return returnString;
}
*/
public String typeNameStringRelatedNoMapped(ModelRelation relation, ModelField... flds) {
return typeNameStringRelatedNoMapped(Arrays.asList(flds), relation);
}
public String typeNameStringRelatedNoMapped(List<ModelField> flds, ModelRelation relation) {
StringBuilder returnString = new StringBuilder();
if (flds.size() < 1) {
return "";
}
int i = 0;
if (relation.findKeyMapByRelated(flds.get(i).getName()) == null) {
returnString.append(flds.get(i).getType());
returnString.append(" ");
returnString.append(flds.get(i).getName());
}
i++;
for (; i < flds.size(); i++) {
if (relation.findKeyMapByRelated(flds.get(i).getName()) == null) {
if (returnString.length() > 0) returnString.append(", ");
returnString.append(flds.get(i).getType());
returnString.append(" ");
returnString.append(flds.get(i).getName());
}
}
return returnString.toString();
}
public String typeNameStringRelatedAndMain(ModelRelation relation, ModelField... flds) {
return typeNameStringRelatedAndMain(Arrays.asList(flds), relation);
}
public String typeNameStringRelatedAndMain(List<ModelField> flds, ModelRelation relation) {
StringBuilder returnString = new StringBuilder();
if (flds.size() < 1) {
return "";
}
int i = 0;
for (; i < flds.size() - 1; i++) {
ModelKeyMap keyMap = relation.findKeyMapByRelated(flds.get(i).getName());
if (keyMap != null) {
returnString.append(keyMap.getFieldName());
returnString.append(", ");
} else {
returnString.append(flds.get(i).getName());
returnString.append(", ");
}
}
ModelKeyMap keyMap = relation.findKeyMapByRelated(flds.get(i).getName());
if (keyMap != null) returnString.append(keyMap.getFieldName());
else returnString.append(flds.get(i).getName());
return returnString.toString();
}
public int compareTo(ModelEntity otherModelEntity) {
/* This DOESN'T WORK, so forget it... using two passes
//sort list by fk dependencies
if (this.getEntityName().equals(otherModelEntity.getEntityName())) {
return 0;
}
//look through relations for dependencies from this entity to the other
Iterator relationsIter = this.getRelationsIterator();
while (relationsIter.hasNext()) {
ModelRelation modelRelation = (ModelRelation) relationsIter.next();
if ("one".equals(modelRelation.getType()) && modelRelation.getRelEntityName().equals(otherModelEntity.getEntityName())) {
//this entity is dependent on the other entity, so put that entity earlier in the list
return -1;
}
}
//look through relations for dependencies from the other to this entity
Iterator otherRelationsIter = otherModelEntity.getRelationsIterator();
while (otherRelationsIter.hasNext()) {
ModelRelation modelRelation = (ModelRelation) otherRelationsIter.next();
if ("one".equals(modelRelation.getType()) && modelRelation.getRelEntityName().equals(this.getEntityName())) {
//the other entity is dependent on this entity, so put that entity later in the list
return 1;
}
}
return 0;
*/
return this.getEntityName().compareTo(otherModelEntity.getEntityName());
}
public void convertFieldMapInPlace(Map<String, Object> inContext, Delegator delegator) {
convertFieldMapInPlace(inContext, delegator.getModelFieldTypeReader(this));
}
public void convertFieldMapInPlace(Map<String, Object> inContext, ModelFieldTypeReader modelFieldTypeReader) {
Iterator<ModelField> modelFields = this.getFieldsIterator();
while (modelFields.hasNext()) {
ModelField modelField = modelFields.next();
String fieldName = modelField.getName();
Object oldValue = inContext.get(fieldName);
if (oldValue != null) {
inContext.put(fieldName, this.convertFieldValue(modelField, oldValue, modelFieldTypeReader, inContext));
}
}
}
public Object convertFieldValue(String fieldName, Object value, Delegator delegator) {
ModelField modelField = this.getField(fieldName);
if (modelField == null) {
String errMsg = "Could not convert field value: could not find an entity field for the name: [" + fieldName + "] on the [" + this.getEntityName() + "] entity.";
throw new IllegalArgumentException(errMsg);
}
return convertFieldValue(modelField, value, delegator);
}
public Object convertFieldValue(ModelField modelField, Object value, Delegator delegator) {
if (value == null || value == GenericEntity.NULL_FIELD) {
return null;
}
String fieldJavaType = null;
try {
fieldJavaType = delegator.getEntityFieldType(this, modelField.getType()).getJavaType();
} catch (GenericEntityException e) {
String errMsg = "Could not convert field value: could not find Java type for the field: [" + modelField.getName() + "] on the [" + this.getEntityName() + "] entity: " + e.toString();
Debug.logError(e, errMsg, module);
throw new IllegalArgumentException(errMsg);
}
try {
return ObjectType.simpleTypeConvert(value, fieldJavaType, null, null, false);
} catch (GeneralException e) {
String errMsg = "Could not convert field value for the field: [" + modelField.getName() + "] on the [" + this.getEntityName() + "] entity to the [" + fieldJavaType + "] type for the value [" + value + "]: " + e.toString();
Debug.logError(e, errMsg, module);
throw new IllegalArgumentException(errMsg);
}
}
/** Convert a field value from one Java data type to another. This is the preferred method -
* which takes into consideration the user's locale and time zone (for conversions that
* require them).
* @return the converted value
*/
public Object convertFieldValue(ModelField modelField, Object value, Delegator delegator, Map<String, ? extends Object> context) {
ModelFieldTypeReader modelFieldTypeReader = delegator.getModelFieldTypeReader(this);
return this.convertFieldValue(modelField, value, modelFieldTypeReader, context);
}
/** Convert a field value from one Java data type to another. This is the preferred method -
* which takes into consideration the user's locale and time zone (for conversions that
* require them).
* @return the converted value
*/
public Object convertFieldValue(ModelField modelField, Object value, ModelFieldTypeReader modelFieldTypeReader, Map<String, ? extends Object> context) {
if (value == null || value == GenericEntity.NULL_FIELD) {
return null;
}
String fieldJavaType = modelFieldTypeReader.getModelFieldType(modelField.getType()).getJavaType();
try {
return ObjectType.simpleTypeConvert(value, fieldJavaType, null, (TimeZone) context.get("timeZone"), (Locale) context.get("locale"), true);
} catch (GeneralException e) {
String errMsg = "Could not convert field value for the field: [" + modelField.getName() + "] on the [" + this.getEntityName() + "] entity to the [" + fieldJavaType + "] type for the value [" + value + "]: " + e.toString();
Debug.logError(e, errMsg, module);
throw new IllegalArgumentException(errMsg);
}
}
/**
* @return Returns the noAutoStamp.
*/
public boolean getNoAutoStamp() {
return this.noAutoStamp;
}
/**
* @param noAutoStamp The noAutoStamp to set.
*/
public void setNoAutoStamp(boolean noAutoStamp) {
this.noAutoStamp = noAutoStamp;
}
@Override
public String toString() {
return "ModelEntity[" + getEntityName() + "]";
}
public Element toXmlElement(Document document, String packageName) {
if (UtilValidate.isNotEmpty(this.getPackageName()) && !packageName.equals(this.getPackageName())) {
Debug.logWarning("Export EntityModel XML Element [" + this.getEntityName() + "] with a NEW package - " + packageName, module);
}
Element root = document.createElement("entity");
root.setAttribute("entity-name", this.getEntityName());
if (!this.getEntityName().equals(ModelUtil.dbNameToClassName(this.getPlainTableName())) ||
!ModelUtil.javaNameToDbName(this.getEntityName()).equals(this.getPlainTableName())) {
root.setAttribute("table-name", this.getPlainTableName());
}
root.setAttribute("package-name", packageName);
// additional elements
if (UtilValidate.isNotEmpty(this.getDefaultResourceName())) {
root.setAttribute("default-resource-name", this.getDefaultResourceName());
}
if (UtilValidate.isNotEmpty(this.getDependentOn())) {
root.setAttribute("dependent-on", this.getDependentOn());
}
if (this.getDoLock()) {
root.setAttribute("enable-lock", "true");
}
if (this.getNoAutoStamp()) {
root.setAttribute("no-auto-stamp", "true");
}
if (this.getNeverCache()) {
root.setAttribute("never-cache", "true");
}
if (this.getNeverCheck()) {
root.setAttribute("never-check", "true");
}
if (!this.getAutoClearCache()) {
root.setAttribute("auto-clear-cache", "false");
}
if (this.getSequenceBankSize() != null) {
root.setAttribute("sequence-bank-size", this.getSequenceBankSize().toString());
}
if (UtilValidate.isNotEmpty(this.getTitle())) {
root.setAttribute("title", this.getTitle());
}
if (UtilValidate.isNotEmpty(this.getCopyright())) {
root.setAttribute("copyright", this.getCopyright());
}
if (UtilValidate.isNotEmpty(this.getAuthor())) {
root.setAttribute("author", this.getAuthor());
}
if (UtilValidate.isNotEmpty(this.getVersion())) {
root.setAttribute("version", this.getVersion());
}
// description element
if (UtilValidate.isNotEmpty(this.getDescription())) {
UtilXml.addChildElementValue(root, "description", this.getDescription(), document);
}
// append field elements
Iterator<ModelField> fieldIter = this.getFieldsIterator();
while (fieldIter != null && fieldIter.hasNext()) {
ModelField field = fieldIter.next();
if (!field.getIsAutoCreatedInternal()) {
root.appendChild(field.toXmlElement(document));
}
}
// append PK elements
Iterator<ModelField> pkIter = this.getPksIterator();
while (pkIter != null && pkIter.hasNext()) {
ModelField pk = pkIter.next();
Element pkey = document.createElement("prim-key");
pkey.setAttribute("field", pk.getName());
root.appendChild(pkey);
}
// append relation elements
Iterator<ModelRelation> relIter = this.getRelationsIterator();
while (relIter != null && relIter.hasNext()) {
ModelRelation rel = relIter.next();
root.appendChild(rel.toXmlElement(document));
}
// append index elements
Iterator<ModelIndex> idxIter = this.getIndexesIterator();
while (idxIter != null && idxIter.hasNext()) {
ModelIndex idx = idxIter.next();
root.appendChild(idx.toXmlElement(document));
}
return root;
}
public Element toXmlElement(Document document) {
return this.toXmlElement(document, this.getPackageName());
}
/**
* Writes entity model information in the Apple EOModelBundle format.
*
* For document structure and definition see: http://developer.apple.com/documentation/InternetWeb/Reference/WO_BundleReference/Articles/EOModelBundle.html
*
* For examples see the JavaRealEstate.framework and JavaBusinessLogic.framework packages which are in the /Library/Frameworks directory after installing the WebObjects Examples package (get latest version of WebObjects download for this).
*
* This is based on examples and documentation from WebObjects 5.4, downloaded 20080221.
*
* @param writer
* @param entityPrefix
* @param helperName
*/
public void writeEoModelText(PrintWriter writer, String entityPrefix, String helperName, Set<String> entityNameIncludeSet, ModelReader entityModelReader) throws GenericEntityException {
if (entityPrefix == null) entityPrefix = "";
if (helperName == null) helperName = "localderby";
UtilPlist.writePlistPropertyMap(this.createEoModelMap(entityPrefix, helperName, entityNameIncludeSet, entityModelReader), 0, writer, false);
}
public Map<String, Object> createEoModelMap(String entityPrefix, String helperName, Set<String> entityNameIncludeSet, ModelReader entityModelReader) throws GenericEntityException {
final boolean useRelationshipNames = false;
ModelFieldTypeReader modelFieldTypeReader = ModelFieldTypeReader.getModelFieldTypeReader(helperName);
Map<String, Object> topLevelMap = new HashMap<String, Object>();
topLevelMap.put("name", this.getEntityName());
topLevelMap.put("externalName", this.getTableName(helperName));
topLevelMap.put("className", "EOGenericRecord");
// for classProperties add field names AND relationship names to get a nice, complete chart
List<String> classPropertiesList = new LinkedList<String>();
topLevelMap.put("classProperties", classPropertiesList);
for (ModelField field: this.fieldsList) {
if (field.getIsAutoCreatedInternal()) continue;
if (field.getIsPk()) {
classPropertiesList.add(field.getName() + "*");
} else {
classPropertiesList.add(field.getName());
}
}
for (ModelRelation relationship: this.relations) {
if (!entityNameIncludeSet.contains(relationship.getRelEntityName())) continue;
if (useRelationshipNames || relationship.isAutoRelation()) {
classPropertiesList.add(relationship.getCombinedName());
}
}
// attributes
List<Map<String, Object>> attributesList = new LinkedList<Map<String, Object>>();
topLevelMap.put("attributes", attributesList);
for (ModelField field: this.fieldsList) {
if (field.getIsAutoCreatedInternal()) continue;
ModelFieldType fieldType = modelFieldTypeReader.getModelFieldType(field.getType());
Map<String, Object> attributeMap = new HashMap<String, Object>();
attributesList.add(attributeMap);
if (field.getIsPk()) {
attributeMap.put("name", field.getName() + "*");
} else {
attributeMap.put("name", field.getName());
}
attributeMap.put("columnName", field.getColName());
attributeMap.put("valueClassName", fieldType.getJavaType());
String sqlType = fieldType.getSqlType();
if (sqlType.indexOf("(") >= 0) {
attributeMap.put("externalType", sqlType.substring(0, sqlType.indexOf("(")));
// since there is a field length set that
String widthStr = sqlType.substring(sqlType.indexOf("(") + 1, sqlType.indexOf(")"));
// if there is a comma split by it for width,precision
if (widthStr.indexOf(",") >= 0) {
attributeMap.put("width", widthStr.substring(0, widthStr.indexOf(",")));
// since there is a field precision set that
attributeMap.put("precision", widthStr.substring(widthStr.indexOf(",") + 1));
} else {
attributeMap.put("width", widthStr);
}
} else {
attributeMap.put("externalType", sqlType);
}
}
// primaryKeyAttributes
List<String> primaryKeyAttributesList = new LinkedList<String>();
topLevelMap.put("primaryKeyAttributes", primaryKeyAttributesList);
for (ModelField pkField : getPkFields()) {
primaryKeyAttributesList.add(pkField.getName());
}
// relationships
List<Map<String, Object>> relationshipsMapList = new LinkedList<Map<String, Object>>();
for (ModelRelation relationship: this.relations) {
if (entityNameIncludeSet.contains(relationship.getRelEntityName())) {
ModelEntity relEntity = entityModelReader.getModelEntity(relationship.getRelEntityName());
Map<String, Object> relationshipMap = new HashMap<String, Object>();
relationshipsMapList.add(relationshipMap);
if (useRelationshipNames || relationship.isAutoRelation()) {
relationshipMap.put("name", relationship.getCombinedName());
} else {
relationshipMap.put("name", relationship.getKeyMaps().iterator().next().getFieldName());
}
relationshipMap.put("destination", relationship.getRelEntityName());
if ("many".equals(relationship.getType())) {
relationshipMap.put("isToMany", "Y");
relationshipMap.put("isMandatory", "N");
} else {
relationshipMap.put("isToMany", "N");
relationshipMap.put("isMandatory", "Y");
}
relationshipMap.put("joinSemantic", "EOInnerJoin");
List<Map<String, Object>> joinsMapList = new LinkedList<Map<String, Object>>();
relationshipMap.put("joins", joinsMapList);
for (ModelKeyMap keyMap: relationship.getKeyMaps()) {
Map<String, Object> joinsMap = new HashMap<String, Object>();
joinsMapList.add(joinsMap);
ModelField thisField = this.getField(keyMap.getFieldName());
if (thisField != null && thisField.getIsPk()) {
joinsMap.put("sourceAttribute", keyMap.getFieldName() + "*");
} else {
joinsMap.put("sourceAttribute", keyMap.getFieldName());
}
ModelField relField = null;
if (relEntity != null) relField = relEntity.getField(keyMap.getRelFieldName());
if (relField != null && relField.getIsPk()) {
joinsMap.put("destinationAttribute", keyMap.getRelFieldName() + "*");
} else {
joinsMap.put("destinationAttribute", keyMap.getRelFieldName());
}
}
}
}
if (relationshipsMapList.size() > 0) {
topLevelMap.put("relationships", relationshipsMapList);
}
return topLevelMap;
}
public String getAuthor() {
return modelInfo.getAuthor();
}
public String getCopyright() {
return modelInfo.getCopyright();
}
public String getDefaultResourceName() {
return modelInfo.getDefaultResourceName();
}
public String getDescription() {
return modelInfo.getDescription();
}
public String getTitle() {
return modelInfo.getTitle();
}
public String getVersion() {
return modelInfo.getVersion();
}
}