| /* |
| * 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.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.TreeSet; |
| |
| import org.ofbiz.base.lang.ThreadSafe; |
| import org.ofbiz.base.util.UtilValidate; |
| import org.ofbiz.base.util.UtilXml; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| |
| /** |
| * An object that models the <code><relation></code> element. |
| * |
| */ |
| @ThreadSafe |
| @SuppressWarnings("serial") |
| public final class ModelRelation extends ModelChild { |
| |
| /** |
| * Returns a new <code>ModelRelation</code> instance, initialized with the specified values. |
| * |
| * @param modelEntity The <code>ModelEntity</code> this relation is a member of. |
| * @param description The relation description. |
| * @param type The relation type. |
| * @param title The relation title. |
| * @param relEntityName The related entity's name. |
| * @param fkName The foreign key name. |
| * @param keyMaps The key maps included in this relation. |
| * @param isAutoRelation <code>true</code> if this relation was generated automatically by the entity engine. |
| */ |
| public static ModelRelation create(ModelEntity modelEntity, String description, String type, String title, String relEntityName, String fkName, List<ModelKeyMap> keyMaps, boolean isAutoRelation) { |
| if (description == null) { |
| description = ""; |
| } |
| if (type == null) { |
| type = ""; |
| } |
| if (title == null) { |
| title = ""; |
| } |
| if (relEntityName == null) { |
| relEntityName = ""; |
| } |
| if (fkName == null) { |
| fkName = ""; |
| } |
| if (keyMaps == null) { |
| keyMaps = Collections.emptyList(); |
| } else { |
| keyMaps = Collections.unmodifiableList(keyMaps); |
| } |
| return new ModelRelation(modelEntity, description, type, title, relEntityName, fkName, keyMaps, isAutoRelation); |
| } |
| |
| /** |
| * Returns a new <code>ModelRelation</code> instance, initialized with the specified values. |
| * |
| * @param modelEntity The <code>ModelEntity</code> this relation is a member of. |
| * @param relationElement The <code><relation></code> element containing the values for this relation. |
| * @param isAutoRelation <code>true</code> if this relation was generated automatically by the entity engine. |
| */ |
| public static ModelRelation create(ModelEntity modelEntity, Element relationElement, boolean isAutoRelation) { |
| String type = relationElement.getAttribute("type").intern(); |
| String title = relationElement.getAttribute("title").intern(); |
| String relEntityName = relationElement.getAttribute("rel-entity-name").intern(); |
| String fkName = relationElement.getAttribute("fk-name").intern(); |
| String description = UtilXml.childElementValue(relationElement, "description"); |
| List<ModelKeyMap >keyMaps = Collections.emptyList(); |
| List<? extends Element> elementList = UtilXml.childElementList(relationElement, "key-map"); |
| if (!elementList.isEmpty()) { |
| keyMaps = new ArrayList<ModelKeyMap>(elementList.size()); |
| for (Element keyMapElement : elementList) { |
| keyMaps.add(new ModelKeyMap(keyMapElement)); |
| } |
| keyMaps = Collections.unmodifiableList(keyMaps); |
| } |
| return new ModelRelation(modelEntity, description, type, title, relEntityName, fkName, keyMaps, isAutoRelation); |
| } |
| |
| /* |
| * Developers - this is an immutable class. Once constructed, the object should not change state. |
| * Therefore, 'setter' methods are not allowed. If client code needs to modify the object's |
| * state, then it can create a new copy with the changed values. |
| */ |
| |
| /** the title, gives a name/description to the relation */ |
| private final String title; |
| |
| /** the type: either "one" or "many" or "one-nofk" */ |
| private final String type; |
| |
| /** the name of the related entity */ |
| private final String relEntityName; |
| |
| /** the name to use for a database foreign key, if applies */ |
| private final String fkName; |
| |
| /** keyMaps defining how to lookup the relatedTable using columns from this table */ |
| private final List<ModelKeyMap> keyMaps; |
| |
| private final boolean isAutoRelation; |
| |
| /** A String to uniquely identify this relation. */ |
| private final String fullName; |
| |
| private final String combinedName; |
| |
| private ModelRelation(ModelEntity modelEntity, String description, String type, String title, String relEntityName, String fkName, List<ModelKeyMap> keyMaps, boolean isAutoRelation) { |
| super(modelEntity, description); |
| this.title = title; |
| this.type = type; |
| this.relEntityName = relEntityName; |
| this.fkName = fkName; |
| this.keyMaps = keyMaps; |
| this.isAutoRelation = isAutoRelation; |
| StringBuilder sb = new StringBuilder(); |
| sb.append(modelEntity == null ? "Unknown" : modelEntity.getEntityName()).append("->").append(title).append(relEntityName).append("["); |
| Set<ModelKeyMap> keyMapSet = new TreeSet<ModelKeyMap>(keyMaps); |
| Iterator<ModelKeyMap> setIter = keyMapSet.iterator(); |
| while (setIter.hasNext()) { |
| ModelKeyMap keyMap = setIter.next(); |
| sb.append(keyMap); |
| if (setIter.hasNext()) { |
| sb.append(","); |
| } |
| } |
| sb.append("]"); |
| this.fullName = sb.toString(); |
| this.combinedName = title.concat(relEntityName); |
| } |
| |
| /** Returns the combined name (title + related entity name). */ |
| public String getCombinedName() { |
| return this.combinedName; |
| } |
| |
| /** Returns the title. */ |
| public String getTitle() { |
| return this.title; |
| } |
| |
| /** Returns the type. */ |
| public String getType() { |
| return this.type; |
| } |
| |
| /** Returns the related entity name. */ |
| public String getRelEntityName() { |
| return this.relEntityName; |
| } |
| |
| /** Returns the foreign key name. */ |
| public String getFkName() { |
| return this.fkName; |
| } |
| |
| /** Returns the key maps. */ |
| public List<ModelKeyMap> getKeyMaps() { |
| return this.keyMaps; |
| } |
| |
| /** Returns <code>true</code> if this relation was generated automatically by the entity engine. */ |
| public boolean isAutoRelation() { |
| return isAutoRelation; |
| } |
| |
| /** Find a KeyMap with the specified fieldName */ |
| public ModelKeyMap findKeyMap(String fieldName) { |
| for (ModelKeyMap keyMap: keyMaps) { |
| if (keyMap.getFieldName().equals(fieldName)) return keyMap; |
| } |
| return null; |
| } |
| |
| /** Find a KeyMap with the specified relFieldName */ |
| public ModelKeyMap findKeyMapByRelated(String relFieldName) { |
| for (ModelKeyMap keyMap: keyMaps) { |
| if (keyMap.getRelFieldName().equals(relFieldName)) |
| return keyMap; |
| } |
| return null; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| if (obj instanceof ModelRelation) { |
| ModelRelation that = (ModelRelation) obj; |
| return this.fullName.equals(that.fullName); |
| } |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| return this.fullName.hashCode(); |
| } |
| |
| @Override |
| public String toString() { |
| return this.fullName; |
| } |
| |
| // TODO: Externalize this. |
| public String keyMapString(String separator, String afterLast) { |
| StringBuilder stringBuilder = new StringBuilder(""); |
| |
| if (keyMaps.size() < 1) { |
| return ""; |
| } |
| |
| int i = 0; |
| |
| for (; i < keyMaps.size() - 1; i++) { |
| stringBuilder.append(keyMaps.get(i).getFieldName()); |
| stringBuilder.append(separator); |
| } |
| stringBuilder.append(keyMaps.get(i).getFieldName()); |
| stringBuilder.append(afterLast); |
| return stringBuilder.toString(); |
| } |
| |
| // TODO: Externalize this. |
| public String keyMapUpperString(String separator, String afterLast) { |
| if (keyMaps.size() < 1) |
| return ""; |
| |
| StringBuilder returnString = new StringBuilder(keyMaps.size() * 10); |
| int i=0; |
| while (true) { |
| ModelKeyMap kmap = keyMaps.get(i); |
| returnString.append(ModelUtil.upperFirstChar(kmap.getFieldName())); |
| |
| i++; |
| if (i >= keyMaps.size()) { |
| returnString.append(afterLast); |
| break; |
| } |
| |
| returnString.append(separator); |
| } |
| |
| return returnString.toString(); |
| } |
| |
| // TODO: Externalize this. |
| public String keyMapRelatedUpperString(String separator, String afterLast) { |
| if (keyMaps.size() < 1) |
| return ""; |
| |
| StringBuilder returnString = new StringBuilder(keyMaps.size() * 10); |
| int i=0; |
| while (true) { |
| ModelKeyMap kmap = keyMaps.get(i); |
| returnString.append(ModelUtil.upperFirstChar(kmap.getRelFieldName())); |
| |
| i++; |
| if (i >= keyMaps.size()) { |
| returnString.append(afterLast); |
| break; |
| } |
| |
| returnString.append(separator); |
| } |
| |
| return returnString.toString(); |
| } |
| |
| // TODO: Externalize this. |
| public Element toXmlElement(Document document) { |
| Element root = document.createElement("relation"); |
| root.setAttribute("type", this.getType()); |
| if (UtilValidate.isNotEmpty(this.getTitle())) { |
| root.setAttribute("title", this.getTitle()); |
| } |
| root.setAttribute("rel-entity-name", this.getRelEntityName()); |
| |
| if (UtilValidate.isNotEmpty(this.getFkName())) { |
| root.setAttribute("fk-name", this.getFkName()); |
| } |
| |
| Iterator<ModelKeyMap> kmIter = this.keyMaps.iterator(); |
| while (kmIter != null && kmIter.hasNext()) { |
| ModelKeyMap km = kmIter.next(); |
| root.appendChild(km.toXmlElement(document)); |
| } |
| |
| return root; |
| } |
| } |