/*
* Copyright 2013, We The Internet Ltd.
*
* All rights reserved.
*
* Distributed under a modified BSD License as follow:
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistribution in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution, unless otherwise
* agreed to in a written document signed by a director of We The Internet Ltd.
*
* Neither the name of We The Internet nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package xapi.dev.template;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import xapi.args.ArgHandlerLogLevel;
import xapi.args.ArgHandlerString;
import xapi.args.ArgProcessorBase;
import xapi.args.OptionLogLevel;
import xapi.dev.source.SourceBuilder;
import xapi.log.api.LogLevel;
import xapi.log.api.LogService;
public class TemplateGeneratorOptions extends ArgProcessorBase implements OptionLogLevel{
private final List<String> templates = new ArrayList<String>();
private final List<String> extraData = new ArrayList<String>();
private final PayloadTypeArg payloadArg;
private final Map<String, SourceBuilder<?>> context;
private LogLevel logLevel;
private String outputLocation = "src/main/java";
public TemplateGeneratorOptions() {
logLevel = LogLevel.INFO;
payloadArg = new PayloadTypeArg();
context = new HashMap<String, SourceBuilder<?>>();
registerHandler(new TemplateLocationArg(templates));
registerHandler(payloadArg);
registerHandler(new ExtraOptionsArg(extraData));
registerHandler(new TemplateOutputLocationArg(this));
registerHandler(new ArgHandlerLogLevel(this));
}
public static class TemplateOutputLocationArg extends ArgHandlerString{
private final TemplateGeneratorOptions opts;
public TemplateOutputLocationArg(TemplateGeneratorOptions opts) {
this.opts = opts;
}
@Override
public boolean setString(String str) {
opts.outputLocation = str.endsWith(File.separator)
? str : str + File.separator;
return true;
}
@Override
public String getPurpose() {
return "Location to output generated files. Default location is ${launch_directory}/src/main/java.";
}
@Override
public String getTag() {
return "-output";
}
@Override
public String[] getTagArgs() {
return new String[]{"${workspace_loc:some-project}/src/main/java"};
}
}
public static class TemplateLocationArg extends ArgHandlerString{
private final List<String> templates;
public TemplateLocationArg(List<String> templates) {
this.templates = templates;
}
@Override
public boolean setString(String str) {
StringTokenizer st = new StringTokenizer(str, ",");
while (st.hasMoreTokens()) {
templates.add(st.nextToken().trim());
}
return true;
}
@Override
public String getPurpose() {
return "Locations of template to generate from classpath resources, using / as a delimiter.";
}
@Override
public String getTag() {
return "-template";
}
@Override
public String[] getTagArgs() {
return new String[]{"package/location/TemplateFile.x"};
}
@Override
public boolean isRequired() {
return true;
}
}
public static class ExtraOptionsArg extends ArgHandlerString{
private final List<String> extras;
public ExtraOptionsArg(List<String> extras) {
this.extras = extras;
}
@Override
public boolean setString(String str) {
StringTokenizer st = new StringTokenizer(str, ",");
while (st.hasMoreTokens()) {
extras.add(st.nextToken().trim());
}
return true;
}
@Override
public String getPurpose() {
return "Extra data you wish to make available to your context's payload object.";
}
@Override
public String getTag() {
return "-extra";
}
@Override
public String[] getTagArgs() {
return new String[]{"\"String Data Of Your Choosing\""};
}
}
public static class PayloadTypeArg extends ArgHandlerString{
private String payloadClass = "java.lang.Object";
private Object payload;
@Override
public boolean setString(String str) {
payloadClass = str;
return true;
}
@Override
public String getPurpose() {
return "Fully qualified classname of payload used in the SourceBuilder object.\n\t This class must be " +
"static with a zero-arg public constructor.\n\t For complex projects using multiple generators, " +
"you are recommended to use interfaces that will be injected via X_Inject.singleton()";
}
@Override
public String getTag() {
return "-payload";
}
@Override
public String[] getTagArgs() {
return new String[]{"com.template.payload.ClassName"};
}
public Object getPayload(LogService logger, TemplateGeneratorOptions options) {
if (payload == null){
try{
payload = Class.forName(payloadClass).newInstance();
}catch(Exception e){
throw new CompilationFailed("Unable to instantiate payload type.", e);
}
if (payload instanceof TemplateClassGenerator)
((TemplateClassGenerator) payload).initialize(logger, options);
}
return payload;
}
}
@Override
protected String getName() {
return "TemplateToJava";
}
public List<String> getTemplates() {
return templates;
}
@SuppressWarnings({"rawtypes", "unchecked"})
public SourceBuilder<?> getContext(LogService logger, String forTemplate){
SourceBuilder ctx = context.get(forTemplate);
if (ctx == null){
ctx = new SourceBuilder();
Object payload = payloadArg.getPayload(logger, this);
ctx.setPayload(payload);
}
return ctx;
}
public List<String> getExtraData() {
return extraData;
}
public String getOutputLocation() {
return outputLocation;
}
@Override
public LogLevel getLogLevel() {
return logLevel;
}
@Override
public void setLogLevel(LogLevel logLevel) {
this.logLevel = logLevel;
}
}