Package org.objectweb.speedo.metadata

Source Code of org.objectweb.speedo.metadata.SpeedoClass

/**
* Speedo: an implementation of JDO compliant personality on top of JORM generic
* I/O sub-system.
* Copyright (C) 2001-2004 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
*
*
*
* Contact: speedo@objectweb.org
*
* Authors: S.Chassande-Barrioz.
*
*/

package org.objectweb.speedo.metadata;

import org.objectweb.jorm.metainfo.api.Class;
import org.objectweb.speedo.api.SpeedoException;
import org.objectweb.speedo.api.SpeedoRuntimeException;
import org.objectweb.speedo.mim.api.HomeItf;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
* Describes a persistence capable class.
*
* @author S.Chassande-Barrioz
*/
public class SpeedoClass extends SpeedoElement {
  /**
   * The class has been previously enhanced and no additional operation is
   * required.
   */
  public final static byte ALREADY_ENHANCED = 1;

  /**
   * The enhancement is required.
   */
  public final static byte ENHANCEMENT_REQUIRED = 2;

  /**
   * The enhancement of the class has failed.
   */
  public final static byte ENHANCEMENT_FAILED = 3;

  /**
   * The persistent class has no no-arg constructor.
   */
  public final static byte NO_NO_ARG_CONSTRUCTOR = 1;

  /**
   * The persistent class has no-arg constructor but it is not public
   */
  public final static byte NON_PUBLIC_NO_ARG_CONSTRUCTOR = 2;

  /**
   * The persistent class has a public no-arg constructor.
   */
  public final static byte PUBLIC_NO_ARG_CONSTRUCTOR = 3;

  /**
   * Class name.
   */
  public String name;

  /**
   * Class name for queries.
   */
  public String nameForQuery;

  /**
   * Description of the package which contains this class.
   */
  public SpeedoPackage moPackage;

  /**
   * Defines the identifier of the persistent class.
   */
  public SpeedoIdentity identity;

  /**
   * Defines the field used for database optimitic locking policy.
   */
  public SpeedoField versionField;

  /**
   * Defines the inheritance strategy if this class inherits from a persistent
   * class.
   */
  public SpeedoInheritance inheritance;

  /**
   * Description of the version.
   */
  public SpeedoVersion version;

  /**
   * Attribute detachable.
   */
  public boolean isDetachable;

  /**
   * Description of persistent capable fields of this class. The HashMap key
   * is the field name.
   */
  public Map fields;

  /**
   * Description of fetchgroups defined for this class. The HashMap key is the
   * field name.
   */
  public Map fetchGroups;

  /**
   * Indicates if the class is abstract.
   */
  public boolean isAbstract;

  /**
   * Indicates if the class implements InstanceCallbacks
   */
  public boolean isInstanceCallbacks;

  /**
   * Indicates if the class implements Serailizable
   */
  public boolean isSerializable;

  /**
   * JORM meta object corresponding to this Speedo meta object.
   */
  public Class jormclass;

  /**
   * Register some callback methods and their associated application method to
   * which the callback is mapped.
   * It contains an Integer key identifying a particular callback, which is associated
   * with an ArrayList of methods to be called when this callback is fired.
   * Such methods are specified through a metaobject specifying the callback:
   * @see SpeedoCallback
   * @see HomeItf#PRE_NEW
   */
  public HashMap callBacks;

  /**
   * Number of fields of this class (including inherited fields).
   */
  private int fieldsCount = -1;

  /**
   * Number of fields composing the primary key
   */
  private int pkFieldsCount = -1;

  /**
   * Specify the status of the persistent class with regards to the
   * enhancement process. The 3 only possible state are #ALREADY_ENHANCED,
   * #ENHANCEMENT_REQUIRED or #ENHANCEMENT_FAILED.
   *
   * @see #ALREADY_ENHANCED
   * @see #ENHANCEMENT_REQUIRED
   * @see #ENHANCEMENT_FAILED
   */
  public byte enhancementStatus = ENHANCEMENT_REQUIRED;

  /**
   * Contains the predefined query key = a query name value = the
   * SpeedoPredefinedQuery instance
   *
   * @see SpeedoPredefinedQuery
   */
  public Map name2query;

  /**
   * Qualifies the status of the no-arg constructor of the persistent class.
   *
   * @see #NO_NO_ARG_CONSTRUCTOR
   * @see #NON_PUBLIC_NO_ARG_CONSTRUCTOR
   * @see #PUBLIC_NO_ARG_CONSTRUCTOR
   */
  public byte noArgConstructorStatus = NO_NO_ARG_CONSTRUCTOR;

  /**
   * The main table of the persistent class. External tables are reachable
   * from joins.
   *
   * @see #joinToExtTables
   */
  public SpeedoTable mainTable;

  /**
   * Is the join to reach external tables. It can be null if there is no
   * external table.
   */
  public SpeedoJoin[] joinToExtTables;

  //TODO: Seb --> remove this method for next commit
  public String getObjectidClass() {   
        return identity.objectidClass;   
  }
 
 
  /**
   * @return the fully qualified name of the class (include the package name)
   *         the package separator is a dot
   */
  public String getFQName() {
    if (moPackage.name == null || moPackage.name.length() == 0) {
      return name;
    } else {
      return moPackage.name + "." + name;
    }
  }

  /**
   * Transforms a SpeedoClass into a String.
   *
   * @return the Sting corresponding to the SpeedoClass.
   */
  public String toString() {
    String s = ("\n class name : " + name + ", identityType : "
        + getIdentityType() + ", objectidClass : " + identity.objectidClass
        + ",version : " + version + ", persistenceCapableSuperClass : " + getSuperClassName());
    s += ", \t fields:[";
    Iterator it = fields.values().iterator();
    while (it.hasNext()) {
      s = s + "\t" + it.next().toString();
    }
    s += "], \t fetchGroups:[";
    Iterator it2 = fetchGroups.values().iterator();
    while (it2.hasNext()) {
      s += "\t" + it2.next().toString();
    }
    s += "]";
    return s;
  }

  public boolean enhancementFailed() {
    return enhancementStatus == ENHANCEMENT_FAILED;
  }

  public boolean isAlreadyEnhanced() {
    return enhancementStatus == ALREADY_ENHANCED;
  }

  public void setAlreadyEnhanced(boolean v) {
    if (v && enhancementStatus == ENHANCEMENT_REQUIRED) {
      enhancementStatus = ALREADY_ENHANCED;
    }
  }

  public boolean requireEnhancement() {
    return enhancementStatus == ENHANCEMENT_REQUIRED;
  }

  public void setRequireEnhancement(boolean v) {
    if (v && enhancementStatus == ALREADY_ENHANCED) {
      enhancementStatus = ENHANCEMENT_REQUIRED;
    }
  }

  /**
   * Adds a SpeedoField to the class. Precondition: this field doesn't exist
   * in the jdoFields HashMap.
   *
   * @param field
   *            field to add.
   */
  public void add(Object field) {
    SpeedoField f = (SpeedoField) field;
    f.moClass = this;
    f.number = fieldsCount++;
    fields.put(f.name, field);
  }

  /**
   * Adds a SpeedoField to the class.
   *
   * @param field
   *            field to add.
   * @param failsOnError
   *            if an error must be thrown or creates a warning.
   * @param logger
   *            logger for writting warn message if necessary.
   * @exception SpeedoException
   *                if the field was already defined into the class.
   */
  public void add(Object field, boolean failsOnError, Logger logger)
      throws SpeedoException {
    SpeedoField f = (SpeedoField) field;
    if (fields.containsKey(f.name)) {
      if (failsOnError)
        throw new SpeedoException("The field " + f.name + " of class "
            + name + " is defined twice.");
      else
        logger.log(BasicLevel.ERROR, "The field " + f.name
            + " of class " + name + " is defined twice.");
    } else {
      logger.log(BasicLevel.DEBUG, "Add the field '" + f.name
          + "' in class '" + name + "'.");
      f.moClass = this;
      fields.put(f.name, field);
    }
  }

  public void setDatastoreIdSequenceName(String sequenceName) {
    identity.setDatastoreIdSequenceName(sequenceName);
  }

  /**
   * Adds a SpeedoFetchGroup to the class. Precondition: this fetchgroup
   * doesn't exist in the jdoFtechGroups HashMap.
   *
   * @param fetchGroup
   *            the fetchgroup to add.
   */
  public void addFetchGroup(Object fetchGroup) {
    SpeedoFetchGroup fg = (SpeedoFetchGroup) fetchGroup;
    fetchGroups.put(fg.name, fetchGroup);
  }

  /**
   * Adds a SpeedoFetchgroup to the class.
   *
   * @param fetchGroup
   *            the fetchgroup to add.
   * @param failsOnError
   *            if an error must be thrown or creates a warning.
   * @param logger
   *            logger for writting warn message if necessary.
   * @exception SpeedoException
   *                if the field was already defined into the class.
   */
  public void addFetchGroup(Object fetchGroup, boolean failsOnError,
      Logger logger) throws SpeedoException {
    SpeedoFetchGroup fg = (SpeedoFetchGroup) fetchGroup;
    if (fetchGroups.containsKey(fg.name)) {
      if (failsOnError)
        throw new SpeedoException("The fetchgroup " + fg.name
            + " of class " + name + " is defined twice.");
      else
        logger.log(BasicLevel.ERROR, "The fetchgroup " + fg.name
            + " of class " + name + " is defined twice.");
    } else {
      logger.log(BasicLevel.DEBUG, "Add the fetchgroup '" + fg.name
          + "' in class '" + name + "'.");
      fetchGroups.put(fg.name, fetchGroup);
    }
  }

  /**
   * Computes the field numbers for the fields of this class.
   *
   * @return the number of fields of this class (including inherited fields).
   */
  public int computeFieldNumbers() {
    if (fieldsCount != -1) {
      return fieldsCount;
    }
    if (getSuperClassName() == null) {
      fieldsCount = 0;
    } else {
      SpeedoClass jdoSuperClass = moPackage.xmlDescriptor.smi
          .getSpeedoClass(getSuperClassName(), moPackage);
      if (jdoSuperClass == null) {
        throw personality.newUserRuntimeException(
            "The persistence-capable-superclass field has a bad value: '"
                + getSuperClassName()
                + "'. See the description of the class '"
                + getFQName() + "' from the file '"
                + getXMLFileName() + "'.");
      }
      fieldsCount = jdoSuperClass.computeFieldNumbers();
    }
    Iterator i = fields.values().iterator();
    while (i.hasNext()) {
      SpeedoField jf = (SpeedoField) i.next();
      jf.number = fieldsCount++;
    }
    return fieldsCount;
  }

  public String getJormFileName() {
    return getFQName().replace('.', File.separatorChar) + ".pd";
  }

  public boolean generateObjectId() {
    return getPkFieldCount() > 1;
  }

  public int getPkFieldCount() {
    if (pkFieldsCount == -1) {
      pkFieldsCount = 0;
      if (getIdentityType() == SpeedoIdentity.USER_ID
          && (identity.objectidClass == null || identity.objectidClass
              .length() == 0)) {
        Iterator it = fields.values().iterator();
        while (it.hasNext()) {
          if (((SpeedoField) it.next()).primaryKey) {
            pkFieldsCount++;
          }
        }
      }
    }
    return pkFieldsCount;
  }
 
  public List getPKFields() {
        SpeedoClass parent = getSuper();
        List idFields;
        if (parent == null) {
            idFields = new ArrayList();
        } else {
            idFields = parent.getPKFields();
        }
        Iterator fieldsIt = fields.values().iterator();
        while (fieldsIt.hasNext()) {
            SpeedoField f = (SpeedoField) fieldsIt.next();
            if (f.primaryKey) {
                idFields.add(f);
            }
        }
        return idFields;
  }

  /**
   * Find in the class or in its parent, the unique persistent field marked as
   * primary key.
   *
   * @return the unique pk fields if it exists one, null otherwise.
   * @throws SpeedoException
   *             if there are several persistent fields marked as primary key.
   */
  public SpeedoField getUniquePKField() throws SpeedoException {
    final ArrayList al = new ArrayList();
    for (Iterator it = fields.values().iterator(); it.hasNext();) {
      SpeedoField sf = (SpeedoField) it.next();
      if (sf.primaryKey) {
        al.add(sf);
      }
    }
    final int s = al.size();
    if (s == 0) {
      if (getSuper() != null) {
        return getSuper().getUniquePKField();
      }
      return null;
    } else if (s > 1) {
      throw new SpeedoException(
          "several fields have been marked as primary-key "
              + al + " in the " + getSourceDesc() + ".");
    }
    return (SpeedoField) al.get(0);
  }

  public SpeedoClass getSpeedoClassFromContext(String className) {
    return moPackage.xmlDescriptor.smi.getSpeedoClass(className, moPackage);
  }

  public String getXMLFileName() {
    return moPackage.xmlDescriptor.xmlFile;
  }

  public SpeedoClass getSuper() {
    if (getSuperClassName() == null) {
      return null;
    } else {
      return getSpeedoClassFromContext(getSuperClassName());
    }
  }
 
  public SpeedoField getInheritedField(String name) {
    SpeedoClass sc = getSuper();
    if (sc == null) {
      return null;
    }
    return sc.getField(name);
  }

  public SpeedoClass getAncestor() {
    SpeedoClass tmp = getSuper();
    SpeedoClass ancestor = null;
    while (tmp != null && ancestor != tmp) {
      ancestor = tmp;
      tmp = tmp.getSuper();
    }
    return ancestor;
  }
   
  /**
   * Finds a field from its name. The fields can belong this class or an
   * ancestor of this class.
   *
   * @param fieldName
   *            is the name of a persistent field. the name can be fully
   *            qualified (ie the field name is prefixed by the class name,
   *            the separator is a dot or #)
   * @return the SpeedoField instance if it has been found., otherwise null
   */
  public SpeedoField getField(String fieldName) {
    int idx = fieldName.lastIndexOf('.');
    SpeedoField sf;
    if (idx == -1) {
      idx = fieldName.lastIndexOf('#');
    }
    if (idx != -1) {
      // the specified field name is a fully qualified name (include class
      // name)
      String className = fieldName.substring(0, idx);
      String fn = fieldName.substring(idx + 1);
      SpeedoClass sc = getSpeedoClassFromContext(className);
      if (sc != null) {
        // The class has been found, searches in the field in this class
        // (recusivity)
        return sc.getField(fn);
      } else {
        return null;
      }
    }
    sf = (SpeedoField) fields.get(fieldName);
    if (sf == null && getSuperClassName() != null) {
      // try in the parent
      sf = getSuper().getField(fieldName);
    }
    return sf;
  }
    public SpeedoField getFieldFromColumn(String colname) {
        for (Iterator it = fields.values().iterator(); it.hasNext();) {
            SpeedoField sf = (SpeedoField) it.next();
            if (sf.columns == null) {
                continue;
            }
            for (int i = 0; i < sf.columns.length; i++) {
                if (sf.columns[i].table == mainTable
                        && colname.equals(sf.columns[i].name)) {
                    return sf;
                }
            }
        }
        return null;
    }

  public void setIdentityType(byte identityType) {
    identity.strategy = identityType;
  }

  public byte getIdentityType() {
    return identity.strategy;
  }

  public void setSuperClassName(String superClassName) throws SpeedoException {
      if (superClassName != null) {
      if (inheritance == null) {
        inheritance = new SpeedoInheritance();
        inheritance.clazz = this;
      }
      this.inheritance.superClassName = superClassName;
      }
  }

  public String getSuperClassName() {
    if (inheritance == null) {
      return null;
    } else {
      return inheritance.superClassName;
    }
  }

    public void addJoin(SpeedoJoin j) {
        joinToExtTables = (SpeedoJoin[])
            addInArray(j, joinToExtTables, SpeedoJoin[].class);
    }
    public void removeJoin(SpeedoJoin j) {
        joinToExtTables = (SpeedoJoin[])
            removeInArray(j, joinToExtTables, SpeedoJoin[].class);
    }

  public String getSourceDesc() {
    StringBuffer sb = new StringBuffer();
    sb.append("class '").append(getFQName());
    sb.append("' in desc '");
    sb.append(moPackage.xmlDescriptor.xmlFile).append("'");
    return sb.toString();
  }

  public String getSourceDescShort() {
    StringBuffer sb = new StringBuffer();
    sb.append("[").append(getFQName()).append("]");
    return sb.toString();
  }

    public SpeedoJoin getJoin(String tableName) {
        if (joinToExtTables != null) {
            for (int i = 0; i < joinToExtTables.length; i++) {
                if (joinToExtTables[i].extTable.name.equals(tableName)) {
                    return joinToExtTables[i];
                }
            }
        }
        return null;
    }
    public SpeedoJoin getJoin(String tableName, boolean createifnone) {
        SpeedoJoin join = getJoin(tableName);
        if (createifnone && join == null) {
            join = new SpeedoJoin();
            join.mainTable = mainTable;
            join.extTable = new SpeedoTable();
            join.extTable.name = tableName;
            addJoin(join);
        }
        return join;
    }
    public int getJoinIndex(SpeedoJoin join) {
        if (joinToExtTables != null) {
            for (int i = 0; i < joinToExtTables.length; i++) {
                if (joinToExtTables[i].equals(join)) {
                    return i;
                }
            }
        }
        return -1;
    }
    public boolean containsJoin(SpeedoJoin join) {
        return getJoinIndex(join) != -1;
    }
    public SpeedoTable getExtTable(String tableName, boolean createifnone) {
        SpeedoJoin join = getJoin(tableName, createifnone);
        return join == null ? null : join.extTable;
    }
 
  /**
   * Look for a column with a given name defined into the given SpeedoClass.
   *
   * @param colname  The name of the column.
   * @param mainonly  Speficy if we must look only for main table columns.
   * @return      The column found or null if none.
   */
  public SpeedoColumn getColumn(String colname, boolean mainonly) {
    for (Iterator it = fields.values().iterator(); it.hasNext();) {
      SpeedoField sf = (SpeedoField) it.next();
      if (sf.columns == null) {
          continue;
      }
      for (int i = 0; i < sf.columns.length; i++) {
        if (mainonly && (sf.columns[i].table != mainTable)) {
          continue;
        }
        if (sf.columns[i].name == null) {
            continue;
        }
        if (colname.equals(sf.columns[i].name)) {
          return sf.columns[i];
        }
      }
    }
    return null;
  }
 
  public List getTableIndexes() {
      ArrayList indexes = new ArrayList();
        if (mainTable != null) {
          indexes.addAll(mainTable.indexes);
        }
        if (joinToExtTables != null) {
          //get the indexes of the joins
          for(int i = 0; i < joinToExtTables.length; i++) {
            indexes.addAll(joinToExtTables[i].extTable.indexes);
          }
        }
        return indexes;
  }
  public List getParents() {
      SpeedoClass c = getSuper();
      if (c == null) {
          return Collections.EMPTY_LIST;
      }
      List parents = new ArrayList();
      while(c != null) {
          parents.add(0, c);
          c = c.getSuper();
      }
      return parents;
  }
}
TOP

Related Classes of org.objectweb.speedo.metadata.SpeedoClass

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.