Package org.data2semantics.platform.domain

Source Code of org.data2semantics.platform.domain.JavaDomain

package org.data2semantics.platform.domain;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.data2semantics.platform.annotation.DomainDefinition;
import org.data2semantics.platform.annotation.Factory;
import org.data2semantics.platform.annotation.In;
import org.data2semantics.platform.annotation.Main;
import org.data2semantics.platform.annotation.Out;
import org.data2semantics.platform.core.Module;
import org.data2semantics.platform.core.ModuleInstance;
import org.data2semantics.platform.core.data.DataType;
import org.data2semantics.platform.core.data.Input;
import org.data2semantics.platform.core.data.InstanceInput;
import org.data2semantics.platform.core.data.InstanceOutput;
import org.data2semantics.platform.core.data.JavaType;
import org.data2semantics.platform.core.data.Output;
import org.data2semantics.platform.exception.InconsistentWorkflowException;
import org.data2semantics.platform.exception.WorkflowCodeMatchException;
import org.data2semantics.platform.util.PlatformUtil;

@DomainDefinition(prefix="java")
public class JavaDomain implements Domain
{
  private static JavaDomain domain = new JavaDomain();
 
  @Override
  public boolean typeMatches(Output output, Input input)
  {
    DataType outputType = output.dataType();
    DataType inputType =  input.dataType();
   
    return PlatformUtil.isAssignableFrom( inputType.clazz(), outputType.clazz());
  }

  @Override
  public boolean check(ModuleInstance instance, List<String> errors)
  {
    return true; // TODO
  }

  @Override
  public List<DataType> conversions(DataType type)
  {
    return Collections.emptyList(); // TODO
  }

  @Override
  public boolean execute(ModuleInstance instance, List<String> errors, Map<String, Object> outputs)
  {
    // Three cases based on inputs :
    Class<?> curClass =  loadClass(instance.module().source());
 
    // Tagged input fields -> Build using default constructor
    if(fieldsMatchesInputs(instance.inputs(), curClass))     
      return fieldInputExecute(instance, errors, outputs);

    // Factory methods with tagged parameters
    for(Method curMethod : curClass.getMethods())
      if(factoryMethodMatchesInputs(instance.inputs(), curMethod))
        return factoryMethodExecute(instance, curMethod, errors, outputs);
   
    // Constructor with tagged parameters.
    for(Constructor<?> curConstructor: curClass.getConstructors())
      if(constructorMatchesInputs(instance.inputs(), curConstructor))
        return constructorExecute(instance, curConstructor, errors, outputs);
   
    errors.add("No module execution available for inputs of this module" );
    return false;
  }
 

  private boolean constructorExecute(ModuleInstance instance, Constructor<?> constructor,
      List<String> errors, Map<String, Object> outputs) {
   
    // Create an array of objects to pass to the constructor
    // (ie. put the input values into the right order)   
    Annotation[][] annotations = constructor.getParameterAnnotations();
    Object [] args = new Object[annotations.length]; // this will be passed to the constructor
   
    // Find the values (in order) for each parameter of the constructor
    for(int i=0;i<annotations.length;i++)
    {
      In ia = getAnnotation(annotations[i], In.class);
      InstanceInput ii = instance.input(ia.name());
      args[i] = ii.value();
    }
   
    // Call constructor to instantiate the module object
    Object moduleObject = null;
    try {
      moduleObject = constructor.newInstance(args);
    } catch (IllegalAccessException e) {
      throw new RuntimeException("Constructor not accessible ("+constructor+").", e);
    } catch (IllegalArgumentException e) {
      throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
      throw new RuntimeException("Constructor threw exception ("+constructor+").", e);
    } catch (InstantiationException e) {
      throw new RuntimeException(e);
    }
   
    return executeInstantiated(moduleObject, instance, errors, outputs);
  }

  private boolean factoryMethodExecute(ModuleInstance instance, Method factoryMethod,
      List<String> errors, Map<String, Object> outputs) {
   
    // Create an array of objects to pass to the factory nethod
    // (ie. put the input values into the right order)
    Annotation[][] annotations = factoryMethod.getParameterAnnotations();
    Object [] args = new Object[annotations.length];
   
    for(int i=0;i<annotations.length;i++){
      for(int j=0;j<annotations[i].length;j++){
        if(annotations[i][j] instanceof In)
        {
          In ia = (In)annotations[i][j];
          InstanceInput ii = instance.input(ia.name());
          args[i] = ii.value();
        }
      }
    }
   
    // Call the factory method to instantiate the module object
    Object moduleObject = null;
    try {
      moduleObject = factoryMethod.invoke( null, args);
    } catch (IllegalAccessException e) {
      throw new RuntimeException("Factory method not accessible (method: "+factoryMethod+").", e);
    } catch (IllegalArgumentException e) {
      throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
      throw new RuntimeException(e);
    }
   
    return executeInstantiated(moduleObject, instance, errors, outputs);
  }

  /**
   * Executes a module with Inputs defined as class fields.
   *
   * @param instance
   * @param errors
   * @param outputs
   * @return
   */
  private boolean fieldInputExecute(ModuleInstance instance, List<String> errors, Map<String, Object> outputs)
  {
   
    // Instantiate class with default constructor
    Class<?> curClass =  loadClass(instance.module().source());
    Object moduleObject = null;
   
    try {
      // Instantiate the module object
      Constructor<?> defaultConstructor = curClass.getConstructor();
      moduleObject = defaultConstructor.newInstance();
     
      // Enter the correct values into the fields
      List<InstanceInput> inputs = instance.inputs();
      Map<String, Field > nameToFieldMap = new LinkedHashMap<String, Field>();
     
      // -- Create a map from names to fields
      for(Field f : curClass.getFields())
      {
        for(Annotation a : f.getAnnotations())
        {   
          if(a instanceof In)
          {
            if(nameToFieldMap.containsKey(((In) a).name()))
              throw new WorkflowCodeMatchException("Multiple input field with the same name for input with name : " +((In)a).name());
         
            nameToFieldMap.put(((In)a).name(), f);
          }
        }
      }
     
      // -- enter the values
      for(InstanceInput ii : inputs)
      {
        Field curField = nameToFieldMap.get(ii.name());
        curField.set(moduleObject, ii.value());
      }
       
    } catch (NoSuchMethodException e) {
      throw new RuntimeException("Module instantiated by fields should have a default constructor.", e);
    } catch (SecurityException e) {
      throw new RuntimeException("Default constructor is not accessible.", e);
    } catch (Exception e ){
      throw new RuntimeException("Failed to instantiate object", e);
    }
   
    // Execute the instantiated module object (and collect the results)
    boolean success = executeInstantiated(moduleObject, instance, errors, outputs);
   
    return success;
  }

  /**
   * Executes an instantiated object and collects all the results to be set as instanceoutputs.
   * @param moduleObject
   * @param errors
   * @param outputs A map collection the values returned for the various outputs
   * @return
   */
  private boolean executeInstantiated(
      Object moduleObject, ModuleInstance instance, List<String> errors, Map<String, Object> outputs)
  {
    Class<?> curClass =  loadClass(instance.module().source());
   
    // Retrieve the main method and its annotation
    Method mainMethod = PlatformUtil.getMainMethod(curClass);
    Main mainAnnotation = PlatformUtil.getMainAnnotation(curClass);
   
    try {
      // This is where the module is actually executed
      Object result = mainMethod.invoke(moduleObject);
     
      // Store the result of the main method as the first output
      if(result != null) // if the main method is not null
        outputs.put(mainAnnotation.name(), result);
     
    } catch (Exception e)
    {
      throw new RuntimeException("Something went wrong during module execution.", e);
    }
   
    // Loop through all fields to check for outputs
    for(Field field : curClass.getFields())
    {
      Out anno = getAnnotation(field.getAnnotations(), Out.class);
      if(anno != null)
      {
        String name = anno.name();
        Object value = null;
        try {
          value = field.get(moduleObject);
        } catch (IllegalArgumentException e) {
          throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
          throw new RuntimeException("Output field '"+field+"' in module '"+instance.module().source()+"' not accessible. ");
        }
       
        outputs.put(name, value);
      }
    }
   
    // Loop through all methods to check for outputs
    for(Method method : curClass.getMethods())
    {
      Out anno = getAnnotation(method.getAnnotations(), Out.class);
     
      if(anno != null)
      {
        String name = anno.name();
        Object value = null;
        try {
          value = method.invoke(moduleObject);
        } catch (IllegalArgumentException e) {
          throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
          throw new RuntimeException("Output method '"+method+"' in module '"+instance.module().source()+"' not accessible. ", e);
        } catch (InvocationTargetException e) {
          throw new RuntimeException("Output method '"+method+"' in module '"+instance.module().source()+"' threw Exception of type "+e.getClass()+". ", e);
        }
       
        outputs.put(name, value);
      }
    }
   
    return true;
  }

  @SuppressWarnings("unchecked")
  private <T extends Annotation> T getAnnotation(Annotation[] annotations, Class<T> cls)
  {
    for(Annotation anno : annotations)
      if(cls.isAssignableFrom(anno.getClass()))
        return (T)anno;
   
    return null;
  }

  private boolean constructorMatchesInputs(List<InstanceInput> inputs,
      Constructor<?> curConstructor) {
   
    Annotation[][] paramAnnotations = curConstructor.getParameterAnnotations();
    Class<?> [] paramTypes = curConstructor.getParameterTypes();
   
    return methodMatchesInputs(inputs, paramAnnotations, paramTypes);
  }

  private boolean factoryMethodMatchesInputs(List<InstanceInput> inputs,
      Method m) {
   
    if(!hasFactoryAnnotation(m)) return false;
    Annotation [][] paramAnnotations = m.getParameterAnnotations();
    Class<?> [] paramTypes = m.getParameterTypes();

    return methodMatchesInputs(inputs, paramAnnotations, paramTypes);
  }

  private boolean methodMatchesInputs(List<InstanceInput> inputs, Annotation[][] paramAnnotations, Class<?> [] paramTypes) {
 
    Map<String, Class<?>> inputNameToParamType = new LinkedHashMap<String, Class<?>>();
   
    for(int i=0;i<paramAnnotations.length;i++){
      boolean found = false;
      for(int j=0;j<paramAnnotations[i].length;j++){
        if(paramAnnotations[i][j] instanceof In){
          found = true;
          inputNameToParamType.put(((In)paramAnnotations[i][j]).name(), paramTypes[i]);
        }
      }
      if(!found) {
        throw new WorkflowCodeMatchException("Method tagged with factory without all of it's parameter tagged as input");
      }
    }
   
    if(inputNameToParamType.size() != inputs.size())
      return false;
   
    for(InstanceInput ii : inputs){
      if(!inputNameToParamType.containsKey(ii.name()))
        return false;
   
      Class<?> paramClazz = inputNameToParamType.get(ii.name());
     
      if(!(ii.dataType() instanceof JavaType))
        return false;
     
      JavaType jType = (JavaType)ii.dataType();
   
      if(!PlatformUtil.isAssignableFrom(paramClazz, jType.clazz()))
        return false;
    }
   
    return true;
  }

  private boolean fieldsMatchesInputs(List<InstanceInput> list,
      Class<?> curClass) {
   
    Map<String, Field > nameToFieldMap = new LinkedHashMap<String, Field>();
   
    for(Field f : curClass.getFields()){
      for(Annotation a : f.getAnnotations()){
       
        if(a instanceof In){
          if(nameToFieldMap.containsKey(((In) a).name()))
            throw new WorkflowCodeMatchException("Multiple input field with the same name for input with name : " +((In)a).name());
       
          nameToFieldMap.put(((In)a).name(), f);
        }
      }
    }
   
    if(nameToFieldMap.size() != list.size())
      return false;
   
    for(InstanceInput ii : list){
      if(!nameToFieldMap.containsKey(ii.name()))
        return false;
   
      Field f = nameToFieldMap.get(ii.name());
     
      if(!(ii.dataType() instanceof JavaType))
        return false;
     
      JavaType jType = (JavaType)ii.dataType();
   
      if(!PlatformUtil.isAssignableFrom(f.getType(), jType.clazz()))
        return false;
     
     
    }
   
    return true;
  }

  @Override
  public DataType inputType(String source, String name)
  {
   
    Class<?> theClass = loadClass(source);
   
    Method[] methods = theClass.getMethods();
    Field[] fields = theClass.getFields();
    Constructor<?>[] constructors = theClass.getConstructors();
   
    for(Field f : fields){
      In inputAnnotation = getInputAnnotations(f);
      if(inputAnnotation != null && inputAnnotation.name().equals(name)){
        JavaType jType = new JavaType(f.getType());
        return jType;
      }
    }

    // Case where input are defined as parameter of constructors.
    for(Constructor c : constructors){
      Annotation [][] parameterAnnotations = c.getParameterAnnotations();
      for(int i =0; i< parameterAnnotations.length;i++){
        for(int j=0;j< parameterAnnotations[i].length;j++){
          if (parameterAnnotations[i][j] instanceof In)
          { In in = (In)parameterAnnotations[i][j];
            if(in.name().equals(name)){
              Class[] paramTypes = c.getParameterTypes();
              JavaType jType = new JavaType(paramTypes[i]);
              return jType;
            }
          }
        }
      }
    }
   
    // Case where inputs are defined as parameter of input factory method.
    for(Method m : methods){
      if(hasFactoryAnnotation(m)){
        Annotation [][] parameterAnnotations = m.getParameterAnnotations();
        for(int i =0; i< parameterAnnotations.length;i++){
          for(int j=0;j< parameterAnnotations[i].length;j++){
            if (parameterAnnotations[i][j] instanceof In)
            { In in = (In)parameterAnnotations[i][j];
              if(in.name().equals(name)){
                Class[] paramTypes = m.getParameterTypes();
                JavaType jType = new JavaType(paramTypes[i]);
                return jType;
              }
            }
          }
        } 
      }
     
    }
   
   
    throw new IllegalArgumentException("@In field with name "+name+" not found in "+source+" (perhaps it isn't public?).");
  }

  private Class<?> loadClass(String source)
  {
    ClassLoader classLoader = getClass().getClassLoader();
    Class <?> theClass = null;
   
    try
    {
      theClass = classLoader.loadClass(source);
    } catch (ClassNotFoundException e)
    {
      throw new IllegalArgumentException("Source class can not be loaded " + source);
    }
    return theClass;
  }

  private boolean  hasFactoryAnnotation(Method m)
  {
    Annotation[] annotations = m.getAnnotations();
    for(Annotation a : annotations){
      if( a instanceof Factory){
        return true;
      }
    }
    return false;
  }

  private In getInputAnnotations(Field f)
  {
    Annotation[] annotations = f.getAnnotations();
    for(Annotation a : annotations){
      if(a instanceof In){
        return (In)a;
      }
    }
    return null;
  }
 
  private Out getOutputAnnotations(Field f)
  {
    Annotation[] annotations = f.getAnnotations();
    for(Annotation a : annotations){
      if(a instanceof Out){
        return (Out)a;
      }
    }
    return null;
  }

  @Override
  /**
   * Look within annotated source code and tries to find output named name.
   * Return its java type as datatype.
   */
  public DataType outputType(String source, String name)
  {
    Class<?> theClass = loadClass(source);
    Method[] methods = theClass.getMethods();
    Field[] fields = theClass.getFields();

    for (Field f : fields)
    {
      Out outputAnnotation = getOutputAnnotations(f);
      if (outputAnnotation != null
          && outputAnnotation.name().equals(name))
      {
        JavaType jType = new JavaType(f.getType());
        return jType;
      }
    }

    for (Method m : methods)
    {
     
      Annotation[] annotations = m.getAnnotations();
      for(Annotation a : annotations){
        if(a instanceof Out){
          Out outAnnotation = (Out) a;
          if(outAnnotation.name().equals(name)){
            if(m.getReturnType().equals(Void.TYPE)){
              throw new IllegalArgumentException("@Out method with name "+((Out)a).name()+" has a void return type.");
            }
            JavaType jType = new JavaType(m.getReturnType());
            return jType;
          }
        }
        if(a instanceof Main){
          Main mainAnnotation = (Main)a;
          if(mainAnnotation.name().equals(name)){
            JavaType jType = new JavaType(m.getReturnType());
            return jType;
          }
        }
      }

    }
   
   
    throw new IllegalArgumentException("@Out field with name "+name+" not found in "+source+".");
  }

  @Override

  public List<String> outputs(String source)
  {
    Class <?> theClass = loadClass(source);
    List<String> outputNames = new ArrayList<String>();
   
    Method[] methods = theClass.getMethods();
    for(Method m : methods){
     
      Annotation[] annotations = m.getAnnotations();
      for(Annotation a : annotations){
        if(a instanceof Main){
          outputNames.add(0,((Main)a).name());
        }
        if(a instanceof Out){
          if(m.getReturnType().equals(Void.TYPE)){
            throw new IllegalArgumentException("@Out method with name "+((Out)a).name()+" has a void return type.");
          }
          outputNames.add(((Out)a).name());
        }
       
      }
    }
   
    Field[] fields = theClass.getFields();
    for(Field f : fields){
      Out outputAnnotation = getOutputAnnotations(f);
      if(outputAnnotation != null)
        outputNames.add(outputAnnotation.name());
    }
   
    return outputNames;
  }

  @Override
  public boolean valueMatches(Object value, DataType type)
  {
    //Because this is java domain
    if(!(type instanceof JavaType))
      return false;
   
    JavaType jType = (JavaType)type;
   
    return PlatformUtil.isAssignableFrom(jType.clazz(), value.getClass());
   
  }
 
  public static JavaDomain domain()
  {
    return domain;
  }

  @Override
  public String inputDescription(String source, String name)
  {
   
    Class<?> theClass = loadClass(source);
   
    Method[] methods = theClass.getMethods();
    Field[] fields = theClass.getFields();
    Constructor<?>[] constructors = theClass.getConstructors();
   
    for(Field f : fields){
      In inputAnnotation = getInputAnnotations(f);
      if(inputAnnotation != null && inputAnnotation.name().equals(name))
        return inputAnnotation.description();
    }

    // Case where input are defined as parameter of constructors.
    for(Constructor c : constructors){
      Annotation [][] parameterAnnotations = c.getParameterAnnotations();
      for(int i =0; i< parameterAnnotations.length;i++){
        for(int j=0;j< parameterAnnotations[i].length;j++){
          if (parameterAnnotations[i][j] instanceof In)
          { In in = (In)parameterAnnotations[i][j];
            if(in.name().equals(name))
              return in.description();
          }
        }
      }
    }
   
    // Case where inputs are defined as parameter of input factory method.
    for(Method m : methods){
      if(hasFactoryAnnotation(m)){
        Annotation [][] parameterAnnotations = m.getParameterAnnotations();
        for(int i =0; i< parameterAnnotations.length;i++){
          for(int j=0;j< parameterAnnotations[i].length;j++){
            if (parameterAnnotations[i][j] instanceof In)
            { In in = (In)parameterAnnotations[i][j];
              if(in.name().equals(name))
                return in.description();
            }
          }
        } 
      }
     
    }
   
    throw new IllegalArgumentException("@In field with name "+name+" not found in "+source+".");
  }

  @Override
  public String outputDescription(String source, String name)
  {
    Class<?> theClass = loadClass(source);
    Method[] methods = theClass.getMethods();
    Field[] fields = theClass.getFields();

    for (Field f : fields)
    {
      Out outputAnnotation = getOutputAnnotations(f);
      if (outputAnnotation != null
          && outputAnnotation.name().equals(name))
          return outputAnnotation.description();

    }

    for (Method m : methods)
    {
      //if(m.getReturnType().equals(Void.TYPE)) continue;
     
      Annotation[] annotations = m.getAnnotations();
      for(Annotation a : annotations){
        if(a instanceof Out){
          Out outAnnotation = (Out) a;
          if(outAnnotation.name().equals(name))       
            return outAnnotation.description();

        }
        if(a instanceof Main){
          Main mainAnnotation = (Main)a;
          if(mainAnnotation.name().equals(name))        
            return mainAnnotation.description();

        }
      }

    }
   
   
    throw new IllegalArgumentException("@In field with name "+name+" not found in "+source+".");
  }

  @Override
  public boolean validate(String source, List<String> errors) {
   
    Class<?> theClass = loadClass(source);
    Method[] methods = theClass.getDeclaredMethods();
   
   
    // Check if @Out, @Factory, @Main annotations are only used in public methods.
    for(Method m : methods){
     
      //We ignore all public methods, since they will have no problem with respect to our annotations
      if((m.getModifiers() & Modifier.PUBLIC) != 0) continue;
     
      Annotation[] annotations = m.getAnnotations();
      for(Annotation a : annotations){
        if(a instanceof Out || a instanceof Main || a instanceof Factory){
          errors.add( "Method " +m.getName()+ " from " +source+ " is not public while it is annotated as "+a);
        }
      }
     
    }
   
    // Check if there are more than one input type, whether their type are consistent.
   
    checkInputConsistency(source, errors);
   
    return errors.size()==0;
  }

  private void checkInputConsistency(String source, List<String> errors) {
   
    Class<?> theClass = loadClass(source);
   
    Method[] methods = theClass.getMethods();
    Field[] fields = theClass.getFields();
    Constructor<?>[] constructors = theClass.getConstructors();
   
    Map<String, JavaType> inputNameToTypeMap = new LinkedHashMap<String, JavaType>();
   
    for(Field f : fields){
      In inputAnnotation = getInputAnnotations(f);
      if(inputAnnotation != null){
        JavaType jType = new JavaType(f.getType());
        if(inputNameToTypeMap.containsKey(inputAnnotation.name())){
          JavaType storedType = inputNameToTypeMap.get(inputAnnotation.name());
          if(!storedType.equals(jType)){
            errors.add("Inputs named as : '"+inputAnnotation.name() + "' are declared using  different types : " + storedType.clazz()+ " != "+jType.clazz());
          }
        } else {
          inputNameToTypeMap.put(inputAnnotation.name(), jType);
        }
      }
    }

    // Case where input are defined as parameter of constructors.
    for(Constructor c : constructors){
      Annotation [][] parameterAnnotations = c.getParameterAnnotations();
      for(int i =0; i< parameterAnnotations.length;i++){
        for(int j=0;j< parameterAnnotations[i].length;j++){
          if (parameterAnnotations[i][j] instanceof In)
          { In in = (In)parameterAnnotations[i][j];
            Class<?>[] paramTypes = c.getParameterTypes();
            JavaType jType = new JavaType(paramTypes[i]);
            if(inputNameToTypeMap.containsKey(in.name())){
              JavaType storedType = inputNameToTypeMap.get(in.name());
              if(!storedType.equals(jType)){
                errors.add("Inputs named as : '"+in.name() + "' are declared using  different types : " + storedType.clazz()+ " != "+jType.clazz());
              }
            } else {
              inputNameToTypeMap.put(in.name(), jType);
            }
          }
        }
      }
    }
   
    // Case where inputs are defined as parameter of input factory method.
    for(Method m : methods){
      if(hasFactoryAnnotation(m)){
        Annotation [][] parameterAnnotations = m.getParameterAnnotations();
        for(int i =0; i< parameterAnnotations.length;i++){
          for(int j=0;j< parameterAnnotations[i].length;j++){
            if (parameterAnnotations[i][j] instanceof In)
            { In in = (In)parameterAnnotations[i][j];
              Class <?>[] paramTypes = m.getParameterTypes();
              JavaType jType = new JavaType(paramTypes[i]);
              if(inputNameToTypeMap.containsKey(in.name())){
                JavaType storedType = inputNameToTypeMap.get(in.name());
                if(!storedType.equals(jType)){
                  errors.add("Inputs named as : '"+in.name() + "' are declared using  different types : " + storedType.clazz()+ " != "+jType.clazz());
                }
              } else {
                inputNameToTypeMap.put(in.name(), jType);
                  }   
            }
          }
        } 
      }
     
    }
   
  }

  @Override
  public boolean printInput(String source, String name)
  {
  Class<?> theClass = loadClass(source);
   
    Method[] methods = theClass.getMethods();
    Field[] fields = theClass.getFields();
    Constructor<?>[] constructors = theClass.getConstructors();
   
    for(Field f : fields){
      In inputAnnotation = getInputAnnotations(f);
      if(inputAnnotation != null && inputAnnotation.name().equals(name)){
        return inputAnnotation.print();
      }
    }

    // Case where input are defined as parameter of constructors.
    for(Constructor c : constructors){
      Annotation [][] parameterAnnotations = c.getParameterAnnotations();
      for(int i =0; i< parameterAnnotations.length;i++){
        for(int j=0;j< parameterAnnotations[i].length;j++){
          if (parameterAnnotations[i][j] instanceof In)
          { In in = (In)parameterAnnotations[i][j];
            if(in.name().equals(name)){
              return in.print();
            }
          }
        }
      }
    }
   
    // Case where inputs are defined as parameter of input factory method.
    for(Method m : methods){
      if(hasFactoryAnnotation(m)){
        Annotation [][] parameterAnnotations = m.getParameterAnnotations();
        for(int i =0; i< parameterAnnotations.length;i++){
          for(int j=0;j< parameterAnnotations[i].length;j++){
            if (parameterAnnotations[i][j] instanceof In)
            { In in = (In)parameterAnnotations[i][j];
              if(in.name().equals(name)){
                return in.print();
              }
            }
          }
        } 
      }
     
    }
   
   
    throw new IllegalArgumentException("@In field with name "+name+" not found in "+source+" (perhaps it isn't public?).");
  }

  @Override
  public boolean printOutput(String source, String name)
  {
    Class<?> theClass = loadClass(source);
    Method[] methods = theClass.getMethods();
    Field[] fields = theClass.getFields();

    for (Field f : fields)
    {
      Out outputAnnotation = getOutputAnnotations(f);
      if (outputAnnotation != null
          && outputAnnotation.name().equals(name))
      {
        return outputAnnotation.print();
      }
    }

    for (Method m : methods)
    {
     
      Annotation[] annotations = m.getAnnotations();
      for(Annotation a : annotations){
        if(a instanceof Out){
          Out outAnnotation = (Out) a;
          if(outAnnotation.name().equals(name)){
            return outAnnotation.print();

          }
        }
        if(a instanceof Main){
          Main mainAnnotation = (Main)a;
          if(mainAnnotation.name().equals(name)){
            return mainAnnotation.print();
          }
        }
      }

    }
   
    throw new IllegalArgumentException("@Out field with name "+name+" not found in "+source+".");
  }



}
TOP

Related Classes of org.data2semantics.platform.domain.JavaDomain

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.