Package com.puppetlabs.geppetto.pp.dsl.eval

Source Code of com.puppetlabs.geppetto.pp.dsl.eval.PPExpressionEquivalenceCalculator

/**
* Copyright (c) 2013 Puppet Labs, Inc. and other contributors, as listed below.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*   Puppet Labs
*/
package com.puppetlabs.geppetto.pp.dsl.eval;

import java.util.Collections;
import java.util.Iterator;

import com.puppetlabs.geppetto.pp.DoubleQuotedString;
import com.puppetlabs.geppetto.pp.Expression;
import com.puppetlabs.geppetto.pp.ExpressionTE;
import com.puppetlabs.geppetto.pp.FunctionCall;
import com.puppetlabs.geppetto.pp.LiteralBoolean;
import com.puppetlabs.geppetto.pp.LiteralDefault;
import com.puppetlabs.geppetto.pp.LiteralName;
import com.puppetlabs.geppetto.pp.LiteralNameOrReference;
import com.puppetlabs.geppetto.pp.LiteralRegex;
import com.puppetlabs.geppetto.pp.LiteralUndef;
import com.puppetlabs.geppetto.pp.ParenthesisedExpression;
import com.puppetlabs.geppetto.pp.SingleQuotedString;
import com.puppetlabs.geppetto.pp.TextExpression;
import com.puppetlabs.geppetto.pp.UnquotedString;
import com.puppetlabs.geppetto.pp.VariableExpression;
import com.puppetlabs.geppetto.pp.VariableTE;
import com.puppetlabs.geppetto.pp.VerbatimTE;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.util.PolymorphicDispatcher;

/**
* @author henrik
*
*/
public class PPExpressionEquivalenceCalculator {

  private PolymorphicDispatcher<Boolean> eqDispatcher = new PolymorphicDispatcher<Boolean>(
    "_eq", 2, 2, Collections.singletonList(this), PolymorphicDispatcher.NullErrorHandler.<Boolean> get()) {
    @Override
    protected Boolean handleNoSuchMethod(Object... params) {
      return null;
    }
  };

  private Class<?> eqOrder[] = {
      /* A very important order */
      FunctionCall.class, DoubleQuotedString.class, UnquotedString.class, SingleQuotedString.class,
      ExpressionTE.class, VariableTE.class, VerbatimTE.class, LiteralName.class, LiteralNameOrReference.class,
      LiteralUndef.class, LiteralDefault.class, LiteralBoolean.class, LiteralRegex.class,
      VariableExpression.class, String.class };

  protected Boolean _eq(DoubleQuotedString e1, DoubleQuotedString e2) {
    if(e1.getStringPart().size() != e2.getStringPart().size())
      return Boolean.FALSE;
    Iterator<TextExpression> itor1 = e1.getStringPart().iterator();
    Iterator<TextExpression> itor2 = e2.getStringPart().iterator();

    Boolean result = null;
    while(itor1.hasNext()) {
      result = isEquivalent(itor1.next(), itor2.next());
      if(result == null)
        break;
      if(!result)
        return result; // give up (false) if two segments are unequal

    }
    return result; // do source compare if result is null, else it is true here
  }

  protected Boolean _eq(DoubleQuotedString e1, ExpressionTE e2) {
    return isEquivalent(e1, e2.getExpression());
  }

  protected Boolean _eq(DoubleQuotedString e1, LiteralName e2) {
    if(e1.getStringPart().size() != 1)
      return Boolean.FALSE;
    return isEquivalent(e1.getStringPart().get(0), e2);
  }

  protected Boolean _eq(DoubleQuotedString e1, LiteralNameOrReference e2) {
    if(e1.getStringPart().size() != 1)
      return Boolean.FALSE;
    return isEquivalent(e1.getStringPart().get(0), e2);
  }

  protected Boolean _eq(DoubleQuotedString e1, SingleQuotedString e2) {
    if(e1.getStringPart().size() != 1)
      return Boolean.FALSE;
    return isEquivalent(e1.getStringPart().get(0), e2);
  }

  protected Boolean _eq(DoubleQuotedString e1, String e2) {
    if(e1.getStringPart().size() != 1)
      return Boolean.FALSE;
    return isEquivalent(e1.getStringPart().get(0), e2);
  }

  protected Boolean _eq(DoubleQuotedString e1, UnquotedString e2) {
    return isEquivalent(e1, e2.getExpression());

  }

  protected Boolean _eq(DoubleQuotedString e1, VariableExpression e2) {
    if(e1.getStringPart().size() != 1)
      return Boolean.FALSE;
    return isEquivalent(e1.getStringPart().get(0), e2);
  }

  protected Boolean _eq(DoubleQuotedString e1, VerbatimTE e2) {
    if(e1.getStringPart().size() != 1)
      return Boolean.FALSE;
    return isEquivalent(e1.getStringPart().get(0), e2);
  }

  protected Boolean _eq(ExpressionTE e1, ExpressionTE e2) {
    return isEquivalent(e1.getExpression(), e2.getExpression());
  }

  protected Boolean _eq(ExpressionTE e1, String e2) {
    Expression tmp = e1.getExpression();
    tmp = ((ParenthesisedExpression) tmp).getExpr();
    return isEquivalent(tmp, e2);
    // // The various expr that can represent a variable
    // if(tmp instanceof LiteralName)
    // return isEquivalent(tmp, e2);
    // if(tmp instanceof LiteralNameOrReference)
    // return isEquivalent(tmp, e2);
    // if(tmp instanceof VariableExpression)
    // return isEquivalent(tmp, e2);
    //
    // return Boolean.FALSE;
  }

  protected Boolean _eq(ExpressionTE e1, VariableExpression e2) {
    Expression tmp = e1.getExpression();
    tmp = ((ParenthesisedExpression) tmp).getExpr();
    // The various expr that can represent a variable
    if(tmp instanceof LiteralName)
      return isEquivalent(((LiteralName) tmp).getValue(), e2);
    if(tmp instanceof LiteralNameOrReference)
      return isEquivalent(((LiteralNameOrReference) tmp).getValue(), e2);
    if(tmp instanceof VariableExpression)
      return isEquivalent(tmp, e2);

    return Boolean.FALSE;

  }

  protected Boolean _eq(ExpressionTE e1, VariableTE e2) {
    Expression tmp = e1.getExpression();
    tmp = ((ParenthesisedExpression) tmp).getExpr();
    // The various expr that can represent a variable
    if(tmp instanceof LiteralName)
      return isEquivalent(((LiteralName) tmp).getValue(), e2);
    if(tmp instanceof LiteralNameOrReference)
      return isEquivalent(((LiteralNameOrReference) tmp).getValue(), e2);
    if(tmp instanceof VariableExpression)
      return isEquivalent(tmp, e2);

    return Boolean.FALSE;
  }

  protected Boolean _eq(FunctionCall e1, FunctionCall e2) {
    // debatable, Function calls without parameters are almost certain to return the same value
    // but all other functions may return different result even if given exactly the same input, as it is completely
    // unknown if they use time or random numbers, perform some kind of UUID calculation etc.
    // However, since the purpose of this logic is to find user copy/paste mistakes, this logic treats functions with
    // the same text as if they produce the same value.
    // Puppet is supposedly a functional language so it should be relatively safe to assume that two function expressions
    // with the same text produce the same result.

    // if names are not equivalent
    if(!isEquivalent(e1.getLeftExpr(), e2.getLeftExpr()))
      return Boolean.FALSE;
    // if different number of arguments
    if(e1.getParameters().size() != e2.getParameters().size())
      return Boolean.FALSE;

    // if parameter expressions are not equivalent
    EList<Expression> p1 = e1.getParameters();
    EList<Expression> p2 = e2.getParameters();
    for(int i = 0; i < p1.size(); i++)
      if(!isEquivalent(p1.get(i), p2.get(i)))
        return Boolean.FALSE;
    return Boolean.TRUE;
  }

  protected Boolean _eq(LiteralBoolean e1, LiteralBoolean e2) {
    return e1.isValue() == e2.isValue();
  }

  protected Boolean _eq(LiteralDefault e1, LiteralDefault e2) {
    return Boolean.TRUE;
  }

  protected Boolean _eq(LiteralName e1, LiteralName e2) {
    return e1.getValue().equals(e2.getValue());
  }

  protected Boolean _eq(LiteralName e1, LiteralNameOrReference e2) {
    return e1.getValue().equals(e2.getValue());
  }

  protected Boolean _eq(LiteralName e1, String e2) {
    return e1.getValue().equals(e2);
  }

  protected Boolean _eq(LiteralNameOrReference e1, LiteralNameOrReference e2) {
    return e1.getValue().equals(e2.getValue());
  }

  protected Boolean _eq(LiteralNameOrReference e1, String e2) {
    return e1.getValue().equals(e2);
  }

  protected Boolean _eq(LiteralRegex e1, LiteralRegex e2) {
    return e1.getValue().equals(e2.getValue());
  }

  protected Boolean _eq(LiteralUndef e1, LiteralUndef e2) {
    return Boolean.TRUE;
  }

  protected Boolean _eq(SingleQuotedString e1, ExpressionTE e2) {
    return isEquivalent(e1.getText(), e2);
  }

  protected Boolean _eq(SingleQuotedString e1, LiteralName e2) {
    return isEquivalent(e1.getText(), e2);
  }

  protected Boolean _eq(SingleQuotedString e1, LiteralNameOrReference e2) {
    return isEquivalent(e1.getText(), e2);
  }

  protected Boolean _eq(SingleQuotedString e1, SingleQuotedString e2) {
    return isEquivalent(e1.getText(), e2);
  }

  protected Boolean _eq(SingleQuotedString e1, String e2) {
    return e1.getText().equals(e2);
  }

  protected Boolean _eq(SingleQuotedString e1, VerbatimTE e2) {
    return isEquivalent(e1.getText(), e2);
  }

  protected Boolean _eq(UnquotedString e1, Expression e2) {
    Expression tmp = e1.getExpression();
    boolean e2IsVar = e2 instanceof VariableExpression;
    if(tmp instanceof LiteralName) {
      if(e2IsVar)
        return isEquivalent(((LiteralName) tmp).getValue(), e2);
      return Boolean.FALSE;
    }
    else if(tmp instanceof LiteralNameOrReference) {
      if(e2IsVar)
        return isEquivalent(((LiteralNameOrReference) tmp).getValue(), e2);
      return Boolean.FALSE;
    }
    // all other expression wrapped in e1 represent themselves
    return isEquivalent(e1.getExpression(), e2);
  }

  protected Boolean _eq(UnquotedString e1, ExpressionTE e2) {
    return isEquivalent(e1.getExpression(), e2.getExpression());
  }

  protected Boolean _eq(UnquotedString e1, UnquotedString e2) {
    return isEquivalent(e1.getExpression(), e2.getExpression());
  }

  protected Boolean _eq(UnquotedString e1, VariableExpression e2) {
    Expression tmp = e1.getExpression();
    if(tmp instanceof LiteralName)
      return isEquivalent(((LiteralName) tmp).getValue(), e2);
    if(tmp instanceof LiteralNameOrReference)
      return isEquivalent(((LiteralNameOrReference) tmp).getValue(), e2);
    if(tmp instanceof VariableExpression)
      return isEquivalent(tmp, e2);
    return Boolean.FALSE;

  }

  protected Boolean _eq(UnquotedString e1, VariableTE e2) {
    return isEquivalent(e1.getExpression(), e2.getVarName());
  }

  protected Boolean _eq(UnquotedString e1, VerbatimTE e2) {
    return isEquivalent(e1.getExpression(), e2.getText());
  }

  protected Boolean _eq(VariableExpression e1, String e2) {
    String s = e1.getVarName();
    if(s.startsWith("$"))
      s = s.substring(1);
    return s.equals(e2);
  }

  protected Boolean _eq(VariableExpression e1, VariableExpression e2) {
    return e1.getVarName().equals(e2.getVarName());
  }

  protected Boolean _eq(VariableTE e1, LiteralName e2) {
    String s = e1.getVarName();
    if(s.startsWith("$"))
      s = s.substring(1);
    return isEquivalent(s, e2);
  }

  protected Boolean _eq(VariableTE e1, LiteralNameOrReference e2) {
    String s = e1.getVarName();
    if(s.startsWith("$"))
      s = s.substring(1);
    return isEquivalent(s, e2);
  }

  protected Boolean _eq(VariableTE e1, String e2) {
    String s = e1.getVarName();
    if(s.startsWith("$"))
      s = s.substring(1);
    return s.equals(e2);
  }

  protected Boolean _eq(VariableTE e1, VariableTE e2) {
    return e1.getVarName().equals(e2.getVarName());
  }

  protected Boolean _eq(VerbatimTE e1, String e2) {
    return e1.getText().equals(e2);
  }

  protected Boolean _eq(VerbatimTE e1, VerbatimTE e2) {
    return e1.getText().equals(e2.getText());
  }

  private Boolean doEq(Object e1, Object e2) {

    return eqDispatcher.invoke(e1, e2);
  }

  private int eqPriority(Object e1) {
    Class<?> candidateClass = e1.getClass();
    for(int i = 0; i < eqOrder.length; i++) {
      if(eqOrder[i].isAssignableFrom(candidateClass))
        return i;
    }
    return -1;
  }

  public Boolean isEquivalent(Object e1, Object e2) {
    if(e1 == e2)
      return Boolean.TRUE;
    if(e1 == null || e2 == null)
      return Boolean.FALSE;
    if(e1.equals(e2))
      return Boolean.TRUE;

    Boolean isEq = eqPriority(e1) > eqPriority(e2)
        ? doEq(e2, e1)
        : doEq(e1, e2);
    if(isEq == null && e1 instanceof EObject && e2 instanceof EObject) {
      // no eq possible, compare source text if available
      INode n1 = NodeModelUtils.getNode((EObject) e1);
      INode n2 = NodeModelUtils.getNode((EObject) e2);
      if(n1 == null || n2 == null)
        return Boolean.FALSE;

      // compare source text, but skip hidden nodes
      isEq = NodeModelUtils.getTokenText(n1).equals(NodeModelUtils.getTokenText(n2));
    }
    return isEq;
  }
}
TOP

Related Classes of com.puppetlabs.geppetto.pp.dsl.eval.PPExpressionEquivalenceCalculator

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.