package org.springframework.roo.addon.layers.repository.jpa;
import java.util.Arrays;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.springframework.roo.classpath.PhysicalTypeIdentifierNamingUtils;
import org.springframework.roo.classpath.PhysicalTypeMetadata;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder;
import org.springframework.roo.classpath.itd.AbstractItdTypeDetailsProvidingMetadataItem;
import org.springframework.roo.metadata.MetadataIdentificationUtils;
import org.springframework.roo.model.DataType;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.model.SpringJavaType;
import org.springframework.roo.project.LogicalPath;
/**
* Metadata for {@link RooJpaRepository}.
*
* @author Stefan Schmidt
* @author Andrew Swan
* @since 1.2.0
*/
public class RepositoryJpaMetadata extends
AbstractItdTypeDetailsProvidingMetadataItem {
private static final String PROVIDES_TYPE_STRING = RepositoryJpaMetadata.class
.getName();
private static final String PROVIDES_TYPE = MetadataIdentificationUtils
.create(PROVIDES_TYPE_STRING);
private static final String SPRING_JPA_REPOSITORY = "org.springframework.data.jpa.repository.JpaRepository";
private static final String SPRING_JPA_SPECIFICATION_EXECUTOR = "org.springframework.data.jpa.repository.JpaSpecificationExecutor";
public static String createIdentifier(final JavaType javaType,
final LogicalPath path) {
return PhysicalTypeIdentifierNamingUtils.createIdentifier(
PROVIDES_TYPE_STRING, javaType, path);
}
public static JavaType getJavaType(final String metadataIdentificationString) {
return PhysicalTypeIdentifierNamingUtils.getJavaType(
PROVIDES_TYPE_STRING, metadataIdentificationString);
}
public static String getMetadataIdentiferType() {
return PROVIDES_TYPE;
}
public static LogicalPath getPath(final String metadataIdentificationString) {
return PhysicalTypeIdentifierNamingUtils.getPath(PROVIDES_TYPE_STRING,
metadataIdentificationString);
}
public static boolean isValid(final String metadataIdentificationString) {
return PhysicalTypeIdentifierNamingUtils.isValid(PROVIDES_TYPE_STRING,
metadataIdentificationString);
}
/**
* Constructor
*
* @param identifier the identifier for this item of metadata (required)
* @param aspectName the Java type of the ITD (required)
* @param governorPhysicalTypeMetadata the governor, which is expected to
* contain a {@link ClassOrInterfaceTypeDetails} (required)
* @param annotationValues (required)
* @param identifierType the type of the entity's identifier field
* (required)
*/
public RepositoryJpaMetadata(final String identifier,
final JavaType aspectName,
final PhysicalTypeMetadata governorPhysicalTypeMetadata,
final RepositoryJpaAnnotationValues annotationValues,
final JavaType identifierType) {
super(identifier, aspectName, governorPhysicalTypeMetadata);
Validate.notNull(annotationValues, "Annotation values required");
Validate.notNull(identifierType, "Id type required");
// Make the user's Repository interface extend Spring Data's
// JpaRepository interface if it doesn't already
ensureGovernorExtends(new JavaType(SPRING_JPA_REPOSITORY, 0,
DataType.TYPE, null, Arrays.asList(
annotationValues.getDomainType(), identifierType)));
// ... and likewise extend JpaSpecificationExecutor<Foo>, to allow query
// by specification
ensureGovernorExtends(new JavaType(SPRING_JPA_SPECIFICATION_EXECUTOR,
0, DataType.TYPE, null, Arrays.asList(annotationValues
.getDomainType())));
builder.addAnnotation(new AnnotationMetadataBuilder(
SpringJavaType.REPOSITORY));
// Build the ITD
itdTypeDetails = builder.build();
}
@Override
public String toString() {
final ToStringBuilder builder = new ToStringBuilder(this);
builder.append("identifier", getId());
builder.append("valid", valid);
builder.append("aspectName", aspectName);
builder.append("destinationType", destination);
builder.append("governor", governorPhysicalTypeMetadata.getId());
builder.append("itdTypeDetails", itdTypeDetails);
return builder.toString();
}
}