/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.extension.convertor;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.Collection;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.teiid.core.designer.util.ModelType;
import org.teiid.designer.extension.convertor.mxd.MetaclassType;
import org.teiid.designer.extension.convertor.mxd.ModelExtension;
import org.teiid.designer.extension.convertor.mxd.ObjectFactory;
import org.teiid.designer.runtime.spi.ITeiidTranslator;
import org.teiid.designer.runtime.spi.TeiidPropertyDefinition;
/**
*
*/
public class MxdConvertor {
private static final String METAMODEL_URI = "http://www.metamatrix.com/metamodels/Relational"; //$NON-NLS-1$
private static final String SCHEMA_LOCATION = "http://www.jboss.org/teiiddesigner/ext/2012 http://www.jboss.org/teiiddesigner/ext/2012/modelExtension.xsd"; //$NON-NLS-1$
private static final String NAMESPACE_URI = "http://www.teiid.org/translator/{NAME}/2014"; //$NON-NLS-1$
private static MxdConvertor INSTANCE;
private final ObjectFactory factory = new ObjectFactory();
/**
* @return singleton instance
*/
public static MxdConvertor getInstance() {
if (INSTANCE == null)
INSTANCE = new MxdConvertor();
return INSTANCE;
}
private char[] readFromFile(File sourceFile) throws IOException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(sourceFile));
StringBuilder builder = new StringBuilder();
String ls = System.getProperty("line.separator"); //$NON-NLS-1$
String line = null;
while ((line = reader.readLine()) != null) {
builder.append(line);
builder.append(ls);
}
return builder.toString().toCharArray();
} finally {
if (reader != null)
reader.close();
}
}
/**
* Reads a teiid annotated source file, ie. containing 'ExtensionMetadataProperty'
* annotations, parses the annotations and return a collection of {@link MetaclassType}s.
*
* @param sourceFile
* @return collection of {@link MetaclassType}
* @throws IOException
*/
public Collection<MetaclassType> read(File sourceFile) throws IOException {
char[] source = readFromFile(sourceFile);
ASTParser parser = ASTParser.newParser(AST.JLS4);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setSource(source);
parser.setResolveBindings(true);
CompilationUnit cu = (CompilationUnit) parser.createAST(null);
TranslatorAnnotationVisitor visitor = new TranslatorAnnotationVisitor();
cu.accept(visitor);
return visitor.getMetaclasses();
}
/**
* Reads a set of teiid property definitions and returns a
* collection of {@link MetaclassType}s.
*
* @param extensions
* @return collection of {@link MetaclassType}
*/
public Collection<MetaclassType> read(Collection<TeiidPropertyDefinition> extensions) {
TeiidPropertyDefinitionConvertor defnConvertor = new TeiidPropertyDefinitionConvertor();
return defnConvertor.getMetaclasses(extensions);
}
/**
* @param namespacePrefix name denoting type of data, eg. odata, mongodb
* @param modelType the type of model represented by the translator
* @param metaClasses collection of meta classes extracted from a file using {@link #read(File)}
* @param output the destination output stream of the resulting xml
*
* @throws Exception
*/
public void write(String namespacePrefix, ModelType.Type modelType, Collection<MetaclassType> metaClasses, OutputStream output) throws Exception {
ModelExtension element = factory.createModelExtension();
// Namespace already included: xmlns="http://www.jboss.org/teiiddesigner/ext/2012">
element.setMetamodelUri(METAMODEL_URI);
// version="1"
element.setVersion(new BigInteger("1")); //$NON-NLS-1$
// namespacePrefix="odata"
// namespacePrefix="mongodb"
element.setNamespacePrefix(namespacePrefix);
// namespaceUri="http://www.jboss.org/teiiddesigner/ext/odata/2012"
// namespaceUri="http://www.teiid.org/translator/mongodb/2013"
String namespaceUri = NAMESPACE_URI.replace("{NAME}", namespacePrefix); //$NON-NLS-1$
element.setNamespaceUri(namespaceUri);
// model type
element.getModelType().add(modelType.name());
// adds the meta classes
element.getExtendedMetaclass().addAll(metaClasses);
JAXBContext context = JAXBContext.newInstance(ModelExtension.class);
Marshaller marshaller = context.createMarshaller();
// Setting this will auto-add the xsi namespace
marshaller.setProperty("jaxb.schemaLocation", SCHEMA_LOCATION); //$NON-NLS-1$
marshaller.setProperty("jaxb.formatted.output",Boolean.TRUE); //$NON-NLS-1$
marshaller.marshal(element, output);
}
/**
* Convenience method uniting the {@link #read(Collection)} and
* {@link #write(String, org.teiid.core.designer.util.ModelType.Type, Collection, OutputStream)}
* functions for a single {@link ITeiidTranslator}.
*
* @param translator
* @param output the destination output stream of the resulting xml
* @return true if conversion was successful
*
* @throws Exception
*/
public boolean convert(ITeiidTranslator translator, OutputStream output) throws Exception {
Collection<TeiidPropertyDefinition> extensions = translator.getExtensionPropertyDefinitions();
if (extensions == null || extensions.isEmpty())
return false;
String name = translator.getName();
// HACK - fixes erroneous excel extension until TEIID-2974 is fixed and available to Designer
if(name!=null && name.equals("excel")) { //$NON-NLS-1$
for(TeiidPropertyDefinition extDefn : extensions) {
String extName = extDefn.getName();
if(extName!=null && extName.endsWith("FIRST_DATA_ROW_NUMBER")) { //$NON-NLS-1$
extDefn.setOwner("org.teiid.metadata.Table"); //$NON-NLS-1$
}
}
}
try {
ModelType.Type modelType = ModelType.Type.PHYSICAL;
Collection<MetaclassType> metaClasses = read(extensions);
write(name, modelType, metaClasses, output);
return true;
} catch (IllegalArgumentException e) {
throw new Exception(e);
}
}
}