package gw.vark;
import gw.config.CommonServices;
import gw.lang.launch.ArgInfo;
import gw.lang.launch.ArgInfo.IProgramSource;
import gw.lang.parser.*;
import gw.lang.parser.exceptions.ParseResultsException;
import gw.lang.reflect.*;
import gw.lang.reflect.gs.IGosuProgram;
import gw.lang.reflect.gs.IProgramInstance;
import gw.lang.reflect.java.JavaTypes;
import gw.util.GosuExceptionUtil;
import gw.util.GosuStringUtil;
import gw.util.Pair;
import gw.util.StreamUtil;
import gw.vark.annotations.Depends;
import gw.vark.typeloader.AntlibTypeLoader;
import gw.vark.util.Stopwatch;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Target;
import java.io.*;
import java.util.*;
private static final String REF_ID = AardvarkProgram.class.getName();
public static AardvarkProgram
getInstance(Project project) {
return (AardvarkProgram) project.getReference(REF_ID);
}
public static AardvarkProgram
parseWithTimer(Project project, File programFile, InputStream in)
throws ParseResultsException
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.start();
project.log("Parsing Aardvark buildfile...", Project.MSG_VERBOSE);
AardvarkProgram program = parse(project, programFile, in);
stopwatch.stop();
project.log("Done parsing Aardvark buildfile in " + stopwatch.getElapsedInMS() + " ms");
return program;
}
public static AardvarkProgram
parse(Project project, File programFile, InputStream in)
throws ParseResultsException
{
Reader reader = StreamUtil.getInputStreamReader(in);
File baseDir;
if (programFile != null) {
baseDir = programFile.getParentFile();
}
else {
baseDir = new File(".");
}
return parse(project, baseDir, reader);
}
public static AardvarkProgram
parse(Project project, File varkFile)
throws ParseResultsException
{
try {
Reader reader = StreamUtil.getInputStreamReader(new FileInputStream(varkFile));
return parse(project, varkFile.getParentFile(), reader);
}
catch (IOException e) {
throw GosuExceptionUtil.forceThrow(e);
}
}
public static AardvarkProgram
parse(Project project, File baseDir, Reader reader)
throws ParseResultsException {
try {
String content = StreamUtil.getContent(reader);
IGosuProgramParser programParser = GosuParserFactory.createProgramParser();
List<String> packages = getDefaultTypeUsesPackages();
ITypeUsesMap typeUses = CommonServices.getGosuIndustrialPark().createTypeUsesMap(packages);
for( String aPackage : packages )
{
typeUses.addToDefaultTypeUses( aPackage );
}
IType supertype = TypeSystem.getByFullName("gw.vark.AardvarkFile");
ParserOptions options = new ParserOptions().withTypeUsesMap(typeUses).withSuperType(supertype);
IParseResult result = programParser.parseExpressionOrProgram( content, new StandardSymbolTable( true ), options );
AardvarkProgram aardvarkProgram = new AardvarkProgram(project, baseDir, result.getProgram());
project.addReference(REF_ID, aardvarkProgram);
return aardvarkProgram;
} catch (IOException e) {
throw GosuExceptionUtil.forceThrow(e);
}
}
{
return Arrays.asList(Depends.class.getPackage().getName() + ".*", AntlibTypeLoader.GW_VARK_TASKS_PACKAGE + "*");
}
private final Project _project;
private final File _baseDir;
private final IGosuProgram _gosuProgram;
private IProgramInstance _programInstance;
private List<Target> _runtimeGeneratedTargets = new ArrayList<Target>();
_project = project;
_baseDir = baseDir.getAbsoluteFile();
_gosuProgram = gosuProgram;
}
if (_programInstance == null) {
_programInstance = _gosuProgram.getProgramInstance();
_programInstance.evaluate(null);
}
}
return _runtimeGeneratedTargets;
}
return _baseDir;
}
public void runBuild(LinkedHashMap<String, TargetCall> targetCalls)
throws BuildException {
Throwable error = null;
try {
_project.fireBuildStarted();
_project.init();
_project.setBaseDir(_baseDir);
try
{
maybeEvaluate();
addTargets(_project, targetCalls);
}
catch( Exception e )
{
throw new BuildException(e);
}
Vector<String> targets = new Vector<String>();
if (targetCalls.size() > 0) {
targets.addAll(targetCalls.keySet());
}
else if (_project.getDefaultTarget() != null) {
targets.add(_project.getDefaultTarget());
}
if (targets.size() == 0) {
_project.log("No targets to run", Project.MSG_ERR);
}
else {
_project.executeTargets(targets);
}
} catch (RuntimeException e) {
error = e;
throw e;
} catch (Error e) {
error = e;
throw e;
} finally {
_project.fireBuildFinished(error);
}
}
_project.init();
_project.setBaseDir(_baseDir);
_project.log(getHelp(_gosuProgram));
}
public static String
getHelp( IType gosuProgram )
{
StringBuilder help = new StringBuilder();
help.append("\nValid targets:\n\n");
List<Pair<String, String>> nameDocPairs = new ArrayList<Pair<String, String>>();
int maxLen = 0;
for( IMethodInfo methodInfo : gosuProgram.getTypeInfo().getMethods() )
{
if( Aardvark.isTargetMethod(gosuProgram, methodInfo) && methodInfo.getDescription() != null)
{
String name = camelCaseToHyphenated(methodInfo.getDisplayName());
maxLen = Math.max( maxLen, name.length() );
String description = methodInfo.getDescription();
if (!methodInfo.getOwnersType().equals(gosuProgram)) {
description += "\n [in " + methodInfo.getOwnersType().getName() + "]";
}
IParameterInfo[] parameters = methodInfo.getParameters();
for (int i = 0, parametersLength = parameters.length; i < parametersLength; i++) {
IParameterInfo param = parameters[i];
description += "\n -" + param.getName();
if (methodInfo instanceof IOptionalParamCapable) {
IExpression defaultValue = ((IOptionalParamCapable) methodInfo).getDefaultValueExpressions()[i];
if (defaultValue != null) {
description += " (optional, default " + defaultValue.evaluate() + ")";
}
}
if (GosuStringUtil.isNotBlank(param.getDescription())) {
description += ": " + param.getDescription();
}
}
nameDocPairs.add( Pair.make( name, description) );
}
}
for( Pair<String, String> nameDocPair : nameDocPairs )
{
String name = nameDocPair.getFirst();
String command = " " + name + GosuStringUtil.repeat( " ", maxLen - name.length() ) + " - ";
int start = command.length();
String docs = nameDocPair.getSecond();
Iterator<String> iterator = Arrays.asList( docs.split( "\n" ) ).iterator();
if( iterator.hasNext() )
{
command += iterator.next();
}
while( iterator.hasNext() )
{
command += "\n" + GosuStringUtil.repeat( " ", start ) + iterator.next();
}
help.append( command ).append("\n");
}
help.append( "\nFEED THE VARK!" );
return help.toString();
}
private void addTargets( Project project, Map<String, TargetCall> targetCalls )
{
List<Target> targets = new ArrayList<Target>(getRuntimeGeneratedTargets());
for ( final IMethodInfo methodInfo : _gosuProgram.getTypeInfo().getMethods() )
{
if ( Aardvark.isTargetMethod(_gosuProgram, methodInfo) )
{
String rawTargetName = stripParens(methodInfo.getName());
String hyphenatedTargetName = camelCaseToHyphenated(rawTargetName);
TargetCall targetCall = targetCalls.get(rawTargetName);
if (targetCall == null) {
targetCall = targetCalls.get(hyphenatedTargetName);
}
AardvarkTarget target = new AardvarkTarget(methodInfo, _programInstance, targetCall);
target.setProject( project );
target.setName( hyphenatedTargetName );
target.setDescription( methodInfo.getDescription() );
IAnnotationInfo dependsAnnotation = methodInfo.getAnnotation( TypeSystem.get( Depends.class ) );
if (dependsAnnotation != null) {
Depends dependsAnnotationValue = (Depends) dependsAnnotation.getInstance();
String[] dependencies = dependsAnnotationValue.value();
for ( String dependencyTarget : dependencies ) {
target.addDependency( camelCaseToHyphenated(dependencyTarget) );
}
}
targets.add(target);
if (!rawTargetName.equals(hyphenatedTargetName)) {
Target camelcaseTarget = new Target();
camelcaseTarget.setName(rawTargetName);
camelcaseTarget.addDependency(hyphenatedTargetName);
project.addTarget(camelcaseTarget);
}
}
}
for (Target target : targets) {
project.addTarget(target);
}
}
int openParenIdx = str.lastIndexOf("(");
return str.substring(0, openParenIdx);
}
for (int i = 0; i < str.length(); i++) {
if (Character.isUpperCase(str.charAt(i))) {
return true;
}
}
return false;
}
if (hasUpperCase(str)) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (Character.isUpperCase(c)) {
sb.append('-');
sb.append(Character.toLowerCase(c));
}
else {
sb.append(c);
}
}
return sb.toString();
}
else {
return str;
}
}
private final IMethodInfo _methodInfo;
private final IProgramInstance _gosuProgramInstance;
private final TargetCall _targetCall;
AardvarkTarget(IMethodInfo methodInfo, IProgramInstance gosuProgramInstance, TargetCall targetCall) {
_methodInfo = methodInfo;
_gosuProgramInstance = gosuProgramInstance;
_targetCall = targetCall;
}
@Override
public void execute()
throws BuildException {
int argArraySize = _methodInfo.getOwnersType() instanceof IGosuProgram ? 1 : 0;
int offset = argArraySize;
argArraySize += _methodInfo.getParameters().length;
Object[] args = new Object[argArraySize];
Map<String, String> userParams = _targetCall != null ? _targetCall.getParams() : Collections.<String, String>emptyMap();
IParameterInfo[] parameters = _methodInfo.getParameters();
for (int i = 0, parametersLength = parameters.length; i < parametersLength; i++) {
IParameterInfo paramInfo = parameters[i];
if (paramInfo.getFeatureType().equals(JavaTypes.STRING())) {
args[offset + i] = determineStringParamVal(paramInfo.getName(), userParams, i);
}
else if (paramInfo.getFeatureType().equals(JavaTypes.pBOOLEAN()) || paramInfo.getFeatureType().equals(JavaTypes.BOOLEAN())) {
args[offset + i] = determineBooleanParamVal(paramInfo.getName(), userParams, i);
}
else if (paramInfo.getFeatureType().equals(JavaTypes.pINT()) || paramInfo.getFeatureType().equals(JavaTypes.INTEGER())) {
args[offset + i] = determineIntParamVal(paramInfo.getName(), userParams, i);
}
else {
throw new IllegalArgumentException("type " + paramInfo.getFeatureType() + " for \"" + paramInfo.getName() + "\" not supported");
}
}
if (userParams.size() > 0) {
throw new IllegalArgumentException("no parameter named \"" + userParams.keySet().iterator().next() + "\"");
}
_methodInfo.getCallHandler().handleCall(_gosuProgramInstance, args);
}
boolean hasUserParam = userParams.containsKey(paramName);
if (hasUserParam) {
String userValue = userParams.remove(paramName);
if (userValue == null) {
throw new IllegalArgumentException("\"" + paramName + "\" is expected to be followed by a value");
}
return userValue;
}
else {
IExpression defaultValue = ((IOptionalParamCapable)_methodInfo).getDefaultValueExpressions()[i];
if (defaultValue == null) {
throw new IllegalArgumentException("requires parameter \"" + paramName + "\"");
}
return defaultValue.evaluate();
}
}
boolean hasUserParam = userParams.containsKey(paramName);
if (hasUserParam) {
String userValue = userParams.remove(paramName);
if (userValue == null) {
return true;
}
else if (userValue.equals("true")) {
return Boolean.TRUE;
}
else if (userValue.equals("false")) {
return Boolean.FALSE;
}
else {
throw new IllegalArgumentException("\"" + paramName + "\" value is expected to be a boolean, was \"" + userValue + "\"");
}
}
else {
IExpression defaultValue = ((IOptionalParamCapable)_methodInfo).getDefaultValueExpressions()[i];
if (defaultValue == null) {
return false;
}
return defaultValue.evaluate();
}
}
boolean hasUserParam = userParams.containsKey(paramName);
if (hasUserParam) {
String userValue = userParams.remove(paramName);
if (userValue == null) {
throw new IllegalArgumentException("\"" + paramName + "\" is expected to be followed by a value");
}
try {
return new Integer(userValue);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("\"" + paramName + "\" value is expected to be an int, was \"" + userValue + "\"");
}
}
else {
IExpression defaultValue = ((IOptionalParamCapable)_methodInfo).getDefaultValueExpressions()[i];
if (defaultValue == null) {
throw new IllegalArgumentException("requires parameter \"" + paramName + "\"");
}
return defaultValue.evaluate();
}
}
}
}