001: /**
002: * Copyright (C) 2001-2005 France Telecom R&D
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */package org.objectweb.speedo.metadata;
018:
019: import java.util.ArrayList;
020: import java.util.HashMap;
021: import java.util.List;
022: import java.util.Map;
023:
024: import org.objectweb.speedo.api.SpeedoRuntimeException;
025:
026: /**
027: * Defines a the Speedo meta information about the inheritance.
028: * There is 3 possible mappings
029: * - The first mapping is the <b>horizontal</b>. Each concrete class has its own
030: * table containg all fields (fields of the class + inherited fields). The
031: * strategy for this mapping is new-table for each class. In each class, all
032: * inherited field must be mapped included inherited field. This means that in a
033: * class all inherited fields must be mapped into the tables of the current
034: * class. (#remappedInheritedFields)
035: * - The second mapping is <b>filtered</b>. All classes are mapped into the same
036: * tables. The table name is defined on the parent class. The strategy of the
037: * children classes is 'superclass-table'. To distinguish classes, a
038: * discriminator is required. (#discriminator)
039: * - The third mapping is <b>vertical</b>.All classes have its own table
040: * containing only fields of the class (not the inherited fields). Each table
041: * of devrived classes must defines a join to its parent (#join). In a vertical
042: * mapping it is possible and advised to use a discriminator similary than the
043: * filtered mapping. The strategy of the children is 'new-table'.
044: *
045: * @author S.Chassande-Barrioz
046: */
047: public class SpeedoInheritance extends SpeedoElement {
048:
049: private static final long serialVersionUID = -7618319063954294352L;
050:
051: public final static int STRATEGY_UNKOWN = -1;
052: public final static int STRATEGY_NEW_TABLE = 0;
053: public final static int STRATEGY_SUPERCLASS_TABLE = 1;
054: public final static int STRATEGY_SUBCLASS_TABLE = 2;
055: private final static String[] STRATEGY_NAMES = { "new-table",
056: "superclass-table", "subclass-table" };
057:
058: public final static String strategy2str(int s) {
059: if (-1 < s && s < STRATEGY_NAMES.length) {
060: return STRATEGY_NAMES[s];
061: } else {
062: return null;
063: }
064: }
065:
066: public final static int parseStrategy(String strategyName) {
067: for (int i = 0; i < STRATEGY_NAMES.length; i++) {
068: if (STRATEGY_NAMES[i].equals(strategyName)) {
069: return i;
070: }
071: }
072: return STRATEGY_UNKOWN;
073: }
074:
075: /**
076: * Is the inheritance strategy. It must be defined at initialisation time.
077: * @see #STRATEGY_NEW_TABLE
078: * @see #STRATEGY_SUBCLASS_TABLE
079: * @see #STRATEGY_SUPERCLASS_TABLE
080: * #see #STRATEGY_UNKOWN
081: */
082: public int strategy;
083:
084: /**
085: * Is speedo meta object representing the class with inheritance. It is not
086: * the parent class but the class which has a parent.
087: * It must be defined at initialisation time. It must be not null.
088: */
089: public SpeedoClass clazz;
090:
091: /**
092: * Super class name.
093: */
094: public String super ClassName;
095:
096: /**
097: * Is the meta object representing the join to herited table in case of
098: * vertical mapping. It can be null if the mapping is not 'vertical'.
099: */
100: public SpeedoJoin join;
101:
102: /**
103: * is the list of field inherited (SpeedoInheritedField) from ancestors.
104: * The mapping of these fields are redefined. Typical case whith inherited
105: * fields correspond to horizontal mapping of the inheritance (one table
106: * per class).
107: * key is the field name (could be fully qualified)
108: * value is a SpeedoInheritedField
109: */
110: public Map remappedInheritedFields;
111:
112: /**
113: * In case of filtered of vertical mapping, a discriminator permits to
114: * distinguish the classes of persistent instances. This field can be null
115: * if there is no discriminator (horizontal mapping case for instance).
116: */
117: public SpeedoDiscriminator discriminator;
118:
119: public static final String SPEEDO_DEFAULT_DISCRIMINENT_VALUE = "SPEEDO_DEFAULT_DISCRIMINENT_VALUE";
120: /**
121: * In case of there is discriminator, this fields defines the values of the
122: * discriminator parts.
123: * key = discriminator part description (SpeedoField or SpeedoNoFieldColumn)
124: * value = the value of the discriminator part for the current class;
125: *
126: * @see SpeedoDiscriminator
127: * @see SpeedoDiscriminator#elements
128: */
129: public Map discriminatorValues;
130:
131: public SpeedoInheritance() {
132: super ();
133: }
134:
135: public SpeedoInheritance(SpeedoClass moClass) {
136: this ();
137: this .clazz = moClass;
138: }
139:
140: /**
141: * Adds a SpeedoInheritedField for defining the mapping of an inherited
142: * field.
143: * @param sif is the field to add
144: */
145: public void add(SpeedoInheritedField sif) {
146: if (remappedInheritedFields == null) {
147: remappedInheritedFields = new HashMap();
148: }
149: remappedInheritedFields.put(sif.name, sif);
150: }
151:
152: /**
153: * @param fieldName is the
154: * @return a new SpeedoInheritedField corresponding to an existing persistent
155: * and inherited field.
156: * @throws SpeedoRuntimeException if the field has not been found or if the
157: * field belong the current class (#clazz).
158: */
159: public SpeedoInheritedField newSpeedoInheritedField(String fieldName)
160: throws SpeedoRuntimeException {
161: SpeedoField sf = clazz.getField(fieldName);
162: //check that the persistent field exists
163: if (sf == null) {
164: throw new SpeedoRuntimeException(
165: "Field '"
166: + fieldName
167: + "' has not been found in the inheritance tree from the class '"
168: + clazz.getFQName() + "'.");
169: }
170: return newSpeedoInheritedField(sf);
171: }
172:
173: public SpeedoInheritedField newSpeedoInheritedField(SpeedoField sf)
174: throws SpeedoRuntimeException {
175: //check that the persistent field exists
176: // checks that the field comes from an ancestor.
177: if (sf.moClass == clazz) {
178: throw new SpeedoRuntimeException(
179: "Field '"
180: + sf.name
181: + "' is not an inherited field, because it is defined in the current class '"
182: + clazz.getFQName() + "'.");
183: }
184: //create the meta object and fill it.
185: SpeedoInheritedField sif = new SpeedoInheritedField();
186: sif.name = sf.getFQFieldName();
187: sif.inheritedField = sf;
188: sif.moClass = clazz;
189: //Add it into #remappedInheritedFields
190: add(sif);
191: return sif;
192: }
193:
194: public boolean isHorizontalMapping() {
195: return strategy == STRATEGY_NEW_TABLE && join == null;
196: }
197:
198: public boolean isVerticalMapping() {
199: return strategy == STRATEGY_NEW_TABLE && join != null;
200: }
201:
202: public boolean isFilteredMapping() {
203: return strategy == STRATEGY_SUPERCLASS_TABLE;
204: }
205: }
|