Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModelFactory.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModelFactory.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModelFactory.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaModelFactory.java Fri Mar 18 17:02:29 2005 @@ -0,0 +1,277 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jdo.impl.model.java.runtime; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.lang.reflect.Field; + +import javax.jdo.spi.JDOImplHelper; +import javax.jdo.spi.JDOPermission; + +import org.apache.jdo.model.ModelException; +import org.apache.jdo.model.ModelFatalException; +import org.apache.jdo.model.java.JavaModel; +import org.apache.jdo.model.java.JavaModelFactory; +import org.apache.jdo.model.java.JavaType; +import org.apache.jdo.model.jdo.JDOModelFactory; +import org.apache.jdo.impl.model.java.AbstractJavaModelFactory; +import org.apache.jdo.impl.model.java.ReflectionJavaType; +import org.apache.jdo.impl.model.jdo.caching.JDOModelFactoryImplCaching; +import org.apache.jdo.util.I18NHelper; + +/** + * A reflection based JavaModelFactory implementation used at runtime. + * The implementation takes <code>java.lang.Class</code> and + * <code>java.lang.reflect.Field</code> instances to get Java related + * metadata about types and fields. This implementation caches JavaModel + * instance sper ClassLoader. + * <p> + * RuntimeJavaModelFactory implements the singleton pattern; method + * [EMAIL PROTECTED] #getInstance()} provides access to the singleton factory + * instance. This method also registers a model listener at the + * JDOImplHelper to handle the runtime metadata as generated by the + * enhancer. + * + * @author Michael Bouschen + * @since JDO 1.0.1 + */ +public class RuntimeJavaModelFactory + extends AbstractJavaModelFactory +{ + /** The singleton RuntimeJavaModelFactory instance. */ + private static final RuntimeJavaModelFactory runtimeJavaModelFactory = + new RuntimeJavaModelFactory(); + + /** I18N support */ + private final static I18NHelper msg = + I18NHelper.getInstance("org.apache.jdo.impl.model.java.Bundle"); //NOI18N + + /** */ + static + { + // initialize RuntimeJavaModelFactory singleton instance + try { + JDOImplHelper helper = + (JDOImplHelper) AccessController.doPrivileged( + new PrivilegedAction () { + public Object run () { + return JDOImplHelper.getInstance(); + } + } + ); + // register listener to JDOImplHelpers class registration + RegisterClassListener crl = new RegisterClassListener( + helper, runtimeJavaModelFactory); + helper.addRegisterClassListener(crl); + } + catch (SecurityException ex) { + throw new ModelFatalException( + msg.msg("EXC_CannotGetJDOImplHelper"), ex); // NOI18N + } + } + + /** + * Creates a new RuntimeJavaModelFactory. This constructor should not + * be called directly; instead, the singleton access method + * [EMAIL PROTECTED] #getInstance()} should be used. + */ + protected RuntimeJavaModelFactory() {} + + /** + * Returns the singleton instance of RuntimeJavaModelFactory. On first + * call it registers a model listener at the JDOImplHelper. + * This method checks that the caller is authorized for + * <code>JDOPermission("getMetadata")</code>, and if not, throws + * <code>ModelFatalException</code> wrapping the SecurityException. + * @return RuntimeJavaModelFactory instance + * @exception ModelFatalException if the caller does not have the + * getMetadata permission. + */ + public static RuntimeJavaModelFactory getInstance() + throws ModelFatalException + { + // first check whether caller has the getMetadata permission + SecurityManager sec = System.getSecurityManager(); + if (sec != null) { + try { + // throws exception if caller is not authorized + sec.checkPermission(JDOPermission.GET_METADATA); + } + catch (SecurityException ex) { + throw new ModelFatalException( + msg.msg("EXC_CannotGetRuntimeJavaModelFactory"), ex); // NOI18N + } + } + + return runtimeJavaModelFactory; + } + + /** + * Creates a new empty JavaModel instance. A factory implementation may + * use the specified key when caching the new JavaModel instance. + * <p> + * This implementation only accepts <code>java.lang.ClassLoader</code> + * instances as key and does not support <code>null</code> keys. A + * ModelException indicates an invalid key. + * <p> + * The method automatically sets the parent/child relationship for the + * created JavaModel according to the parent/child relationship of the + * ClassLoader passed as key. + * @param key the key that may be used to cache the returned JavaModel + * instance. + * @return a new JavaModel instance. + * @exception ModelException if impossible; the key is of an + * inappropriate type or the key is <code>null</code> and this + * JavaModelFactory does not support <code>null</code> keys. + */ + public JavaModel createJavaModel(Object key) + throws ModelException + { + if ((key == null) || (!(key instanceof ClassLoader))) + throw new ModelException(msg.msg("EXC_InvalidJavaModelKey", //NOI18N + (key==null?"null":key.getClass().getName()))); + + ClassLoader classLoader = (ClassLoader)key; + JavaModel javaModel = new RuntimeJavaModel(classLoader); + + // check parent <-> child relationship + if (classLoader != ClassLoader.getSystemClassLoader()) { + // if the specified classLoader is not the system class loader + // try to get the parent class loader and update the parent property + try { + ClassLoader parentClassLoader = classLoader.getParent(); + if (parentClassLoader != null) { + javaModel.setParent(getJavaModel(parentClassLoader)); + } + } + catch (SecurityException ex) { + // ignore => parentClassLoader and parent JavaModel are null + } + } + return javaModel; + } + + /** + * Returns the JavaModel instance for the specified key. + * @param key the key used to cache the returned JavaModel instance + */ + public JavaModel getJavaModel(Object key) + { + if (key == null) { + // null classLoader might happen for classes loaded by the + // bootstrap class loder + key = ClassLoader.getSystemClassLoader(); + } + return super.getJavaModel(key); + } + + /** + * Returns a JavaType instance for the specified type description + * (optional operation). This method is a convenience method and a + * short cut for <code>getJavaModel(key).getJavaType(typeName)</code>. + * <p> + * The RuntimeJavaModelFactory supports this short cut and accepts + * <code>java.lang.Class</code> instances as valid arguments for this + * method. The method throws a + * [EMAIL PROTECTED] org.apache.jdo.model.ModelFatalException}, if the specified + * type descriptor is not a <code>java.lang.Class</code> instance. + * @param typeDesc the type description + * @return a JavaType instance for the specified type. + * @exception ModelFatalException the specified type description is not + * a <code>java.lang.Class</code> instance. + */ + public JavaType getJavaType(Object typeDesc) + { + if (typeDesc == null) + return null; + + try { + Class clazz = (Class)typeDesc; + ClassLoader classLoader = getClassLoaderPrivileged(clazz); + return getJavaModel(classLoader).getJavaType(clazz); + } + catch (ClassCastException ex) { + throw new ModelFatalException(msg.msg("EXC_InvalidTypeDesc", //NOI18N + typeDesc.getClass().getName())); + } + } + + // ===== Methods not defined in JavaModelFactory ===== + + /** + * Calls getClassLoader on the specified class instance in a + * doPrivileged block. Any SecurityException is wrapped into a + * ModelFatalException. + * @return the class loader that loaded the specified class instance. + * @exception ModelFatalException wraps the SecurityException thrown by + * getClassLoader. + */ + public ClassLoader getClassLoaderPrivileged(final Class clazz) + { + if (clazz == null) + return null; + + try { + return (ClassLoader) AccessController.doPrivileged( + new PrivilegedAction () { + public Object run () { + return clazz.getClassLoader(); + } + } + ); + } + catch (SecurityException ex) { + throw new ModelFatalException( + msg.msg("EXC_CannotGetClassLoader", clazz), ex); //NOI18N + } + } + + /** + * Returns the <code>java.lang.Class</code> wrapped in the specified + * JavaType. + * @return the <code>java.lang.Class</code> for the specified + * JavaType. + * @exception ModelFatalException the specified JavaType does + * not wrap a <code>java.lang.Class</code> instance. + */ + public Class getJavaClass(JavaType javaType) + { + if (javaType == null) + return null; + + try { + return ((ReflectionJavaType)javaType).getJavaClass(); + } + catch (ClassCastException ex) { + throw new ModelFatalException(msg.msg( + "EXC_InvalidJavaType", javaType.getClass())); //NOI18N + } + } + + //========= Internal helper methods ========== + + /** + * Returns the JDOModelFactory instance used to get/create JDOModel + * instances. + * @return JDOModelFactory instance. + */ + protected JDOModelFactory getJDOModelFactory() + { + return JDOModelFactoryImplCaching.getInstance(); + } +}
Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaType.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaType.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaType.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/RuntimeJavaType.java Fri Mar 18 17:02:29 2005 @@ -0,0 +1,279 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jdo.impl.model.java.runtime; + +import java.util.Map; +import java.util.HashMap; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import java.lang.reflect.Field; + +import org.apache.jdo.impl.model.java.PredefinedType; +import org.apache.jdo.impl.model.java.ReflectionJavaField; +import org.apache.jdo.impl.model.java.ReflectionJavaType; +import org.apache.jdo.model.ModelFatalException; +import org.apache.jdo.model.java.JavaField; +import org.apache.jdo.model.java.JavaModel; +import org.apache.jdo.model.java.JavaModelFactory; +import org.apache.jdo.model.java.JavaType; +import org.apache.jdo.model.jdo.JDOClass; +import org.apache.jdo.model.jdo.JDOField; +import org.apache.jdo.model.jdo.JDOModel; +import org.apache.jdo.util.I18NHelper; + + + +/** +/** + * A reflection based JavaType implementation used at runtime. + * The implementation takes <code>java.lang.Class</code> and + * <code>java.lang.reflect.Field</code> instances to get Java related + * metadata about types and fields. + * + * @author Michael Bouschen + * @since JDO 1.0.1 + */ +public class RuntimeJavaType + extends ReflectionJavaType +{ + /** The JDOModel instance to lookup JDO metadata. */ + private JDOModel jdoModel; + + /** Flag indicating whether the superclass is checked already. */ + private boolean superclassUnchecked = true; + + /** Flag indicating whether the JDOClass info is retrieved already. */ + private boolean jdoClassUnchecked = true; + + /** The JDO metadata, if this type represents a pc class. */ + private JDOClass jdoClass; + + /** Map of JavaField instances, key is the field name. */ + private Map javaFields = new HashMap(); + + /** JavaModelFactory */ + private static final RuntimeJavaModelFactory javaModelFactory = + (RuntimeJavaModelFactory) AccessController.doPrivileged( + new PrivilegedAction () { + public Object run () { + return RuntimeJavaModelFactory.getInstance(); + } + } + ); + + /** I18N support */ + private final static I18NHelper msg = + I18NHelper.getInstance("org.apache.jdo.impl.model.java.Bundle"); //NOI18N + + /** Constructor. */ + public RuntimeJavaType(Class clazz, JDOModel jdoModel) + { + // Pass null as the superclass to the super call. This allows lazy + // evaluation of the superclass (see getSuperclass implementation). + super(clazz, null); + this.jdoModel = jdoModel; + } + + /** + * Determines if this JavaType object represents an array type. + * @return <code>true</code> if this object represents an array type; + * <code>false</code> otherwise. + */ + public boolean isArray() + { + return clazz.isArray(); + } + + /** + * Returns <code>true</code> if this JavaType represents a persistence + * capable class. + * <p> + * A [EMAIL PROTECTED] org.apache.jdo.model.ModelFatalException} indicates a + * problem accessing the JDO meta data for this JavaType. + * @return <code>true</code> if this JavaType represents a persistence + * capable class; <code>false</code> otherwise. + * @exception ModelFatalException if there is a problem accessing the + * JDO metadata + */ + public boolean isPersistenceCapable() + throws ModelFatalException + { + return (getJDOClass() != null); + } + + /** + * Returns the JavaType representing the superclass of the entity + * represented by this JavaType. If this JavaType represents either the + * Object class, an interface, a primitive type, or <code>void</code>, + * then <code>null</code> is returned. If this object represents an + * array class then the JavaType instance representing the Object class + * is returned. + * @return the superclass of the class represented by this JavaType. + */ + public synchronized JavaType getSuperclass() + { + if (superclassUnchecked) { + superclassUnchecked = false; + superclass = getJavaTypeInternal(clazz.getSuperclass()); + } + return superclass; + } + + /** + * Returns the JDOClass instance if this JavaType represents a + * persistence capable class. The method returns <code>null</code>, + * if this JavaType does not represent a persistence capable class. + * <p> + * A [EMAIL PROTECTED] org.apache.jdo.model.ModelFatalException} indicates a + * problem accessing the JDO meta data for this JavaType. + * @return the JDOClass instance if this JavaType represents a + * persistence capable class; <code>null</code> otherwise. + * @exception ModelFatalException if there is a problem accessing the + * JDO metadata + */ + public synchronized JDOClass getJDOClass() + throws ModelFatalException + { + if (jdoClassUnchecked) { + jdoClassUnchecked = false; + jdoClass = jdoModel.getJDOClass(getName()); + } + return jdoClass; + } + + /** + * Returns the JavaType representing the component type of an array. + * If this JavaType does not represent an array type this method + * returns <code>null</code>. + * @return the JavaType representing the component type of this + * JavaType if this class is an array; <code>null</code> otherwise. + */ + public JavaType getArrayComponentType() + { + JavaType componentType = null; + if (isArray()) { + Class componentClass = clazz.getComponentType(); + if (componentClass != null) + componentType = getJavaTypeInternal(componentClass); + } + return componentType; + } + + /** + * Returns a JavaField instance that reflects the field with the + * specified name of the class or interface represented by this + * JavaType instance. The method returns <code>null</code>, if the + * class or interface (or one of its superclasses) does not have a + * field with that name. + * @param fieldName the name of the field + * @return the JavaField instance for the specified field in this class + * or <code>null</code> if there is no such field. + */ + public JavaField getJavaField(String fieldName) + { + JavaField javaField = getDeclaredJavaField(fieldName); + if (javaField == null) { + // check superclass + JavaType superclass = getSuperclass(); + if ((superclass != null) && + (superclass != PredefinedType.objectType)) { + javaField = superclass.getJavaField(fieldName); + } + } + return javaField; + } + + // ===== Methods not defined in JavaType ===== + + /** + * RegisterClassListener calls this method to create a RuntimeJavaField + * instance when processing the enhancer generated metadata. + * @param jdoField the JDO field metadata + * @param type the type of the field + * @return the RuntimeJavaField representation + */ + public JavaField createJavaField(JDOField jdoField, JavaType type) + { + String name = jdoField.getName(); + synchronized(javaFields) { + JavaField javaField = (JavaField)javaFields.get(name); + if (javaField != null) { + throw new ModelFatalException(msg.msg( + "ERR_MultipleJavaField", //NOI18N + "RuntimeJavaType.createJavaField", name, getName())); //NOI18N + } + javaField = new RuntimeJavaField(jdoField, type, this); + javaFields.put(name, javaField); + return javaField; + } + } + + /** + * Returns a JavaField instance that reflects the declared field with + * the specified name of the class or interface represented by this + * JavaType instance. The method returns <code>null</code>, if the + * class or interface does not declared a field with that name. It does + * not check whether one of its superclasses declared such a field. + * @param fieldName the name of the field + * @return the JavaField instance for the specified field in this class + */ + public JavaField getDeclaredJavaField(String fieldName) + { + synchronized (javaFields) { + JavaField javaField = (JavaField)javaFields.get(fieldName); + if (javaField == null) { + JDOClass jdoClass = getJDOClass(); + if (jdoClass != null) { + // pc class => look for JDOField first + JDOField jdoField = jdoClass.getDeclaredField(fieldName); + if (jdoField != null) { + javaField = new RuntimeJavaField(jdoField, this); + javaFields.put(fieldName, javaField); + } + } + + // if no field info check reflection + if (javaField == null) { + Field field = ReflectionJavaField.getDeclaredFieldPrivileged( + clazz, fieldName); + if (field != null) { + javaField = new RuntimeJavaField(field, this); + javaFields.put(fieldName, javaField); + } + } + } + return javaField; + } + } + + /** + * Returns a JavaType instance for the specified Class object. + * This method provides a hook such that RuntimeJavaType subclasses can + * implement their own mapping of Class objects to JavaType instances. + * <p> + * This implementation delegates the call to the javaModelFactory. + * @param clazz the Class instance representing the type + * @return a JavaType instance for the name of the specified class + * object or <code>null</code> if not present in this model instance. + */ + protected JavaType getJavaTypeInternal(Class clazz) + { + return javaModelFactory.getJavaType(clazz); + } + +} Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/package.html URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/package.html?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/package.html (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/java/runtime/package.html Fri Mar 18 17:02:29 2005 @@ -0,0 +1,27 @@ +<!-- + Copyright 2005 The Apache Software Foundation. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<html> +<head> +<title>Runtime JavaModel implementation package.</title> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> +</head> + +<body bgcolor="#FFFFFF"> +<p>This package contains a runtime specific JavaModel implementation +based on reflection. +</body> +</html> Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/Bundle.properties URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/Bundle.properties?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/Bundle.properties (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/Bundle.properties Fri Mar 18 17:02:29 2005 @@ -0,0 +1,84 @@ +# +# Copyright 2005 The Apache Software Foundation. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Generic messages +# +#NOI18N +ERR_MissingJavaModel=Missing JavaModel. + +# +# JDOModelImpl +# +EXC_XMLError=Error during reading XML meta data of resource ''{0}''. +EXC_NonPCSuperclass=Superclass ''{0}'' of persistence-capable class ''{1}'' is not persistence-capable. +EXC_MissingJDOMetadata=Missing JDO metadata for enhanced class ''{0}''. +#NOI18N +ERR_MultipleJDOClassInstances=JDOModelImpl.lookupXMLMetadata: muliple JDOClass instances for persistence-capable class ''{0}''. + +# +# Assertion +# +#NOI18N +ERR_AssertionFailed=Assertion failed: {0} + +# +# JDOClassImpl +# +EXC_InvalidMember=Invalid member ''{0}''. +EXC_CannotCreateJDOField=Cannot create new JDOField after field number calculation. +EXC_CannotRemoveJDOField=Cannot remove JDOField after after field number calculation. +EXC_CannotResolveObjectIdClass=Cannot resolve objectid-class ''{0}'' of persistence-capable class ''{1}''. +EXC_CannotResolvePCSuperClass=Cannot resolve persistence-capable-superclass ''{0}'' of persistence-capable class ''{1}''. +#NOI18N +ERR_InvalidInheritedFieldNumber=JDOClassImpl.getFieldList inheritedFields.size() != inheritedFieldsCount. + + +# +# JDOFieldImpl +# +EXC_RelationshipAlreadyDefined=Field ''{0}'' already defined as relationship ''{1}''. +EXC_IllegalJDOPrefix=Cannot set the persistence-modifier of field ''{0}'' to persistent or transactional. Fields whose name begins with ''jdo'' cannot be persistent or transactional. +#NOI18N +ERR_MissingJavaModifier=Missing java modifier of field ''{0}''. + +# +# JDOCollectionImpl +# +EXC_CannotResolveElementType=Cannot resolve element-type ''{0}'' of collection field ''{1}'' in class ''{2}''. + +# +# JDOMapImpl +# +EXC_CannotResolveKeyType=Cannot resolve key-type ''{0}'' of map field ''{1}'' in class ''{2}''. +EXC_CannotResolveValueType=Cannot resolve value-type ''{0}'' of map field ''{1}'' in class ''{2}''. + +# +# RuntimeJDOModelFactory +# +EXC_NoJDOImplHelper=Cannot get JDOImplHelper instance. +EXC_InvalidJDOModelKey=Invalid key for runtime JDOModel lookup: expected ''java.lang.ClassLoader'' instance, found ''{0}'' instance. + +# +# JDOParser +# +EXC_MissingJDODTD=Cannot load javax/jdo/jdo.dtd, because the file does not exist in the jdo.jar file, or the JDOParser class is not granted permission to read this file. The metadata .xml file contained PUBLIC={0} SYSTEM={1}. + +# +# JDOHandlerImpl +# +EXC_ModelException=Exception during model update, see nested exception for details. +EXC_MissingPackageName=Missing name specification in <package> element. +EXC_UnknownAttribute=Unknown {0} attribute: {1} \= {2}. Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOArrayImplDynamic.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOArrayImplDynamic.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOArrayImplDynamic.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOArrayImplDynamic.java Fri Mar 18 17:02:29 2005 @@ -0,0 +1,80 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jdo.impl.model.jdo; + +import org.apache.jdo.impl.model.jdo.util.TypeSupport; +import org.apache.jdo.model.java.JavaType; +import org.apache.jdo.model.jdo.JDOArray; +import org.apache.jdo.model.jdo.JDOField; + +/** + * An instance of this class represents the JDO relationship metadata + * of a array relationship field. This dynamic implementation only + * stores property values explicitly set by setter method. + * + * @author Michael Bouschen + * @since 1.1 + * @version 1.1 + */ +public class JDOArrayImplDynamic extends JDORelationshipImpl + implements JDOArray { + + /** Property embeddedElement. */ + protected Boolean embeddedElement; + + /** + * Determines whether the values of the elements should be stored + * if possible as part of the instance instead of as their own instances + * in the datastore. + * @return <code>true</code> if the elements should be stored as part of + * the instance; <code>false</code> otherwise + */ + public boolean isEmbeddedElement() { + if (embeddedElement != null) { + // return embeddedElement, if explicitly set by the setter + return embeddedElement.booleanValue(); + } + + // not set => calculate + JavaType elementType = getElementType(); + return (elementType != null) ? + TypeSupport.isEmbeddedElementType(elementType) : false; + } + + /** + * Set whether the values of the elements should be stored + * if possible as part of the instance instead of as their own instances + * in the datastore. + * @param embeddedElement flag indicating whether the elements should be + * stored as part of the instance + */ + public void setEmbeddedElement(boolean embeddedElement) { + this.embeddedElement = (embeddedElement ? Boolean.TRUE : Boolean.FALSE); + } + + /** + * Get the type representation of the array component type. + * @return the array component type + */ + public JavaType getElementType() { + JDOField jdoField = getDeclaringField(); + JavaType fieldType = jdoField.getType(); + return (fieldType != null) ? fieldType.getArrayComponentType() : null; + } + +} + Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOClassImplDynamic.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOClassImplDynamic.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOClassImplDynamic.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOClassImplDynamic.java Fri Mar 18 17:02:29 2005 @@ -0,0 +1,1036 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jdo.impl.model.jdo; + +import java.util.*; +import java.lang.reflect.Modifier; + +import org.apache.jdo.impl.model.jdo.util.TypeSupport; +import org.apache.jdo.model.ModelException; +import org.apache.jdo.model.ModelFatalException; +import org.apache.jdo.model.java.JavaModel; +import org.apache.jdo.model.java.JavaType; +import org.apache.jdo.model.jdo.JDOClass; +import org.apache.jdo.model.jdo.JDOField; +import org.apache.jdo.model.jdo.JDOIdentityType; +import org.apache.jdo.model.jdo.JDOMember; +import org.apache.jdo.model.jdo.JDOModel; +import org.apache.jdo.model.jdo.JDOPackage; + +import org.apache.jdo.util.I18NHelper; + +/** + * An instance of this class represents the JDO metadata of a persistence + * capable class. This dynamic implementation only stores property + * values explicitly set by setter method. It does not store any + * calculated values such as list of managed or persistent fields, + * list of field numbers etc. + * <p> + * TBD: + * <ul> + * <li> Property change support + * </ul> + * + * @author Michael Bouschen + * @since 1.1 + * @version 1.1 + */ +public class JDOClassImplDynamic + extends JDOMemberImpl + implements JDOClass +{ + /** Property identityType. Default see [EMAIL PROTECTED] #getIdentityType}. */ + protected int identityType = JDOIdentityType.UNSPECIFIED; + + /** Property objectIdClass. No default. */ + protected transient JavaType objectIdClass; + + /** Property declaredObjectIdClassName. No default. */ + private String declaredObjectIdClassName; + + /** Property requiresExtent. It defaults to <code>true</code>. */ + private boolean requiresExtent = true; + + /** Property pcSuperclassName. No default. */ + private String pcSuperclassName; + + /** Relationship JDOClass<->JDOClass. */ + protected JDOClass pcSuperclass; + + /** Property javaType. No default.*/ + protected transient JavaType javaType; + + /** Relationship JDOModel<->JDOClass. Initialized during creation.*/ + private JDOModel declaringModel; + + /** + * Relationship JDOClass<->JDOMember. + * Map of fields declared by this JDOClass. Key is the unqualified + * field name, value is the JDOField instance. + */ + private Map declaredFields = new HashMap(); + + /** + * Relationship JDOClass<->JDOMember. + * Map of inner classes declared by this JDOClass. + * Key is the unqualified name of the inner class, + * value is the JDOClass instance of the inner class. + */ + private Map declaredClasses = new HashMap(); + + /** Relationship JDOClass -> JDOPackage. */ + private JDOPackage jdoPackage; + + /** Flag indicating whether XML metadata is processed already. */ + private boolean xmlProcessed = false; + + /** I18N support */ + protected final static I18NHelper msg = + I18NHelper.getInstance(JDOClassImplDynamic.class); + + /** + * Get the JDO identity type of this JDOClass. + * The identity type of the least-derived persistence-capable class defines + * the identity type for all persistence-capable classes that extend it. + * The identity type of the least-derived persistence-capable class is + * defaulted to [EMAIL PROTECTED] JDOIdentityType#APPLICATION} if objectid-class is + * specified, and [EMAIL PROTECTED] JDOIdentityType#DATASTORE}, if not. + * @return the JDO identity type, one of + * [EMAIL PROTECTED] JDOIdentityType#APPLICATION}, + * [EMAIL PROTECTED] JDOIdentityType#DATASTORE}, or + * [EMAIL PROTECTED] JDOIdentityType#NONDURABLE} + */ + public int getIdentityType() { + if (identityType != JDOIdentityType.UNSPECIFIED) { + // return identity type, if explicitly set by the setter + return identityType; + } + + // not set => caclulate + JDOClass pcRoot = getPersistenceCapableRootClass(); + int result = 0; + if (pcRoot == this) { + // this is the least-derived pc class + result = (pcRoot.getDeclaredObjectIdClassName() != null) ? + JDOIdentityType.APPLICATION : JDOIdentityType.DATASTORE; + } + else { + // get the identityType from the least-derived pc class + result = pcRoot.getIdentityType(); + } + + return result; + } + + /** + * Set the object identity type of this JDOClass. + * @param identityType an integer indicating the JDO identity type, one of: + * [EMAIL PROTECTED] JDOIdentityType#APPLICATION}, + * [EMAIL PROTECTED] JDOIdentityType#DATASTORE}, or + * [EMAIL PROTECTED] JDOIdentityType#NONDURABLE} + */ + public void setIdentityType(int identityType) { + this.identityType = identityType; + } + + /** + * Get the JavaType representation of the object identity class + * (primary key class) for this JDOClass. + * @return the JavaType representation of the object identity class. + */ + public JavaType getObjectIdClass() { + if (objectIdClass != null) { + // return objectIdClass if explicitly set by the setter + return objectIdClass; + } + + // not set => try to resolve ObjectId class + JavaType type = null; + String name = getDeclaredObjectIdClassName(); + if (name != null) { + JavaModel javaModel = getDeclaringModel().getJavaModel(); + type = javaModel.getJavaType(name); + if (Modifier.isAbstract(type.getModifiers())) + // do not return ObjectId class if abstract + type = null; + } + else { + JDOClass superclass = getPersistenceCapableSuperclass(); + if (superclass != null) { + type = superclass.getObjectIdClass(); + } + } + return type; + } + + /** + * Set the JavaType representation of the object identity class + * (primary key class) for this JDOClass. + * @param objectIdClass the JavaType representation of the + * object identity class + */ + public void setObjectIdClass(JavaType objectIdClass) { + this.objectIdClass = objectIdClass; + } + + /** + * Get the fully qualified name of the object identity class + * (primary key class) for this JDOClass. + * @return the name of the object identity class. + */ + public String getDeclaredObjectIdClassName() { + if (declaredObjectIdClassName != null) { + // ObjectId is declared, but it might not be qualified + int index = declaredObjectIdClassName.indexOf('.'); + if (index == -1) { + // not qualified => try to resolve it + JavaType type = TypeSupport.resolveType(getDeclaringModel(), + declaredObjectIdClassName, getPackagePrefix()); + if (type == null) { + throw new ModelFatalException( + msg.msg("EXC_CannotResolveObjectIdClass", //NOI18N + declaredObjectIdClassName, getName())); + } + this.declaredObjectIdClassName = type.getName(); + } + } + return declaredObjectIdClassName; + } + + /** + * Set the fully qualified name of the object identity class + * (primary key class) for this JDOClass. + * @param declaredObjectIdClassName the name of the object identity class + */ + public void setDeclaredObjectIdClassName(String declaredObjectIdClassName) { + this.declaredObjectIdClassName = declaredObjectIdClassName; + } + + /** + * Determines whether an extent must be managed for the + * persistence-capable class described by this JDOClass. + * @return <code>true</code> if this class must manage an extent; + * <code>false</code> otherwise + */ + public boolean requiresExtent() { + return requiresExtent; + } + + /** + * Set whether an extent must be managed for the + * persistence-capable class described by this JDOClass. + * @param requiresExtent <code>true</code> if this class must manage + * an extent; <code>false</code> otherwise + */ + public void setRequiresExtent(boolean requiresExtent) { + this.requiresExtent = requiresExtent; + } + + /** + * Get the fully qualified class name of the persistence-capable superclass + * of the persistence-capable class described by this JDOClass. If this + * class does not have a persistence-capable superclass then + * <code>null</code> is returned. + * @return the fully qualified name of the persistence-capable superclass + * or <code>null</code> if there is no persistence-capable superclass + */ + public String getPersistenceCapableSuperclassName() { + if (pcSuperclassName != null) { + // pcSuperclassName is declared, but it might not be qualified + int index = pcSuperclassName.indexOf('.'); + if (index == -1) { + // not qualified => try to resolve it + JavaType type = TypeSupport.resolveType(getDeclaringModel(), + pcSuperclassName, getPackagePrefix()); + if (type == null) { + throw new ModelFatalException( + msg.msg("EXC_CannotResolvePCSuperClass", //NOI18N + pcSuperclassName, getName())); + } + this.pcSuperclassName = type.getName(); + } + } + return pcSuperclassName; + } + + /** + * Set the fully qualified class name of the persistence-capable superclass + * of the persistence-capable class described by this JDOClass. + * @param pcSuperclassName the fully qualified name of the + * persistence-capable superclass + */ + public void setPersistenceCapableSuperclassName(String pcSuperclassName) { + this.pcSuperclassName = pcSuperclassName; + } + + /** + * Provides the JavaType representaion corresponding to this JDOClass. + * <p> + * Note the difference between Object.getClass() and this method. The + * former returns the class of the object in hand, this returns the class + * of the object represented by this meta data. + * @return the JavaType object corresponding to this JDOClass. + */ + public JavaType getJavaType() { + if (javaType != null) { + // return java type, if explicitly set by the setter + return javaType; + } + + // not set => calculate + JavaModel javaModel = declaringModel.getJavaModel(); + return javaModel.getJavaType(getName()); + } + + /** + * Set the JavaType representation corresponding to this JDOClass. + * @param javaType the JavaType representation for this JDOClass + */ + public void setJavaType(JavaType javaType) { + this.javaType = javaType; + } + + /** + * Remove the supplied member from the collection of members maintained by + * this JDOClass. + * @param member the member to be removed + * @exception ModelException if impossible + */ + public void removeDeclaredMember(JDOMember member) throws ModelException { + if (member instanceof JDOField) { + declaredFields.remove(member.getName()); + } + else if (member instanceof JDOClass) { + declaredClasses.remove(member.getName()); + } + else { + String name = (member == null) ? "null" : member.getName(); //NOI18N + throw new ModelException( + msg.msg("EXC_InvalidMember", name)); //NOI18N + } + } + + /** + * Returns the collection of JDOMember instances declared by this + * JDOClass in form of an array. + * @return the members declared by this JDOClass + */ + public JDOMember[] getDeclaredMembers() { + List copy = new ArrayList(declaredFields.values()); + copy.addAll(declaredClasses.values()); + return (JDOMember[])copy.toArray(new JDOMember[copy.size()]); + } + + /** + * Returns the declaring JDOModel of this JDOClass. + * @return the JDOModel that owns this JDOClass + */ + public JDOModel getDeclaringModel() { + return declaringModel; + } + + /** + * Set the declaring JDOModel for this JDOClass. + * @param model the declaring JDOModel of this JDOClass + */ + public void setDeclaringModel(JDOModel model) { + this.declaringModel = model; + } + + /** + * Returns the JDOClass instance for the persistence-capable superclass + * of this JDOClass. If this class does not have a persistence-capable + * superclass then <code>null</code> is returned. + * @return the JDClass instance of the persistence-capable superclass + * or <code>null</code> if there is no persistence-capable superclass + */ + public JDOClass getPersistenceCapableSuperclass() { + if (pcSuperclass != null) { + // return pcSuperclass if explicitly set by the setter + return pcSuperclass; + + } + + // not set => try to resolve persistence capable superclass + String name = getPersistenceCapableSuperclassName(); + if (pcSuperclassName != null) { + JavaType type = TypeSupport.resolveType( + getDeclaringModel(), pcSuperclassName, getPackagePrefix()); + if (type == null) { + throw new ModelFatalException( + msg.msg("EXC_CannotResolvePCSuperClass", //NOI18N + pcSuperclassName, getName())); + } + JDOClass jdoClass = type.getJDOClass(); + // pcSuperclassName might be unqualified + this.pcSuperclassName = type.getName(); + return jdoClass; + } + + return null; + } + + /** + * Set the JDOClass for the persistence-capable superclass + * of this JDOClass. + * @param pcSuperclass the JDClass instance of the persistence-capable + * superclass + */ + public void setPersistenceCapableSuperclass(JDOClass pcSuperclass) { + this.pcSuperclass = pcSuperclass; + this.pcSuperclassName = + pcSuperclass != null ? pcSuperclass.getName() : null; + } + + /** + * Returns the JDOPackage instance corresponding to the package name + * of this JDOClass. + * @return the JDOPackage instance of this JDOClass. + */ + public JDOPackage getJDOPackage() { + return jdoPackage; + } + + /** + * Sets the JDOPackage instance corresponding to the package name + * of this JDOClass. + * @param jdoPackage the JDOPackage of this JDOClass. + */ + public void setJDOPackage(JDOPackage jdoPackage) { + this.jdoPackage = jdoPackage; + } + + /** + * This method returns a JDOField instance for the field with the specified + * name. If this JDOClass already declares such a field, the existing + * JDOField instance is returned. Otherwise, it creates a new JDOField + * instance, sets its declaringClass and returns the new instance. + * <P> + * Note, if the field numbers for the managed fields of this JDOClass are + * calculated, this methid will fail to create a new JDOField. Any new field + * would possibly invalidate existing field number + * @param name the name of the field + * @exception ModelException if impossible + */ + public JDOField createJDOField(String name) throws ModelException { + // check whether there is a field with the specified name + JDOField field = (JDOField)declaredFields.get(name); + if (field == null) { + field = newJDOFieldInstance(); + field.setName(name); + field.setDeclaringClass(this); + declaredFields.put(name, field); + } + return field; + } + + /** + * This method returns a JDOClass instance representing an inner class of + * this JDOClass If this JDOClass already declares such an inner class, + * the existing JDOClass instance is returned. Otherwise, it creates a new + * JDOClass instance, sets its declaringClass and returns the new instance. + * @param name the name of the inner class + * @exception ModelException if impossible + */ + public JDOClass createJDOClass(String name) throws ModelException { + JDOClass innerClass = (JDOClass)declaredClasses.get(name); + if (innerClass == null) { + innerClass = newJDOClassInstance(); + innerClass.setName(name); + innerClass.setDeclaringClass(this); + declaredClasses.put(name, innerClass); + } + return innerClass; + } + + /** + * Returns the collection of JDOClass instances declared by this JDOClass. + * @return the classes declared by this JDOClass + */ + public JDOClass[] getDeclaredClasses() { + return (JDOClass[])declaredClasses.values().toArray( + new JDOClass[declaredClasses.size()]); + } + + /** + * Returns the collection of JDOField instances declared by this JDOClass + * in the form of an array. This does not include inherited fields. + * @return the fields declared by this JDOClass + */ + public JDOField[] getDeclaredFields() { + Collection tmp = declaredFields.values(); + return (JDOField[])tmp.toArray(new JDOField[tmp.size()]); + } + + /** + * Returns the collection of managed JDOField instances declared by this + * JDOClass in the form of an array. The returned array does not include + * inherited fields. A field is a managed field, if it has the + * persistence-modifier + * [EMAIL PROTECTED] org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT} or + * [EMAIL PROTECTED] org.apache.jdo.model.jdo.PersistenceModifier#TRANSACTIONAL}. + * The position of the fields in the returned array equals their + * relative field number as returned by + * [EMAIL PROTECTED] JDOField#getRelativeFieldNumber()}. The following holds + * true for any field in the returned array: + * <ul> + * <li> <code>getDeclaredManagedFields()[i].getRelativeFieldNumber() + * == i</code> + * <li> <code>getDeclaredManagedFields()[field.getRelativeFieldNumber()] + * == field</code> + * </ul> + * @return the managed fields declared by this JDOClass + */ + public JDOField[] getDeclaredManagedFields() { + // Get the list of declared fields, skip the non managed fields + // and store the remaining fields into a list + List fieldList = new ArrayList(); + for (Iterator i = declaredFields.values().iterator(); i.hasNext();) { + JDOField field = (JDOField)i.next(); + if (field.isManaged()) + fieldList.add(field); + } + + // Sort all declared fields. JDOFieldImpl implements Comparable. + // It uses the field name for comparison. + Collections.sort(fieldList); + JDOField[] fields = new JDOField[fieldList.size()]; + fieldList.toArray(fields); + return fields; + } + + /** + * Returns the collection of managed JDOField instances of this JDOClass + * in the form of an array. The returned array includes inherited fields. + * A field is a managed field, if it has the persistence-modifier + * [EMAIL PROTECTED] org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT} or + * [EMAIL PROTECTED] org.apache.jdo.model.jdo.PersistenceModifier#TRANSACTIONAL}. + * The position of the fields in the returned array equals their + * absolute field number as returned by + * [EMAIL PROTECTED] JDOField#getFieldNumber()}. The following holds true for + * any field in the returned array: + * <ul> + * <li> <code>getManagedFields()[i].getFieldNumber() == i</code> + * <li> <code>getManagedFields()[field.getFieldNumber()] == field</code> + * </ul> + * @return the managed fields of this JDOClass + */ + public JDOField[] getManagedFields() { + JDOField[] fields = null; + JDOField[] declared = getDeclaredManagedFields(); + JDOClass superclass = getPersistenceCapableSuperclass(); + if (superclass == null) { + // no pc superclass + fields = declared; + } + else { + // pc superclass + JDOField[] inherited = superclass.getManagedFields(); + fields = new JDOField[inherited.length+declared.length]; + System.arraycopy(inherited, 0, fields, 0, inherited.length); + System.arraycopy(declared, 0, fields, + inherited.length, declared.length); + } + + return fields; + } + + /** + * Returns the collection of persistent JDOField instances of this JDOClass + * in the form of an array. The returned array includes inherited fields. + * A field is a persistent field, if it has the persistence-modifier + * [EMAIL PROTECTED] org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT}. + * Please note, the position of the fields in the returned array might not + * equal their absolute field number as returned by + * [EMAIL PROTECTED] JDOField#getFieldNumber()}. + * @return the persistent fields of this JDOClass + */ + public JDOField[] getPersistentFields() { + JDOField[] fields = getManagedFields(); + JDOField[] tmp = new JDOField[fields.length]; + int length = 0; + for (int i = 0; i < fields.length; i++) { + JDOField field = fields[i]; + if (field.isPersistent()) { + tmp[length++] = field; + } + } + // now fill he returned array + // the array should have the correct length + JDOField[] result = new JDOField[length]; + System.arraycopy(tmp, 0, result, 0, length); + + return result; + } + + /** + * Returns the collection of identifying fields of this JDOClass in the form + * of an array. The method returns the JDOField instances defined as + * primary key fields (see [EMAIL PROTECTED] JDOField#isPrimaryKey}). + * @return the identifying fields of this JDOClass + */ + public JDOField[] getPrimaryKeyFields() { + JDOField[] fields = getManagedFields(); + JDOField[] tmp = new JDOField[fields.length]; + int length = 0; + for (int i = 0; i < fields.length; i++) { + JDOField field = fields[i]; + if (fields[i].isPrimaryKey()) { + tmp[length++] = field; + } + } + // now fill the returned array + // the array should have the correct length + JDOField[] result = new JDOField[length]; + System.arraycopy(tmp, 0, result, 0, length); + + return result; + } + + /** + * Returns the collection of persistent relationship fields of this JDOClass + * in the form of an array. The method returns the JDOField instances + * defined as relationship (method [EMAIL PROTECTED] JDOField#getRelationship} returns + * a non null value) and having the persistence-modifier + * [EMAIL PROTECTED] org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT}. + * @return the persistent relationship fields of this JDOClass + */ + public JDOField[] getPersistentRelationshipFields() { + JDOField[] fields = getPersistentFields(); + JDOField[] tmp = new JDOField[fields.length]; + int length = 0; + for (int i = 0; i < fields.length; i++) { + JDOField field = fields[i]; + if (field.isPersistent() && field.isRelationship()) { + tmp[length++] = field; + } + } + // now fill the returned array, + // the arrays should have the correct length + JDOField[] result = new JDOField[length]; + System.arraycopy(tmp, 0, result, 0, length); + + return result; + } + + /** + * Returns the collection of default fetch group fields of this JDOClass + * in the form of an array. The method returns the JDOField instances + * defined as part of the default fetch group + * (method [EMAIL PROTECTED] JDOField#isDefaultFetchGroup} returns <code>true</code>. + * @return the default fetch group fields of this JDOClass + * @since 1.1 + */ + public JDOField[] getDefaultFetchGroupFields() { + JDOField[] fields = getManagedFields(); + JDOField[] tmp = new JDOField[fields.length]; + int length = 0; + for (int i = 0; i < fields.length; i++) { + JDOField field = fields[i]; + if (field.isDefaultFetchGroup()) { + tmp[length++] = field; + } + } + // now fill defaultFetchGroupFields + // the arrays should have the correct length + JDOField[] result = new JDOField[length]; + System.arraycopy(tmp, 0, result, 0, length); + + return result; + } + + /** + * Returns an array of absolute field numbers of the managed fields of this + * JDOClass. The returned array includes field numbers of inherited fields. + * A field is a managed field, if it has the persistence-modifier + * [EMAIL PROTECTED] org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT} or + * [EMAIL PROTECTED] org.apache.jdo.model.jdo.PersistenceModifier#TRANSACTIONAL}. + * Only managed fields have a valid field number, thus the field number in + * the returned array equals its index: + * <br> + * <code>getManagedFields()[i] == i</code> + */ + public int[] getManagedFieldNumbers() { + JDOField[] fields = getManagedFields(); + int[] fieldNumbers = new int[fields.length]; + for (int i = 0; i < fields.length; i++) { + fieldNumbers[i] = i; + } + + return fieldNumbers; + } + + /** + * Returns an array of absolute field numbers of the persistent fields of + * this JDOClass. The returned array includes field numbers of inherited + * fields. A persistent field has the persistence-modifier + * [EMAIL PROTECTED] org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT}. + */ + public int[] getPersistentFieldNumbers() { + JDOField[] fields = getManagedFields(); + int[] tmp = new int[fields.length]; + int length = 0; + for (int i = 0; i < fields.length; i++) { + JDOField field = fields[i]; + if (field.isPersistent()) { + tmp[length++] = i; + } + } + // now fill the returned array, it should have the correct length + int[] fieldNumbers = new int[length]; + System.arraycopy(tmp, 0, fieldNumbers, 0, length); + + return fieldNumbers; + } + + /** + * Returns an array of absolute field numbers of the identifying fields + * of this JDOClass. A field number is included in the returned array, + * iff the corresponding JDOField instance is defined as primary key field + * (see [EMAIL PROTECTED] JDOField#isPrimaryKey}). + * @return array of numbers of the identifying fields + */ + public int[] getPrimaryKeyFieldNumbers() { + JDOField[] fields = getManagedFields(); + int[] tmp = new int[fields.length]; + int length = 0; + for (int i = 0; i < fields.length; i++) { + JDOField field = fields[i]; + if (field.isPrimaryKey()) { + tmp[length++] = i; + } + } + // now fill the returned array, it should have the correct length + int[] fieldNumbers = new int[length]; + System.arraycopy(tmp, 0, fieldNumbers, 0, length); + + return fieldNumbers; + } + + /** + * Returns an array of absolute field numbers of the non identifying, + * persistent fields of this JDOClass. A field number is included in the + * returned array, iff the corresponding JDOField instance is persistent and + * not a not a primary key field (see [EMAIL PROTECTED] JDOField#isPrimaryKey}). + * A field is a persistent field, if it has the persistence-modifier + * [EMAIL PROTECTED] org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT} or + * (see [EMAIL PROTECTED] JDOField#getPersistenceModifier}). + * @return array of numbers of the non identifying, persistent fields + */ + public int[] getPersistentNonPrimaryKeyFieldNumbers() { + JDOField[] fields = getManagedFields(); + int[] tmp = new int[fields.length]; + int length = 0; + for (int i = 0; i < fields.length; i++) { + JDOField field = fields[i]; + if (field.isPersistent() && !field.isPrimaryKey()) { + tmp[length++] = i; + } + } + // now fill the returned array, it should have the correct length + int[] fieldNumbers = new int[length]; + System.arraycopy(tmp, 0, fieldNumbers, 0, length); + + return fieldNumbers; + } + + /** + * Returns an array of absolute field numbers of persistent relationship + * fields of this JDOClass. A field number is included in the returned + * array, iff the corresponding JDOField instance is a relationship (method + * [EMAIL PROTECTED] JDOField#getRelationship} returns a non null value) and has the + * persistence-modifier + * [EMAIL PROTECTED] org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT}. + * @return the field numbers of the persistent relationship fields + */ + public int[] getPersistentRelationshipFieldNumbers() { + JDOField[] fields = getManagedFields(); + int[] tmp = new int[fields.length]; + int length = 0; + for (int i = 0; i < fields.length; i++) { + JDOField field = fields[i]; + if (field.isPersistent() && field.isRelationship()) { + tmp[length++] = i; + } + } + // now fill the returned array, it should have the correct length + int[] fieldNumbers = new int[length]; + System.arraycopy(tmp, 0, fieldNumbers, 0, length); + + return fieldNumbers; + } + + /** + * Returns an array of absolute field numbers of persistent, serializable + * fields of this JDOClass. A field number is included in the returned + * array, iff the corresponding JDOField instance is serializable (method + * [EMAIL PROTECTED] JDOField#isSerializable} returns <code>true</code>) and has the + * persistence-modifier + * [EMAIL PROTECTED] org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT}. + * @return the field numbers of serializable fields + */ + public int[] getPersistentSerializableFieldNumbers() { + JDOField[] fields = getManagedFields(); + int[] tmp = new int[fields.length]; + int length = 0; + for (int i = 0; i < fields.length; i++) { + JDOField field = fields[i]; + if (field.isPersistent() && field.isSerializable()) { + tmp[length++] = i; + } + } + // now fill the returned array it should have the correct length + int[] fieldNumbers = new int[length]; + System.arraycopy(tmp, 0, fieldNumbers, 0, length); + + return fieldNumbers; + } + + /** + * Returns JDOField metadata for a particular managed field specified by + * field name. It returns <code>null</code> if the specified name does not + * denote a managed field of this JDOClass. The field name may be + * unqualified and or qualified (see [EMAIL PROTECTED] #getField(String fieldName)}). + * @param fieldName the name of the managed field for which field metadata + * is needed. + * @return JDOField metadata for the managed field or <code>null</code> + * if there is no such field. + */ + public JDOField getManagedField(String fieldName) { + JDOField field = getField(fieldName); + if ((field != null) && !field.isManaged()) + // return null for a non managed field + return null; + return field; + } + + /** + * Returns JDOField metadata for a particular field specified by field name. + * It returns <code>null</code> if the specified name does not denote a + * field of this JDOClass. + * <p> + * The method supports lookup by unqualified and by qualified field name. + * <ul> + * <li> In the case of an unqualified field name the method starts checking + * this JDOClass for a field with the specified name. If this class does not + * define such a field, it checks the inheritance hierarchy starting with + * its direct persistence-capable superclass. The method finds the first + * field with the specified name in a bootom-up lookup of the inheritance + * hierarchy. Hidden fields are not visible. + * <li> In the case of a qualified field name the method assumes a fully + * qualified class name (called qualifier class) as the field qualifier. + * The qualifier class must be a either this class or a persistence-capable + * superclass (direct or indirect) of this class. Then the method searches + * the field definition in the inheritance hierarchy staring with the + * qualifier class. Any field declarations with the same name in subclasses + * of the qualifier class are not considered. This form allows accessing + * fields hidden by subclasses. The method returns <code>null</code> if the + * qualifier class does not denote a valid class or if the qualifier class + * is not a persistence-capable superclass of this class. + * </ul> + * @param fieldName the unqualified or qualified name of field for which + * field metadata is needed. + * @return JDOField metadata for the field or <code>null</code> + * if there is no such field. + */ + public JDOField getField(String fieldName) { + // check fieldName + if ((fieldName == null) || (fieldName.length() == 0)) { + return null; + } + + JDOField field = null; + int index = fieldName.lastIndexOf('.'); + if (index != -1) { + // qualified field name + String className = fieldName.substring(0, index); + fieldName = fieldName.substring(index + 1); + // move to the specified class in the inheritance hierarchy, + // starting with the current class and get the field from there + for (JDOClassImplDynamic next = this; next != null; + next = (JDOClassImplDynamic)next.getPersistenceCapableSuperclass()) { + if (className.equals(next.getName())) { + field = next.getFieldInternal(fieldName); + } + } + } + else { + // unqualified field name => call getFieldInternal + field = getFieldInternal(fieldName); + } + + return field; + } + + /** + * Provides metadata for a particular field specified by the absolute field + * number. The field number must be a valid absolute field number for this + * JDOClass: <code>0 <= fieldNumber < this.getManagedFields().length</code> + * If the field number is valid the returned JDoField instance denotes a + * managed field, meaning the field has the persistence-modifier + * [EMAIL PROTECTED] org.apache.jdo.model.jdo.PersistenceModifier#PERSISTENT} or + * [EMAIL PROTECTED] org.apache.jdo.model.jdo.PersistenceModifier#TRANSACTIONAL}. + * If the field number is not valid then the method returns + * <code>null</code>. + * @param fieldNumber the number for which field metadata is needed. + * @return JDOField metadata for the field or <code>null</code> + * if there is no such field. + */ + public JDOField getField(int fieldNumber) { + JDOField field = null; + JDOField[] fields = getManagedFields(); + if ((0 <= fieldNumber) && (fieldNumber < fields.length)) + field = fields[fieldNumber]; + return field; + } + + /** + * Returns JDOField metadata for a particular declared field specified by + * field name. Please note, the method does not return inherited fields. + * The field name must not be qualified by a class name. The method returns + * <code>null</code> if the field name does not denote a field declared by + * JDOClass. + * @param fieldName the unqualified name of field for which field metadata + * is needed. + * @return JDOField metadata for the field or <code>null</code> + * if there is no such field declared by this JDOClass. + */ + public JDOField getDeclaredField(String fieldName) { + return (JDOField)declaredFields.get(fieldName); + } + + /** + * Returns the number of managed fields declared in this class. + * This does not include inherited fields. + * @return number of declared fields in the Class represented by this + * JDOClass + */ + public int getDeclaredManagedFieldCount() { + return getDeclaredManagedFields().length; + } + + /** + * Returns the number of inherited managed fields for this class. + * @return number of inherited fields + */ + public int getInheritedManagedFieldCount() { + int count = 0; + JDOClass superclass = getPersistenceCapableSuperclass(); + if (superclass != null) { + count = + superclass.getInheritedManagedFieldCount() + + superclass.getDeclaredManagedFieldCount(); + } + + return count; + } + + /** + * Returns the package name including a terminating dot if this class has a + * package. The method returns the empty string if this class is in the + * default package. + * @return package prefix for this class. + */ + public String getPackagePrefix() { + String className = getName(); + int index = className.lastIndexOf('.'); + return (index == -1) ? "" : className.substring(0, index + 1); //NOI18N + } + + /** + * Returns the least-derived (topmost) persistence-capable class in the + * hierarchy of this JDOClass. It returns this JDOClass if it has no + * persistence-capable superclass. + * @return the topmost persistence-capable class in the hierarchy. + */ + public JDOClass getPersistenceCapableRootClass() { + JDOClass superclass = getPersistenceCapableSuperclass(); + if (superclass == null) { + // no superclass => return this + return this; + } + else { + return superclass.getPersistenceCapableRootClass(); + } + } + + //========= Helper methods used by JDOModelImpl/XML reader only ========== + + /** + * Determines whether the class represented by this JDOClass is activated. + * A class is activated, if the class XML metadata is processed for this + * JDOClass. + * @return <code>true</code> if XML metadata is processed; + * <code>false</code> otherwise + */ + public boolean isXMLProcessed() { + return xmlProcessed; + } + + /** + * Sets the flag indicating that the class XML metadata for this + * JDOClass is processed to <code>true</code>. + */ + public void setXMLProcessed() { + this.xmlProcessed = true; + } + + + //========= Internal helper methods ========== + + /** + * Returns the JDOField definition for the specified field. + * The method expects unqualified field names. The method + * performs a bottom up lookup in the case of multiple fields + * with the same name in an inheritance hierarchy. So it starts + * checking this class, then it checks its superclas, etc. + * @param fieldName the unqualified field name + * @return the corresponding JDOField instance if exists; + * <code>null</code> otherwise. + */ + protected JDOField getFieldInternal(String fieldName) { + // first check the declared fields + JDOField field = (JDOField)declaredFields.get(fieldName); + if (field != null) + return field; + + // not in actual class => check superclass + JDOClassImplDynamic superclass = + (JDOClassImplDynamic)getPersistenceCapableSuperclass(); + if (superclass != null) { + return superclass.getFieldInternal(fieldName); + } + + // not found => return null + return null; + } + + /** + * Returns a new instance of the JDOClass implementation class. + */ + protected JDOClass newJDOClassInstance() { + return new JDOClassImplDynamic(); + } + + /** + * Returns a new instance of the JDOField implementation class. + */ + protected JDOField newJDOFieldInstance() { + return new JDOFieldImplDynamic(); + } + +} Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOCollectionImplDynamic.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOCollectionImplDynamic.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOCollectionImplDynamic.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOCollectionImplDynamic.java Fri Mar 18 17:02:29 2005 @@ -0,0 +1,138 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jdo.impl.model.jdo; + +import org.apache.jdo.impl.model.jdo.util.TypeSupport; +import org.apache.jdo.model.ModelFatalException; +import org.apache.jdo.model.java.JavaType; +import org.apache.jdo.model.jdo.JDOClass; +import org.apache.jdo.model.jdo.JDOCollection; +import org.apache.jdo.model.jdo.JDOField; +import org.apache.jdo.model.jdo.JDOModel; +import org.apache.jdo.util.I18NHelper; + +/** + * An instance of this class represents the JDO relationship metadata + * of a collection relationship field. This dynamic implementation only + * stores property values explicitly set by setter method. + * + * @author Michael Bouschen + * @since 1.1 + * @version 1.1 + */ +public class JDOCollectionImplDynamic extends JDORelationshipImpl + implements JDOCollection { + + /** Property embeddedElement. */ + protected Boolean embeddedElement; + + /** Property elementType. */ + protected transient JavaType elementType; + + /** Property elementTypeName. Defaults to java.lang.Object. */ + private String elementTypeName = "java.lang.Object"; //NOI18N + + /** I18N support */ + private final static I18NHelper msg = + I18NHelper.getInstance(JDOCollectionImplDynamic.class); + + /** + * Determines whether the values of the elements should be stored if + * possible as part of the instance instead of as their own instances + * in the datastore. + * @return <code>true</code> if the elements should be stored as part of + * the instance; <code>false</code> otherwise + */ + public boolean isEmbeddedElement() { + if (embeddedElement != null) { + // return embeddedElement, if explicitly set by the setter + return embeddedElement.booleanValue(); + } + + // not set => calculate + JavaType type = getElementType(); + return (type != null) ? + TypeSupport.isEmbeddedElementType(type) : false; + } + + /** + * Set whether the values of the elements should be stored if possible as + * part of the instance instead of as their own instances in the datastore. + * @param embeddedElement <code>true</code> if elements should be stored + * as part of the instance + */ + public void setEmbeddedElement(boolean embeddedElement) { + this.embeddedElement = (embeddedElement ? Boolean.TRUE : Boolean.FALSE); + } + + /** + * Get the type representation of the collection elements. + * @return the element type + */ + public JavaType getElementType() { + if (elementType != null) { + // return elementType, if explicitly set by the setter + return elementType; + } + + // not set => calculate + JavaType type = null; + if (elementTypeName != null) { + JDOField jdoField = getDeclaringField(); + JDOClass jdoClass = jdoField.getDeclaringClass(); + JDOModel jdoModel = jdoClass.getDeclaringModel(); + type = TypeSupport.resolveType(jdoModel, elementTypeName, + jdoClass.getPackagePrefix()); + if (type == null) { + throw new ModelFatalException( + msg.msg("EXC_CannotResolveElementType", elementTypeName, + jdoField.getName(), jdoClass.getName())); //NOI18N + } + } + + return type; + } + + /** + * Set the type representation of the collection elements. + * @param elementType the type representation of the collection elements + */ + public void setElementType(JavaType elementType) { + this.elementType = elementType; + if (elementType != null) { + setElementTypeName(elementType.getName()); + } + } + + /** + * Get the type of collection elements as string. + * @return the element type as string + */ + public String getElementTypeName() { + return elementTypeName; + } + + /** + * Set string representation of the type of collection elements. + * @param elementTypeName a string representation of the type of elements in + * the collection. + */ + public void setElementTypeName(String elementTypeName) { + this.elementTypeName = elementTypeName; + } + +} Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOElementImpl.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOElementImpl.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOElementImpl.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOElementImpl.java Fri Mar 18 17:02:29 2005 @@ -0,0 +1,152 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jdo.impl.model.jdo; + +import java.util.List; +import java.util.ArrayList; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.beans.PropertyVetoException; +import java.beans.VetoableChangeListener; +import java.beans.VetoableChangeSupport; + +import org.apache.jdo.model.jdo.JDOElement; +import org.apache.jdo.model.jdo.JDOExtension; + +/** + * This is the super interface for JDO metadata elements, + * such as JDOClass, JDOField and JDORelationship. + * + * @author Michael Bouschen + */ +public class JDOElementImpl + implements JDOElement +{ + /** List of vendorExtensions. */ + private List vendorExtensions = new ArrayList(); + + /** Property change support. */ + private transient PropertyChangeSupport propertyChangeSupport; + + /** Vetoable change support. */ + private transient VetoableChangeSupport vetoableChangeSupport; + + /** + * Remove the supplied vendor extension from the collection of extensions + * maintained by this JDOElement. + */ + public void removeJDOExtension(JDOExtension vendorExtension) + { + vendorExtensions.remove(vendorExtension); + } + + /** + * Returns the collection of vendor extensions for this JDOElement + * in the form of an array. + * @return the vendor extensions for this JDOClass + */ + public JDOExtension[] getJDOExtensions() + { + return (JDOExtension[])vendorExtensions.toArray( + new JDOExtension[vendorExtensions.size()]); + } + + /** + * Creates a new JDOExtension instance and attaches it to the specified + * JDOElement object. + */ + public JDOExtension createJDOExtension() + { + JDOExtension jdoExtension = new JDOExtensionImpl(); + vendorExtensions.add(jdoExtension); + return jdoExtension; + } + + /** + * Fires property change event. + * @param name property name + * @param o old value + * @param n new value + */ + protected void firePropertyChange (String name, Object o, Object n) + { + if (propertyChangeSupport != null) { + propertyChangeSupport.firePropertyChange(name, o, n); + } + } + + /** + * Add a property change listener. + * @param l the listener to add + */ + public synchronized void addPropertyChangeListener (PropertyChangeListener l) + { + if (propertyChangeSupport == null) { + propertyChangeSupport = new PropertyChangeSupport(this); + } + propertyChangeSupport.addPropertyChangeListener(l); + } + + /** + * Remove a property change listener. + * @param l the listener to remove + */ + public synchronized void removePropertyChangeListener(PropertyChangeListener l) + { + if (propertyChangeSupport != null) { + propertyChangeSupport.removePropertyChangeListener(l); + } + } + + /** Fires vetoable change event. + * @param name property name + * @param o old value + * @param n new value + * @exception PropertyVetoException when the change is vetoed by a listener + */ + protected void fireVetoableChange (String name, Object o, Object n) + throws PropertyVetoException + { + if (vetoableChangeSupport != null) { + vetoableChangeSupport.fireVetoableChange(name, o, n); + } + } + + /** + * Add a vetoable change listener. + * @param l the listener to add + */ + public void addVetoableChangeListener(VetoableChangeListener l) + { + if (vetoableChangeSupport == null) { + vetoableChangeSupport = new VetoableChangeSupport(this); + } + vetoableChangeSupport.addVetoableChangeListener(l); + } + + /** + * Remove a vetoable change listener. + * @param l the listener to remove + */ + public void removeVetoableChangeListener(VetoableChangeListener l) + { + if (vetoableChangeSupport != null) { + vetoableChangeSupport.removeVetoableChangeListener(l); + } + + } +} Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOExtensionImpl.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOExtensionImpl.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOExtensionImpl.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/model/jdo/JDOExtensionImpl.java Fri Mar 18 17:02:29 2005 @@ -0,0 +1,86 @@ +/* + * Copyright 2005 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.jdo.impl.model.jdo; + +import org.apache.jdo.model.jdo.JDOExtension; + +/** + * An instance of this class represents a JDO vendor specific extension. + * + * @author Michael Bouschen + */ +public class JDOExtensionImpl + implements JDOExtension +{ + /** Property vendorName. No default. */ + private String vendorName; + + /** Property key. No default. */ + private String key; + + /** Property value. No default. */ + private Object value; + + /** + * Returns the vendor name of this vendor extension. + */ + public String getVendorName() + { + return vendorName; + } + + /** + * Sets the vendor name for this vendor extension. + */ + public void setVendorName(String vendorName) + { + this.vendorName = vendorName; + } + + /** + * Returns the key of this vendor extension. + */ + public String getKey() + { + return key; + } + + /** + * Sets the key for this vendor extension. + */ + public void setKey(String key) + { + this.key = key; + } + + /** + * Returns the value of this vendor extension. + */ + public Object getValue() + { + return value; + } + + /** + * Sets the value for this vendor extension. + */ + public void setValue(Object value) + { + this.value = value; + } + +}