/*
* gvNIX is an open source tool for rapid application development (RAD).
* Copyright (C) 2010 Generalitat Valenciana
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.gvnix.addon.jpa.addon.batch;
import java.io.File;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.Validate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.gvnix.addon.jpa.addon.JpaOperations;
import org.gvnix.addon.jpa.annotations.batch.GvNIXJpaBatch;
import org.springframework.roo.classpath.PhysicalTypeCategory;
import org.springframework.roo.classpath.PhysicalTypeIdentifier;
import org.springframework.roo.classpath.TypeLocationService;
import org.springframework.roo.classpath.TypeManagementService;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetails;
import org.springframework.roo.classpath.details.ClassOrInterfaceTypeDetailsBuilder;
import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder;
import org.springframework.roo.model.JavaPackage;
import org.springframework.roo.model.JavaType;
import org.springframework.roo.model.JdkJavaType;
import org.springframework.roo.model.RooJavaType;
import org.springframework.roo.model.SpringJavaType;
import org.springframework.roo.project.Path;
import org.springframework.roo.project.PathResolver;
import org.springframework.roo.project.ProjectOperations;
/**
* Implementation of {@link JpaBatchOperations}
*
* @author <a href="http://www.disid.com">DISID Corporation S.L.</a> made for <a
* href="http://www.dgti.gva.es">General Directorate for Information
* Technologies (DGTI)</a>
* @since 1.1
*/
@Component
@Service
public class JpaBatchOperationsImpl implements JpaBatchOperations {
@Reference
private ProjectOperations projectOperations;
@Reference
private TypeLocationService typeLocationService;
@Reference
private TypeManagementService typeManagementService;
@Reference
private PathResolver pathResolver;
/** {@inheritDoc} */
public boolean isCommandAvailable() {
// Check if gvNIX JPA dependencies installed
return projectOperations
.isFeatureInstalledInFocusedModule(JpaOperations.FEATURE_NAME_GVNIX_JPA);
}
/**
* Generates new a JavaType for batch service class based on
* <code>entity</code> class name.
*
* @param entity
* @param targetPackage if null uses <code>entity</code> package
* @return
*/
private JavaType generateJavaType(JavaType entity, JavaPackage targetPackage) {
if (targetPackage == null) {
targetPackage = entity.getPackage();
}
return new JavaType(String.format("%s.%sBatchService",
targetPackage.getFullyQualifiedPackageName(),
entity.getSimpleTypeName()));
}
/** {@inheritDoc} */
public void createAll(JavaPackage targetPackage) {
// Use the TypeLocationService to scan project for all types with a
// specific annotation
for (JavaType entity : typeLocationService
.findTypesWithAnnotation(RooJavaType.ROO_JPA_ACTIVE_RECORD)) {
ClassOrInterfaceTypeDetails entityDetails = typeLocationService
.getTypeDetails(entity);
if (entityDetails.isAbstract()) {
// ignore abstract classes
continue;
}
if (targetPackage == null) {
create(entity, null);
}
else {
create(entity, generateJavaType(entity, targetPackage));
}
}
}
/** {@inheritDoc} */
@Override
public void create(JavaType entity, JavaType target) {
Validate.notNull(entity, "Entity required");
if (target == null) {
target = generateJavaType(entity, null);
}
Validate.isTrue(
!JdkJavaType.isPartOfJavaLang(target.getSimpleTypeName()),
"Target name '%s' must not be part of java.lang",
target.getSimpleTypeName());
int modifier = Modifier.PUBLIC;
final String declaredByMetadataId = PhysicalTypeIdentifier
.createIdentifier(target,
pathResolver.getFocusedPath(Path.SRC_MAIN_JAVA));
File targetFile = new File(
typeLocationService
.getPhysicalTypeCanonicalPath(declaredByMetadataId));
Validate.isTrue(!targetFile.exists(), "Type '%s' already exists",
target);
// Prepare class builder
final ClassOrInterfaceTypeDetailsBuilder cidBuilder = new ClassOrInterfaceTypeDetailsBuilder(
declaredByMetadataId, modifier, target,
PhysicalTypeCategory.CLASS);
// Prepare annotations array
List<AnnotationMetadataBuilder> annotations = new ArrayList<AnnotationMetadataBuilder>(
2);
// Add @Service annotations
annotations.add(new AnnotationMetadataBuilder(SpringJavaType.SERVICE));
// Add @GvNIXJpaBatch annotation
AnnotationMetadataBuilder jpaBatchAnnotation = new AnnotationMetadataBuilder(
new JavaType(GvNIXJpaBatch.class));
jpaBatchAnnotation.addClassAttribute("entity", entity);
annotations.add(jpaBatchAnnotation);
// Set annotations
cidBuilder.setAnnotations(annotations);
typeManagementService.createOrUpdateTypeOnDisk(cidBuilder.build());
}
}