001: // $Id: PropertyFactory.java 10119 2006-07-14 00:09:19Z steve.ebersole@jboss.com $
002: package org.hibernate.tuple;
003:
004: import java.lang.reflect.Constructor;
005:
006: import org.hibernate.EntityMode;
007: import org.hibernate.mapping.PropertyGeneration;
008: import org.hibernate.engine.IdentifierValue;
009: import org.hibernate.engine.UnsavedValueFactory;
010: import org.hibernate.engine.VersionValue;
011: import org.hibernate.id.IdentifierGenerator;
012: import org.hibernate.mapping.KeyValue;
013: import org.hibernate.mapping.PersistentClass;
014: import org.hibernate.mapping.Property;
015: import org.hibernate.property.Getter;
016: import org.hibernate.property.PropertyAccessor;
017: import org.hibernate.property.PropertyAccessorFactory;
018: import org.hibernate.type.AssociationType;
019: import org.hibernate.type.Type;
020: import org.hibernate.type.VersionType;
021: import org.hibernate.util.ReflectHelper;
022:
023: /**
024: * Responsible for generation of runtime metamodel {@link Property} representations.
025: * Makes distinction between identifier, version, and other (standard) properties.
026: *
027: * @author Steve Ebersole
028: */
029: public class PropertyFactory {
030:
031: /**
032: * Generates an IdentifierProperty representation of the for a given entity mapping.
033: *
034: * @param mappedEntity The mapping definition of the entity.
035: * @param generator The identifier value generator to use for this identifier.
036: * @return The appropriate IdentifierProperty definition.
037: */
038: public static IdentifierProperty buildIdentifierProperty(
039: PersistentClass mappedEntity, IdentifierGenerator generator) {
040:
041: String mappedUnsavedValue = mappedEntity.getIdentifier()
042: .getNullValue();
043: Type type = mappedEntity.getIdentifier().getType();
044: Property property = mappedEntity.getIdentifierProperty();
045:
046: IdentifierValue unsavedValue = UnsavedValueFactory
047: .getUnsavedIdentifierValue(mappedUnsavedValue,
048: getGetter(property), type,
049: getConstructor(mappedEntity));
050:
051: if (property == null) {
052: // this is a virtual id property...
053: return new IdentifierProperty(type, mappedEntity
054: .hasEmbeddedIdentifier(), mappedEntity
055: .hasIdentifierMapper(), unsavedValue, generator);
056: } else {
057: return new IdentifierProperty(property.getName(), property
058: .getNodeName(), type, mappedEntity
059: .hasEmbeddedIdentifier(), unsavedValue, generator);
060: }
061: }
062:
063: /**
064: * Generates a VersionProperty representation for an entity mapping given its
065: * version mapping Property.
066: *
067: * @param property The version mapping Property.
068: * @param lazyAvailable Is property lazy loading currently available.
069: * @return The appropriate VersionProperty definition.
070: */
071: public static VersionProperty buildVersionProperty(
072: Property property, boolean lazyAvailable) {
073: String mappedUnsavedValue = ((KeyValue) property.getValue())
074: .getNullValue();
075:
076: VersionValue unsavedValue = UnsavedValueFactory
077: .getUnsavedVersionValue(mappedUnsavedValue,
078: getGetter(property), (VersionType) property
079: .getType(), getConstructor(property
080: .getPersistentClass()));
081:
082: boolean lazy = lazyAvailable && property.isLazy();
083:
084: return new VersionProperty(
085: property.getName(),
086: property.getNodeName(),
087: property.getValue().getType(),
088: lazy,
089: property.isInsertable(),
090: property.isUpdateable(),
091: property.getGeneration() == PropertyGeneration.INSERT
092: || property.getGeneration() == PropertyGeneration.ALWAYS,
093: property.getGeneration() == PropertyGeneration.ALWAYS,
094: property.isOptional(),
095: property.isUpdateable() && !lazy, property
096: .isOptimisticLocked(), property
097: .getCascadeStyle(), unsavedValue);
098: }
099:
100: /**
101: * Generate a "standard" (i.e., non-identifier and non-version) based on the given
102: * mapped property.
103: *
104: * @param property The mapped property.
105: * @param lazyAvailable Is property lazy loading currently available.
106: * @return The appropriate StandardProperty definition.
107: */
108: public static StandardProperty buildStandardProperty(
109: Property property, boolean lazyAvailable) {
110:
111: final Type type = property.getValue().getType();
112:
113: // we need to dirty check collections, since they can cause an owner
114: // version number increment
115:
116: // we need to dirty check many-to-ones with not-found="ignore" in order
117: // to update the cache (not the database), since in this case a null
118: // entity reference can lose information
119:
120: boolean alwaysDirtyCheck = type.isAssociationType()
121: && ((AssociationType) type).isAlwaysDirtyChecked();
122:
123: return new StandardProperty(
124: property.getName(),
125: property.getNodeName(),
126: type,
127: lazyAvailable && property.isLazy(),
128: property.isInsertable(),
129: property.isUpdateable(),
130: property.getGeneration() == PropertyGeneration.INSERT
131: || property.getGeneration() == PropertyGeneration.ALWAYS,
132: property.getGeneration() == PropertyGeneration.ALWAYS,
133: property.isOptional(), alwaysDirtyCheck
134: || property.isUpdateable(), property
135: .isOptimisticLocked(), property
136: .getCascadeStyle(), property.getValue()
137: .getFetchMode());
138: }
139:
140: private static Constructor getConstructor(
141: PersistentClass persistentClass) {
142: if (persistentClass == null
143: || !persistentClass.hasPojoRepresentation()) {
144: return null;
145: }
146:
147: try {
148: return ReflectHelper.getDefaultConstructor(persistentClass
149: .getMappedClass());
150: } catch (Throwable t) {
151: return null;
152: }
153: }
154:
155: private static Getter getGetter(Property mappingProperty) {
156: if (mappingProperty == null
157: || !mappingProperty.getPersistentClass()
158: .hasPojoRepresentation()) {
159: return null;
160: }
161:
162: PropertyAccessor pa = PropertyAccessorFactory
163: .getPropertyAccessor(mappingProperty, EntityMode.POJO);
164: return pa.getGetter(mappingProperty.getPersistentClass()
165: .getMappedClass(), mappingProperty.getName());
166: }
167:
168: }
|