![JAR search and dependency download from the Maven repository](/logo.png)
org.chromattic.metamodel.mapping.BeanMappingBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of chromattic.metamodel Show documentation
Show all versions of chromattic.metamodel Show documentation
Chromattic Framework Metamodel
The newest version!
/*
* Copyright (C) 2010 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.chromattic.metamodel.mapping;
import org.chromattic.api.NameConflictResolution;
import org.chromattic.api.RelationshipType;
import org.chromattic.api.annotations.AutoCreated;
import org.chromattic.api.annotations.Create;
import org.chromattic.api.annotations.DefaultValue;
import org.chromattic.api.annotations.Destroy;
import org.chromattic.api.annotations.FindById;
import org.chromattic.api.annotations.FormattedBy;
import org.chromattic.api.annotations.Id;
import org.chromattic.api.annotations.Mandatory;
import org.chromattic.api.annotations.ManyToOne;
import org.chromattic.api.annotations.MappedBy;
import org.chromattic.api.annotations.MixinType;
import org.chromattic.api.annotations.Name;
import org.chromattic.api.annotations.NamingPolicy;
import org.chromattic.api.annotations.NamingPrefix;
import org.chromattic.api.annotations.OneToMany;
import org.chromattic.api.annotations.OneToOne;
import org.chromattic.api.annotations.Owner;
import org.chromattic.api.annotations.Path;
import org.chromattic.api.annotations.PrimaryType;
import org.chromattic.api.annotations.Properties;
import org.chromattic.api.annotations.Property;
import org.chromattic.api.annotations.WorkspaceName;
import org.chromattic.metamodel.bean.BeanFilter;
import org.chromattic.metamodel.bean.BeanInfo;
import org.chromattic.metamodel.bean.BeanValueInfo;
import org.chromattic.metamodel.bean.PropertyInfo;
import org.chromattic.metamodel.bean.SimpleValueInfo;
import org.chromattic.metamodel.bean.BeanInfoBuilder;
import org.chromattic.metamodel.bean.ValueKind;
import org.chromattic.metamodel.bean.ValueInfo;
import org.chromattic.metamodel.mapping.jcr.PropertyDefinitionMapping;
import org.chromattic.metamodel.mapping.jcr.PropertyMetaType;
import org.chromattic.metamodel.type.SimpleTypeMapping;
import org.chromattic.metamodel.type.SimpleTypeResolver;
import org.reflext.api.ClassTypeInfo;
import org.reflext.api.MethodInfo;
import org.reflext.api.TypeInfo;
import org.reflext.api.TypeResolver;
import org.reflext.api.VoidTypeInfo;
import org.reflext.api.annotation.AnnotationInfo;
import org.reflext.api.annotation.AnnotationParameterInfo;
import org.reflext.api.annotation.AnnotationType;
import org.reflext.api.introspection.AnnotationTarget;
import org.reflext.api.introspection.MethodIntrospector;
import org.reflext.api.visit.HierarchyScope;
import org.reflext.core.TypeResolverImpl;
import org.reflext.jlr.JavaLangReflectReflectionModel;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
/**
* The bean mapping builder.
*
* @author Julien Viet
* @version $Revision$
*/
public class BeanMappingBuilder {
/** Used for retrieving {@code java.lang.Object} info. */
private final TypeResolver domain = TypeResolverImpl.create(JavaLangReflectReflectionModel.getInstance());
/** . */
private final ClassTypeInfo FORMATTED_BY = (ClassTypeInfo)domain.resolve(FormattedBy.class);
/** . */
private final AnnotationType FORMATTED_BY_ANNOTATION_TYPE = AnnotationType.get(FORMATTED_BY);
/** . */
private final SimpleTypeResolver simpleTypeResolver;
public BeanMappingBuilder() {
this(new SimpleTypeResolver());
}
public BeanMappingBuilder(SimpleTypeResolver simpleTypeResolver) {
this.simpleTypeResolver = simpleTypeResolver;
}
public Map build(ClassTypeInfo... classTypes) {
return build(org.chromattic.common.collection.Collections.set(classTypes));
}
public Map build(Set classTypes) {
// Clone for modification
classTypes = new HashSet(classTypes);
// Build beans
final AtomicReference objectCTI = new AtomicReference();
BeanFilter filter = new BeanFilter() {
public boolean accept(ClassTypeInfo cti) {
boolean accept = false;
if (cti.getName().equals(Object.class.getName())) {
objectCTI.set(cti);
accept = true;
} else {
accept |= cti.getDeclaredAnnotation(AnnotationType.get(PrimaryType.class)) != null;
accept |= cti.getDeclaredAnnotation(AnnotationType.get(MixinType.class)) != null;
}
return accept;
}
};
Map beans = new BeanInfoBuilder(simpleTypeResolver, filter).build(classTypes);
// Create context
Context ctx = new Context(new SimpleTypeResolver(), new HashSet(beans.values()));
// Build object bean info ahead as it does not contain any annotation
if (objectCTI.get() != null) {
BeanInfo objectBean = beans.remove(objectCTI.get());
BeanMapping objectMapping = new BeanMapping(
objectBean,
NodeTypeKind.PRIMARY,
"nt:base",
NameConflictResolution.FAIL,
null,
false,
true,
null);
ctx.beanMappings.put(objectBean, objectMapping);
ctx.beans.remove(objectBean);
}
// Build mappings
Map beanMappings = ctx.build();
// Resolve relationships
for (BeanMapping beanMapping : beanMappings.values()) {
for (PropertyMapping propertyMapping : beanMapping.getProperties().values()) {
if (propertyMapping instanceof RelationshipMapping, ?, ?>) {
RelationshipMapping, ?, ?> relationshipMapping = (RelationshipMapping, ?, ?>)propertyMapping;
relationshipMapping.resolve();
}
}
}
//
Map classTypeMappings = new HashMap();
for (Map.Entry beanMapping : beanMappings.entrySet()) {
classTypeMappings.put(beanMapping.getKey().getClassType(), beanMapping.getValue());
}
//
return classTypeMappings;
}
private class Context {
/** . */
final SimpleTypeResolver typeResolver;
/** . */
final Map beanClassTypeMap;
/** . */
final Set beans;
/** . */
final Map beanMappings;
private Context(SimpleTypeResolver typeResolver, Set beans) {
//
Map beanClassTypeMap = new HashMap();
for (BeanInfo bean : beans) {
beanClassTypeMap.put(bean.getClassType(), bean);
}
//
this.typeResolver = typeResolver;
this.beanClassTypeMap = beanClassTypeMap;
this.beans = beans;
this.beanMappings = new HashMap();
}
public Map build() {
while (true) {
Iterator iterator = beans.iterator();
if (iterator.hasNext()) {
BeanInfo bean = iterator.next();
resolve(bean);
} else {
return beanMappings;
}
}
}
private BeanMapping resolve(ClassTypeInfo classType) {
BeanInfo bean = beanClassTypeMap.get(classType);
if (bean != null) {
return resolve(bean);
} else {
return null;
}
}
private BeanMapping resolve(BeanInfo bean) {
BeanMapping mapping = beanMappings.get(bean);
if (mapping == null) {
if (beans.remove(bean)) {
mapping = create(bean);
beanMappings.put(bean, mapping);
build(mapping);
} else {
// It does not resolve
}
}
return mapping;
}
private BeanMapping create(BeanInfo bean) {
Collection extends Annotation> annotations = bean.getAnnotations(PrimaryType.class, MixinType.class);
if (annotations.size() != 1) {
throw new InvalidMappingException(bean.getClassType(), "Class is not annotated with a primary type of mixin type");
}
//
Annotation mappingAnnotation = annotations.iterator().next();
//
NameConflictResolution onDuplicate = NameConflictResolution.FAIL;
NamingPolicy namingPolicy = bean.getAnnotation(NamingPolicy.class);
if (namingPolicy != null) {
onDuplicate = namingPolicy.onDuplicate();
}
//
ClassTypeInfo formatter = null;
AnnotationInfo formattedBy = bean.getAnnotation(FORMATTED_BY_ANNOTATION_TYPE);
if (formattedBy != null) {
AnnotationParameterInfo valueParameter = (AnnotationParameterInfo)formattedBy.getParameter("value");
formatter = valueParameter.getValue();
}
//
NamingPrefix namingPrefix = bean.getAnnotation(NamingPrefix.class);
String prefix = null;
if (namingPrefix != null) {
prefix = namingPrefix.value();
}
//
NodeTypeKind nodeTypeKind;
String nodeTypeName;
boolean orderable;
boolean abstract_;
if (mappingAnnotation instanceof PrimaryType) {
PrimaryType typeAnnotation = (PrimaryType)mappingAnnotation;
nodeTypeKind = NodeTypeKind.PRIMARY;
nodeTypeName = typeAnnotation.name();
orderable = typeAnnotation.orderable();
abstract_ = typeAnnotation.abstract_();
} else {
MixinType typeAnnotation = (MixinType)mappingAnnotation;
nodeTypeKind = NodeTypeKind.MIXIN;
nodeTypeName = typeAnnotation.name();
orderable = false;
abstract_ = true;
}
//
return new BeanMapping(bean, nodeTypeKind, nodeTypeName, onDuplicate, formatter, orderable, abstract_, prefix);
}
private void build(BeanMapping beanMapping) {
BeanInfo bean = beanMapping.bean;
// First build the parent mapping if any
if (bean.getParent() != null) {
beanMapping.parent = resolve(bean.getParent());
}
//
Map> properties = new HashMap>();
for (PropertyInfo, ?> property : bean.getProperties().values()) {
// Determine kind
Collection extends Annotation> annotations = property.getAnnotations(
Property.class,
Properties.class,
OneToOne.class,
OneToMany.class,
ManyToOne.class,
Id.class,
Path.class,
Name.class,
WorkspaceName.class
);
//
if (annotations.size() > 1) {
throw new InvalidMappingException(bean.getClassType(), "The property " + property + " declares too many annotations " + annotations);
}
// Build the correct mapping or fail
PropertyMapping, ?, ?> mapping = null;
if (annotations.size() == 1) {
Annotation annotation = annotations.iterator().next();
ValueInfo value = property.getValue();
if (property.getValueKind() == ValueKind.SINGLE) {
if (value instanceof SimpleValueInfo>) {
SimpleValueInfo> simpleValue = (SimpleValueInfo>)value;
if (annotation instanceof Property) {
Property propertyAnnotation = (Property)annotation;
if (simpleValue.getValueKind() instanceof ValueKind.Single) {
PropertyInfo, ValueKind.Single> a = (PropertyInfo, ValueKind.Single>)property;
mapping = createValueMapping(propertyAnnotation, a);
} else {
PropertyInfo, ValueKind.Single> a = (PropertyInfo, ValueKind.Single>)property;
mapping = createValueMapping(propertyAnnotation, a);
}
} else if (annotation instanceof Id) {
mapping = createAttribute((PropertyInfo)property, NodeAttributeType.ID);
} else if (annotation instanceof Path) {
mapping = createAttribute((PropertyInfo)property, NodeAttributeType.PATH);
} else if (annotation instanceof Name) {
mapping = createAttribute((PropertyInfo)property, NodeAttributeType.NAME);
} else if (annotation instanceof WorkspaceName) {
mapping = createAttribute((PropertyInfo)property, NodeAttributeType.WORKSPACE_NAME);
} else {
throw new InvalidMappingException(bean.getClassType(), "The property " + property + " is not annotated");
}
} else if (value instanceof BeanValueInfo) {
if (annotation instanceof OneToOne) {
OneToOne oneToOne = (OneToOne)annotation;
switch (oneToOne.type()) {
case HIERARCHIC:
mapping = createHierarchicOneToOne(beanMapping, oneToOne, (PropertyInfo) property);
break;
case EMBEDDED:
mapping = createEmbeddedOneToOne((PropertyInfo) property);
break;
default:
throw new InvalidMappingException(bean.getClassType(), "Expecting that the @OneToOne property " +
property + " to be annotated with " + RelationshipType.HIERARCHIC + " or "
+ RelationshipType.EMBEDDED + " instead of " + oneToOne.type());
}
} else if (annotation instanceof ManyToOne) {
ManyToOne manyToOne = (ManyToOne)annotation;
switch (manyToOne.type()) {
case HIERARCHIC:
mapping = createHierarchicManyToOne(beanMapping, manyToOne, (PropertyInfo)property);
break;
case PATH:
case REFERENCE:
mapping = createReferenceManyToOne(manyToOne, (PropertyInfo)property);
break;
default:
throw new InvalidMappingException(bean.getClassType(), "Expecting that the @ManyToOne property " +
property + " to be annotated with " + RelationshipType.HIERARCHIC + ", "
+ RelationshipType.PATH + " or " + RelationshipType.REFERENCE + " instead of " +
manyToOne.type());
}
} else {
throw new InvalidMappingException(bean.getClassType(), "Annotation " + annotation + " is forbidden " +
" on property " + property);
}
} else {
throw new AssertionError();
}
} else if (property.getValueKind() instanceof ValueKind.Multi) {
if (value instanceof SimpleValueInfo) {
SimpleValueInfo> simpleValue = (SimpleValueInfo>)value;
if (annotation instanceof Property) {
Property propertyAnnotation = (Property)annotation;
if (simpleValue.getValueKind() instanceof ValueKind.Single) {
PropertyInfo, ValueKind.Single> a = (PropertyInfo, ValueKind.Single>)property;
mapping = createValueMapping(propertyAnnotation, a);
} else {
PropertyInfo, ValueKind.Single> a = (PropertyInfo, ValueKind.Single>)property;
mapping = createValueMapping(propertyAnnotation, a);
}
} else if (annotation instanceof Properties) {
mapping = createProperties((PropertyInfo, ValueKind.Map>)property);
} else {
throw new InvalidMappingException(bean.getClassType(), "Annotation " + annotation + " is forbidden " +
" on property " + property);
}
} else if (value instanceof BeanValueInfo) {
if (annotation instanceof OneToMany) {
OneToMany oneToMany = (OneToMany)annotation;
switch (oneToMany.type()) {
case HIERARCHIC:
mapping = createHierarchicOneToMany(beanMapping, oneToMany, (PropertyInfo)property);
break;
case PATH:
case REFERENCE:
mapping = createReferenceOneToMany(oneToMany, (PropertyInfo)property);
break;
default:
throw new InvalidMappingException(bean.getClassType(), "Expecting that the @OneToMany property " +
property + " to be annotated with " + RelationshipType.HIERARCHIC + ", "
+ RelationshipType.PATH + " or " + RelationshipType.REFERENCE + " instead of " +
oneToMany.type());
}
} else if (annotation instanceof Properties) {
mapping = createProperties((PropertyInfo, ValueKind.Map>)property);
} else {
throw new InvalidMappingException(bean.getClassType(), "Annotation " + annotation + " is forbidden " +
" on property " + property);
}
} else {
throw new AssertionError();
}
} else {
throw new AssertionError();
}
}
//
if (mapping != null) {
// Resolve parent property without any check for now
PropertyInfo parentProperty = property.getParent();
if (parentProperty != null) {
BeanInfo ancestor = parentProperty.getOwner();
BeanMapping ancestorMapping = resolve(ancestor);
mapping.parent = ancestorMapping.properties.get(parentProperty.getName());
}
//
properties.put(mapping.property.getName(), mapping);
}
}
// Wire
beanMapping.properties.putAll(properties);
for (PropertyMapping, ?, ?> propertyMapping : beanMapping.properties.values()) {
propertyMapping.owner = beanMapping;
}
// Take care of methods
MethodIntrospector introspector = new MethodIntrospector(HierarchyScope.ALL);
Set methodMappings = new HashSet();
// Create
for (AnnotationTarget annotatedMethods : introspector.resolveMethods(bean.getClassType(), Constants.CREATE)) {
MethodInfo method = annotatedMethods.getTarget();
if (!method.isStatic()) {
List parameterTypes = method.getParameterTypes();
if (parameterTypes.size() < 2) {
if (parameterTypes.size() == 1) {
TypeInfo argTI = parameterTypes.get(0);
if (argTI instanceof ClassTypeInfo) {
ClassTypeInfo argCTI = (ClassTypeInfo)argTI;
if (!argCTI.getName().equals(String.class.getName())) {
throw new InvalidMappingException(bean.getClassType(), "The argument of the @Create method " +
method + " must be a java.lang.String instead of " + method.getSignature());
}
} else {
throw new InvalidMappingException(bean.getClassType(), "The argument of the @Create method " +
method + " must be a java.lang.String instead of " + method.getSignature());
}
}
ClassTypeInfo returnTypeInfo = bean.resolveToClass(method.getReturnType());
if (returnTypeInfo != null) {
BeanMapping createBeanMapping = resolve(returnTypeInfo);
if (createBeanMapping == null) {
throw new InvalidMappingException(bean.getClassType(), "Could not resolve the return type " + returnTypeInfo + " to a chromattic bean among beans " +
beans + " and mappings " + beanMappings.values());
}
methodMappings.add(new CreateMapping(method, createBeanMapping));
} else {
throw new InvalidMappingException(bean.getClassType(), "Invalid @Create method " + method +
" return type " + returnTypeInfo);
}
} else {
throw new InvalidMappingException(bean.getClassType(), "The signature of the @Create method " +
method + "should have zero or one argument instead of " + method.getSignature());
}
} else {
throw new InvalidMappingException(bean.getClassType(), "The @Create method " +
method + " must not be static");
}
}
// Destroy
for (AnnotationTarget annotatedMethods : introspector.resolveMethods(bean.getClassType(), Constants.DESTROY)) {
MethodInfo method = annotatedMethods.getTarget();
if (!method.isStatic()) {
List parameterTypes = method.getParameterTypes();
if (parameterTypes.size() != 0) {
throw new InvalidMappingException(bean.getClassType(), "The @Destroy method " +
method + " must have no arguments");
}
if (!(method.getReturnType() instanceof VoidTypeInfo)) {
throw new InvalidMappingException(bean.getClassType(), "The @Destroy method " +
method + " must have a void return type");
}
methodMappings.add(new DestroyMapping(method));
} else {
throw new InvalidMappingException(bean.getClassType(), "The @Destroy method " +
method + " must not be static");
}
}
// Find by id
for (AnnotationTarget annotatedMethods : introspector.resolveMethods(bean.getClassType(), Constants.FIND_BY_ID)) {
MethodInfo method = annotatedMethods.getTarget();
if (!method.isStatic()) {
List parameterTypes = method.getParameterTypes();
if (parameterTypes.size() == 1) {
TypeInfo argTI = parameterTypes.get(0);
if (argTI instanceof ClassTypeInfo) {
ClassTypeInfo argCTI = (ClassTypeInfo)argTI;
if (argCTI.getName().equals(String.class.getName())) {
ClassTypeInfo cti = (ClassTypeInfo)bean.getClassType().resolve(method.getReturnType());
methodMappings.add(new FindByIdMapping(method, cti));
} else {
throw new InvalidMappingException(bean.getClassType(), "The argument of the @FindById method " +
method + " must be a java.lang.String instead of " + method.getSignature());
}
} else {
throw new InvalidMappingException(bean.getClassType(), "The argument of the @FindById method " +
method + " must be a java.lang.String instead of " + method.getSignature());
}
} else {
throw new InvalidMappingException(bean.getClassType(), "The signature of the @FindById method " +
method + "should a single java.lang.String argument instead of " + method.getSignature());
}
} else {
throw new InvalidMappingException(bean.getClassType(), "The @FindById method " +
method + " must not be static");
}
}
//
beanMapping.methods.addAll(methodMappings);
}
private AttributeMapping createAttribute(PropertyInfo property, NodeAttributeType type) {
TypeInfo effectiveType = property.getValue().getEffectiveType();
if (!(effectiveType instanceof ClassTypeInfo)) {
throw new InvalidMappingException(property.getOwner().getClassType(), "The property " + property +
" must be of type java.lang.String");
}
ClassTypeInfo effectiveClassType = (ClassTypeInfo)effectiveType;
if (!effectiveClassType.getName().equals(String.class.getName())) {
throw new InvalidMappingException(property.getOwner().getClassType(), "The property " + property +
" must be of type java.lang.String");
}
return new AttributeMapping(property, type);
}
private PropertiesMapping createProperties(PropertyInfo property) {
if (property.getValueKind() != ValueKind.MAP) {
throw new InvalidMappingException(property.getOwner().getClassType(), "The @Properties " + property +
" must be of type java.util.Map instead of " + property.getValue().getEffectiveType());
}
TypeInfo type = property.getValue().getEffectiveType();
//
PropertyMetaType> mt = null;
ValueKind valueKind;
ValueInfo vi = property.getValue();
if (vi instanceof SimpleValueInfo>) {
SimpleValueInfo> svi = (SimpleValueInfo>)vi;
if (svi.getTypeMapping() != null) {
mt = svi.getTypeMapping().getPropertyMetaType();
}
valueKind = svi.getValueKind();
} else {
if (type.getName().equals(Object.class.getName())) {
mt = null;
}
valueKind = ValueKind.SINGLE;
}
//
String prefix = null;
NamingPrefix namingPrefix = property.getAnnotation(NamingPrefix.class);
if (namingPrefix != null) {
prefix = namingPrefix.value();
}
//
return new PropertiesMapping(property, prefix, mt, valueKind);
}
private
ValueMapping
createValueMapping(
Property propertyAnnotation,
PropertyInfo, ValueKind.Single> property) {
//
PropertyMetaType> propertyMetaType = PropertyMetaType.get(propertyAnnotation.type());
//
SimpleTypeMapping resolved = typeResolver.resolveType(property.getValue().getDeclaredType(), propertyMetaType);
if (resolved == null) {
throw new InvalidMappingException(property.getOwner().getClassType(), "No simple type mapping "
+ property.getValue().getDeclaredType() + " for property " + property);
}
//
List defaultValueList = null;
DefaultValue defaultValueAnnotation = property.getAnnotation(DefaultValue.class);
if (defaultValueAnnotation != null) {
String[] defaultValues = defaultValueAnnotation.value();
defaultValueList = new ArrayList(defaultValues.length);
defaultValueList.addAll(Arrays.asList(defaultValues));
defaultValueList = Collections.unmodifiableList(defaultValueList);
}
//
PropertyDefinitionMapping> propertyDefinition = new PropertyDefinitionMapping(
propertyAnnotation.name(),
resolved.getPropertyMetaType(),
defaultValueList,
false);
//
return new ValueMapping(property, propertyDefinition);
}
private RelationshipMapping.OneToMany.Reference createReferenceOneToMany(OneToMany annotation, PropertyInfo property) {
MappedBy mappedBy = property.getAnnotation(MappedBy.class);
if (mappedBy == null) {
throw new InvalidMappingException(property.getOwner().getClassType(), "The reference @OneToMany relationship " +
property + "must carry an @MappedBy annotation");
}
RelationshipMapping.OneToMany.Reference mapping;
mapping = new RelationshipMapping.OneToMany.Reference(property, mappedBy.value(), annotation.type());
mapping.relatedBeanMapping = resolve(property.getValue().getBean());
return mapping;
}
private RelationshipMapping.OneToMany.Hierarchic createHierarchicOneToMany(BeanMapping beanMapping, OneToMany annotation, PropertyInfo property) {
RelationshipMapping.OneToMany.Hierarchic mapping;
NamingPrefix namingPrefix = property.getAnnotation(NamingPrefix.class);
String declaredPrefix = namingPrefix != null ? namingPrefix.value() : null;
String prefix = declaredPrefix == null ? beanMapping.getPrefix() : declaredPrefix;
mapping = new RelationshipMapping.OneToMany.Hierarchic(property, declaredPrefix, prefix);
mapping.relatedBeanMapping = resolve(property.getValue().getBean());
return mapping;
}
private RelationshipMapping.ManyToOne.Reference createReferenceManyToOne(ManyToOne annotation, PropertyInfo property) {
MappedBy mappedBy = property.getAnnotation(MappedBy.class);
if (mappedBy == null) {
throw new InvalidMappingException(property.getOwner().getClassType(), "The reference @ManyToOne relationship " +
property + "must carry an @MappedBy annotation");
}
RelationshipMapping.ManyToOne.Reference mapping;
mapping = new RelationshipMapping.ManyToOne.Reference(property, mappedBy.value(), annotation.type());
mapping.relatedBeanMapping = resolve(property.getValue().getBean());
return mapping;
}
private RelationshipMapping.ManyToOne.Hierarchic createHierarchicManyToOne(BeanMapping beanMapping, ManyToOne annotation, PropertyInfo property) {
RelationshipMapping.ManyToOne.Hierarchic mapping;
NamingPrefix namingPrefix = property.getAnnotation(NamingPrefix.class);
String declaredPrefix = namingPrefix != null ? namingPrefix.value() : null;
String prefix = declaredPrefix == null ? beanMapping.getPrefix() : declaredPrefix;
mapping = new RelationshipMapping.ManyToOne.Hierarchic(property, declaredPrefix, prefix);
mapping.relatedBeanMapping = resolve(property.getValue().getBean());
return mapping;
}
private RelationshipMapping.OneToOne.Embedded createEmbeddedOneToOne(PropertyInfo property) {
RelationshipMapping.OneToOne.Embedded mapping;
boolean owner = property.getAnnotation(Owner.class) != null;
mapping = new RelationshipMapping.OneToOne.Embedded(property, owner);
mapping.relatedBeanMapping = resolve(property.getValue().getBean());
return mapping;
}
private RelationshipMapping.OneToOne.Hierarchic createHierarchicOneToOne(
BeanMapping beanMapping,
OneToOne annotation,
PropertyInfo property) {
MappedBy mappedBy = property.getAnnotation(MappedBy.class);
if (mappedBy == null) {
throw new InvalidMappingException(property.getOwner().getClassType(), "The @OneToOne relationship " +
property + "must carry an @MappedBy annotation");
}
boolean owner = property.getAnnotation(Owner.class) != null;
boolean autocreated = property.getAnnotation(AutoCreated.class) != null;
boolean mandatory = property.getAnnotation(Mandatory.class) != null;
String declaredPrefix;
String localName;
int index = mappedBy.value().indexOf(':');
if (index == -1) {
declaredPrefix = null;
localName = mappedBy.value();
} else {
declaredPrefix = mappedBy.value().substring(0, index);
localName = mappedBy.value().substring(index + 1);
}
String prefix = declaredPrefix == null ? beanMapping.getPrefix() : declaredPrefix;
RelationshipMapping.OneToOne.Hierarchic mapping;
mapping = new RelationshipMapping.OneToOne.Hierarchic(property, owner, declaredPrefix, prefix, localName, mandatory, autocreated);
mapping.relatedBeanMapping = resolve(property.getValue().getBean());
return mapping;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy