Package modTransf.rules.core

Source Code of modTransf.rules.core.RuleCallAction$ExtendedArguments

//Source file: H:\\temp\\generated\\modTransf\\rules\\core\\RuleCallAction.java

package modTransf.rules.core;

import modTransf.engine.Arguments;
import modTransf.engine.RuleContext;
import modTransf.engine.TransformationException;
import modTransf.engine.EngineLifeCycle;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Collection;
import modTransf.engine.Rule;
import modTransf.engine.ParameterDescriptor;
import modTransf.engine.EngineException;
import modTransf.engine.ArrayArguments;
import modTransf.util.TransposedListView;

/**
* This action allows to call a rule.
* This action can be used as action and as a guard. A call to a rule return a
* boolean indicating if the rule has been executed.
* The parameter values are compute, and passed as arguments to the rule. Then the
* rule is called. Finally, the output parameter values (as defined by the called
* rule) are set in the current rule.
* If one parameter denotes a collection, the rule is called with each possible
* combination of the cartesian product of the arguments.
* @todo Check the parameter count (be care of problems because some rules are not
* initialized).
* @todo Be able to create an instance and call it dynamically. call( ruleName, argumentExpr, context)
* setParameterExpression( String params, RuleContext context )
*/
public class RuleCallAction implements GuardClause, ActionClause
{

   /**
    * The rule to call.
    */
   protected String ruleName;

   /**
    * The rule to call !
    */
   protected Rule rule;

   /**
    * The parameters expressions to get/set the rule arguments.
    */
   protected List parameters = new ArrayList();

  private boolean parameterChecked = false;

  /**
    * Constructor.
    * This constructor is to be called by subclasses. The subclasses should ensure
    * that the ruleName is set before calling "callRule()".
    */
   protected RuleCallAction()
   {
   }

   /**
    * Constructor.
    */
   public RuleCallAction(String ruleName)
   {
    this.ruleName = ruleName;
   }

   /**
    * Sets the value of the rule property.
    *
    * @param aRule the new value of the rule property
    */
   public void setRuleName(String aRule)
   {
      ruleName = aRule;
   }

   /**
    * @param expr
    */
   public void addParameterExpression(ParameterExpression expr)
   {
     parameters.add(expr);
   }

   /**
    * Get the list of parameter expressions.
    * @return List
    */
   public List getParameterExpressions()
   {
     return parameters;
   }

  /**
   * Call the rule. Retrieve the arguments by using the associated expressions,
   * then call the rule in a new context. If the arguments contain one or more
   * collection, the rule is called for each possible combination. Each result
   * is stored in the variable denoted by the expressions.
   * The engineStart() method should have been called prior to any call to this method.
   *
   * @param currentBean The current bean (used in 'this' expressions).
   * @param context RuleContext
   * @return boolean
   * @throws TransformationException
   */
  protected boolean callRule( RuleContext context )
    throws TransformationException
  {
    //System.out.println("RuleCall.callRule( '" + ruleName + "') ");

    // Check if the rule is set. If not, call the engineStart() method.
    // This should normally be done by the engine at startup. The extra call is made
    // for convenience.
    if( rule==null)
    {
      try
      {
        engineStart(context);
      }
      catch(EngineException ex)
      {
        throw new TransformationException(ex);
      }
    }

    boolean isCalled = false;

    // Get the in arguments
    ExtendedArguments args = getInArguments(context);

     //System.out.println("RuleCall.callRule( '" + ruleName + "', "+args + ") ");

     // call the rule for each combination in case of collections. The result
     // saving should be done for each call.
     // call the rule
     if( args.containsCollection() )
     {
       // Iterate on all combinations
       ArgumentsIterator combinationsIter = new ArgumentsIterator( args );
       List res = new ArrayList();
       while(combinationsIter.hasNext() )
       {
         Arguments curArgs = combinationsIter.nextArguments();
         if( executeRuleInNewContext( curArgs, context ) )
           {
             //System.out.println("add args '" + curArgs + "'." );
             res.add( curArgs );
             isCalled = true;
           }
       }
       // Save results
       if( isCalled )
         storeOutArg( toArguments(res), context );
     }
     else
     { // No iteration, use args directly
       if( executeRuleInNewContext( args, context ) )
         {
           storeOutArg(args, context);
           isCalled = true;
         }
     }

  return isCalled;
  }

  /**
   * Transform a List of Arguments into an Arguments of List
   *
   * @param res List
   * @return Arguments
   */
  protected Arguments toArguments(List listOfLists)
  {
    return new TransposedListView(listOfLists);
  }

  /**
   * Get the in argument values from the call expressions.
   * @param context RuleContext
   * @throws TransformationException
   */
  private ExtendedArguments getInArguments(RuleContext context)
    throws TransformationException
  {
    // Get in parameter values
    // Iterate on expressions and build Arguments. Only in arguments are read.
     ExtendedArguments args = new ExtendedArguments(parameters.size());
     // Iterate on call expressions
     Iterator paramIter = parameters.iterator();
     // Rule domains are used to check the direction
     Iterator descIter = rule.getParameterDescriptors().iterator();
     while(paramIter.hasNext())
     {
       ParameterDescriptor paramDesc = (ParameterDescriptor)descIter.next();
       ParameterExpression exprValue = (ParameterExpression)paramIter.next();
       //System.out.println( ruleName + ".desc."+paramDesc.isIn(context)+ " ");
       if( paramDesc.isIn(context) )
       {
         Object arg = exprValue.getValue(context);
         args.add(arg);
       }
       else
       // out parameter, put an null value.
         args.add(null);
       }
     }
     return args;
  }

  /**
   * Try to Execute the rule with the provided args. Create a new context for
   * the execution.
   * @param args Arguments
   * @param context RuleContext
   * @return boolean
   */
  protected boolean executeRuleInNewContext( Arguments args, RuleContext context )
    throws TransformationException
  {
    context.enterLocalContext();
    try
    {
      return rule.execute(args, context);
    }
    finally
    {
      context.exitLocalContext();
    }
  }

  /**
   * Store the out arguments in the context.
   * @param args Arguments
   * @param context RuleContext
   * @throws TransformationException
   */
  protected void storeOutArg( Arguments args, RuleContext context )
    throws TransformationException
  {
    if( args.size() != parameters.size() )
      throw new TransformationException("Returned args count should match parameter descriptor count. Expected "
                                        + parameters.size() + ", found " + args.size() + ".");

      // Iterate on call parameters expressions
    Iterator paramIter = parameters.iterator();
      // Iterate on rule domains to find the direction
    Iterator descIter = rule.getParameterDescriptors().iterator();
      // Iterate on argument values
    Iterator argsIter = args.iterator();

    while(paramIter.hasNext())
    {
      ParameterDescriptor paramDesc = (ParameterDescriptor)descIter.next();
      ParameterExpression exprValue = (ParameterExpression)paramIter.next();
      Object value = argsIter.next();
      //System.out.println("store result (isOut=" +paramDesc.isOut(context) + ") '" + value + "'" );
      if( paramDesc.isOut(context) )
      {
        if( value != null )
          exprValue.setValue( value, context);
      }
    }
  }

   /**
    * @param args
    * @param context
    */
   public void setUpLocalVariables(Object args, RuleContext context)
   {

   }

   /**
    * @param object
    * @param request
    * @return boolean
    * @throws ispuml.mdaTransformation.TransformationException
    */
   public boolean isAllowed(Object object, RuleContext request)
     throws TransformationException
   {
     return callRule(request);
   }

   /**
    * @param context
    */
   public void engineStart(RuleContext context)
    throws EngineException
  {
     rule = context.getTransformation().getRuleSet().getRule(ruleName);
     if( rule == null )
       throw new EngineException("No rule found under name '" + ruleName + "'." );

     // Check number of parameters
     checkParameterCount();

     // call life cycle on parameters if needed
     Iterator iter = parameters.iterator();
     while( iter.hasNext() )
     {
       Object param = iter.next();
       if( param instanceof EngineLifeCycle )
         ((EngineLifeCycle)param).engineStart(context);
     }
   }

   /**
    * Check if the parameter count of the rule to call is compatible with the
    * number of declared parameters.
    * This method can only be called if the rule to call is already initialized.
    * So, it is not always possible to call it from engineStart().
    * @throws EngineException
    */
   private void checkParameterCount()
    throws EngineException
  {
    List descr = rule.getParameterDescriptors();

    // Try to get the desc of the rule to call. If we can't get it, abort.
    // This happen when the rule is not yet initialized.
    if( descr == null )
      return;

    int requiredParameterCount = descr.size();
    if( requiredParameterCount != parameters.size() )
      throw new EngineException( "RuleCall - Rule '" + ruleName + "' requires "
                                 + requiredParameterCount +" parameters. "
                                 + parameters.size() + " are provided." );
  }

   /**
    * @param context
    */
   public void engineFinish(RuleContext context)
    throws EngineException
  {
     // call life cycle on parameters if needed
     Iterator iter = parameters.iterator();
     while( iter.hasNext() )
     {
       Object param = iter.next();
       if( param instanceof EngineLifeCycle )
         ((EngineLifeCycle)param).engineFinish(context);
     }

   }

  /**
   * execute
   *
   * @param bean Object
   * @param request RuleContext
   * @return Object
   */
  public Object execute(Object bean, RuleContext request)
    throws TransformationException
  {
    return new Boolean (callRule(request));
  }

  /**
   * An Arguments knowing if it contains collections.
   */
  private class ExtendedArguments extends ArrayArguments
  {
    private boolean containsCollection = false;

    public ExtendedArguments()
    {
      super();
    }
    public ExtendedArguments(Collection coll)
    {
      super(coll);
    }
    public ExtendedArguments(int initialCapacity)
    {
      super(initialCapacity);
    }

    public boolean containsCollection()
    {
      return containsCollection;
    }

    public void setContainsCollection(boolean contains)
    {
       containsCollection = contains;
    }

    private void checkCollection( Object object )
    {
      if( object instanceof Collection )
        containsCollection = true;
    }

    public boolean add( Object object )
    {
      checkCollection(object);
      return super.add(object);
    }

    public void add( int index, Object object )
    {
      checkCollection(object);
      super.add(index, object);
    }
  }
}
TOP

Related Classes of modTransf.rules.core.RuleCallAction$ExtendedArguments

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.