All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.jdo.api.persistence.enhancer.meta.JDOMetaDataProperties Maven / Gradle / Ivy

/*
 * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

//JDOMetaDataProperties - Java Source


//***************** package ***********************************************

package com.sun.jdo.api.persistence.enhancer.meta;


//***************** import ************************************************

import java.lang.reflect.Modifier;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;


//#########################################################################
/**
 *  This class parses properties containing meta data information
 *  about classes. The syntax of the properties is the following:
 *  
  • * the keys in the properties file are fully qualified classnames or * fully qualified fieldnames *
  • * a fields is separated by a classname with a hash mark ('#') * (e.g. "test.Test#test1") *
  • * all classnames are given in a natural form (e.g. "java.lang.Integer", * "java.lang.Integer[][]", "int", "test.Test$Test1") *
  • * property keys are classnames and fieldnames * (e.g. "test.Test=...", "test.Test#field1=...")
    *
  • * Classnames can have the following attributes: *
    • * jdo:{persistent|transactional} *
    • * super: <classname> *
    • * access: {public|protected|package|private} *
  • * Fieldnames can have the following attributes: *
    • * type:<type> *
    • * access: {public|protected|package|private} *
    • * jdo:{persistent|transactional|transient} *
    • * annotation:{pk|dfg|mediated} *
    *
  • * the names of the attributes can be ommitted: you can say
    * test.Test1#field1=jdo:persistent,type:java.lang.String,pk,...
    * or
    * test.Test1#field1=persistent,java.lang.String,pk,...
    * or
    * test.Test1#field1=jdo:persistent,java.lang.String,pk,...
    *
  • * in order to find fields of a class, a line for the class has to be * specified in the properties: To find the field * test.Test1#field, the keys test.Test1 and * test.Test1#Field have to be present. *
* This class is not thread safe. */ //######################################################################### public final class JDOMetaDataProperties { /** * The delimiter of a property key between the class- and fieldname. */ private static final char FIELD_DELIMITER = '#'; /** * A string of delimiter characters between attributes. */ private static final String PROPERTY_DELIMITERS = " \t,;"; /** * A delimiter character between attribute name and attribute value */ private static final char PROPERTY_ASSIGNER = ':'; //attribute names for classes and fields private static final String PROPERTY_ACCESS_MODIFIER = "access"; private static final String PROPERTY_JDO_MODIFIER = "jdo"; private static final String PROPERTY_SUPER_CLASSNAME = "super"; private static final String PROPERTY_OID_CLASSNAME = "oid"; private static final String PROPERTY_TYPE = "type"; private static final String PROPERTY_ANNOTATION_TYPE = "annotation"; //values of the access attribute of classes and fields. private static final String ACCESS_PRIVATE = "private"; private static final String ACCESS_PACKAGE_LOCAL = "package"; private static final String ACCESS_PROTECTED = "protected"; private static final String ACCESS_PUBLIC = "public"; //values of the jdo attribute of classes and fields. private static final String JDO_TRANSIENT = "transient"; private static final String JDO_PERSISTENT = "persistent"; private static final String JDO_TRANSACTIONAL = "transactional"; //values of the annotation type attribute of fields. private static final String ANNOTATION_TYPE_PK = "pk"; private static final String ANNOTATION_TYPE_DFG = "dfg"; private static final String ANNOTATION_TYPE_MEDIATED = "mediated"; /** * The properties to parse. */ private final Properties properties; /** * A map of already read class properties. The keys are the * classnames, the values are the appropriate * JDOClass-object. */ private final Map cachedJDOClasses = new HashMap (); /** * A constant for the cache indicating that a given classname * if not specified in the properties. */ private static final JDOClass NULL = new JDOClass (null); /** * A temporary vector (this is the reason why the implementation is not * thread safe). */ private final List tmpTokens = new ArrayList (); /********************************************************************** * Creates a new object with the given properties. * * @param props The properties. * * @see #properties *********************************************************************/ public JDOMetaDataProperties(Properties props) { this.properties = props; } //JDOMetaDataProperties. /********************************************************************** * Get the information about the class with the given name. * * @param classname The classname. * * @return The information about the class or null if no * information is given. * * @throws JDOMetaDataUserException If something went wrong parsing * the properties. *********************************************************************/ public JDOClass getJDOClass(String classname) throws JDOMetaDataUserException { classname = toCanonicalClassName(classname); JDOClass clazz = (JDOClass) this.cachedJDOClasses.get(classname); if (clazz == NULL) // already searched but not found { return null; } if (clazz != null) { return clazz; } // load it from the properties file String s = this.properties.getProperty(classname); if (s == null) { // class not defined this.cachedJDOClasses.put(classname, NULL); return null; } // the class could be found in the properties clazz = parseJDOClass(classname, s); // parse the class attributes parseJDOFields(clazz); // parse all fields validateDependencies(clazz); // check dependencies this.cachedJDOClasses.put(clazz.getName(), clazz); return clazz; } // JDOMetaDataProperties.getJDOClass() /********************************************************************** * Gets the information about the specified field. * * @param classname The name of the class. * @param fieldname The name of the field of the class. * * @return The information about the field or null if * no information could be found. * * @throws JDOMetaDataUserException If something went wrong parsing * the properties. *********************************************************************/ public JDOField getJDOField(String fieldname, String classname) throws JDOMetaDataUserException { JDOClass clazz = getJDOClass(classname); return (clazz != null ? clazz.getField(fieldname) : null); } // JDOMetaDataProperties.getJDOField() /********************************************************************** * Gets all classnames in the properties. * * @return All classnames in the properties. *********************************************************************/ public String[] getKnownClassNames() { Collection classnames = new HashSet(); for (Enumeration names = this.properties.propertyNames(); names.hasMoreElements();) { String name = (String) names.nextElement(); if (name.indexOf(FIELD_DELIMITER) < 0) { classnames.add(fromCanonicalClassName(name)); } } return (String[]) classnames.toArray(new String[classnames.size()]); } //JDOMetaDataProperties.getKnownClassNames() /********************************************************************** * Converts a classname given in a given VM-similar notation (with slashes) * into a canonical notation (with dots). * * @param The VM-similar notation of the classname. * * @return The canonical classname. * * @see #fromCanonicalClassName *********************************************************************/ private static String toCanonicalClassName(String classname) { return classname.replace('/', '.'); } // JDOMetaDataProperties.toCanonicalClassName() /********************************************************************** * Converts a classname given in a canonical form (with dots) into * a VM-similar notation (with slashes) * * @param classname The canonical classname. * * @return The VM-similar classname notation. * * @see #toCanonicalClassName *********************************************************************/ private static String fromCanonicalClassName(String classname) { return classname.replace('.', '/'); } // JDOMetaDataProperties.fromCanonicalClassName() /********************************************************************** * Parses the attributes-string of a class and puts them into a * JDOClass-object. * * @param classname The name of the class. * @param atributes The attribute-string as specified in the properties. * * @return @return The create JDOClass-object. * * @throws JDOMetaDataUserException If something went wrong parsing * the attributes. *********************************************************************/ private JDOClass parseJDOClass(String classname, String attributes) throws JDOMetaDataUserException { List props = parseProperties(attributes); //check each property for (int i = 0; i < props.size(); i++) { Property prop = (Property) props.get(i); validateClassProperty(prop, classname); } //check dependencies of all properties checkForDuplicateProperties(props, classname); //properties are OK - assign them to the JDOClass object JDOClass clazz = new JDOClass(classname); for (int i = 0; i < props.size(); i++) { Property prop = (Property) props.get(i); if (prop.name.equals(PROPERTY_ACCESS_MODIFIER)) { clazz.modifiers = getModifiers(prop.value); } else if (prop.name.equals(PROPERTY_JDO_MODIFIER)) { clazz.isPersistent = prop.value.equals(JDO_PERSISTENT); } else if (prop.name.equals(PROPERTY_SUPER_CLASSNAME)) { clazz.setSuperClassName(prop.value); } else if (prop.name.equals(PROPERTY_OID_CLASSNAME)) { clazz.setOidClassName(prop.value); } } return clazz; } //JDOMetaDataProperties.parseJDOClass() /********************************************************************** * Checks if the given attribute-property of a class is valid. * * @param prop The attribute-property. * @param classname The classname. * * @throws JDOMetaDataUserException If the validation failed. *********************************************************************/ private static void validateClassProperty(Property prop, String classname) throws JDOMetaDataUserException { String value = prop.value; if (prop.name == null) // try to guess the property name { // check access modifier if (value.equals(ACCESS_PUBLIC) || value.equals(ACCESS_PROTECTED) || value.equals(ACCESS_PACKAGE_LOCAL) || value.equals(ACCESS_PRIVATE)) { prop.name = PROPERTY_ACCESS_MODIFIER; } // check persistence else if (value.equals(JDO_PERSISTENT) || value.equals(JDO_TRANSIENT)) { prop.name = PROPERTY_JDO_MODIFIER; } // assume the the given value is the superclassname else { prop.name = PROPERTY_SUPER_CLASSNAME; } } else { //do we have a valid property name? String name = prop.name; checkPropertyName (prop.name, new String [] { PROPERTY_OID_CLASSNAME, PROPERTY_ACCESS_MODIFIER, PROPERTY_JDO_MODIFIER, PROPERTY_SUPER_CLASSNAME }, classname); //do we have a valid property value? checkPropertyValue (prop, new String [] { ACCESS_PUBLIC, ACCESS_PROTECTED, ACCESS_PACKAGE_LOCAL, ACCESS_PRIVATE }, PROPERTY_ACCESS_MODIFIER, classname); checkPropertyValue (prop, new String [] { JDO_TRANSIENT, JDO_PERSISTENT }, PROPERTY_JDO_MODIFIER, classname); } } //JDOMetaDataProperties.validateClassProperty() /********************************************************************** * Parses all fields of a given class. * * @param clazz The representation of the class. * * @throws JDOMetaDataUserException If something went wrong parsing * the properties. *********************************************************************/ private void parseJDOFields(JDOClass clazz) throws JDOMetaDataUserException { // search for fields of the class for (Enumeration names = this.properties.propertyNames(); names.hasMoreElements();) { String name = (String) names.nextElement(); if (name.startsWith(clazz.getName() + FIELD_DELIMITER)) // field found { String fieldname = name.substring(name.indexOf(FIELD_DELIMITER) + 1, name.length()); validateFieldName(fieldname, clazz.getName()); clazz.addField(parseJDOField(this.properties.getProperty(name), fieldname, clazz)); } } clazz.sortFields(); } //JDOMetaDataProperties.parseJDOField() /********************************************************************** * Parses the attribute-string of a field. * * @param attributes The attribute-string. * @param fieldname The fieldname. * @param clazz The class to field belongs to. * * @throws JDOMetaDataUserException If something went wrong parsing * the attributes. *********************************************************************/ private JDOField parseJDOField(String attributes, String fieldname, JDOClass clazz) throws JDOMetaDataUserException { List props = parseProperties(attributes); // check each property for (int i = 0; i < props.size(); i++) { Property prop = (Property) props.get(i); validateFieldProperty(prop, fieldname, clazz.getName()); } //check dependencies of all properties checkForDuplicateProperties (props, clazz.getName () + FIELD_DELIMITER + fieldname); //properties are OK - assign them to the JDOField object JDOField field = new JDOField(fieldname); for (int i = 0; i < props.size(); i++) { Property prop = (Property) props.get(i); if (prop.name.equals(PROPERTY_ACCESS_MODIFIER)) { field.modifiers = getModifiers(prop.value); } else if (prop.name.equals(PROPERTY_JDO_MODIFIER)) { field.jdoModifier = prop.value; } else if (prop.name.equals(PROPERTY_TYPE)) { field.setType(prop.value); } else if (prop.name.equals(PROPERTY_ANNOTATION_TYPE)) { field.annotationType = prop.value; } } return field; } //JDOMetaDataProperties.parseJDOField() /********************************************************************** * Checks if the given attribute-property if valid for a field. * * @param prop The attribute-property. * @param fieldname The fieldname. * @param classname The classname. * @throws JDOMetaDataUserException If the check fails. *********************************************************************/ private void validateFieldProperty(Property prop, String fieldname, String classname) throws JDOMetaDataUserException { String value = prop.value; if (prop.name == null) // try to guess the property name { // check access modifier if (value.equals(ACCESS_PUBLIC) || value.equals(ACCESS_PROTECTED) || value.equals(ACCESS_PACKAGE_LOCAL) || value.equals(ACCESS_PRIVATE)) { prop.name = PROPERTY_ACCESS_MODIFIER; } // check persistence else if (value.equals(JDO_PERSISTENT) || value.equals(JDO_TRANSIENT) || value.equals(JDO_TRANSACTIONAL)) { prop.name = PROPERTY_JDO_MODIFIER; } // annotation type? else if (value.equals(ANNOTATION_TYPE_PK) || value.equals(ANNOTATION_TYPE_DFG) || value.equals(ANNOTATION_TYPE_MEDIATED)) { prop.name = PROPERTY_ANNOTATION_TYPE; } else { // assume the the given value is the type prop.name = PROPERTY_TYPE; } } else { String entry = classname + FIELD_DELIMITER + fieldname; //do we have a valid property name? checkPropertyName (prop.name, new String [] { PROPERTY_ACCESS_MODIFIER, PROPERTY_JDO_MODIFIER, PROPERTY_TYPE, PROPERTY_ANNOTATION_TYPE }, entry); //do we have a valid property value checkPropertyValue (prop, new String [] { ACCESS_PUBLIC, ACCESS_PROTECTED, ACCESS_PACKAGE_LOCAL, ACCESS_PRIVATE }, PROPERTY_ACCESS_MODIFIER, entry); checkPropertyValue (prop, new String [] { JDO_PERSISTENT, JDO_TRANSIENT, JDO_TRANSACTIONAL }, PROPERTY_JDO_MODIFIER, entry); checkPropertyValue (prop, new String [] { ANNOTATION_TYPE_PK, ANNOTATION_TYPE_DFG, ANNOTATION_TYPE_MEDIATED }, PROPERTY_ANNOTATION_TYPE, entry); } } //JDOMetaDataProperties.validateFieldProperty() /********************************************************************** * Validates dependencies between a class and its fields and between. * * @param clazz The class. * * @throws JDOMetaDataUserException If the validation fails. *********************************************************************/ private void validateDependencies(JDOClass clazz) throws JDOMetaDataUserException { for (int i = clazz.fields.size() - 1; i >= 0; i--) { JDOField field = (JDOField) clazz.fields.get(i); // set the jdo field modifier according to the jdo class modifier (if jdo field not set // yet) if (field.jdoModifier == null) { field.jdoModifier = (clazz.isPersistent() ? JDO_PERSISTENT : JDO_TRANSIENT); } else if (clazz.isTransient()) { // if we have a non-persistent class // non-persistent classes cannot have persistent fields if (field.isPersistent()) { throw new JDOMetaDataUserException( getErrorMsg(IErrorMessages.ERR_TRANSIENT_CLASS_WITH_PERSISTENT_FIELD, new String[] {clazz.getName(), field.getName()})); } //non-persistent classes cannot have transactional fields if (field.isTransactional()) { throw new JDOMetaDataUserException( getErrorMsg(IErrorMessages.ERR_TRANSIENT_CLASS_WITH_TRANSACTIONAL_FIELD, new String[] {clazz.getName(), field.getName()})); } } //a non-persistent class cannot have an annotated field if (field.isAnnotated() && clazz.isTransient()) { throw new JDOMetaDataUserException(getErrorMsg(IErrorMessages.ERR_TRANSIENT_CLASS_WITH_ANNOTATED_FIELD, new String[] {clazz.getName(), field.getName()})); } //a non-persistent field cannot have an annotation type if (!field.isPersistent() && field.isAnnotated()) { field.annotationType = ANNOTATION_TYPE_MEDIATED; } //set the annotation type if not done yet if (!field.isAnnotated() && clazz.isPersistent()) { field.annotationType = ANNOTATION_TYPE_MEDIATED; } } } //JDOMetaDataProperties.validateDependencies() /********************************************************************** * Checks if a given fieldname is a valid Java identifier. * * @param fieldname The fieldname. * @param classname The corresponding classname. * * @throws JDOMetaDataUserException If the check fails. *********************************************************************/ private static void validateFieldName(String fieldname, String classname) throws JDOMetaDataUserException { if (fieldname.length() == 0) { throw new JDOMetaDataUserException( getErrorMsg(IErrorMessages.ERR_EMPTY_FIELDNAME, new String[] {classname})); } if (!Character.isJavaIdentifierStart(fieldname.charAt(0))) { throw new JDOMetaDataUserException( getErrorMsg(IErrorMessages.ERR_INVALID_FIELDNAME, new String[] {classname, fieldname})); } for (int i = fieldname.length() - 1; i >= 0; i--) { final char c = fieldname.charAt(i); if (!Character.isJavaIdentifierPart(c)) { throw new JDOMetaDataUserException( getErrorMsg(IErrorMessages.ERR_INVALID_FIELDNAME, new String[] {classname, fieldname})); } } } //JDOMetaDataProperties.checkFieldName() /********************************************************************** * Checks if an attribute-property was entered twice for a class or field. * * @param props The properties. * @param entry The class- or fieldname. * * @throws JDOMetaDataUserException If the check fails. *********************************************************************/ private static void checkForDuplicateProperties(List props, String entry) throws JDOMetaDataUserException { for (int i = 0; i < props.size(); i++) { for (int j = i + 1; j < props.size(); j++) { Property p1 = (Property) props.get(i); Property p2 = (Property) props.get(j); if (p1.name.equals(p2.name) && !p1.value.equals(p2.value)) { throw new JDOMetaDataUserException(getErrorMsg(IErrorMessages.ERR_DUPLICATE_PROPERTY_NAME, new String[] {entry, p1.name, p1.value, p2.value})); } } } } //JDOMetaDataProperties.checkForDuplicateEntries() /********************************************************************** * Checks if an attribute name is recognized by the parser. * * @param name The name of the attribute. * @param validnames A list of valid names (the attribute name has to * be in this list). * @param entry The class- or fieldname. * * @throws JDOMetaDataUserException If the check fails. *********************************************************************/ private static void checkPropertyName(String name, String[] validnames, String entry) throws JDOMetaDataUserException { for (String validname : validnames) { if (name.equals(validname)) { return; } } throw new JDOMetaDataUserException( getErrorMsg(IErrorMessages.ERR_INVALID_PROPERTY_NAME, new String[] {entry, name})); } //JDOMetaDataProperties.checkPropertyName() /********************************************************************** * Checks if the given value of an attribute-property is recognized by * by the parser if that value belongs to a given attribute name. * * @param prop The attribute-property (with name and value). * @param validvalues A list of valid values. * @param name The name of the attribute-property to check. * @param entry The class- or fieldname. * * @throws JDOMetaDataUserException If the check fails. *********************************************************************/ private static void checkPropertyValue(Property prop, String[] validvalues, String name, String entry) throws JDOMetaDataUserException { if (!prop.name.equals(name)) { return; } for (String validvalue : validvalues) { if (prop.value.equals(validvalue)) { return; } } throw new JDOMetaDataUserException( getErrorMsg(IErrorMessages.ERR_INVALID_PROPERTY_VALUE, new String[] {entry, name, prop.value})); } //JDOMetaDataProperties.checkPropertyValue() /********************************************************************** * Formats an error message with the given parameters. * * @param msg The message with format strings. * @param params The params to format the message with. * * @return The formatted error message. *********************************************************************/ static String getErrorMsg(String msg, String[] params) { return MessageFormat.format(msg, (Object[]) params); } // JDOMetaDataProperties.getErrorMsg() /********************************************************************** * Parses the attribute-string of a class- or fieldname. * * @param attributes The attribute-string. * * @return A list of Propert<-objects for the attributes. * * @exception JDOMetaDataUserException If the parsing fails. *********************************************************************/ List parseProperties(String attributes) throws JDOMetaDataUserException { this.tmpTokens.clear(); StringTokenizer t = new StringTokenizer(attributes, PROPERTY_DELIMITERS); while (t.hasMoreTokens()) { this.tmpTokens.add(parseProperty(t.nextToken())); } return this.tmpTokens; } // JDOMetaDataProperties.getTokens() /********************************************************************** * Parses the given attribute and splits it into name and value. * * @param attribute The attribute-string. * * @return The Propert-object. * * @exception JDOMetaDataUserException If the parsing fails. *********************************************************************/ private Property parseProperty(String attribute) throws JDOMetaDataUserException { Property prop = new Property(); int idx = attribute.indexOf(PROPERTY_ASSIGNER); if (idx < 0) { prop.value = attribute; } else { prop.name = attribute.substring(0, idx); prop.value = attribute.substring(idx + 1, attribute.length()); if (prop.name.length() == 0 || prop.value.length() == 0) { throw new JDOMetaDataUserException( getErrorMsg(IErrorMessages.ERR_EMPTY_PROPERTY_NAME_OR_VALUE, new String[] {attribute})); } } return prop; } // JDOMetaDataProperties.parseProperty() /********************************************************************** * *********************************************************************/ private static int getModifiers(String modifier) { if (modifier.equals(ACCESS_PUBLIC)) { return Modifier.PUBLIC; } if (modifier.equals(ACCESS_PRIVATE)) { return Modifier.PRIVATE; } if (modifier.equals(ACCESS_PROTECTED)) { return Modifier.PROTECTED; } return 0; } // JDOMetaDataProperties.getModifiers() /********************************************************************** * A simple test to run from the command line. * * @param argv The command line arguments. *********************************************************************/ /* public static void main (String [] argv) { if (argv.length != 1) { System.err.println ("Error: no property filename specified"); return; } Properties p = new Properties (); try { java.io.InputStream in = new java.io.FileInputStream (new java.io.File (argv [0])); p.load (in); in.close (); System.out.println ("PROPERTIES: " + p); System.out.println ("############"); JDOMetaDataProperties props = new JDOMetaDataProperties (p); String [] classnames = props.getKnownClassNames (); for (int i = 0; i < classnames.length; i++) { String classname = classnames [i]; System.out.println (classname + ": " + props.getJDOClass (classname)); } } catch (Throwable ex) { ex.printStackTrace (System.err); } } //JDOMetaDataProperties.main() */ //##################################################################### /** * The holder-class for the name and the value of a property. */ //##################################################################### private static final class Property { /** * The name of the property. */ String name = null; /** * The value of the property. */ String value = null; /****************************************************************** * Creates a string-representation of this object. * * @return The string-representation of this object. *****************************************************************/ @Override public String toString() { return '<' + name + ':' + value + '>'; } // Property.toString() } //Property //##################################################################### /** * Holds all unformatted error messages. */ //##################################################################### private interface IErrorMessages { //the unformatted error messages String PREFIX = "Error Parsing meta data properties: "; String ERR_EMPTY_FIELDNAME = PREFIX + "The class ''{0}'' may not have an empty fieldname."; String ERR_INVALID_FIELDNAME = PREFIX + "The field name ''{1}'' of class ''{0}'' is not valid."; String ERR_EMPTY_PROPERTY_NAME_OR_VALUE = PREFIX + "The property name and value may not be empty if a ''" + PROPERTY_ASSIGNER + "'' is specified: ''{0}''."; String ERR_INVALID_PROPERTY_NAME = PREFIX + "Invalid property name for entry ''{0}'': ''{1}''."; String ERR_INVALID_PROPERTY_VALUE = PREFIX + "Invalid value for property ''{1}'' of entry ''{0}'': ''{2}''."; String ERR_DUPLICATE_PROPERTY_NAME = PREFIX + "The property ''{1}'' for the entry ''{0}'' entered twice with values: ''{2}'' and ''{3}''."; String ERR_TRANSIENT_CLASS_WITH_PERSISTENT_FIELD = PREFIX + "A non-persistent class cannot have a persistent field (class ''{0}'' with field ''{1})''."; String ERR_TRANSIENT_CLASS_WITH_TRANSACTIONAL_FIELD = PREFIX + "A non-persistent class cannot have a transactional field (class ''{0}'' with field ''{1})''."; String ERR_TRANSIENT_CLASS_WITH_ANNOTATED_FIELD = PREFIX + "A non-persistent class cannot have an annotated field (''{1}'' of class ''{0}'') can''t have a fetch group."; String ERR_NON_PERSISTENT_ANNOTATED_FIELD = PREFIX + "A non-persistent field (''{1}'' of class ''{0}'') can''t be a annotated."; } //IErrorMessages //##################################################################### /** * A class to hold all parsed attributes of a class. */ //##################################################################### static final class JDOClass { /** * The name of the class. */ private String name; /** * The name of the superclass. */ private String superClassName = null; /** * The name of the oid class. */ private String oidClassName = null; /** * The access modifier. */ private int modifiers = Modifier.PUBLIC; /** * Do we have a persistent class? */ private boolean isPersistent = true; /** * A list of all parsed fields. */ private final List fields = new ArrayList(); /** * */ private String[] managedFieldNames = null; /** * */ private String[] fieldNames = null; /****************************************************************** * Constructs a new object with the given name. * * @param name The name of the class. * @see #name *****************************************************************/ JDOClass(String name) { this.name = name; } // JDOClass. /****************************************************************** * Gets the name of the class. * * @return The name of the class. * * @see #name *****************************************************************/ public String getName() { return this.name; } // JDOClass.getName() /****************************************************************** * *****************************************************************/ public int getModifiers() { return this.modifiers; } // JDOClass.getModifiers() /****************************************************************** * Sets the superclassname. The given classname should have a canonical * form (with dots). It is converted to the CM-similar notation * (with slashes). * * @param classname The superclassname. * @see #superClassName *****************************************************************/ private void setSuperClassName(String classname) { this.superClassName = fromCanonicalClassName(classname); } // JDOClass.setSuperClassName() /****************************************************************** * Gets the superclassname. * * @return The superclassname. * @see #superClassName *****************************************************************/ public String getSuperClassName() { return this.superClassName; } // JDOClass.getSuperClassName() /****************************************************************** * Sets the superclassname. The given classname should have a canonical * form (with dots). It is converted to the CM-similar notation * (with slashes). * * @param classname The superclassname. * @see #superClassName *****************************************************************/ public void setOidClassName(String classname) { this.oidClassName = fromCanonicalClassName(classname); } /****************************************************************** * Gets the oidClassName. * * @return The oidClassName. * @see #oidClassName *****************************************************************/ public String getOidClassName() { return oidClassName; } /****************************************************************** * Do we have a persistent class. * * @return Do we have a persistent class? * @see #isPersistent *****************************************************************/ public boolean isPersistent() { return this.isPersistent; } // JDOMetaClass.isPersistent() /****************************************************************** * Do we have a transient class. * * @return Do we have a transient class? * @see #isPersistent *****************************************************************/ public boolean isTransient() { return !isPersistent(); } // JDOMetaClass.isTransient() /****************************************************************** * Adds a new field. * * @param field The new field. * @see #fields *****************************************************************/ private void addField(JDOField field) { this.fields.add(field); } // JDOClass.addField() /****************************************************************** * Gets the field with the given name. * * @param name The name of the requested field. * @return The field or null if not found. * @see #fields *****************************************************************/ public JDOField getField(String name) { int idx = getIndexOfField(name); return (idx > -1 ? (JDOField) this.fields.get(idx) : null); } // JDOField.getField() /****************************************************************** * Gets the index of the field with the given name. * * @param name The name of the field. * @return The index or -1 if the field was not found. * @see #fields *****************************************************************/ public int getIndexOfField(String name) { for (int i = 0; i < this.fields.size(); i++) { JDOField field = (JDOField) this.fields.get(i); if (field.getName().equals(name)) { return i; } } return -1; } // JDOClass.getIndexOfField() /****************************************************************** * Gets all fields of this class. * * @return The fields. * @see #fields *****************************************************************/ public String[] getFields() { if (this.fieldNames == null) { final int n = this.fields.size(); String[] fields = new String[n]; for (int i = 0; i < n; i++) { fields[i] = ((JDOField) this.fields.get(i)).getName(); } this.fieldNames = fields; } return this.fieldNames; } // JDOClass.getFields() /****************************************************************** * Sorts the fields of this class according to the names. This method * should be called if all fields are added. It is necessary to * establish an order on the fields. * * @see #fields *****************************************************************/ private void sortFields() { Collections.sort(this.fields, new Comparator() { @Override public final int compare(Object f1, Object f2) { JDOField field1 = (JDOField) f1; JDOField field2 = (JDOField) f2; // if we dont have managed fields we dont care if (!(field1.isManaged() && field2.isManaged())) { return (field1.isManaged() ? -1 : 1); } return (field1).getName().compareTo(field2.getName()); } }); } // JDOClass.sortFields() /****************************************************************** * Gets a list of persistent field names of this class. * * @return The persistent fieldnames. * * @see #fields *****************************************************************/ public String[] getManagedFieldNames() { if (this.managedFieldNames == null) { final int n = this.fields.size(); List tmp = new ArrayList(n); for (int i = 0; i < n; i++) { JDOField field = (JDOField) this.fields.get(i); if (field.isManaged()) { tmp.add(field.getName()); } } this.managedFieldNames = (String[]) tmp.toArray(new String[tmp.size()]); } return this.managedFieldNames; } // JDOClass.getManagedFieldNames() /****************************************************************** * Creates a string-representation for this object. * * @return The string-representation of this object. *****************************************************************/ @Override public String toString() { return '<' + PROPERTY_SUPER_CLASSNAME + ':' + this.superClassName + ',' + PROPERTY_ACCESS_MODIFIER + ':' + Modifier.toString (this.modifiers) + ',' + PROPERTY_JDO_MODIFIER + ':' + this.isPersistent + ',' + "fields:" + this.fields + '>'; } //JDOClass.toString() } //JDOClass //##################################################################### /** * A class to hold the properties of a field. */ //##################################################################### static final class JDOField { /** * The name of the field. */ private String name; /** * The type of the field. */ private String type = null; /** * The access modifier of the field. */ private int modifiers = Modifier.PRIVATE; /** * The JDO modifier of the field. */ private String jdoModifier = null; /** * The annotation type. */ private String annotationType = null; /****************************************************************** * Creates a new object with the given name. * * @param name The name of the field. * * @see #name *****************************************************************/ JDOField(String name) { this.name = name; } // JDOField. /****************************************************************** * Gets the name of the field. * * @return The name of the field. * * @see #name *****************************************************************/ public String getName() { return this.name; } // JDOField.getName() /****************************************************************** * Sets the type of the field. The given classname should have a * natural form (with dots) and is converted to a VM-similar * notation (with slashes). * * @param type The natural classname. * * @see #type *****************************************************************/ public void setType(String type) { this.type = fromCanonicalClassName(type); } // JDOField.setType() /****************************************************************** * Gets the type of the field. * * @return The type of the field. * * @see #type *****************************************************************/ public String getType() { return this.type; } // JDOField.getType() /****************************************************************** * *****************************************************************/ public int getModifiers() { return this.modifiers; } // JDOField.getModifiers() /****************************************************************** * Do we have an annotated field? * * @return Do we have an annotated field? * @see #annotationType *****************************************************************/ public boolean isAnnotated() { return this.annotationType != null; } // JDOField.isAnnotated() /****************************************************************** * Do we have a primary key? * * @return Do we have a primary key? * @see #annotationType *****************************************************************/ public boolean isPk() { return (this.annotationType != null && this.annotationType.equals(ANNOTATION_TYPE_PK)); } // JDOField.isPk() /****************************************************************** * Is the field in the default fetch group? * * @return Is the field in the default fetch group? * @see #annotationType *****************************************************************/ public boolean isInDefaultFetchGroup() { return (this.annotationType != null && this.annotationType.equals(ANNOTATION_TYPE_DFG)); } // JDOField.isInDefaultFetchGroup() /****************************************************************** * Returns whether the field is declared transient. * * @return true if declared transient field. * @see #jdoModifier */ public boolean isKnownTransient() { return (jdoModifier != null && jdoModifier.equals(JDO_TRANSIENT)); } /****************************************************************** * Do we have a persistent field. * * @return Do we have a persistent field. * @see #jdoModifier *****************************************************************/ public boolean isPersistent() { return (this.jdoModifier != null && this.jdoModifier.equals(JDO_PERSISTENT)); } // JDOField.isPersistent() /****************************************************************** * Do we have a transactional field. * * @return So we have a transactional field? * @see #jdoModifier *****************************************************************/ public boolean isTransactional() { return (this.jdoModifier != null && this.jdoModifier.equals(JDO_TRANSACTIONAL)); } // JDOField.isTransactional() /****************************************************************** * Do we have a managed field? * * @return Do we have a managed field? *****************************************************************/ public boolean isManaged() { return (isPersistent() || isTransactional()); } // JDOField.isManaged() /****************************************************************** * Creates a string-representation of the object. * * @return The string-representation of the object. *****************************************************************/ @Override public String toString() { return '<' + "name:" + this.name + ',' + PROPERTY_TYPE + ':' + this.type + ',' + PROPERTY_ACCESS_MODIFIER + ':' + Modifier.toString (this.modifiers) + ',' + PROPERTY_JDO_MODIFIER + ':' + this.jdoModifier + ',' + PROPERTY_ANNOTATION_TYPE + ':' + this.annotationType + '>'; } //JDOField.toString() } //JDOField } //JDOMetaDataProperties




© 2015 - 2025 Weber Informatics LLC | Privacy Policy