/**
* Objective Database Abstraction Layer (ODAL)
* Copyright (c) 2004, The ODAL Development Group
* All rights reserved.
* For definition of the ODAL Development Group please refer to LICENCE.txt file
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package com.completex.objective.components.persistency;
import com.completex.objective.components.persistency.core.impl.LinkIterator;
import com.completex.objective.util.PropertyMap;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Represents tree structure used to create Query trees as well as PersistentObject trees.
*
* @author Gennady Krizhevsky
*/
public class Link extends ParentBase implements Parent, Serializable, Cloneable, Mappable {
static final long serialVersionUID = 1L;
public static final String SEP = "|";
private transient Query query;
private transient LifeCycleController lifeCycleController;
protected transient int[] parentIndeces;
protected transient int[] thisIndeces;
private transient boolean lazyRetrieval;
private transient boolean insertBeforeParent; /* it means also "update Before Parent" & "delete After Parent" */
private transient boolean cascadeDelete;
private transient boolean cascadeInsert;
private transient boolean cascadeUpdate;
private transient boolean treatNullAsRemove;
private transient int dependencyIndex = -1;
protected transient InlineMode inlineMode;
private transient boolean retrieved;
private transient boolean adHoc;
private boolean endOfChain;
private Object result;
private String name;
// Meta data:
private List path = new LinkedList();
private static final String TAG_PARENT_INDECES = "parentIndeces";
private static final String TAG_THIS_INDECES = "thisIndeces";
private static final String TAG_NAME = "name";
public static final String TAG_QUERY = "query";
public static final String TAG_QUERY_CLASS = "queryClass";
public Link() {
}
public Link(Map map) {
fromMap(map);
}
public Link(String name) {
setName(name);
}
public Link(String name, Object result) {
this.name = name;
this.result = result;
}
public Link(String name, Object result, boolean adHoc) {
this.name = name;
this.result = result;
this.adHoc = adHoc;
}
/**
* @param query Query object
* @param parentIndeces parent indeces which values are mapped to corresponding "this indeces"
* @param thisIndeces "this indeces" indeces which values are mapped to corresponding parent ones
*/
public Link(Query query, int[] parentIndeces, int thisIndeces []) {
this(query, parentIndeces, thisIndeces, null);
}
/**
* @param query Query object
* @param parentIndeces parent indeces which values are mapped to corresponding "this indeces"
* @param thisIndeces "this indeces" indeces of this link query's SingularResultFactory
* which values are mapped to corresponding parent ones
* @param name link name - mandatory for PersistentObject trees
*/
public Link(Query query, int[] parentIndeces, int thisIndeces [], String name) {
this.query = query;
this.parentIndeces = parentIndeces;
this.name = name;
if (parentIndeces == null) {
addToPath(getName());
} else {
if (thisIndeces == null) {
throw new IllegalArgumentException("thisIndeces == null");
}
if (thisIndeces.length != parentIndeces.length) {
throw new IllegalArgumentException("thisIndeces.length != parentIndeces.length");
}
this.thisIndeces = thisIndeces;
}
}
public Link(Link source) {
this(source.query, source.parentIndeces, source.thisIndeces, source.name);
}
public Link copyAll(Link source) {
this.query = source.query;
this.lifeCycleController = source.lifeCycleController;
this.parentIndeces = source.parentIndeces;
this.thisIndeces = source.thisIndeces;
this.lazyRetrieval = source.lazyRetrieval;
this.insertBeforeParent = source.insertBeforeParent;
this.cascadeDelete = source.cascadeDelete;
this.cascadeInsert = source.cascadeInsert;
this.cascadeUpdate = source.cascadeUpdate;
this.treatNullAsRemove = source.treatNullAsRemove;
this.dependencyIndex = source.dependencyIndex;
this.inlineMode = source.inlineMode;
this.endOfChain = source.endOfChain;
this.result = source.result;
this.name = source.name;
this.path = source.path;
return this;
}
/**
* Returns itself
*
* @return itself
*/
public Link toLink() {
return this;
}
/**
* Sets cascadeDelete = true; cascadeInsert = true; cascadeUpdate = true. Values are used in
* PersistentObject trees
*
* @return itself
*/
public Link setCascadeAll() {
cascadeDelete = true;
cascadeInsert = true;
cascadeUpdate = true;
return this;
}
/**
* Unsets cascadeDelete = true; cascadeInsert = true; cascadeUpdate = true. Values are used in
* PersistentObject trees
*
* @return itself
*/
public Link unsetCascadeAll() {
cascadeDelete = false;
cascadeInsert = false;
cascadeUpdate = false;
return this;
}
/**
* Sets setRelationship to parent
*
* @param relationshipType
* @see RelationshipType
*/
public void setRelationshipToParent(RelationshipType relationshipType) {
if (MANY_TO_ONE.equals(relationshipType)) {
insertBeforeParent = true;
}
}
/**
* Returns LifeCycleController set for this link
*
* @return LifeCycleController set for this link
*/
public LifeCycleController getLifeCycleController() {
return lifeCycleController;
}
/**
* Sets LifeCycleController for this link
*
* @param lifeCycleController
*/
public void setLifeCycleController(LifeCycleController lifeCycleController) {
this.lifeCycleController = lifeCycleController;
}
/**
* Sets link name. Link name is mandatory for PersistentObject trees
*
* @param name link name
*/
public void setName(String name) {
this.name = name;
}
/**
* Returns link name
*
* @return link name
*/
public String getName() {
return name;
}
/**
* Returns true is this link is end of link chain. Marking link as end of chain prevents
* infinite loops of retrievals when circular link references are set.
*
* @return true is this link is end of link chain
*/
public boolean isEndOfChain() {
return endOfChain;
}
/**
* If true - this link is end of link chain. Marking link as end of chain prevents
* infinite loops of retrievals when circular link references are set.
*
* @param endOfChain true is this link is end of link chain
*/
public void setEndOfChain(boolean endOfChain) {
this.endOfChain = endOfChain;
}
/**
* Returns link dependency index
*
* @return link dependency index
*/
public int getDependencyIndex() {
return dependencyIndex;
}
/**
* Sets link dependency index
*
* @param dependencyIndex link dependency index
*/
public void setDependencyIndex(int dependencyIndex) {
this.dependencyIndex = dependencyIndex;
}
/**
* Returns "this indeces" - indeces of this link query's SingularResultFactory
* which values are mapped to corresponding parent ones. Usually they are foregn key ones
*
* @return "this indeces" - indeces of this link query's SingularResultFactory
* which values are mapped to corresponding parent ones
*/
public int[] getThisIndeces() {
return thisIndeces;
}
/**
* Sets "this indeces" - indeces of this link query's SingularResultFactory
* which values are mapped to corresponding parent ones. Usually they are foregn key ones
*
* @param thisIndeces "this indeces" - indeces of this link query's SingularResultFactory
* which values are mapped to corresponding parent ones
*/
public void setThisIndeces(int[] thisIndeces) {
this.thisIndeces = thisIndeces;
}
/**
* Returns parent indeces - indeces of the parent persistent object which contains a link [pointing to itself.
* Usually they are the primary key ones.
*
* @return parent indeces - indeces of the parent persistent object which contains a link [pointing to itself.
* Usually they are the primary key ones.
*/
public int[] getParentIndeces() {
return parentIndeces;
}
/**
* Sets parent indeces - indeces of the parent persistent object which contains a link [pointing to itself.
* Usually they are the primary key ones.
*
* @param parentIndeces indeces of the parent persistent object which contains a link [pointing to itself.
* Usually they are the primary key ones.
*/
public void setParentIndeces(int[] parentIndeces) {
this.parentIndeces = parentIndeces;
}
/**
* Returns full path to this link built of the names of the parent chain
*
* @return full path to this link built of the names of the parent chain
*/
public String getPathString() {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < path.size(); i++) {
buffer.append(path.get(i));
if (i < path.size() - 1) {
buffer.append(SEP);
}
}
return buffer.toString();
}
public void setPath(String pathString) {
path = string2path(pathString);
}
public static String path2string(List path) {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < path.size(); i++) {
buffer.append(path.get(i));
if (i < path.size() - 1) {
buffer.append(SEP);
}
}
return buffer.toString();
}
public static List string2path(String pathString) {
String [] tokens = pathString.split(SEP);
ArrayList path = new ArrayList(tokens.length);
for (int i = 0; i < path.size(); i++) {
path.add(tokens[i]);
}
return path;
}
/**
* Sets full path to this link built of the names of the parent chain
*
* @param path full path to this link built of the names of the parent chain
*/
void setPath(List path) {
this.path = path;
}
/**
* Returns full path to this link built of the names of the parent chain
*
* @return full path to this link built of the names of the parent chain
*/
public List getPath() {
return path;
}
/**
* Appends all of the elements in the specified parentPath to the end of
* this link's path
*
* @param parentPath to append to the end of
* this link's path
*/
public void addParentPath(List parentPath) {
if (parentPath != null) {
for (int i = 0; i < parentPath.size(); i++) {
String parentName = (String) parentPath.get(i);
addToPath0(parentName);
}
}
}
/**
* Adds name to this link's path
*
* @param name to add
*/
public void addToPath(String name) {
addToPath0(name);
setName(name);
}
private void addToPath0(String name) {
if (path.size() > 0) {
String lastName = (String) path.get(path.size() - 1);
if (lastName.equals(name)) {
throw new IllegalArgumentException("Attempt to add name twice");
}
} else if (!ROOT.equals(name)) {
path.add(ROOT);
}
if (name != null) {
path.add(name);
}
}
/**
* Returns result - data that is set during query execution for selects
* or by using setter methods for update operations
*
* @return result - data that is set during query execution for selects
* or by using setter methods for update operations
*/
public Object getResult() {
return result;
}
public Collection getResultAsCollection() {
return (Collection) result;
}
public void addToResultCollection(Object value) {
getResultAsCollection().add(value);
}
public void addNotNullToResultCollection(Object value) {
if (value != null) {
getResultAsCollection().add(value);
}
}
/**
* Sets result - data that is set during query execution for selects
* or by using setter methods for update operations
*
* @param result data that is set during query execution for selects
* or by using setter methods for update operations
*/
public void setResult(Object result) {
this.result = result;
}
/**
* Returns query that is used to retrieve object trees
*
* @return query that is used to retrieve object trees
*/
public Query getQuery() {
return query;
}
/**
* Sets query that is used to retrieve object trees
*
* @param query query that is used to retrieve object trees
*/
public void setQuery(Query query) {
this.query = query;
}
/**
* Returns true the result of this link has to be performed in "lazy" fashion
*
* @return true the result of this link has to be performed in "lazy" fashion
*/
public boolean isLazyRetrieval() {
return lazyRetrieval;
}
/**
* Sets true the result of this link has to be performed in "lazy" fashion
*
* @param lazyRetrieval true the result of this link has to be performed in "lazy" fashion
*/
public void setLazyRetrieval(boolean lazyRetrieval) {
this.lazyRetrieval = lazyRetrieval;
}
/**
* Returns true if the result (data) of this link is to be inserted before the parent link's one
*
* @return true if the result (data) of this link is to be inserted before the parent link's one
*/
public boolean isInsertBeforeParent() {
return insertBeforeParent;
}
/**
* Sets true if the result (data) of this link is to be inserted before the parent link's one
*
* @param insertBeforeParent true if the result (data) of this link is to be inserted before the parent link's one
*/
public void setInsertBeforeParent(boolean insertBeforeParent) {
this.insertBeforeParent = insertBeforeParent;
}
/**
* Returns true if for one-to-one inversed relationship
* (this link contains foreign key object and its child contains the primary key ones)
* nullifying the foregn key field should cause deletion of the child object
*
*
* @return true if for one-to-one inversed relationship
* (this link contains foreign key object and its child contains the primary key ones)
* nullifying the foregn key field should cause deletion of the child object
*/
public boolean isTreatNullAsRemove() {
return treatNullAsRemove;
}
/**
* Sets true if for one-to-one inversed relationship
* (this link contains foreign key object and its child contains the primary key ones)
* nullifying the foregn key field should cause deletion of the child object
*
* @param treatNullAsRemove true if for one-to-one inversed relationship
* (this link contains foreign key object and its child contains the primary key ones)
* nullifying the foregn key field should cause deletion of the child object
*/
public void setTreatNullAsRemove(boolean treatNullAsRemove) {
this.treatNullAsRemove = treatNullAsRemove;
}
/**
* Returns true if delete is to be propagated to this link when the parent one gets deleted
*
* @return true if delete is to be propagated to this link when the parent one gets deleted
*/
public boolean isCascadeDelete() {
return cascadeDelete;
}
/**
* Sets true if delete is to be propagated to this link when the parent one gets deleted
*
* @param cascadeDelete true if delete is to be propagated to this link when the parent one gets deleted
*/
public void setCascadeDelete(boolean cascadeDelete) {
this.cascadeDelete = cascadeDelete;
}
/**
* Returns true if delete is to be propagated to this link when the parent one gets inserted
*
* @return true if delete is to be propagated to this link when the parent one gets inserted
*/
public boolean isCascadeInsert() {
return cascadeInsert;
}
/**
* Sets true if delete is to be propagated to this link when the parent one gets inserted
*
* @param cascadeInsert true if delete is to be propagated to this link when the parent one gets inserted
*/
public void setCascadeInsert(boolean cascadeInsert) {
this.cascadeInsert = cascadeInsert;
}
/**
* Returns true if delete is to be propagated to this link when the parent one gets updated
*
* @return true if delete is to be propagated to this link when the parent one gets updated
*/
public boolean isCascadeUpdate() {
return cascadeUpdate;
}
/**
* Sets true if delete is to be propagated to this link when the parent one gets updated
*
* @param cascadeUpdate true if delete is to be propagated to this link when the parent one gets updated
*/
public void setCascadeUpdate(boolean cascadeUpdate) {
this.cascadeUpdate = cascadeUpdate;
}
/**
* Experimental
*/
public boolean isInline() {
return inlineMode != null;
}
/**
* Experimental
*/
public InlineMode getInlineMode() {
return inlineMode;
}
/**
* Experimental
*/
public void setInlineMode(InlineMode inlineMode) {
this.inlineMode = inlineMode;
}
/**
* Returns new instance of this link that inherits set of its parent properties
*
* @return new instance of this link that inherits set of its parent properties
*/
public Link newInstance() {
Query query = null;
if (this.query != null) {
query = this.query.newQuery();
}
Link link = newInstance0(query);
link.setName(name);
link.setPath(path);
link.setLazyRetrieval(lazyRetrieval);
link.setInsertBeforeParent(insertBeforeParent);
link.setDependencyIndex(dependencyIndex);
link.setCascadeDelete(cascadeDelete);
link.setCascadeInsert(cascadeInsert);
link.setCascadeUpdate(cascadeUpdate);
link.setTreatNullAsRemove(treatNullAsRemove);
link.setEndOfChain(endOfChain);
if (lifeCycleController != null) {
link.setLifeCycleController(lifeCycleController.newLifeCycleInstance());
}
link.path = cloneList(path);
return link;
}
List cloneList(List list) {
if (list instanceof LinkedList) {
return (List) ((LinkedList) list).clone();
} else if (list instanceof ArrayList) {
return (List) ((ArrayList) list).clone();
} else {
throw new RuntimeException("Unsupported type " + list);
}
}
protected Link newInstance0(Query query) {
return new Link(query, parentIndeces, thisIndeces);
}
/**
* Returns Deep copy of this link
*
* @return Deep copy of this link
* @throws CloneNotSupportedException
*/
public Object clone() throws CloneNotSupportedException {
Link link = (Link) super.clone();
Object result = link.getResult();
Object clonedResult = link.getResult();
if (query != null) {
link.setQuery(((Query) query.clone()));
}
if (result != null) {
if (result instanceof com.completex.objective.components.persistency.Cloneable) {
clonedResult = ((com.completex.objective.components.persistency.Cloneable) result).clone();
} else if (result instanceof LinkedList) {
clonedResult = ((LinkedList) result).clone();
populateClonedCollection(((List) clonedResult));
} else if (result instanceof ArrayList) {
clonedResult = ((ArrayList) result).clone();
populateClonedCollection(((List) clonedResult));
} else if (result instanceof HashSet) {
clonedResult = ((HashSet) result).clone();
populateClonedCollection(((Set) clonedResult));
} else if (result instanceof HashMap) {
clonedResult = ((HashMap) result).clone();
populateClonedMap(((Map) clonedResult));
}
}
link.setResult(clonedResult);
if (link.hasChildren()) {
for (LinkIterator it = linkIterator(); it.hasNext();) {
Link child = it.nextLink();
child.clone();
}
}
link.inlineMode = inlineMode;
return link;
}
public void populateClonedCollection(Collection collection) {
if (collection == null) {
return;
}
AbstractPersistentObject[] objects =
(AbstractPersistentObject[]) collection.toArray(new AbstractPersistentObject[collection.size()]);
for (int i = 0; i < objects.length; i++) {
AbstractPersistentObject object = objects[i];
if (objects[i] != null) {
objects[i] = (AbstractPersistentObject) object.clone();
}
}
collection.clear();
collection.addAll(Arrays.asList(objects));
}
public void populateClonedMap(Map map) {
if (map == null) {
return;
}
for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
Object value = entry.getValue();
if (value instanceof AbstractPersistentObject) {
entry.setValue(((AbstractPersistentObject) value).clone());
}
}
}
/**
* Copies results from "from" link to this one without touching children
*
* @param from
*/
public void copyResultsOneLevel(Link from) {
copyResultsOneLevel(from, this);
}
/**
* Copies results from "from" link to this one including children
*
* @param from
*/
public void copyResults(Link from) {
copyResults(from, this, 0);
}
private static void copyResultsOneLevel(Link from, Link to) {
if (from == null || to == null) {
return;
}
if (from.getResult() != null) {
to.setResult(from.getResult());
}
}
// Copy results from parameter to this:
public static void copyResults(Link from, Link to, int level) {
level++;
if (from == null || to == null) {
return;
}
if (from.getResult() != null) {
to.setResult(from.getResult());
}
LinkedHashMap toChildren = to.getChildren();
if (toChildren != null) {
for (LinkIterator it = from.linkIterator(); it.hasNext();) {
Link fromChild = it.nextLink();
String name = fromChild.getName();
Link toChild = (Link) toChildren.get(name);
if (toChild != null) {
copyResults(fromChild, toChild, level);
} else {
// case when ad-hoc results are added:
fromChild.setAdHoc(true);
toChildren.put(name, fromChild);
}
}
}
}
public boolean isAdHoc() {
return adHoc;
}
public void setAdHoc(boolean adHoc) {
this.adHoc = adHoc;
}
public boolean isRetrieved() {
return retrieved;
}
public void setRetrieved(boolean retrieved) {
this.retrieved = retrieved;
}
public Map toMap() {
Map map = super.toMap();
toMapArray(map, TAG_PARENT_INDECES, parentIndeces);
toMapArray(map, TAG_THIS_INDECES, thisIndeces);
map.put(TAG_NAME, name);
if (query != null) {
map.put(TAG_QUERY, ((Mappable) query).toMap());
map.put(TAG_QUERY_CLASS, query.getClass().getName());
}
return map;
}
public void fromMap(Map map) {
super.fromMap(map);
PropertyMap propertyMap = PropertyMap.toPropertyMap(map);
parentIndeces = fromMapToIntArray(propertyMap, TAG_PARENT_INDECES);
thisIndeces = fromMapToIntArray(propertyMap, TAG_THIS_INDECES);
name = propertyMap.getProperty(TAG_NAME);
Map queryMap = propertyMap.getMap(TAG_QUERY);
if (queryMap != null) {
String queryClassName = propertyMap.getProperty(TAG_QUERY_CLASS, true);
try {
query = (Query) Class.forName(queryClassName).newInstance();
} catch (Exception e) {
throw new OdalRuntimePersistencyException("Cannot instantiate class by name " + queryClassName, e);
}
((Mappable) query).fromMap(queryMap);
}
}
protected void toMapArray(Map map, String tag, int [] array) {
if (array != null) {
String [] arrayS = new String[array.length];
for (int i = 0; i < array.length; i++) {
arrayS[i] = String.valueOf(array[i]);
}
map.put(tag, Arrays.asList(arrayS));
}
}
protected int [] fromMapToIntArray(PropertyMap map, String tag) {
int [] array = null;
List list = map.getList(tag);
if (list != null) {
array = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
String value = (String) list.get(i);
int intValue = 0;
if (value != null) {
intValue = Integer.parseInt(value);
}
array[i] = intValue;
}
}
return array;
}
public String toString() {
StringBuffer buffer = new StringBuffer(" Link : {");
buffer.append("name = ").append(name);
buffer.append(parentIndecesBuffer());
buffer.append("; dependencyIndex = (").append(dependencyIndex).append(")");
buffer.append("; path = ").append(getPathString());
buffer.append("; parent path = ");
StringBuffer parentIndecesBuffer = new StringBuffer("; parentIndeces [");
if (parentIndeces != null) {
for (int i = 0; i < parentIndeces.length; i++) {
if (i > 0) {
parentIndecesBuffer.append(", ");
}
parentIndecesBuffer.append(parentIndeces[i]);
}
} else {
parentIndecesBuffer.append("null");
}
parentIndecesBuffer.append("]");
if (getParentLink() != null) {
buffer.append(getParentLink().getPathString());
} else {
buffer.append("null");
}
buffer.append("; result = (").append(result).append(")");
buffer.append("}");
return super.toString() + buffer.toString();
}
/**
* Returns summary string
*
* @return summary string
*/
public String toSummaryString() {
StringBuffer buffer = new StringBuffer(" Link<");
buffer.append("name = ").append(name);
buffer.append(parentIndecesBuffer()).append(">");
return super.toString() + buffer.toString();
}
private StringBuffer parentIndecesBuffer() {
StringBuffer parentIndecesBuffer = new StringBuffer("; parentIndeces [");
if (parentIndeces != null) {
for (int i = 0; i < parentIndeces.length; i++) {
if (i > 0) {
parentIndecesBuffer.append(", ");
}
parentIndecesBuffer.append(parentIndeces[i]);
}
} else {
parentIndecesBuffer.append("null");
}
parentIndecesBuffer.append("]");
return parentIndecesBuffer;
}
public static final RelationshipType ONE_TO_MANY = RelationshipType.ONE_TO_MANY;
public static final RelationshipType ONE_TO_ONE = RelationshipType.ONE_TO_ONE;
public static final RelationshipType MANY_TO_ONE = RelationshipType.MANY_TO_ONE;
public static final RelationshipType MANY_TO_MANY = RelationshipType.MANY_TO_MANY;
public static final String INLINE_INNER = "inner";
public static final String INLINE_OUTER = "outer";
/**
* Inner (or equi-) join mode:
*/
public static final InlineMode INNER_JOIN_MODE = new InlineMode(INLINE_INNER);
/**
* Outer (left outer) join mode
*/
public static final InlineMode OUTER_JOIN_MODE = new InlineMode(INLINE_OUTER);
public static InlineMode toInlineMode(String modeName) {
if (INLINE_INNER.equalsIgnoreCase(modeName)) {
return INNER_JOIN_MODE;
} else if (INLINE_OUTER.equalsIgnoreCase(modeName)) {
return OUTER_JOIN_MODE;
} else {
throw new IllegalArgumentException("Unknown inline mode name: " + modeName);
}
}
public boolean isInner() {
return getInlineMode() == INNER_JOIN_MODE;
}
public boolean isOuter() {
return getInlineMode() == OUTER_JOIN_MODE;
}
public void setInlineMode(String childName, InlineMode inlineMode) {
getChild(childName).setInlineMode(inlineMode);
}
/**
* Represents entities relationship in ER paradigm
*/
public static class RelationshipType {
public static final RelationshipType ONE_TO_MANY = new RelationshipType("one_to_many");
public static final RelationshipType ONE_TO_ONE = new RelationshipType("one_to_one");
public static final RelationshipType MANY_TO_ONE = new RelationshipType("many_to_one");
public static final RelationshipType MANY_TO_MANY = new RelationshipType("many_to_many");
private String name;
protected RelationshipType(String name) {
this.name = name;
}
public String toString() {
return name;
}
public String getName() {
return name;
}
public static RelationshipType name2type(String name) {
if (ONE_TO_MANY.getName().equals(name)) {
return ONE_TO_MANY;
} else if (ONE_TO_ONE.getName().equals(name)) {
return ONE_TO_ONE;
} else if (MANY_TO_ONE.getName().equals(name)) {
return MANY_TO_ONE;
} else {
throw new UnsupportedOperationException(name);
}
}
}
/**
* Represents query inlining mode. Inlined queries are executed in the same SQL statement
* as the main query.
*/
public static class InlineMode {
private String name;
protected InlineMode(String name) {
this.name = name;
}
public String toString() {
return name;
}
}
}
|