com.legstar.codegen.CodeGenMake Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of legstar-codegen Show documentation
Show all versions of legstar-codegen Show documentation
Common code generation classes for LegStar
The newest version!
/*******************************************************************************
* Copyright (c) 2015 LegSem.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* LegSem - initial API and implementation
******************************************************************************/
package com.legstar.codegen;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* This Ant task iteratively calls the Velocity template engine to create
* a list of artifacts described in an xml file.
* The xml file typically describes a target as a sequential list of steps.
* Each step is associated with a velocity template and produces an artifact.
* TODO describe the format of xml make in an xsd
*/
public class CodeGenMake extends Task {
/** The name of the calling generator. */
private String mGeneratorName;
/** The cixs make file name. */
private String mCodeGenMakeFileName;
/**
* Velocity templates are applied against a model.
* This is the model name.
*/
private String mModelName;
/**
* Velocity templates are applied against a model.
* This is the model itself.
*/
private Object mModel;
/** XML element representing a code generation target. */
public static final String CODEGEN_TARGET_XML_E = "target";
/** XML attribute representing a code generation target name. */
public static final String CODEGEN_TARGET_NAME_XML_A = "name";
/** XML attribute representing a code generation target directory. */
public static final String CODEGEN_TARGET_DIR_XML_A = "dir";
/** XML element representing a code generation step with a template. */
public static final String CODEGEN_STEP_XML_E = "step";
/** XML attribute representing a code generation template name. */
public static final String CODEGEN_TEMPLATE_NAME_XML_A = "templateName";
/** XML attribute representing a code generation target file. */
public static final String CODEGEN_TEMPLATE_TARGET_FILE_XML_A = "targetFile";
/** XML attribute representing a code generation target character set. */
public static final String CODEGEN_TEMPLATE_TARGET_CHARSETNAME_XML_A = "targetCharsetName";
/** Logger. */
private final Log _log = LogFactory.getLog(CodeGenMake.class);
/** @{inheritDoc */
@Override
public void init() {
try {
_log.info("Initializing Code generation make processor");
CodeGenUtil.initVelocity();
} catch (Exception e) {
throw new BuildException(e.getMessage());
}
}
/** @{inheritDoc */
@Override
public void execute() {
long start = System.currentTimeMillis();
try {
_log.debug("Start make processor");
Document doc = getInput();
if (_log.isDebugEnabled()) {
_log.debug("Make file name = " + mCodeGenMakeFileName);
_log.debug("Model name = " + mModelName);
}
processTargets(doc);
} catch (CodeGenMakeException e) {
_log.error("Make processor failure", e);
throw new BuildException(e.getMessage());
}
long end = System.currentTimeMillis();
_log.info("Make processing success for " + mCodeGenMakeFileName);
_log.info("Duration = " + (end - start) + " ms");
}
/**
* Check input values and load the xml make file.
*
* @return an in-memory DOM xml make
* @throws CodeGenMakeException if initialization fails
*/
private Document getInput() throws CodeGenMakeException {
if (mCodeGenMakeFileName == null || mCodeGenMakeFileName.length() == 0) {
throw new CodeGenMakeException("Missing make file parameter");
}
if (mModelName == null || mModelName.length() == 0) {
throw new CodeGenMakeException("Missing model name parameter");
}
if (mModel == null) {
throw new CodeGenMakeException("Missing model parameter");
}
File makeFile = new File(mCodeGenMakeFileName);
if (!makeFile.exists()) {
throw new CodeGenMakeException("Code generation make file "
+ makeFile + " does not exist");
}
return load(makeFile);
}
/**
* Process targets sequentially, invoking the velocity engine for each
* target.
*
* @param doc a valid DOM for a cixs make
* @throws CodeGenMakeException if processing fails
*/
private void processTargets(final Document doc) throws CodeGenMakeException {
NodeList listOfElements = doc.getElementsByTagName(
CODEGEN_TARGET_XML_E);
if (listOfElements == null || listOfElements.getLength() == 0) {
throw (new CodeGenMakeException(
"Empty or invalid code generation make file"));
}
Element targetElement = (Element) listOfElements.item(0);
String targetName = targetElement
.getAttribute(CODEGEN_TARGET_NAME_XML_A);
if (targetName == null || targetName.length() == 0) {
throw new CodeGenMakeException("Missing name attribute for "
+ CODEGEN_TARGET_XML_E + " element");
}
String targetDir = targetElement.getAttribute(CODEGEN_TARGET_DIR_XML_A);
if (targetDir != null && targetDir.length() > 0) {
try {
CodeGenUtil.checkDirectory(targetDir, true);
} catch (IllegalArgumentException e) {
throw new CodeGenMakeException(e);
}
}
listOfElements = targetElement.getElementsByTagName(
CODEGEN_STEP_XML_E);
if (_log.isDebugEnabled()) {
_log.debug("Processing target");
_log.debug("Target name = " + targetName);
_log.debug("Target directory = " + targetDir);
}
for (int i = 0; i < listOfElements.getLength(); i++) {
Element templateEl = (Element) listOfElements.item(i);
String templateName = templateEl.getAttribute(
CODEGEN_TEMPLATE_NAME_XML_A);
if (templateName == null || templateName.length() == 0) {
throw new CodeGenMakeException(
"Missing template name attribute for "
+ CODEGEN_STEP_XML_E + " element");
}
String templateTargetFileName = templateEl.getAttribute(
CODEGEN_TEMPLATE_TARGET_FILE_XML_A);
if (templateTargetFileName == null
|| templateTargetFileName.length() == 0) {
throw new CodeGenMakeException(
"Missing template target file name attribute for "
+ CODEGEN_STEP_XML_E + " element");
}
String templateTargetCharsetName = templateEl.getAttribute(
CODEGEN_TEMPLATE_TARGET_CHARSETNAME_XML_A);
if (templateTargetCharsetName.length() == 0) {
templateTargetCharsetName = null;
}
CodeGenUtil.processTemplate(
mGeneratorName,
templateName,
mModelName, mModel,
getParameters(templateEl),
CodeGenUtil.getFile(targetDir, templateTargetFileName),
templateTargetCharsetName);
}
}
/**
* Template elements might have children. These are used to pass additional
* parameters to the template generation process.
* Children are expected to have a single value attribute otherwise, they
* are ignored.
*
* @param templateEl the current template element
* @return a Map of parameters/values
*/
private Map < String, Object > getParameters(final Element templateEl) {
Map < String, Object > parameters = new HashMap < String, Object >();
NodeList childs = templateEl.getChildNodes();
for (int i = 0; i < childs.getLength(); i++) {
if (childs.item(i) instanceof Element) {
Element parmEl = (Element) childs.item(i);
String value = parmEl.getAttribute("value");
if (value != null) {
parameters.put(parmEl.getNodeName(), value);
}
}
}
return parameters;
}
/**
* Loads code generation make file from a serialized XML.
*
* @param makeFile the serialized file
* @return an in-memory DOM code generation make
* @throws CodeGenMakeException if load fails
*/
public Document load(final File makeFile) throws CodeGenMakeException {
DocumentBuilderFactory docBuilderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder;
try {
docBuilderFactory.setNamespaceAware(false);
docBuilder = docBuilderFactory.newDocumentBuilder();
Document doc = docBuilder.parse(makeFile);
return doc;
} catch (ParserConfigurationException e) {
throw (new CodeGenMakeException(e));
} catch (SAXException e) {
throw (new CodeGenMakeException(e));
} catch (IOException e) {
throw (new CodeGenMakeException(e));
}
}
/**
* @return the code generation Make File name
*/
public String getCodeGenMakeFileName() {
return mCodeGenMakeFileName;
}
/**
* @param codeGenMakeFileName the code generation Make File name to set
*/
public void setCodeGenMakeFileName(final String codeGenMakeFileName) {
mCodeGenMakeFileName = codeGenMakeFileName;
}
/**
* @return the model name
*/
public String getModelName() {
return mModelName;
}
/**
* @param modelName the model name to set
*/
public void setModelName(final String modelName) {
mModelName = modelName;
}
/**
* @return the model used to apply templates to
*/
public Object getModel() {
return mModel;
}
/**
* @param model the model to set
*/
public void setModel(final Object model) {
mModel = model;
}
/**
* @return the name of the calling generator
*/
public String getGeneratorName() {
return mGeneratorName;
}
/**
* @param generatorName the name of the calling generator to set
*/
public void setGeneratorName(final String generatorName) {
mGeneratorName = generatorName;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy