aboutsummaryrefslogtreecommitdiffstats
path: root/src/codegen/java/org
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen/java/org')
-rw-r--r--src/codegen/java/org/apache/fop/tools/EventConventionException.java28
-rw-r--r--src/codegen/java/org/apache/fop/tools/EventProducerCollector.java183
-rw-r--r--src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java200
-rw-r--r--src/codegen/java/org/apache/fop/tools/merge-translation.xsl55
-rw-r--r--src/codegen/java/org/apache/fop/tools/model2translation.xsl35
5 files changed, 501 insertions, 0 deletions
diff --git a/src/codegen/java/org/apache/fop/tools/EventConventionException.java b/src/codegen/java/org/apache/fop/tools/EventConventionException.java
new file mode 100644
index 000000000..675f4a0ca
--- /dev/null
+++ b/src/codegen/java/org/apache/fop/tools/EventConventionException.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.tools;
+
+public class EventConventionException extends Exception {
+
+ public EventConventionException(String message) {
+ super(message);
+ }
+
+}
diff --git a/src/codegen/java/org/apache/fop/tools/EventProducerCollector.java b/src/codegen/java/org/apache/fop/tools/EventProducerCollector.java
new file mode 100644
index 000000000..e42395ae7
--- /dev/null
+++ b/src/codegen/java/org/apache/fop/tools/EventProducerCollector.java
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.tools;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.fop.events.EventProducer;
+import org.apache.fop.events.model.EventMethodModel;
+import org.apache.fop.events.model.EventModel;
+import org.apache.fop.events.model.EventProducerModel;
+import org.apache.fop.events.model.EventSeverity;
+
+import com.thoughtworks.qdox.JavaDocBuilder;
+import com.thoughtworks.qdox.model.DefaultDocletTagFactory;
+import com.thoughtworks.qdox.model.DocletTag;
+import com.thoughtworks.qdox.model.DocletTagFactory;
+import com.thoughtworks.qdox.model.JavaClass;
+import com.thoughtworks.qdox.model.JavaMethod;
+import com.thoughtworks.qdox.model.JavaParameter;
+import com.thoughtworks.qdox.model.Type;
+
+/**
+ * Finds EventProducer interfaces and builds the event model for them.
+ */
+public class EventProducerCollector {
+
+ private static final String CLASSNAME_EVENT_PRODUCER = EventProducer.class.getName();
+ private static final Map PRIMITIVE_MAP;
+
+ static {
+ Map m = new java.util.HashMap();
+ m.put("boolean", Boolean.class);
+ m.put("byte", Byte.class);
+ m.put("char", Character.class);
+ m.put("short", Short.class);
+ m.put("int", Integer.class);
+ m.put("long", Long.class);
+ m.put("float", Float.class);
+ m.put("double", Double.class);
+ PRIMITIVE_MAP = Collections.unmodifiableMap(m);
+ }
+
+ private DocletTagFactory tagFactory;
+ private EventModel model = new EventModel();
+
+ public EventProducerCollector() {
+ this.tagFactory = createDocletTagFactory();
+ }
+
+ protected DocletTagFactory createDocletTagFactory() {
+ return new DefaultDocletTagFactory();
+ }
+
+ public void scanFile(File src, String filename)
+ throws IOException, EventConventionException, ClassNotFoundException {
+ JavaDocBuilder builder = new JavaDocBuilder(this.tagFactory);
+ builder.addSource(src);
+ JavaClass[] classes = builder.getClasses();
+ for (int i = 0, c = classes.length; i < c; i++) {
+ JavaClass clazz = classes[i];
+ if (clazz.isInterface() && implementsInterface(clazz, CLASSNAME_EVENT_PRODUCER)) {
+ processEventProducerInterface(clazz, filename);
+ }
+ }
+ }
+
+ private boolean implementsInterface(JavaClass clazz, String intf) {
+ JavaClass[] classes = clazz.getImplementedInterfaces();
+ for (int i = 0, c = classes.length; i < c; i++) {
+ JavaClass cl = classes[i];
+ if (cl.getFullyQualifiedName().equals(intf)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Processes an EventProducer interface and creates an EventProducerModel from it.
+ * @param clazz the EventProducer interface
+ * @param javaFilename the filename of the Java source of the interface
+ * @throws EventConventionException if the event producer conventions are violated
+ * @throws ClassNotFoundException if a required class cannot be found
+ */
+ protected void processEventProducerInterface(JavaClass clazz, String javaFilename)
+ throws EventConventionException, ClassNotFoundException {
+ EventProducerModel prodMeta = new EventProducerModel(clazz.getFullyQualifiedName());
+ JavaMethod[] methods = clazz.getMethods(true);
+ for (int i = 0, c = methods.length; i < c; i++) {
+ JavaMethod method = methods[i];
+ EventMethodModel methodMeta = createMethodModel(method);
+ prodMeta.addMethod(methodMeta);
+ }
+ this.model.addProducer(prodMeta);
+ }
+
+ private EventMethodModel createMethodModel(JavaMethod method)
+ throws EventConventionException, ClassNotFoundException {
+ JavaClass clazz = method.getParentClass();
+ //Check EventProducer conventions
+ if (!method.getReturns().isVoid()) {
+ throw new EventConventionException("All methods of interface "
+ + clazz.getFullyQualifiedName() + " must have return type 'void'!");
+ }
+ String methodSig = clazz.getFullyQualifiedName() + "." + method.getCallSignature();
+ JavaParameter[] params = method.getParameters();
+ if (params.length < 1) {
+ throw new EventConventionException("The method " + methodSig
+ + " must have at least one parameter: 'Object source'!");
+ }
+ Type firstType = params[0].getType();
+ if (firstType.isPrimitive() || !"source".equals(params[0].getName())) {
+ throw new EventConventionException("The first parameter of the method " + methodSig
+ + " must be: 'Object source'!");
+ }
+
+ //build method model
+ DocletTag tag = method.getTagByName("event.severity");
+ EventSeverity severity;
+ if (tag != null) {
+ severity = EventSeverity.valueOf(tag.getValue());
+ } else {
+ severity = EventSeverity.INFO;
+ }
+ EventMethodModel methodMeta = new EventMethodModel(
+ method.getName(), severity);
+ if (params.length > 1) {
+ for (int j = 1, cj = params.length; j < cj; j++) {
+ JavaParameter p = params[j];
+ Class type;
+ JavaClass pClass = p.getType().getJavaClass();
+ if (p.getType().isPrimitive()) {
+ type = (Class)PRIMITIVE_MAP.get(pClass.getName());
+ if (type == null) {
+ throw new UnsupportedOperationException(
+ "Primitive datatype not supported: " + pClass.getName());
+ }
+ } else {
+ String className = pClass.getFullyQualifiedName();
+ type = Class.forName(className);
+ }
+ methodMeta.addParameter(type, p.getName());
+ }
+ }
+ Type[] exceptions = method.getExceptions();
+ if (exceptions != null && exceptions.length > 0) {
+ //We only use the first declared exception because that is always thrown
+ JavaClass cl = exceptions[0].getJavaClass();
+ methodMeta.setExceptionClass(cl.getFullyQualifiedName());
+ methodMeta.setSeverity(EventSeverity.FATAL); //In case it's not set in the comments
+ }
+ return methodMeta;
+ }
+
+ public EventModel getModel() {
+ return this.model;
+ }
+
+ public void saveModelToXML(File modelFile) throws IOException {
+ getModel().saveToXML(modelFile);
+ }
+
+}
diff --git a/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java b/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java
new file mode 100644
index 000000000..755e3da0b
--- /dev/null
+++ b/src/codegen/java/org/apache/fop/tools/EventProducerCollectorTask.java
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.tools;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.URIResolver;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.w3c.dom.Node;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.selectors.FilenameSelector;
+
+public class EventProducerCollectorTask extends Task {
+
+ private List filesets = new java.util.ArrayList();
+ private File modelFile;
+ private File translationFile;
+
+ /** {@inheritDoc} */
+ public void execute() throws BuildException {
+ try {
+ EventProducerCollector collector = new EventProducerCollector();
+ processFileSets(collector);
+ getModelFile().getParentFile().mkdirs();
+ collector.saveModelToXML(getModelFile());
+ log("Event model written to " + getModelFile());
+ if (getTranslationFile() != null) {
+ updateTranslationFile();
+ }
+ } catch (ClassNotFoundException e) {
+ throw new BuildException(e);
+ } catch (EventConventionException ece) {
+ throw new BuildException(ece);
+ } catch (IOException ioe) {
+ throw new BuildException(ioe);
+ }
+ }
+
+ private static final String MODEL2TRANSLATION = "model2translation.xsl";
+ private static final String MERGETRANSLATION = "merge-translation.xsl";
+
+ protected void updateTranslationFile() throws IOException {
+ try {
+ boolean resultExists = getTranslationFile().exists();
+ SAXTransformerFactory tFactory
+ = (SAXTransformerFactory)SAXTransformerFactory.newInstance();
+
+ //Generate fresh generated translation file as template
+ Source src = new StreamSource(getModelFile());
+ StreamSource xslt1 = new StreamSource(
+ getClass().getResourceAsStream(MODEL2TRANSLATION));
+ if (xslt1.getInputStream() == null) {
+ throw new FileNotFoundException(MODEL2TRANSLATION + " not found");
+ }
+ DOMResult domres = new DOMResult();
+ Transformer transformer = tFactory.newTransformer(xslt1);
+ transformer.transform(src, domres);
+ final Node generated = domres.getNode();
+
+ Node sourceDocument;
+ if (resultExists) {
+ //Load existing translation file into memory (because we overwrite it later)
+ src = new StreamSource(getTranslationFile());
+ domres = new DOMResult();
+ transformer = tFactory.newTransformer();
+ transformer.transform(src, domres);
+ sourceDocument = domres.getNode();
+ } else {
+ //Simply use generated as source document
+ sourceDocument = generated;
+ }
+
+ //Generate translation file (with potentially new translations)
+ src = new DOMSource(sourceDocument);
+ Result res = new StreamResult(getTranslationFile());
+ StreamSource xslt2 = new StreamSource(
+ getClass().getResourceAsStream(MERGETRANSLATION));
+ if (xslt2.getInputStream() == null) {
+ throw new FileNotFoundException(MERGETRANSLATION + " not found");
+ }
+ transformer = tFactory.newTransformer(xslt2);
+ transformer.setURIResolver(new URIResolver() {
+ public Source resolve(String href, String base) throws TransformerException {
+ if ("my:dom".equals(href)) {
+ return new DOMSource(generated);
+ }
+ return null;
+ }
+ });
+ if (resultExists) {
+ transformer.setParameter("generated-url", "my:dom");
+ }
+ transformer.transform(src, res);
+ if (resultExists) {
+ log("Translation file updated: " + getTranslationFile());
+ } else {
+ log("Translation file generated: " + getTranslationFile());
+ }
+ } catch (TransformerException te) {
+ throw new IOException(te.getMessage());
+ }
+ }
+
+ protected void processFileSets(EventProducerCollector collector)
+ throws IOException, EventConventionException, ClassNotFoundException {
+ Iterator iter = filesets.iterator();
+ while (iter.hasNext()) {
+ FileSet fs = (FileSet)iter.next();
+ DirectoryScanner ds = fs.getDirectoryScanner(getProject());
+ String[] srcFiles = ds.getIncludedFiles();
+ File directory = fs.getDir(getProject());
+ for (int i = 0, c = srcFiles.length; i < c; i++) {
+ String filename = srcFiles[i];
+ File src = new File(directory, filename);
+ collector.scanFile(src, filename);
+ }
+ }
+ }
+
+ public void addFileset(FileSet set) {
+ filesets.add(set);
+ }
+
+ public void setModelFile(File f) {
+ this.modelFile = f;
+ }
+
+ public File getModelFile() {
+ return this.modelFile;
+ }
+
+ public void setTranslationFile(File f) {
+ this.translationFile = f;
+ }
+
+ public File getTranslationFile() {
+ return this.translationFile;
+ }
+
+ public static void main(String[] args) {
+ try {
+ Project project = new Project();
+
+ EventProducerCollectorTask generator = new EventProducerCollectorTask();
+ generator.setProject(project);
+ project.setName("Test");
+ FileSet fileset = new FileSet();
+ fileset.setDir(new File("test/java"));
+
+ FilenameSelector selector = new FilenameSelector();
+ selector.setName("**/*.java");
+ fileset.add(selector);
+ generator.addFileset(fileset);
+
+ File targetDir = new File("build/codegen1");
+ targetDir.mkdirs();
+
+ generator.setModelFile(new File("D:/out.xml"));
+ generator.setTranslationFile(new File("D:/out1.xml"));
+ generator.execute();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/codegen/java/org/apache/fop/tools/merge-translation.xsl b/src/codegen/java/org/apache/fop/tools/merge-translation.xsl
new file mode 100644
index 000000000..d15d22fd3
--- /dev/null
+++ b/src/codegen/java/org/apache/fop/tools/merge-translation.xsl
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output indent="yes" method="xml" encoding="UTF-8"/>
+
+ <xsl:param name="generated-url" select="''"/>
+
+ <xsl:template match="catalogue">
+ <catalogue>
+ <xsl:attribute name="xml:lang"><xsl:value-of select="@xml:lang"/></xsl:attribute>
+ <xsl:apply-templates/>
+ <xsl:if test="$generated-url != ''">
+ <xsl:variable name="generated" select="document($generated-url)"/>
+ <xsl:call-template name="add-new-messages">
+ <xsl:with-param name="existing" select="."/>
+ <xsl:with-param name="new" select="$generated/catalogue"/>
+ </xsl:call-template>
+ </xsl:if>
+ </catalogue>
+ </xsl:template>
+
+ <xsl:template name="add-new-messages">
+ <xsl:param name="existing"/>
+ <xsl:param name="new"/>
+ <xsl:for-each select="$new/message">
+ <xsl:variable name="k" select="@key"/>
+ <xsl:if test="not(boolean($existing/message[@key = $k]))">
+ <xsl:apply-templates select="."></xsl:apply-templates>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template match="@*|node()">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/src/codegen/java/org/apache/fop/tools/model2translation.xsl b/src/codegen/java/org/apache/fop/tools/model2translation.xsl
new file mode 100644
index 000000000..a1cf404ee
--- /dev/null
+++ b/src/codegen/java/org/apache/fop/tools/model2translation.xsl
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!-- $Id$ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output indent="yes" method="xml" encoding="UTF-8"/>
+
+ <xsl:template match="event-model">
+ <catalogue>
+ <xsl:attribute name="xml:lang">en</xsl:attribute>
+ <xsl:apply-templates select="//method"></xsl:apply-templates>
+ </catalogue>
+ </xsl:template>
+
+ <xsl:template match="method">
+ <message>
+ <xsl:attribute name="key"><xsl:value-of select="../@name"/>.<xsl:value-of select="@name"/></xsl:attribute>
+ </message>
+ </xsl:template>
+
+</xsl:stylesheet>