mirror of https://github.com/apache/openjpa.git
OPENJPA-2877
This commit is contained in:
parent
c5b97348fc
commit
116eda9903
|
@ -188,6 +188,7 @@ public class FieldMetaData
|
|||
private Boolean _serializableField = null;
|
||||
private boolean _generated = false;
|
||||
private boolean _useSchemaElement = true;
|
||||
private Class _converter;
|
||||
|
||||
// Members aren't serializable. Use a proxy that can provide a Member
|
||||
// to avoid writing the full Externalizable implementation.
|
||||
|
@ -1317,35 +1318,52 @@ public class FieldMetaData
|
|||
}
|
||||
|
||||
Method externalizer = getExternalizerMethod();
|
||||
if (externalizer == null)
|
||||
return val;
|
||||
if (externalizer != null) {
|
||||
// special case for queries: allow the given value to pass through
|
||||
// as-is if it is already in externalized form
|
||||
if (val != null && getType().isInstance(val)
|
||||
&& (!getDeclaredType().isInstance(val)
|
||||
|| getDeclaredType() == Object.class))
|
||||
return val;
|
||||
|
||||
// special case for queries: allow the given value to pass through
|
||||
// as-is if it is already in externalized form
|
||||
if (val != null && getType().isInstance(val)
|
||||
&& (!getDeclaredType().isInstance(val)
|
||||
|| getDeclaredType() == Object.class))
|
||||
return val;
|
||||
|
||||
try {
|
||||
// either invoke the static toExternal(val[, ctx]) method, or the
|
||||
// non-static val.toExternal([ctx]) method
|
||||
if (Modifier.isStatic(externalizer.getModifiers())) {
|
||||
if (externalizer.getParameterTypes().length == 1)
|
||||
return externalizer.invoke(null, new Object[]{ val });
|
||||
return externalizer.invoke(null, new Object[]{ val, ctx });
|
||||
try {
|
||||
// either invoke the static toExternal(val[, ctx]) method, or the
|
||||
// non-static val.toExternal([ctx]) method
|
||||
if (Modifier.isStatic(externalizer.getModifiers())) {
|
||||
if (externalizer.getParameterTypes().length == 1)
|
||||
return externalizer.invoke(null, new Object[]{ val });
|
||||
return externalizer.invoke(null, new Object[]{ val, ctx });
|
||||
}
|
||||
if (val == null)
|
||||
return null;
|
||||
if (externalizer.getParameterTypes().length == 0)
|
||||
return externalizer.invoke(val, (Object[]) null);
|
||||
return externalizer.invoke(val, new Object[]{ ctx });
|
||||
} catch (OpenJPAException ke) {
|
||||
throw ke;
|
||||
} catch (Exception e) {
|
||||
throw new MetaDataException(_loc.get("externalizer-err", this,
|
||||
Exceptions.toString(val), e.toString())).setCause(e);
|
||||
}
|
||||
if (val == null)
|
||||
return null;
|
||||
if (externalizer.getParameterTypes().length == 0)
|
||||
return externalizer.invoke(val, (Object[]) null);
|
||||
return externalizer.invoke(val, new Object[]{ ctx });
|
||||
} catch (OpenJPAException ke) {
|
||||
throw ke;
|
||||
} catch (Exception e) {
|
||||
throw new MetaDataException(_loc.get("externalizer-err", this,
|
||||
Exceptions.toString(val), e.toString())).setCause(e);
|
||||
}
|
||||
|
||||
Class converter = getConverter();
|
||||
if (converter != null) {
|
||||
try {
|
||||
// TODO support CDI (OPENJPA-2714)
|
||||
Object instance = converter.getDeclaredConstructor().newInstance();
|
||||
// see AttributeConverter.java from the JPA specs
|
||||
Method method = converter.getDeclaredMethod("convertToDatabaseColumn", Object.class);
|
||||
return method.invoke(instance, val);
|
||||
} catch (OpenJPAException ke) {
|
||||
throw ke;
|
||||
} catch (Exception e) {
|
||||
throw new MetaDataException(_loc.get("converter-err", this,
|
||||
Exceptions.toString(val), e.toString())).setCause(e);
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1359,50 +1377,67 @@ public class FieldMetaData
|
|||
return fieldValues.get(val);
|
||||
|
||||
Member factory = getFactoryMethod();
|
||||
if (factory == null)
|
||||
return val;
|
||||
if (factory != null) {
|
||||
try {
|
||||
if (val == null && getNullValue() == NULL_DEFAULT)
|
||||
return AccessController.doPrivileged(
|
||||
J2DoPrivHelper.newInstanceAction(getDeclaredType()));
|
||||
|
||||
try {
|
||||
if (val == null && getNullValue() == NULL_DEFAULT)
|
||||
return AccessController.doPrivileged(
|
||||
J2DoPrivHelper.newInstanceAction(getDeclaredType()));
|
||||
// invoke either the constructor for the field type,
|
||||
// or the static type.toField(val[, ctx]) method
|
||||
if (factory instanceof Constructor) {
|
||||
if (val == null)
|
||||
return null;
|
||||
return ((Constructor) factory).newInstance
|
||||
(new Object[]{ val });
|
||||
}
|
||||
|
||||
// invoke either the constructor for the field type,
|
||||
// or the static type.toField(val[, ctx]) method
|
||||
if (factory instanceof Constructor) {
|
||||
if (val == null)
|
||||
return null;
|
||||
return ((Constructor) factory).newInstance
|
||||
(new Object[]{ val });
|
||||
Method meth = (Method) factory;
|
||||
if (meth.getParameterTypes().length == 1)
|
||||
return meth.invoke(null, new Object[]{ val });
|
||||
return meth.invoke(null, new Object[]{ val, ctx });
|
||||
} catch (Exception e) {
|
||||
// unwrap cause
|
||||
if (e instanceof InvocationTargetException) {
|
||||
Throwable t = ((InvocationTargetException) e).
|
||||
getTargetException();
|
||||
if (t instanceof Error)
|
||||
throw (Error) t;
|
||||
e = (Exception) t;
|
||||
|
||||
// allow null values to cause NPEs and illegal arg exceptions
|
||||
// without error
|
||||
if (val == null && (e instanceof NullPointerException
|
||||
|| e instanceof IllegalArgumentException))
|
||||
return null;
|
||||
}
|
||||
|
||||
if (e instanceof OpenJPAException)
|
||||
throw (OpenJPAException) e;
|
||||
if (e instanceof PrivilegedActionException)
|
||||
e = ((PrivilegedActionException) e).getException();
|
||||
throw new MetaDataException(_loc.get("factory-err", this,
|
||||
Exceptions.toString(val), e.toString())).setCause(e);
|
||||
}
|
||||
|
||||
Method meth = (Method) factory;
|
||||
if (meth.getParameterTypes().length == 1)
|
||||
return meth.invoke(null, new Object[]{ val });
|
||||
return meth.invoke(null, new Object[]{ val, ctx });
|
||||
} catch (Exception e) {
|
||||
// unwrap cause
|
||||
if (e instanceof InvocationTargetException) {
|
||||
Throwable t = ((InvocationTargetException) e).
|
||||
getTargetException();
|
||||
if (t instanceof Error)
|
||||
throw (Error) t;
|
||||
e = (Exception) t;
|
||||
|
||||
// allow null values to cause NPEs and illegal arg exceptions
|
||||
// without error
|
||||
if (val == null && (e instanceof NullPointerException
|
||||
|| e instanceof IllegalArgumentException))
|
||||
return null;
|
||||
}
|
||||
|
||||
if (e instanceof OpenJPAException)
|
||||
throw (OpenJPAException) e;
|
||||
if (e instanceof PrivilegedActionException)
|
||||
e = ((PrivilegedActionException) e).getException();
|
||||
throw new MetaDataException(_loc.get("factory-err", this,
|
||||
Exceptions.toString(val), e.toString())).setCause(e);
|
||||
}
|
||||
|
||||
Class converter = getConverter();
|
||||
if (converter != null) {
|
||||
try {
|
||||
// TODO support CDI (OPENJPA-2714)
|
||||
Object instance = converter.getDeclaredConstructor().newInstance();
|
||||
// see AttributeConverter.java from the JPA specs
|
||||
Method method = converter.getDeclaredMethod("convertToEntityAttribute", Object.class);
|
||||
return method.invoke(instance, val);
|
||||
} catch (OpenJPAException ke) {
|
||||
throw ke;
|
||||
} catch (Exception e) {
|
||||
throw new MetaDataException(_loc.get("converter-err", this,
|
||||
Exceptions.toString(val), e.toString())).setCause(e);
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1420,6 +1455,10 @@ public class FieldMetaData
|
|||
_extMethod = DEFAULT_METHOD;
|
||||
}
|
||||
|
||||
public void setConverter(Class converter) {
|
||||
_converter = converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of this field's factory, or null if none.
|
||||
*/
|
||||
|
@ -2044,6 +2083,7 @@ public class FieldMetaData
|
|||
_access = field._access;
|
||||
_orderDec = field._orderDec;
|
||||
_useSchemaElement = field._useSchemaElement;
|
||||
_converter = field._converter;
|
||||
|
||||
// embedded fields can't be versions
|
||||
if (_owner.getEmbeddingMetaData() == null && _version == null)
|
||||
|
@ -2523,4 +2563,8 @@ public class FieldMetaData
|
|||
}
|
||||
return setterName;
|
||||
}
|
||||
|
||||
public Class getConverter() {
|
||||
return _converter;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,6 +119,8 @@ bad-externalizer: The externalizer method "{1}" on field "{0}" is not valid. \
|
|||
"<owning-class>.<method-name>", and that the method is static.
|
||||
externalizer-err: There was an error invoking the externalizer for field \
|
||||
"{0}" on Java value "{1}": {2}
|
||||
converter-err: There was an error invoking the converter for field \
|
||||
"{0}" on Java value "{1}": {2}
|
||||
factory-err: There was an error invoking the factory for field \
|
||||
"{0}" on datastore value "{1}": {2}
|
||||
bad-factory: The factory method supplied for field "{0}" does not exist or \
|
||||
|
|
|
@ -96,6 +96,7 @@ import javax.persistence.AccessType;
|
|||
import javax.persistence.Basic;
|
||||
import javax.persistence.Cacheable;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Convert;
|
||||
import javax.persistence.ElementCollection;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Embedded;
|
||||
|
@ -174,6 +175,7 @@ import org.apache.openjpa.util.InternalException;
|
|||
import org.apache.openjpa.util.MetaDataException;
|
||||
import org.apache.openjpa.util.UnsupportedException;
|
||||
import org.apache.openjpa.util.UserException;
|
||||
import static org.apache.openjpa.persistence.MetaDataTag.CONVERT;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -231,6 +233,7 @@ public class AnnotationPersistenceMetaDataParser
|
|||
_tags.put(ElementType.class, ELEM_TYPE);
|
||||
_tags.put(ExternalValues.class, EXTERNAL_VALS);
|
||||
_tags.put(Externalizer.class, EXTERNALIZER);
|
||||
_tags.put(Convert.class, CONVERT);
|
||||
_tags.put(Factory.class, FACTORY);
|
||||
_tags.put(FetchGroup.class, FETCH_GROUP);
|
||||
_tags.put(FetchGroups.class, FETCH_GROUPS);
|
||||
|
@ -1326,6 +1329,10 @@ public class AnnotationPersistenceMetaDataParser
|
|||
fmd.setTypeOverride(toOverrideType(((Type) anno).
|
||||
value()));
|
||||
break;
|
||||
case CONVERT:
|
||||
if (isMetaDataMode() && !((Convert) anno).disableConversion())
|
||||
fmd.setConverter(((Convert) anno).converter());
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedException(_loc.get("unsupported", fmd,
|
||||
anno.toString()));
|
||||
|
|
|
@ -91,5 +91,6 @@ public enum MetaDataTag {
|
|||
OPENJPA_VERSION,
|
||||
// JPA 2.1
|
||||
STOREDPROCEDURE_QUERIES,
|
||||
STOREDPROCEDURE_QUERY
|
||||
STOREDPROCEDURE_QUERY,
|
||||
CONVERT
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue