package org.springframework.roo.classpath.operations.jsr303;
import static org.springframework.roo.model.JdkJavaType.HASH_SET;
import static org.springframework.roo.model.JpaJavaType.CASCADE_TYPE;
import static org.springframework.roo.model.JpaJavaType.ELEMENT_COLLECTION;
import static org.springframework.roo.model.JpaJavaType.FETCH_TYPE;
import static org.springframework.roo.model.JpaJavaType.MANY_TO_MANY;
import static org.springframework.roo.model.JpaJavaType.MANY_TO_ONE;
import static org.springframework.roo.model.JpaJavaType.ONE_TO_MANY;
import static org.springframework.roo.model.JpaJavaType.ONE_TO_ONE;
import java.util.ArrayList;
import java.util.List;
import org.springframework.roo.classpath.details.annotations.AnnotationAttributeValue;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder;
import org.springframework.roo.classpath.details.annotations.EnumAttributeValue;
import org.springframework.roo.classpath.details.annotations.StringAttributeValue;
import org.springframework.roo.classpath.operations.Cardinality;
import org.springframework.roo.classpath.operations.Fetch;
import org.springframework.roo.model.DataType;
import org.springframework.roo.model.EnumDetails;
import org.springframework.roo.model.JavaSymbolName;
import org.springframework.roo.model.JavaType;
/**
* Properties used by the one side of a many-to-one relationship or an @ElementCollection
* of enums (called a "set").
* <p>
* For example, an Order-LineItem link would have the Order contain a "set" of
* Orders.
* <p>
* Limited support for collection mapping is provided. This reflects the
* pragmatic goals of the tool and the fact a user can edit the generated files
* by hand anyway.
* <p>
* This field is intended for use with JSR 220 and will create a @OneToMany
* annotation or in the case of enums, an @ElementCollection annotation will be
* created.
*
* @author Ben Alex
* @since 1.0
*/
public class SetField extends CollectionField {
private final Cardinality cardinality;
private Fetch fetch;
/**
* Whether the JSR 220 @OneToMany.mappedBy annotation attribute will be
* added
*/
private JavaSymbolName mappedBy;
public SetField(final String physicalTypeIdentifier,
final JavaType fieldType, final JavaSymbolName fieldName,
final JavaType genericParameterTypeName,
final Cardinality cardinality) {
super(physicalTypeIdentifier, fieldType, fieldName,
genericParameterTypeName);
this.cardinality = cardinality;
}
@Override
public void decorateAnnotationsList(
final List<AnnotationMetadataBuilder> annotations) {
super.decorateAnnotationsList(annotations);
final List<AnnotationAttributeValue<?>> attributes = new ArrayList<AnnotationAttributeValue<?>>();
if (cardinality == null) {
// Assume set field is an enum
annotations.add(new AnnotationMetadataBuilder(ELEMENT_COLLECTION));
}
else {
attributes.add(new EnumAttributeValue(
new JavaSymbolName("cascade"), new EnumDetails(
CASCADE_TYPE, new JavaSymbolName("ALL"))));
if (fetch != null) {
JavaSymbolName value = new JavaSymbolName("EAGER");
if (fetch == Fetch.LAZY) {
value = new JavaSymbolName("LAZY");
}
attributes.add(new EnumAttributeValue(new JavaSymbolName(
"fetch"), new EnumDetails(FETCH_TYPE, value)));
}
if (mappedBy != null) {
attributes.add(new StringAttributeValue(new JavaSymbolName(
"mappedBy"), mappedBy.getSymbolName()));
}
switch (cardinality) {
case ONE_TO_MANY:
annotations.add(new AnnotationMetadataBuilder(ONE_TO_MANY,
attributes));
break;
case MANY_TO_MANY:
annotations.add(new AnnotationMetadataBuilder(MANY_TO_MANY,
attributes));
break;
case ONE_TO_ONE:
annotations.add(new AnnotationMetadataBuilder(ONE_TO_ONE,
attributes));
break;
default:
annotations.add(new AnnotationMetadataBuilder(MANY_TO_ONE,
attributes));
break;
}
}
}
public Fetch getFetch() {
return fetch;
}
@Override
public JavaType getInitializer() {
final List<JavaType> params = new ArrayList<JavaType>();
params.add(getGenericParameterTypeName());
return new JavaType(HASH_SET.getFullyQualifiedTypeName(), 0,
DataType.TYPE, null, params);
}
public JavaSymbolName getMappedBy() {
return mappedBy;
}
public void setFetch(final Fetch fetch) {
this.fetch = fetch;
}
public void setMappedBy(final JavaSymbolName mappedBy) {
this.mappedBy = mappedBy;
}
}