Showing posts with label openarchitectureware. Show all posts
Showing posts with label openarchitectureware. Show all posts

Wednesday, July 8, 2009

Migrate oAW projects to Eclipse Galileo

As we all know, oAW moved into the Eclipse Galileo release.
More information on that here.

The new projects can be found here:
Modeling Workflow (MWE)
Model to Text (M2T)
Textual Modeling Framework (TMF)

In the project I'm working on, we use EMF to generate the model objects and oAW to generate services for the generated objects, which then are published using Eclipse Riena.
After the Galileo release, I had to update my current oAW workflow using the new workflow components and dependencies.

First I downloaded the required bundles for my target platform and IDE, you can get them from the Galileo update site.

Galileo - http://download.eclipse.org/releases/galileo/

> Modeling
  • MWE SDK
  • Xpand SDK
  • Xtext SDK
My generator plug-in now has the following dependencies:

Bundles
  • org.eclipse.emf.mwe.core;bundle-version="0.7.0",
  • org.eclipse.emf.mwe.utils;bundle-version="0.7.0",
  • org.eclipse.xtend;bundle-version="0.7.0",
  • org.eclipse.xpand;bundle-version="0.7.0"
Packages
  • com.ibm.icu.text;version="4.0.1",
  • org.antlr.runtime;version="3.0.0",
  • org.eclipse.jdt.core,
  • org.osgi.framework,
  • org.slf4j;version="1.5.6"
Done that I renamed my workflow file from generator.oaw to generator.mwe.
Now finally the changes I made on the file itself:

old generator.oaw

<?xml version="1.0"?>
<workflow>
<property file="workflow/settings.properties"/>

<!-- properties set through the generator -->
<property name="ecoreFile" value=""/>
<property name="outputLocation" value=""/>

<!-- set up EMF for standalone execution -->
<bean class="org.eclipse.mwe.emf.StandaloneSetup" >
<platformUri value=".."/>
</bean>

<!-- load basic model and store it in slot 'model' -->
<component class="org.eclipse.mwe.emf.Reader">
<uri value="${ecoreFile}" />
<modelSlot value="model" />
</component>


<!-- Service Interfaces -->
<component class="org.openarchitectureware.xpand2.Generator">
<metaModel id="mm" class="org.eclipse.m2t.type.emf.EmfRegistryMetaModel"/>
<expand value="template::Service::interface FOREACH model.eClassifiers" />
<globalVarDef name="productName" value="'${productName}'"/>
<globalVarDef name="serviceInterfacePackage" value="'${serviceInterfacePackage}'"/>
<outlet path="${outputLocation}${serviceInterfaceSrc}" >
<postprocessor class="org.openarchitectureware.xpand2.output.JavaBeautifier" />
</outlet>
</component>

<!-- Service Objects -->
<component class="org.openarchitectureware.xpand2.Generator">
<metaModel id="mm" class="org.eclipse.m2t.type.emf.EmfRegistryMetaModel"/>
<expand value="template::Service::javaClass FOREACH model.eClassifiers" />
<globalVarDef name="productName" value="'${productName}'"/>
<globalVarDef name="serviceInternalPackage" value="'${serviceInternalPackage}'"/>
<globalVarDef name="serviceInterfacePackage" value="'${serviceInterfacePackage}'"/>
<outlet path="${outputLocation}${serviceInternalSrc}">
<postprocessor class="org.openarchitectureware.xpand2.output.JavaBeautifier" />
</outlet>
</component>

<!-- Service Properties File -->
<component class="org.openarchitectureware.xpand2.Generator">
<metaModel id="mm" class="org.eclipse.m2t.type.emf.EmfRegistryMetaModel"/>
<expand value="template::Service::properties FOR model" />
<globalVarDef name="serviceInterfacePackage" value="'${serviceInterfacePackage}'"/>
<globalVarDef name="serviceInternalPackage" value="'${serviceInternalPackage}'"/>
<outlet path="${outputLocation}${serviceInternal}/META-INF/spring/">
<postprocessor class="com.softmodeler.generator.postprocessor.XmlBeautifier" />
</outlet>
</component>

<!-- Test Cases -->
<component class="org.openarchitectureware.xpand2.Generator">
<metaModel id="mm" class="org.eclipse.m2t.type.emf.EmfRegistryMetaModel"/>
<expand value="template::Test::javaClass FOREACH model.eClassifiers" />
<globalVarDef name="productName" value="'${productName}'"/>
<globalVarDef name="serviceInterfacePackage" value="'${serviceInterfacePackage}'"/>
<globalVarDef name="testPackage" value="'${testPackage}'"/>
<outlet path="${outputLocation}${testSrc}">
<postprocessor class="org.openarchitectureware.xpand2.output.JavaBeautifier" />
</outlet>
</component>

<!-- All Tests Suite -->
<component class="org.openarchitectureware.xpand2.Generator">
<metaModel id="mm" class="org.eclipse.m2t.type.emf.EmfRegistryMetaModel"/>
<expand value="template::Test::allTests FOR model" />
<globalVarDef name="testPackage" value="'${testPackage}'"/>
<globalVarDef name="productName" value="'${productName}'"/>
<outlet path="${outputLocation}${testSrc}">
<postprocessor class="org.openarchitectureware.xpand2.output.JavaBeautifier" />
</outlet>
</component>
</workflow>




new generator.mwe

<?xml version="1.0"?>
<workflow>
<property file="workflow/settings.properties"/>

<!-- properties set through the generator -->
<property name="ecoreFile" value=""/>
<property name="outputLocation" value=""/>

<!-- set up EMF for standalone execution -->
<bean class="org.eclipse.emf.mwe.utils.StandaloneSetup" >
<platformUri value=".."/>
</bean>

<!-- load model and store it in slot 'model' -->
<component class="org.eclipse.emf.mwe.utils.Reader" uri="${ecoreFile}">
<modelSlot value="model" />
</component>

<!-- first do some cleanup -->
<component class="org.eclipse.emf.mwe.utils.DirectoryCleaner" directory="${outputLocation}${serviceInterfaceSrc}" />
<component class="org.eclipse.emf.mwe.utils.DirectoryCleaner" directory="${outputLocation}${serviceInternalSrc}" />
<component class="org.eclipse.emf.mwe.utils.DirectoryCleaner" directory="${outputLocation}${serviceInternal}" />
<component class="org.eclipse.emf.mwe.utils.DirectoryCleaner" directory="${outputLocation}${testSrc}" />

<!-- Service Interfaces -->
<component class="org.eclipse.xpand2.Generator">
<metaModel id="mm" class="org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel"/>
<expand value="template::Service::interface FOREACH model.eClassifiers" />
<globalVarDef name="productName" value="'${productName}'"/>
<globalVarDef name="serviceInterfacePackage" value="'${serviceInterfacePackage}'"/>
<outlet path="${outputLocation}${serviceInterfaceSrc}" >
<postprocessor class="org.eclipse.xpand2.output.JavaBeautifier" />
</outlet>
</component>

<!-- Service Objects -->
<component class="org.eclipse.xpand2.Generator">
<metaModel id="mm" class="org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel"/>
<expand value="template::Service::javaClass FOREACH model.eClassifiers" />
<globalVarDef name="productName" value="'${productName}'"/>
<globalVarDef name="serviceInternalPackage" value="'${serviceInternalPackage}'"/>
<globalVarDef name="serviceInterfacePackage" value="'${serviceInterfacePackage}'"/>
<outlet path="${outputLocation}${serviceInternalSrc}">
<postprocessor class="org.eclipse.xpand2.output.JavaBeautifier" />
</outlet>
</component>

<!-- Service Properties File -->
<component class="org.eclipse.xpand2.Generator">
<metaModel id="mm" class="org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel"/>
<expand value="template::Service::properties FOR model" />
<globalVarDef name="serviceInterfacePackage" value="'${serviceInterfacePackage}'"/>
<globalVarDef name="serviceInternalPackage" value="'${serviceInternalPackage}'"/>
<outlet path="${outputLocation}${serviceInternal}/META-INF/spring/">
<postprocessor class="com.softmodeler.generator.postprocessor.XmlBeautifier" />
</outlet>
</component>

<!-- Test Cases -->
<component class="org.eclipse.xpand2.Generator">
<metaModel id="mm" class="org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel"/>
<expand value="template::Test::javaClass FOREACH model.eClassifiers" />
<globalVarDef name="productName" value="'${productName}'"/>
<globalVarDef name="serviceInterfacePackage" value="'${serviceInterfacePackage}'"/>
<globalVarDef name="testPackage" value="'${testPackage}'"/>
<outlet path="${outputLocation}${testSrc}">
<postprocessor class="org.eclipse.xpand2.output.JavaBeautifier" />
</outlet>
</component>

<!-- All Tests Suite -->
<component class="org.eclipse.xpand2.Generator">
<metaModel id="mm" class="org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel"/>
<expand value="template::Test::allTests FOR model" />
<globalVarDef name="testPackage" value="'${testPackage}'"/>
<globalVarDef name="productName" value="'${productName}'"/>
<outlet path="${outputLocation}${testSrc}">
<postprocessor class="org.eclipse.xpand2.output.JavaBeautifier" />
</outlet>
</component>
</workflow>



Basically only the namespace of the component classes changed.

Ending the whole story I have to say that I launch the workflow in my application using the org.eclipse.emf.mwe.core.WorkflowRunner.run(...) which works fine.
If I launch the workflow by itself "Run As -> MWE Workflow" I get an strange
"java.lang.ClassNotFoundException: org.eclipse.jface.text.BadLocationException" Exception, strange because I don't get why there should be an dependency on jface.

Thursday, August 21, 2008

oaw Output Postprocessor (Beautifier)

I'm working on a project using oaw to generate java classes, spring definitions, ecore models and a lot more.

There is a pretty nice JavaBeautifier to clean up my generated classes. The problem was the XmlBeautifier, it didn't remove white spaces. This resulted in some pretty ugly xml files.

So I searched the web for some alternative, didn't find one so I modified the original for my own needs.
Here is the code if someone approaches the same problem.



/*
*
*
* Copyright (c) 2005-2006 Sven Efftinge (http://www.efftinge.de) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sven Efftinge (http://www.efftinge.de) - Initial API and implementation
*
*

*/
package com.softmodeler.generator.postprocessor;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openarchitectureware.util.EncodingDetector;
import org.openarchitectureware.xpand2.output.FileHandle;
import org.openarchitectureware.xpand2.output.PostProcessor;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

/**
* *
*
* @author Sven Efftinge (http://www.efftinge.de)
* @author Bernd Kolb
*/
public class XmlBeautifier implements PostProcessor {

private final Log log = LogFactory.getLog(getClass());

private String[] fileExtensions = new String[] { ".xml", ".xsl", ".xsd", ".wsdd", ".wsdl", ".ecore" };

public void setFileExtensions(final String[] fileExtensions) {
this.fileExtensions = fileExtensions;
}

public void beforeWriteAndClose(final FileHandle info) {
if (isXmlFile(info.getTargetFile().getAbsolutePath())) {
try {
// TODO this is only a heuristic, but it should work for most cases. This really is the beginning of reimplementing
// the XML parser just because we do RAM rather then file based beautification...
final String bufferedString = info.getBuffer().toString().trim();
final int indEncoding = bufferedString.indexOf("encoding");
final int indEndHeader = bufferedString.indexOf("?>");
String readEncoding = null;
Document doc = null;
if (bufferedString.startsWith(" 0 && indEncoding < readencoding =" info.getFileEncoding();" doc =" parseDocument(bufferedString," doc =" parseDocument(bufferedString," tfactory =" TransformerFactory.newInstance();" threadid="562510&tstart="90" showtopic="788" serializer =" tfactory.newTransformer();" systemvalue =" doc.getDoctype().getSystemId();" publicid =" doc.getDoctype().getPublicId();" bytearrayoutputstream =" new" string =" byteArrayOutputStream.toString(info.getFileEncoding());" nodelist =" node.getChildNodes();" i =" 0;" child =" nodeList.item(i);"> encodingsToTry = new ArrayList();
if (encoding != null) {
encodingsToTry.add(encoding);
} else {
byte[] sampleBytes = bufferedString.substring(0, Math.min(64, bufferedString.length())).getBytes();
encodingsToTry.add(EncodingDetector.detectEncoding(sampleBytes).displayName());
encodingsToTry.add("ISO-8859-1");
encodingsToTry.add("UTF-8");
encodingsToTry.add("MacRoman");
encodingsToTry.add("UTF-16");
encodingsToTry.add("UTF-16BE");
encodingsToTry.add("UTF-16LE");
}
encodingsToTry.add(System.getProperty("file.encoding"));

Document doc = null;
Exception lastException = null;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setExpandEntityReferences(false);
factory.setValidating(false);

DocumentBuilder builder = factory.newDocumentBuilder();

builder.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
return new InputSource(new StringReader(""));
}
});
builder.setErrorHandler(new ErrorHandler() {
public void error(SAXParseException exception) throws SAXException {
log.warn(exception.getMessage());
}

public void fatalError(SAXParseException exception) throws SAXException {
if (exception.getMessage() != null && exception.getMessage().startsWith("Invalid byte")) {
// ignore, since we try other encodings
} else {
log.warn(exception.getMessage());
}
}

public void warning(SAXParseException exception) throws SAXException {
log.debug(exception.getMessage());
}
});

for (Iterator it = encodingsToTry.iterator(); it.hasNext();) {
String enc = it.next();
try {
doc = builder.parse(new ByteArrayInputStream(bufferedString.getBytes(enc)));
// if no error exit here
break;
} catch (Exception e) {
lastException = e;
}
}
if (doc == null && lastException != null) {
throw lastException;
} else {
return doc;
}
}

public boolean isXmlFile(final String absolutePath) {
for (int i = 0; i <>



The only difference to the original Beautifier is the removeWhiteSpaces method and it's call.

If you want to use this class or make your own for any other job, place the class in your generator plug-in and add the following config in your oaw workflow file:

<component class="org.openarchitectureware.xpand2.Generator">
<metaModel id="mm" class="org.eclipse.m2t.type.emf.EmfRegistryMetaModel"/>
<expand value="template::Nls::modelEcoreFile FOR model" />
<outlet path="${model-ecore}">
<postprocessor class="com.softmodeler.generator.postprocessor.XmlBeautifier"/>
</outlet>
</component>