/**
* Copyright (c) 2009 Farata Systems http://www.faratasystems.com
*
* Licensed under The MIT License
* Re-distributions of files must retain the above copyright notice.
*
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
*
*/
package com.farata.dto2extjs.asap;
import com.farata.dto2extjs.annotations.JSClass;
import com.farata.dto2extjs.annotations.JSClassKind;
import com.farata.dto2extjs.asap.env.IEnvironmentInspector;
import com.farata.dto2extjs.asap.reflect.JSClassDeclarationReflector;
import com.farata.dto2extjs.asap.reflect.JSEnumDeclarationReflector;
import com.farata.dto2extjs.asap.reflect.JSInterfaceDeclarationReflector;
import com.farata.dto2extjs.asap.reflect.JSTypeDeclarationReflector;
import com.farata.dto2extjs.asap.types.InvalidJavaTypeException;
import com.farata.dto2extjs.asap.types.JSTypeReflector;
import com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.apt.Messager;
import com.sun.mirror.declaration.*;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.XMLFilterImpl;
import javax.xml.transform.*;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
public class JSAnnotationProcessor implements AnnotationProcessor {
final protected AnnotationProcessorEnvironment _environment;
final protected JSAnnotationProcessorOptions _options;
final protected IEnvironmentInspector _inspector;
public JSAnnotationProcessor(final AnnotationProcessorEnvironment environment, final JSAnnotationProcessorOptions options, final IEnvironmentInspector inspector) {
_environment = environment;
_options = options;
_inspector = inspector;
}
public void process() {
final Messager messager = _environment.getMessager();
// obtain the declaration of the annotation we want to process
final AnnotationTypeDeclaration jsClass
= (AnnotationTypeDeclaration)_environment.getTypeDeclaration(JSClass.class.getName());
// get the annotated types
final Collection<Declaration> annotatedTypes = _environment.getDeclarationsAnnotatedWith(jsClass);
final Collection<TypeDeclaration> typeDeclarations = new ArrayList<TypeDeclaration>( annotatedTypes.size() );
for (final Declaration decl : annotatedTypes)
if ( decl instanceof TypeDeclaration ) typeDeclarations.add( (TypeDeclaration)decl );
final Workset workset = new Workset(_environment, typeDeclarations);
final JSTypeReflector _typeReflector = new JSTypeReflector(_environment, workset, _options);
for (TypeDeclaration declaration = workset.next(); null != declaration; declaration = workset.next() ) {
final JSTypeDeclarationReflector reflector;
final Templates templates;
final JSClassKind jsClassKind = _typeReflector.resolveTypeOf(declaration, true);
if ( declaration instanceof EnumDeclaration ) {
final EnumDeclaration eDeclaration = (EnumDeclaration)declaration;
reflector = new JSEnumDeclarationReflector( eDeclaration, _typeReflector );
switch (jsClassKind) {
case EXT_JS:
templates = JSTemplatesCache.jsEnumObjects();
break;
case STRING_CONSTANTS:
templates = JSTemplatesCache.jsEnumString();
break;
default:
continue;
}
} else if (declaration instanceof InterfaceDeclaration) {
final InterfaceDeclaration iDeclaration = (InterfaceDeclaration)declaration;
reflector = new JSInterfaceDeclarationReflector( iDeclaration, _typeReflector );
templates = JSTemplatesCache.jsInterface();
} else if (declaration instanceof ClassDeclaration) {
switch (jsClassKind) {
case EXT_JS:
templates = JSTemplatesCache.jsExtJSClass();
break;
case CLASSIC:
templates = JSTemplatesCache.jsClassicJSClass();
break;
default:
continue;
}
final ClassDeclaration cDeclaration = (ClassDeclaration)declaration;
reflector = new JSClassDeclarationReflector( cDeclaration, _typeReflector );
} else {
continue;
}
try {
final Source source = new SAXSource(reflector, noInput());
final Result result = noResult();
XsltOperation.withCurrentClassLoader(new Runnable() {
public void run() {
try {
final Transformer serializer = templates.newTransformer();
try {
serializer.setParameter("base", _options.output().getCanonicalPath());
serializer.setParameter("metadata-dump", _options.dumpMetadata() ? "yes" : "no");
} catch (final Exception e) {
}
XsltUtils.pushPackagePathResolver(_options.packagePathTransformer());
try {
serializer.transform(source, result);
} finally {
XsltUtils.popPackagePathResolver();
}
} catch (final TransformerException ex) {
throw new RuntimeException(ex);
}
}
});
refresh(_options.output());
} catch (final InvalidJavaTypeException ex) {
// Reported by JSTypeReflector
} catch (final Exception ex) {
ex.printStackTrace();
messager.printError( ex.getLocalizedMessage() );
}
}
}
private void refresh(final File file) {
_inspector.refreshFile(file);
}
final private static byte[] VOID_BYTES = {};
private static InputSource noInput() {
return new InputSource( new ByteArrayInputStream(VOID_BYTES) );
}
private static Result noResult() {
return new SAXResult( new XMLFilterImpl() );
}
}