/**
* Copyright (C) 2001-2005 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.objectweb.speedo.metadata;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.objectweb.speedo.api.SpeedoRuntimeException;
/**
* Defines a the Speedo meta information about the inheritance.
* There is 3 possible mappings
* - The first mapping is the <b>horizontal</b>. Each concrete class has its own
* table containg all fields (fields of the class + inherited fields). The
* strategy for this mapping is new-table for each class. In each class, all
* inherited field must be mapped included inherited field. This means that in a
* class all inherited fields must be mapped into the tables of the current
* class. (#remappedInheritedFields)
* - The second mapping is <b>filtered</b>. All classes are mapped into the same
* tables. The table name is defined on the parent class. The strategy of the
* children classes is 'superclass-table'. To distinguish classes, a
* discriminator is required. (#discriminator)
* - The third mapping is <b>vertical</b>.All classes have its own table
* containing only fields of the class (not the inherited fields). Each table
* of devrived classes must defines a join to its parent (#join). In a vertical
* mapping it is possible and advised to use a discriminator similary than the
* filtered mapping. The strategy of the children is 'new-table'.
*
* @author S.Chassande-Barrioz
*/
public class SpeedoInheritance extends SpeedoElement {
private static final long serialVersionUID = -7618319063954294352L;
public final static int STRATEGY_UNKOWN = -1;
public final static int STRATEGY_NEW_TABLE = 0;
public final static int STRATEGY_SUPERCLASS_TABLE = 1;
public final static int STRATEGY_SUBCLASS_TABLE = 2;
private final static String[] STRATEGY_NAMES = {
"new-table", "superclass-table", "subclass-table"
};
public final static String strategy2str(int s) {
if (-1 < s && s < STRATEGY_NAMES.length) {
return STRATEGY_NAMES[s];
} else {
return null;
}
}
public final static int parseStrategy(String strategyName) {
for (int i = 0; i < STRATEGY_NAMES.length; i++) {
if (STRATEGY_NAMES[i].equals(strategyName)) {
return i;
}
}
return STRATEGY_UNKOWN;
}
/**
* Is the inheritance strategy. It must be defined at initialisation time.
* @see #STRATEGY_NEW_TABLE
* @see #STRATEGY_SUBCLASS_TABLE
* @see #STRATEGY_SUPERCLASS_TABLE
* #see #STRATEGY_UNKOWN
*/
public int strategy;
/**
* Is speedo meta object representing the class with inheritance. It is not
* the parent class but the class which has a parent.
* It must be defined at initialisation time. It must be not null.
*/
public SpeedoClass clazz;
/**
* Super class name.
*/
public String superClassName;
/**
* Is the meta object representing the join to herited table in case of
* vertical mapping. It can be null if the mapping is not 'vertical'.
*/
public SpeedoJoin join;
/**
* is the list of field inherited (SpeedoInheritedField) from ancestors.
* The mapping of these fields are redefined. Typical case whith inherited
* fields correspond to horizontal mapping of the inheritance (one table
* per class).
* key is the field name (could be fully qualified)
* value is a SpeedoInheritedField
*/
public Map remappedInheritedFields;
/**
* In case of filtered of vertical mapping, a discriminator permits to
* distinguish the classes of persistent instances. This field can be null
* if there is no discriminator (horizontal mapping case for instance).
*/
public SpeedoDiscriminator discriminator;
public static final String SPEEDO_DEFAULT_DISCRIMINENT_VALUE = "SPEEDO_DEFAULT_DISCRIMINENT_VALUE";
/**
* In case of there is discriminator, this fields defines the values of the
* discriminator parts.
* key = discriminator part description (SpeedoField or SpeedoNoFieldColumn)
* value = the value of the discriminator part for the current class;
*
* @see SpeedoDiscriminator
* @see SpeedoDiscriminator#elements
*/
public Map discriminatorValues;
public SpeedoInheritance() {
super();
}
public SpeedoInheritance(SpeedoClass moClass) {
this();
this.clazz = moClass;
}
/**
* Adds a SpeedoInheritedField for defining the mapping of an inherited
* field.
* @param sif is the field to add
*/
public void add(SpeedoInheritedField sif) {
if (remappedInheritedFields == null) {
remappedInheritedFields = new HashMap();
}
remappedInheritedFields.put(sif.name, sif);
}
/**
* @param fieldName is the
* @return a new SpeedoInheritedField corresponding to an existing persistent
* and inherited field.
* @throws SpeedoRuntimeException if the field has not been found or if the
* field belong the current class (#clazz).
*/
public SpeedoInheritedField newSpeedoInheritedField(String fieldName)
throws SpeedoRuntimeException {
SpeedoField sf = clazz.getField(fieldName);
//check that the persistent field exists
if (sf == null) {
throw new SpeedoRuntimeException("Field '" + fieldName
+ "' has not been found in the inheritance tree from the class '"
+ clazz.getFQName() + "'.");
}
return newSpeedoInheritedField(sf);
}
public SpeedoInheritedField newSpeedoInheritedField(SpeedoField sf)
throws SpeedoRuntimeException {
//check that the persistent field exists
// checks that the field comes from an ancestor.
if (sf.moClass == clazz) {
throw new SpeedoRuntimeException("Field '" + sf.name
+ "' is not an inherited field, because it is defined in the current class '"
+ clazz.getFQName() + "'.");
}
//create the meta object and fill it.
SpeedoInheritedField sif = new SpeedoInheritedField();
sif.name = sf.getFQFieldName();
sif.inheritedField = sf;
sif.moClass = clazz;
//Add it into #remappedInheritedFields
add(sif);
return sif;
}
public boolean isHorizontalMapping() {
return strategy == STRATEGY_NEW_TABLE && join == null;
}
public boolean isVerticalMapping() {
return strategy == STRATEGY_NEW_TABLE && join != null;
}
public boolean isFilteredMapping() {
return strategy == STRATEGY_SUPERCLASS_TABLE;
}
}