You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by cd...@apache.org on 2014/08/27 00:43:47 UTC

[16/51] [partial] Refactored the PMD Maven build - Adjusted the directory structure - Fixed a lot of compile problems - Fixed the maven setup - Made PMD build with Flexmojos 7.1.0 and Apache Flex 4.13.0 - Fixed a few UnitTests

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRule.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRule.java
new file mode 100644
index 0000000..6d0da0f
--- /dev/null
+++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRule.java
@@ -0,0 +1,1164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.adobe.ac.pmd.rules.core;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.logging.Logger;
+
+import com.adobe.ac.pmd.IFlexViolation;
+import com.adobe.ac.pmd.nodes.IAttribute;
+import com.adobe.ac.pmd.nodes.IClass;
+import com.adobe.ac.pmd.nodes.IConstant;
+import com.adobe.ac.pmd.nodes.IFunction;
+import com.adobe.ac.pmd.nodes.INode;
+import com.adobe.ac.pmd.nodes.IPackage;
+import com.adobe.ac.pmd.parser.IParserNode;
+import com.adobe.ac.pmd.parser.NodeKind;
+import com.adobe.ac.utils.StackTraceUtils;
+
+/**
+ * Abstract class for AST-based rule Extends this class if your rule is only
+ * detectable in an AS script block, which can be converted into an Abstract
+ * Syntax Tree. Then you will be able to either use the visitor pattern, or to
+ * iterate from the package node, in order to find your violation(s).
+ * 
+ * @author xagnetti
+ */
+public abstract class AbstractAstFlexRule extends AbstractFlexRule implements IFlexAstRule
+{
+   /**
+    *
+    */
+   protected enum FunctionType
+   {
+      GETTER, NORMAL, SETTER
+   }
+
+   /**
+    *
+    */
+   protected enum VariableOrConstant
+   {
+      CONSTANT, VARIABLE
+   }
+
+   /**
+    *
+    */
+   protected enum VariableScope
+   {
+      IN_CLASS, IN_FUNCTION
+   }
+
+   private interface ExpressionVisitor
+   {
+      void visitExpression( final IParserNode ast );
+   }
+
+   private static final Logger LOGGER = Logger.getLogger( AbstractAstFlexRule.class.getName() );
+
+   /**
+    * @param functionNode
+    * @return
+    */
+   /**
+    * @param functionNode
+    * @return
+    */
+   protected static IParserNode getNameFromFunctionDeclaration( final IParserNode functionNode )
+   {
+      IParserNode nameChild = null;
+
+      for ( final IParserNode child : functionNode.getChildren() )
+      {
+         if ( child.is( NodeKind.NAME ) )
+         {
+            nameChild = child;
+            break;
+         }
+      }
+      return nameChild;
+   }
+
+   /**
+    * @param fieldNode
+    * @return
+    */
+   protected static IParserNode getTypeFromFieldDeclaration( final IParserNode fieldNode )
+   {
+      return fieldNode.getChild( 0 ).getChild( 1 );
+   }
+
+   private final List< IFlexViolation > violations;
+
+   /**
+    * 
+    */
+   public AbstractAstFlexRule()
+   {
+      super();
+
+      violations = new ArrayList< IFlexViolation >();
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see
+    * com.adobe.ac.pmd.rules.core.AbstractFlexRule#isConcernedByTheCurrentFile
+    * ()
+    */
+   @Override
+   public boolean isConcernedByTheCurrentFile()
+   {
+      return true;
+   }
+
+   /**
+    * @param function
+    * @return the added violation positioned on the given function node
+    */
+   protected final IFlexViolation addViolation( final IFunction function )
+   {
+      final IParserNode name = getNameFromFunctionDeclaration( function.getInternalNode() );
+
+      return addViolation( name,
+                           name,
+                           name.getStringValue() );
+   }
+
+   /**
+    * @param function
+    * @param messageToReplace
+    * @return
+    */
+   protected final IFlexViolation addViolation( final IFunction function,
+                                                final String messageToReplace )
+   {
+      final IParserNode name = getNameFromFunctionDeclaration( function.getInternalNode() );
+
+      return addViolation( name,
+                           name,
+                           messageToReplace );
+   }
+
+   /**
+    * @param violatingNode
+    * @return the added violation replacing the threshold value in the message
+    *         if any.
+    */
+   protected final IFlexViolation addViolation( final INode violatingNode )
+   {
+      return addViolation( violatingNode.getInternalNode(),
+                           violatingNode.getInternalNode() );
+   }
+
+   /**
+    * @param violatingNode
+    * @return the added violation replacing the threshold value in the message
+    *         if any.
+    */
+   protected final IFlexViolation addViolation( final INode violatingNode,
+                                                final String... messageToReplace )
+   {
+      return addViolation( violatingNode.getInternalNode(),
+                           violatingNode.getInternalNode(),
+                           messageToReplace );
+   }
+
+   /**
+    * @param violatingNode
+    * @param endNode
+    * @return the added violation replacing the threshold value in the message
+    *         if any.
+    */
+   protected final IFlexViolation addViolation( final IParserNode violatingNode )
+   {
+      return addViolation( violatingNode,
+                           violatingNode );
+   }
+
+   /**
+    * @param beginningNode
+    * @param endNode
+    * @param messageToReplace
+    * @return the add violation replacing the {0} token by the specified message
+    */
+   protected final IFlexViolation addViolation( final IParserNode beginningNode,
+                                                final IParserNode endNode,
+                                                final String... messageToReplace )
+   {
+      if ( isAlreadyViolationAdded( beginningNode ) )
+      {
+         return null;
+      }
+      final IFlexViolation violation = addViolation( ViolationPosition.create( beginningNode.getLine(),
+                                                                               endNode.getLine(),
+                                                                               beginningNode.getColumn(),
+                                                                               endNode.getColumn() ) );
+
+      for ( int i = 0; i < messageToReplace.length; i++ )
+      {
+         violation.replacePlaceholderInMessage( messageToReplace[ i ],
+                                                i );
+      }
+
+      return violation;
+   }
+
+   /**
+    * @param violatingNode
+    * @param endNode
+    * @param messageToReplace
+    * @return the add violation replacing the {0} token by the specified message
+    */
+   protected final IFlexViolation addViolation( final IParserNode violatingNode,
+                                                final String... messageToReplace )
+   {
+      return addViolation( violatingNode,
+                           violatingNode,
+                           messageToReplace );
+   }
+
+   /**
+    * @param violationPosition
+    * @return the added violation positioned at the given position
+    */
+   protected final IFlexViolation addViolation( final ViolationPosition violationPosition )
+   {
+      return addViolation( violations,
+                           violationPosition );
+   }
+
+   /**
+    * find the violations list from the given class node
+    * 
+    * @param classNode
+    */
+   protected void findViolations( final IClass classNode )
+   {
+      findViolationsFromAttributes( classNode.getAttributes() );
+      findViolationsFromConstants( classNode.getConstants() );
+      findViolations( classNode.getFunctions() );
+      if ( classNode.getConstructor() != null )
+      {
+         findViolationsFromConstructor( classNode.getConstructor() );
+      }
+   }
+
+   /**
+    * find violations in every function in a class
+    * 
+    * @param function
+    */
+   protected void findViolations( final IFunction function )
+   {
+   }
+
+   /**
+    * Override this method if you need to find violations from the package ( or
+    * any subsequent node like class or function)
+    * 
+    * @param packageNode
+    */
+   protected void findViolations( final IPackage packageNode )
+   {
+      final IClass classNode = packageNode.getClassNode();
+
+      if ( classNode != null )
+      {
+         findViolations( classNode );
+      }
+   }
+
+   /**
+    * find the violations list from the given functions list
+    * 
+    * @param functions
+    */
+   protected void findViolations( final List< IFunction > functions )
+   {
+      for ( final IFunction function : functions )
+      {
+         findViolations( function );
+      }
+   }
+
+   /**
+    * find the violations list from the given class variables list
+    * 
+    * @param variables
+    */
+   protected void findViolationsFromAttributes( final List< IAttribute > variables )
+   {
+   }
+
+   /**
+    * find the violations list from the given class constants list
+    * 
+    * @param constants
+    */
+   protected void findViolationsFromConstants( final List< IConstant > constants )
+   {
+   }
+
+   /**
+    * find the violations list from the given class constructor node
+    * 
+    * @param constructor
+    */
+   protected void findViolationsFromConstructor( final IFunction constructor )
+   {
+   }
+
+   /**
+    * Find violations in the current file
+    */
+   @Override
+   protected final List< IFlexViolation > findViolationsInCurrentFile()
+   {
+      try
+      {
+         if ( getCurrentPackageNode() != null )
+         {
+            visitCompilationUnit( getCurrentPackageNode().getInternalNode() );
+            findViolations( getCurrentPackageNode() );
+         }
+      }
+      catch ( final Exception e )
+      {
+         LOGGER.warning( "on "
+               + getCurrentFile().getFilePath() );
+         LOGGER.warning( StackTraceUtils.print( e ) );
+      }
+      final List< IFlexViolation > copy = new ArrayList< IFlexViolation >( violations );
+
+      violations.clear();
+
+      return copy;
+   }
+
+   /**
+    * @param statementNode
+    */
+   protected void visitAs( final IParserNode statementNode )
+   {
+   }
+
+   /**
+    * @param catchNode
+    */
+   protected void visitCatch( final IParserNode catchNode )
+   {
+      visitNameTypeInit( catchNode.getChild( 0 ) );
+      visitBlock( catchNode.getChild( 1 ) );
+   }
+
+   /**
+    * @param classNode
+    */
+   protected void visitClass( final IParserNode classNode )
+   {
+      IParserNode content = null;
+      for ( final IParserNode node : classNode.getChildren() )
+      {
+         if ( node.is( NodeKind.CONTENT ) )
+         {
+            content = node;
+            break;
+         }
+      }
+      visitClassContent( content );
+   }
+
+   /**
+    * Visit the condition of a if, while, ...
+    * 
+    * @param condition
+    */
+   protected void visitCondition( final IParserNode condition )
+   {
+      visitExpression( condition );
+   }
+
+   /**
+    * @param doNode
+    */
+   protected void visitDo( final IParserNode doNode )
+   {
+      visitBlock( doNode.getChild( 0 ) );
+      visitCondition( doNode.getChild( 1 ) );
+   }
+
+   /**
+    * @param ifNode
+    */
+   protected void visitElse( final IParserNode ifNode )
+   {
+      visitBlock( ifNode.getChild( 2 ) );
+   }
+
+   /**
+    * Visit empty statement
+    * 
+    * @param statementNode
+    */
+   protected void visitEmptyStatetement( final IParserNode statementNode )
+   {
+   }
+
+   /**
+    * @param finallyNode
+    */
+   protected void visitFinally( final IParserNode finallyNode )
+   {
+      if ( isNodeNavigable( finallyNode ) )
+      {
+         visitBlock( finallyNode.getChild( 0 ) );
+      }
+   }
+
+   /**
+    * @param forNode
+    */
+   protected void visitFor( final IParserNode forNode )
+   {
+      visitBlock( forNode.getChild( 3 ) );
+   }
+
+   /**
+    * @param foreachNode
+    */
+   protected void visitForEach( final IParserNode foreachNode )
+   {
+      visitBlock( foreachNode.getChild( 2 ) );
+   }
+
+   /**
+    * @param functionNode
+    * @param type
+    */
+   protected void visitFunction( final IParserNode functionNode,
+                                 final FunctionType type )
+   {
+      final Iterator< IParserNode > iterator = functionNode.getChildren().iterator();
+      IParserNode currentNode = iterator.next();
+
+      while ( currentNode.is( NodeKind.META_LIST )
+            || currentNode.is( NodeKind.MOD_LIST ) || currentNode.is( NodeKind.AS_DOC )
+            || currentNode.is( NodeKind.MULTI_LINE_COMMENT ) )
+      {
+         currentNode = iterator.next();
+      }
+      currentNode = iterator.next();
+      visitParameters( currentNode );
+      currentNode = iterator.next();
+      visitFunctionReturnType( currentNode );
+      try
+      {
+         // Intrinsic functions in AS2
+         currentNode = iterator.next();
+         visitFunctionBody( currentNode );
+      }
+      catch ( final NoSuchElementException e )
+      {
+      }
+   }
+
+   /**
+    * @param functionReturnTypeNode
+    */
+   protected void visitFunctionReturnType( final IParserNode functionReturnTypeNode )
+   {
+      visitBlock( functionReturnTypeNode );
+   }
+
+   /**
+    * @param ifNode
+    */
+   protected void visitIf( final IParserNode ifNode )
+   {
+      visitCondition( ifNode.getChild( 0 ) );
+      visitThen( ifNode );
+      if ( ifNode.numChildren() == 3 )
+      {
+         visitElse( ifNode );
+      }
+   }
+
+   /**
+    * @param interfaceNode
+    */
+   protected void visitInterface( final IParserNode interfaceNode )
+   {
+   }
+
+   /**
+    * @param methodCallNode
+    */
+   protected void visitMethodCall( final IParserNode methodCallNode )
+   {
+      final Iterator< IParserNode > iterator = methodCallNode.getChildren().iterator();
+      visitExpression( iterator.next() );
+      do
+      {
+         visitExpressionList( iterator.next() );
+      }
+      while ( iterator.hasNext() );
+   }
+
+   /**
+    * @param newExpression
+    */
+   protected void visitNewExpression( final IParserNode newExpression )
+   {
+      visitExpression( newExpression.getChild( 0 ) );
+      visitExpressionList( newExpression.getChild( 1 ) );
+   }
+
+   protected void visitOperator( final IParserNode statementNode )
+   {
+   }
+
+   /**
+    * @param functionParametersNode
+    */
+   protected void visitParameters( final IParserNode functionParametersNode )
+   {
+      if ( isNodeNavigable( functionParametersNode ) )
+      {
+         for ( final IParserNode node2 : functionParametersNode.getChildren() )
+         {
+            visitNameTypeInit( node2.getChild( 0 ) );
+         }
+      }
+   }
+
+   protected void visitRelationalExpression( final IParserNode ast )
+   {
+      visitExpression( ast,
+                       NodeKind.RELATION,
+                       new ExpressionVisitor()
+                       {
+                          public void visitExpression( final IParserNode ast )
+                          {
+                             visitShiftExpression( ast );
+                          }
+                       } );
+   }
+
+   /**
+    * @param ast
+    */
+   protected void visitReturn( final IParserNode ast )
+   {
+      if ( isNodeNavigable( ast ) )
+      {
+         visitExpression( ast.getChild( 0 ) );
+      }
+   }
+
+   /**
+    * @param statementNode
+    */
+   protected void visitStatement( final IParserNode statementNode )
+   {
+      switch ( statementNode.getId() )
+      {
+      case OP:
+         visitOperator( statementNode );
+         break;
+      case AS:
+         visitAs( statementNode );
+         break;
+      case RETURN:
+         visitReturn( statementNode );
+         break;
+      case IF:
+         visitIf( statementNode );
+         break;
+      case FOR:
+         visitFor( statementNode );
+         break;
+      case FOREACH:
+         visitForEach( statementNode );
+         break;
+      case DO:
+         visitDo( statementNode );
+         break;
+      case WHILE:
+         visitWhile( statementNode );
+         break;
+      case SWITCH:
+         visitSwitch( statementNode );
+         break;
+      case TRY:
+         visitTry( statementNode );
+         break;
+      case CATCH:
+         visitCatch( statementNode );
+         break;
+      case FINALLY:
+         visitFinally( statementNode );
+         break;
+      case STMT_EMPTY:
+         visitEmptyStatetement( statementNode );
+         break;
+      case LEFT_CURLY_BRACKET:
+         visitBlock( statementNode );
+         break;
+      default:
+         visitExpressionList( statementNode );
+      }
+   }
+
+   /**
+    * @param switchNode
+    */
+   protected void visitSwitch( final IParserNode switchNode )
+   {
+      final Iterator< IParserNode > iterator = switchNode.getChildren().iterator();
+
+      visitExpression( iterator.next() );
+
+      final IParserNode cases = iterator.next();
+
+      for ( final IParserNode caseNode : cases.getChildren() )
+      {
+         final IParserNode child = caseNode.getChild( 0 );
+
+         if ( child.is( NodeKind.DEFAULT ) )
+         {
+            visitSwitchDefaultCase( caseNode.getChild( 1 ) );
+         }
+         else
+         {
+            visitSwitchCase( caseNode.getChild( 1 ) );
+            visitExpression( child );
+         }
+      }
+   }
+
+   /**
+    * @param switchCaseNode
+    */
+   protected void visitSwitchCase( final IParserNode switchCaseNode )
+   {
+      visitBlock( switchCaseNode );
+   }
+
+   /**
+    * @param defaultCaseNode
+    */
+   protected void visitSwitchDefaultCase( final IParserNode defaultCaseNode )
+   {
+      visitBlock( defaultCaseNode );
+   }
+
+   /**
+    * @param ifNode
+    */
+   protected void visitThen( final IParserNode ifNode )
+   {
+      visitBlock( ifNode.getChild( 1 ) );
+   }
+
+   /**
+    * @param ast
+    */
+   protected void visitTry( final IParserNode ast )
+   {
+      visitBlock( ast.getChild( 0 ) );
+   }
+
+   /**
+    * @param node
+    */
+   protected void visitVariableInitialization( final IParserNode node )
+   {
+      visitExpression( node );
+   }
+
+   /**
+    * @param variableNode
+    * @param varOrConst
+    * @param scope
+    */
+   protected void visitVarOrConstList( final IParserNode variableNode,
+                                       final VariableOrConstant varOrConst,
+                                       final VariableScope scope )
+   {
+      final Iterator< IParserNode > iterator = variableNode.getChildren().iterator();
+
+      IParserNode node = iterator.next();
+      while ( node.is( NodeKind.META_LIST )
+            || node.is( NodeKind.MOD_LIST ) )
+      {
+         node = iterator.next();
+      }
+      while ( node != null )
+      {
+         visitNameTypeInit( node );
+         node = iterator.hasNext() ? iterator.next()
+                                  : null;
+      }
+   }
+
+   /**
+    * @param whileNode
+    */
+   protected void visitWhile( final IParserNode whileNode )
+   {
+      visitCondition( whileNode.getChild( 0 ) );
+      visitBlock( whileNode.getChild( 1 ) );
+   }
+
+   private boolean isAlreadyViolationAdded( final IParserNode nodeToBeAdded )
+   {
+      for ( final IFlexViolation violation : violations )
+      {
+         if ( violation.getBeginLine() == nodeToBeAdded.getLine()
+               && violation.getBeginColumn() == nodeToBeAdded.getColumn() )
+         {
+            return true;
+         }
+      }
+      return false;
+   }
+
+   private boolean isNodeNavigable( final IParserNode node )
+   {
+      return node != null
+            && node.numChildren() != 0;
+   }
+
+   private void visitAdditiveExpression( final IParserNode ast )
+   {
+      visitExpression( ast,
+                       NodeKind.ADD,
+                       new ExpressionVisitor()
+                       {
+                          public void visitExpression( final IParserNode ast )
+                          {
+                             visitMultiplicativeExpression( ast );
+                          }
+                       } );
+   }
+
+   private void visitAndExpression( final IParserNode ast )
+   {
+      visitExpression( ast,
+                       NodeKind.AND,
+                       new ExpressionVisitor()
+                       {
+                          public void visitExpression( final IParserNode ast )
+                          {
+                             visitBitwiseOrExpression( ast );
+                          }
+                       } );
+   }
+
+   private void visitArrayAccessor( final IParserNode ast )
+   {
+      final Iterator< IParserNode > iterator = ast.getChildren().iterator();
+      visitExpression( iterator.next() );
+      do
+      {
+         visitExpression( iterator.next() );
+      }
+      while ( iterator.hasNext() );
+   }
+
+   private void visitBitwiseAndExpression( final IParserNode ast )
+   {
+      visitExpression( ast,
+                       NodeKind.B_AND,
+                       new ExpressionVisitor()
+                       {
+                          public void visitExpression( final IParserNode ast )
+                          {
+                             visitEqualityExpression( ast );
+                          }
+                       } );
+   }
+
+   private void visitBitwiseOrExpression( final IParserNode ast )
+   {
+      visitExpression( ast,
+                       NodeKind.B_OR,
+                       new ExpressionVisitor()
+                       {
+                          public void visitExpression( final IParserNode ast )
+                          {
+                             visitBitwiseXorExpression( ast );
+                          }
+                       } );
+   }
+
+   private void visitBitwiseXorExpression( final IParserNode ast )
+   {
+      visitExpression( ast,
+                       NodeKind.B_XOR,
+                       new ExpressionVisitor()
+                       {
+                          public void visitExpression( final IParserNode ast )
+                          {
+                             visitBitwiseAndExpression( ast );
+                          }
+                       } );
+   }
+
+   private void visitBlock( final IParserNode ast )
+   {
+      if ( isNodeNavigable( ast ) )
+      {
+         for ( final IParserNode node : ast.getChildren() )
+         {
+            visitStatement( node );
+         }
+      }
+      else if ( ast != null )
+      {
+         visitStatement( ast );
+      }
+   }
+
+   private void visitClassContent( final IParserNode ast )
+   {
+      if ( isNodeNavigable( ast ) )
+      {
+         for ( final IParserNode node : ast.getChildren() )
+         {
+            if ( node.is( NodeKind.VAR_LIST ) )
+            {
+               visitVarOrConstList( node,
+                                    VariableOrConstant.VARIABLE,
+                                    VariableScope.IN_CLASS );
+            }
+            else if ( node.is( NodeKind.CONST_LIST ) )
+            {
+               visitVarOrConstList( node,
+                                    VariableOrConstant.CONSTANT,
+                                    VariableScope.IN_CLASS );
+            }
+         }
+         for ( final IParserNode node : ast.getChildren() )
+         {
+            if ( node.is( NodeKind.FUNCTION ) )
+            {
+               visitFunction( node,
+                              FunctionType.NORMAL );
+            }
+            else if ( node.is( NodeKind.SET ) )
+            {
+               visitFunction( node,
+                              FunctionType.SETTER );
+            }
+            else if ( node.is( NodeKind.GET ) )
+            {
+               visitFunction( node,
+                              FunctionType.GETTER );
+            }
+         }
+      }
+   }
+
+   private void visitCompilationUnit( final IParserNode ast )
+   {
+      for ( final IParserNode node : ast.getChildren() )
+      {
+         if ( node.is( NodeKind.PACKAGE )
+               && node.numChildren() >= 2 )
+         {
+            visitPackageContent( node.getChild( 1 ) );
+         }
+         if ( !node.is( NodeKind.PACKAGE )
+               && node.numChildren() > 0 )
+         {
+            visitPackageContent( node );
+         }
+      }
+   }
+
+   private void visitConditionalExpression( final IParserNode ast )
+   {
+      if ( ast != null )
+      {
+         if ( ast.is( NodeKind.CONDITIONAL ) )
+         {
+            final Iterator< IParserNode > iterator = ast.getChildren().iterator();
+            final IParserNode node = iterator.next();
+
+            visitOrExpression( node );
+
+            while ( iterator.hasNext() )
+            {
+               visitExpression( iterator.next() );
+               visitExpression( iterator.next() );
+            }
+         }
+         else
+         {
+            visitOrExpression( ast );
+         }
+      }
+   }
+
+   private void visitEqualityExpression( final IParserNode ast )
+   {
+      visitExpression( ast,
+                       NodeKind.EQUALITY,
+                       new ExpressionVisitor()
+                       {
+                          public void visitExpression( final IParserNode ast )
+                          {
+                             visitRelationalExpression( ast );
+                          }
+                       } );
+   }
+
+   private void visitExpression( final IParserNode ast )
+   {
+      visitExpression( ast,
+                       NodeKind.ASSIGN,
+                       new ExpressionVisitor()
+                       {
+                          public void visitExpression( final IParserNode ast )
+                          {
+                             visitConditionalExpression( ast );
+                          }
+                       } );
+   }
+
+   private void visitExpression( final IParserNode ast,
+                                 final NodeKind kind,
+                                 final ExpressionVisitor visitor )
+   {
+      if ( ast.is( kind ) )
+      {
+         final Iterator< IParserNode > iterator = ast.getChildren().iterator();
+         final IParserNode node = iterator.next();
+
+         visitor.visitExpression( node );
+
+         while ( iterator.hasNext() )
+         {
+            iterator.next();
+            visitor.visitExpression( iterator.next() );
+         }
+      }
+      else
+      {
+         visitor.visitExpression( ast );
+      }
+   }
+
+   private void visitExpressionList( final IParserNode ast )
+   {
+      if ( isNodeNavigable( ast ) )
+      {
+         for ( final IParserNode node : ast.getChildren() )
+         {
+            visitExpression( node );
+         }
+      }
+   }
+
+   private void visitFunctionBody( final IParserNode node )
+   {
+      visitBlock( node );
+   }
+
+   private void visitMultiplicativeExpression( final IParserNode ast )
+   {
+      visitExpression( ast,
+                       NodeKind.MULTIPLICATION,
+                       new ExpressionVisitor()
+                       {
+                          public void visitExpression( final IParserNode ast )
+                          {
+                             visitUnaryExpression( ast );
+                          }
+                       } );
+   }
+
+   private void visitNameTypeInit( final IParserNode ast )
+   {
+      if ( ast != null
+            && ast.numChildren() != 0 )
+      {
+         final Iterator< IParserNode > iterator = ast.getChildren().iterator();
+         IParserNode node;
+
+         iterator.next();
+         iterator.next();
+
+         if ( iterator.hasNext() )
+         {
+            node = iterator.next();
+            visitVariableInitialization( node );
+         }
+      }
+   }
+
+   private void visitObjectInitialization( final IParserNode ast )
+   {
+      if ( isNodeNavigable( ast ) )
+      {
+         for ( final IParserNode node : ast.getChildren() )
+         {
+            visitExpression( node.getChild( 1 ) );
+         }
+      }
+   }
+
+   private void visitOrExpression( final IParserNode ast )
+   {
+      visitExpression( ast,
+                       NodeKind.OR,
+                       new ExpressionVisitor()
+                       {
+                          public void visitExpression( final IParserNode ast )
+                          {
+                             visitAndExpression( ast );
+                          }
+                       } );
+   }
+
+   private void visitPackageContent( final IParserNode ast )
+   {
+      if ( isNodeNavigable( ast ) )
+      {
+         for ( final IParserNode node : ast.getChildren() )
+         {
+            if ( node.is( NodeKind.CLASS ) )
+            {
+               visitClass( node );
+            }
+            else if ( node.is( NodeKind.INTERFACE ) )
+            {
+               visitInterface( node );
+            }
+         }
+      }
+   }
+
+   private void visitPrimaryExpression( final IParserNode ast )
+   {
+      if ( ast.is( NodeKind.NEW ) )
+      {
+         visitNewExpression( ast );
+      }
+      else if ( ast.numChildren() != 0
+            && ast.is( NodeKind.ARRAY ) )
+      {
+         visitExpressionList( ast );
+      }
+      else if ( ast.is( NodeKind.OBJECT ) )
+      {
+         visitObjectInitialization( ast );
+      }
+      else if ( ast.is( NodeKind.E4X_ATTR ) )
+      {
+         final IParserNode node = ast.getChild( 0 );
+
+         if ( !node.is( NodeKind.NAME )
+               && !node.is( NodeKind.STAR ) )
+         {
+            visitExpression( node );
+         }
+      }
+      else
+      {
+         visitExpressionList( ast );
+      }
+   }
+
+   private void visitShiftExpression( final IParserNode ast )
+   {
+      visitExpression( ast,
+                       NodeKind.SHIFT,
+                       new ExpressionVisitor()
+                       {
+                          public void visitExpression( final IParserNode ast )
+                          {
+                             visitAdditiveExpression( ast );
+                          }
+                       } );
+   }
+
+   private void visitUnaryExpression( final IParserNode ast )
+   {
+      switch ( ast.getId() )
+      {
+      case PRE_INC:
+      case PRE_DEC:
+      case MINUS:
+      case PLUS:
+         visitUnaryExpression( ast.getChild( 0 ) );
+         break;
+      default:
+         visitUnaryExpressionNotPlusMinus( ast );
+      }
+   }
+
+   private void visitUnaryExpressionNotPlusMinus( final IParserNode ast )
+   {
+      switch ( ast.getId() )
+      {
+      case DELETE:
+      case VOID:
+      case TYPEOF:
+      case NOT:
+      case B_NOT:
+         visitExpression( ast.getChild( 0 ) );
+         break;
+      default:
+         visitUnaryPostfixExpression( ast );
+      }
+   }
+
+   private void visitUnaryPostfixExpression( final IParserNode ast )
+   {
+      switch ( ast.getId() )
+      {
+      case ARRAY_ACCESSOR:
+         visitArrayAccessor( ast );
+         break;
+      case DOT:
+      case E4X_FILTER:
+         visitExpression( ast.getChild( 0 ) );
+         visitExpression( ast.getChild( 1 ) );
+         break;
+      case POST_INC:
+      case POST_DEC:
+         visitPrimaryExpression( ast.getChild( 0 ) );
+         break;
+      case CALL:
+         visitMethodCall( ast );
+         break;
+      case E4X_STAR:
+         visitExpression( ast.getChild( 0 ) );
+         break;
+      default:
+         visitPrimaryExpression( ast );
+         break;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRuleTest.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRuleTest.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRuleTest.java
new file mode 100644
index 0000000..35aa5e6
--- /dev/null
+++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractAstFlexRuleTest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.adobe.ac.pmd.rules.core;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.adobe.ac.pmd.IFlexViolation;
+import com.adobe.ac.pmd.files.IAs3File;
+import com.adobe.ac.pmd.files.IFlexFile;
+import com.adobe.ac.pmd.files.IMxmlFile;
+import com.adobe.ac.pmd.nodes.IPackage;
+import com.adobe.ac.pmd.nodes.impl.NodeFactory;
+import com.adobe.ac.pmd.parser.IAS3Parser;
+import com.adobe.ac.pmd.parser.exceptions.TokenException;
+
+import de.bokelberg.flex.parser.AS3Parser;
+
+public abstract class AbstractAstFlexRuleTest extends AbstractFlexRuleTest
+{
+   @Override
+   protected List< IFlexViolation > processFile( final String resourcePath ) throws IOException,
+                                                                            TokenException
+   {
+      if ( !getIgnoreFiles().contains( resourcePath ) )
+      {
+         final IAS3Parser parser = new AS3Parser();
+         final IFlexFile file = getTestFiles().get( resourcePath );
+
+         IPackage rootNode = null;
+
+         if ( file == null )
+         {
+            throw new IOException( resourcePath
+                  + " is not found" );
+         }
+         if ( file instanceof IAs3File )
+         {
+            rootNode = NodeFactory.createPackage( parser.buildAst( file.getFilePath() ) );
+         }
+         else
+         {
+            rootNode = NodeFactory.createPackage( parser.buildAst( file.getFilePath(),
+                                                                   ( ( IMxmlFile ) file ).getScriptBlock() ) );
+         }
+         return getRule().processFile( file,
+                                       rootNode,
+                                       getTestFiles() );
+      }
+      return new ArrayList< IFlexViolation >();
+   }
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexMetaDataRule.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexMetaDataRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexMetaDataRule.java
new file mode 100644
index 0000000..a1f0552
--- /dev/null
+++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexMetaDataRule.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.adobe.ac.pmd.rules.core;
+
+import java.util.List;
+
+import com.adobe.ac.pmd.nodes.IAttribute;
+import com.adobe.ac.pmd.nodes.IClass;
+import com.adobe.ac.pmd.nodes.IFunction;
+import com.adobe.ac.pmd.nodes.IMetaDataListHolder;
+
+/**
+ * @author xagnetti
+ */
+public abstract class AbstractFlexMetaDataRule extends AbstractAstFlexRule
+{
+   /*
+    * (non-Javadoc)
+    * @see
+    * com.adobe.ac.pmd.rules.core.AbstractAstFlexRule#findViolations(com.adobe
+    * .ac.pmd.nodes.IClass)
+    */
+   @Override
+   protected final void findViolations( final IClass classNode )
+   {
+      super.findViolations( classNode );
+
+      if ( classNode.getMetaDataCount() > 0 )
+      {
+         findViolationsFromMetaDataList( classNode );
+         findViolationsFromClassMetaData( classNode );
+      }
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see
+    * com.adobe.ac.pmd.rules.core.AbstractAstFlexRule#findViolations(com.adobe
+    * .ac.pmd.nodes.IFunction)
+    */
+   @Override
+   protected final void findViolations( final IFunction function )
+   {
+      if ( function.getMetaDataCount() > 0 )
+      {
+         findViolationsFromMetaDataList( function );
+         findViolationsFromFunctionMetaData( function );
+      }
+   }
+
+   /**
+    * @param function
+    */
+   protected void findViolationsFromAttributeMetaData( final IAttribute attribute )
+   {
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see
+    * com.adobe.ac.pmd.rules.core.AbstractAstFlexRule#findViolationsFromAttributes
+    * (java.util.List)
+    */
+   @Override
+   protected final void findViolationsFromAttributes( final List< IAttribute > variables )
+   {
+      for ( final IAttribute attribute : variables )
+      {
+         if ( attribute.getMetaDataCount() > 0 )
+         {
+            findViolationsFromMetaDataList( attribute );
+            findViolationsFromAttributeMetaData( attribute );
+         }
+      }
+   }
+
+   /**
+    * @param classNode
+    */
+   protected void findViolationsFromClassMetaData( final IClass classNode )
+   {
+   }
+
+   /**
+    * @param function
+    */
+   protected void findViolationsFromFunctionMetaData( final IFunction function )
+   {
+   }
+
+   /**
+    * @param holder
+    */
+   protected void findViolationsFromMetaDataList( final IMetaDataListHolder holder )
+   {
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRule.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRule.java
new file mode 100644
index 0000000..2611ccf
--- /dev/null
+++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRule.java
@@ -0,0 +1,354 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.adobe.ac.pmd.rules.core;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+import net.sourceforge.pmd.CommonAbstractRule;
+import net.sourceforge.pmd.PropertyDescriptor;
+import net.sourceforge.pmd.RuleContext;
+import net.sourceforge.pmd.properties.IntegerProperty;
+import net.sourceforge.pmd.rules.regex.RegexHelper;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.adobe.ac.pmd.IFlexViolation;
+import com.adobe.ac.pmd.files.IFlexFile;
+import com.adobe.ac.pmd.nodes.IPackage;
+import com.adobe.ac.pmd.rules.core.thresholded.IThresholdedRule;
+
+/**
+ * Abstract FlexPMD rule. Extends this class if you want to find violations at a
+ * very low level. Otherwise extends AbstractAstFlexRule, or
+ * AbstractRegexpBasedRule.
+ * 
+ * @author xagnetti
+ */
+public abstract class AbstractFlexRule extends CommonAbstractRule implements IFlexRule
+{
+   protected static final String    MAXIMUM            = "maximum";
+   protected static final String    MINIMUM            = "minimum";
+   private static final String      AS3_COMMENT_TOKEN  = "//";
+   private static final Logger      LOGGER             = Logger.getLogger( AbstractFlexRule.class.getName() );
+   private static final String      MXML_COMMENT_TOKEN = "<!--";
+   private IFlexFile                currentFile;
+   private IPackage                 currentPackageNode;
+   private Set< String >            excludes;
+   private Map< String, IFlexFile > filesInSourcePath;
+
+   /**
+    * 
+    */
+   public AbstractFlexRule()
+   {
+      super();
+
+      setDefaultPriority();
+   }
+
+   /**
+    * not used in FlexPMD
+    */
+   public final void apply( final List< ? > astCompilationUnits,
+                            final RuleContext ctx )
+   {
+   }
+
+   /**
+    * @return Extracts the rulename from the qualified name of the underlying
+    *         class
+    */
+   public final String getRuleName()
+   {
+      final String qualifiedClassName = this.getClass().getName();
+      final String className = StringUtils.substringAfter( qualifiedClassName,
+                                                           "." );
+
+      return className.replace( "Rule",
+                                "" );
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see
+    * com.adobe.ac.pmd.rules.core.IFlexRule#processFile(com.adobe.ac.pmd.files
+    * .IFlexFile, com.adobe.ac.pmd.nodes.IPackage, java.util.Map)
+    */
+   public final List< IFlexViolation > processFile( final IFlexFile file,
+                                                    final IPackage packageNode,
+                                                    final Map< String, IFlexFile > files )
+   {
+      List< IFlexViolation > violations = new ArrayList< IFlexViolation >();
+
+      currentFile = file;
+      filesInSourcePath = files;
+      currentPackageNode = packageNode;
+
+      if ( isConcernedByTheCurrentFile()
+            && !isFileExcluded( file ) )
+      {
+         onRuleStart();
+         violations = findViolationsInCurrentFile();
+      }
+
+      return violations;
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see com.adobe.ac.pmd.rules.core.IFlexRule#setExcludes(java.util.Set)
+    */
+   public void setExcludes( final Set< String > excludesToBeSet )
+   {
+      excludes = excludesToBeSet;
+   }
+
+   /**
+    * @param violatedLine
+    * @return
+    */
+   boolean isViolationIgnored( final String violatedLine )
+   {
+      final boolean containsNoPmd = lineContainsNoPmd( violatedLine,
+                                                       MXML_COMMENT_TOKEN )
+            || lineContainsNoPmd( violatedLine,
+                                  AS3_COMMENT_TOKEN );
+
+      if ( !containsNoPmd )
+      {
+         return false;
+      }
+      final String name = getRuleName().replaceAll( "Rule",
+                                                    "" );
+      final String ruleName = name.contains( "." ) ? StringUtils.substringAfterLast( name,
+                                                                                     "." )
+                                                  : name;
+      final String strippedLine = computeStrippedLine( violatedLine );
+      return strippedLineContainsNoPmdAndRuleName( MXML_COMMENT_TOKEN,
+                                                   ruleName,
+                                                   strippedLine )
+            || strippedLineContainsNoPmdAndRuleName( AS3_COMMENT_TOKEN,
+                                                     ruleName,
+                                                     strippedLine );
+   }
+
+   /**
+    * @param violations
+    * @param position
+    * @return
+    */
+   protected final IFlexViolation addViolation( final List< IFlexViolation > violations,
+                                                final ViolationPosition position )
+   {
+      final IFlexViolation violation = new Violation( position, this, getCurrentFile() );
+      final int beginLine = position.getBeginLine();
+
+      prettyPrintMessage( violation );
+
+      if ( beginLine == -1
+            || beginLine == 0 )
+      {
+         violations.add( violation );
+      }
+      else if ( beginLine <= getCurrentFile().getLinesNb() )
+      {
+         if ( isViolationIgnored( getCurrentFile().getLineAt( beginLine ) ) )
+         {
+            LOGGER.info( getRuleName()
+                  + " has been ignored in " + getCurrentFile().getFilename() + " (" + beginLine + ")" );
+         }
+         else
+         {
+            violations.add( violation );
+         }
+      }
+
+      return violation;
+   }
+
+   protected final IFlexViolation addViolation( final List< IFlexViolation > violations,
+                                                final ViolationPosition position,
+                                                final String... messageToReplace )
+   {
+      final IFlexViolation violation = addViolation( violations,
+                                                     position );
+
+      for ( int i = 0; i < messageToReplace.length; i++ )
+      {
+         violation.replacePlaceholderInMessage( messageToReplace[ i ],
+                                                i );
+      }
+
+      return violation;
+   }
+
+   /**
+    * @return
+    */
+   protected abstract List< IFlexViolation > findViolationsInCurrentFile();
+
+   /**
+    * @return the current file under investigation
+    */
+   protected IFlexFile getCurrentFile()
+   {
+      return currentFile;
+   }
+
+   /**
+    * @return
+    */
+   protected final IPackage getCurrentPackageNode()
+   {
+      return currentPackageNode;
+   }
+
+   /**
+    * @return
+    */
+   protected abstract ViolationPriority getDefaultPriority();
+
+   /**
+    * @return
+    */
+   protected final Map< String, IFlexFile > getFilesInSourcePath()
+   {
+      return filesInSourcePath;
+   }
+
+   /**
+    * @param rule
+    * @return
+    */
+   protected final Map< String, PropertyDescriptor > getThresholdedRuleProperties( final IThresholdedRule rule )
+   {
+      final Map< String, PropertyDescriptor > properties = new LinkedHashMap< String, PropertyDescriptor >();
+
+      properties.put( rule.getThresholdName(),
+                      new IntegerProperty( rule.getThresholdName(),
+                                           "",
+                                           rule.getDefaultThreshold(),
+                                           properties.size() ) );
+
+      return properties;
+   }
+
+   /**
+    * @return is this rule concerned by the current file
+    */
+   protected abstract boolean isConcernedByTheCurrentFile();
+
+   /**
+    * Called when the rule is started on the current file
+    */
+   protected void onRuleStart()
+   {
+   }
+
+   private String computeStrippedLine( final String violatedLine )
+   {
+      final String comment_token = getCurrentFile().isMxml() ? MXML_COMMENT_TOKEN
+                                                            : AS3_COMMENT_TOKEN;
+      String strippedLine = violatedLine;
+
+      if ( violatedLine.indexOf( comment_token
+            + " N" ) > 0 )
+      {
+         strippedLine = StringUtils.strip( violatedLine.substring( violatedLine.indexOf( comment_token
+               + " N" ) ) );
+      }
+      else if ( violatedLine.indexOf( comment_token
+            + "N" ) > 0 )
+      {
+         strippedLine = StringUtils.strip( violatedLine.substring( violatedLine.indexOf( comment_token
+               + "N" ) ) );
+      }
+      return strippedLine;
+   }
+
+   private boolean isFileExcluded( final IFlexFile file )
+   {
+      if ( excludes != null )
+      {
+         for ( final String exclusion : excludes )
+         {
+            final Pattern pattern = Pattern.compile( exclusion );
+
+            if ( RegexHelper.isMatch( pattern,
+                                      file.getFilePath() ) )
+            {
+               return true;
+            }
+         }
+      }
+      return false;
+   }
+
+   private boolean lineContainsNoPmd( final String violatedLine,
+                                      final String comment_token )
+   {
+      return violatedLine.contains( comment_token
+            + " No PMD" )
+            || violatedLine.contains( comment_token
+                  + " NO PMD" ) || violatedLine.contains( comment_token
+                  + " NOPMD" ) || violatedLine.contains( comment_token
+                  + "NOPMD" );
+   }
+
+   private void prettyPrintMessage( final IFlexViolation violation )
+   {
+      final int nbOfBraces = violation.getRuleMessage().split( "\\{" ).length - 1;
+
+      if ( this instanceof IThresholdedRule )
+      {
+         final IThresholdedRule thresholdeRule = ( IThresholdedRule ) this;
+
+         violation.replacePlaceholderInMessage( String.valueOf( thresholdeRule.getThreshold() ),
+                                                nbOfBraces - 2 );
+         violation.replacePlaceholderInMessage( String.valueOf( thresholdeRule.getActualValueForTheCurrentViolation() ),
+                                                nbOfBraces - 1 );
+      }
+      if ( getDescription() != null )
+      {
+         violation.appendToMessage( ". " );
+         violation.appendToMessage( getDescription() );
+      }
+   }
+
+   private void setDefaultPriority()
+   {
+      setPriority( Integer.valueOf( getDefaultPriority().toString() ) );
+   }
+
+   private boolean strippedLineContainsNoPmdAndRuleName( final String comment_token,
+                                                         final String ruleName,
+                                                         final String strippedLine )
+   {
+      return strippedLine.endsWith( comment_token
+            + " No PMD" )
+            || strippedLine.endsWith( comment_token
+                  + " NO PMD" ) || strippedLine.endsWith( comment_token
+                  + " NOPMD" ) || strippedLine.endsWith( comment_token
+                  + "NOPMD" ) || strippedLine.contains( ruleName );
+   }
+}

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRuleTest.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRuleTest.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRuleTest.java
new file mode 100644
index 0000000..ac44b0c
--- /dev/null
+++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractFlexRuleTest.java
@@ -0,0 +1,264 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.adobe.ac.pmd.rules.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+
+import com.adobe.ac.pmd.FlexPmdTestBase;
+import com.adobe.ac.pmd.IFlexViolation;
+import com.adobe.ac.pmd.files.IFlexFile;
+import com.adobe.ac.pmd.parser.exceptions.TokenException;
+
+public abstract class AbstractFlexRuleTest extends FlexPmdTestBase
+{
+   final static class AssertPosition
+   {
+      public static AssertPosition create( final String message,
+                                           final int expectedLine,
+                                           final int actualLine )
+      {
+         return new AssertPosition( message, expectedLine, actualLine );
+      }
+
+      public int    actualLine;
+      public int    expectedLine;
+      public String message;
+
+      private AssertPosition( final String messageToBeSet,
+                              final int expectedLineToBeSet,
+                              final int actualLineToBeSet )
+      {
+         super();
+         message = messageToBeSet;
+         expectedLine = expectedLineToBeSet;
+         actualLine = actualLineToBeSet;
+      }
+   }
+
+   protected final static class ExpectedViolation
+   {
+      protected String              file;
+      protected ViolationPosition[] positions;
+
+      public ExpectedViolation( final String fileToBeSet,
+                                final ViolationPosition[] positionsToBeSet )
+      {
+         super();
+         file = fileToBeSet;
+         positions = positionsToBeSet;
+      }
+   }
+
+   protected static StringBuffer buildFailuresMessage( final List< AssertPosition > failures )
+   {
+      final StringBuffer message = new StringBuffer( 42 );
+
+      for ( final AssertPosition assertPosition : failures )
+      {
+         message.append( assertPosition.message
+               + ": expected <" + assertPosition.expectedLine + "> but actually <"
+               + assertPosition.actualLine + ">\n" );
+      }
+      return message;
+   }
+
+   protected static List< AssertPosition > buildFailureViolations( final String resourcePath,
+                                                                   final ViolationPosition[] expectedPositions,
+                                                                   final List< IFlexViolation > violations )
+   {
+      List< AssertPosition > failures;
+      failures = new ArrayList< AssertPosition >();
+
+      for ( int i = 0; i < expectedPositions.length; i++ )
+      {
+         final IFlexViolation violation = violations.get( i );
+         final ViolationPosition expectedPosition = expectedPositions[ i ];
+
+         if ( expectedPosition.getBeginLine() != violation.getBeginLine() )
+         {
+            failures.add( AssertPosition.create( BEGIN_LINE_NOT_CORRECT
+                                                       + " at " + i + "th violation on " + resourcePath,
+                                                 expectedPosition.getBeginLine(),
+                                                 violation.getBeginLine() ) );
+         }
+         if ( expectedPosition.getEndLine() != violation.getEndLine() )
+         {
+            failures.add( AssertPosition.create( END_LINE_NOT_CORRECT
+                                                       + " at " + i + "th violation on " + resourcePath,
+                                                 expectedPosition.getEndLine(),
+                                                 violation.getEndLine() ) );
+         }
+      }
+      return failures;
+   }
+
+   protected static StringBuffer buildMessageName( final Map< String, List< IFlexViolation >> violatedFiles )
+   {
+      final StringBuffer buffer = new StringBuffer( 100 );
+
+      for ( final String violatedFileName : violatedFiles.keySet() )
+      {
+         final List< IFlexViolation > violations = violatedFiles.get( violatedFileName );
+
+         buffer.append( violatedFileName
+               + " should not contain any violations " + " (" + violations.size() + " found" );
+
+         if ( violations.size() == 1 )
+         {
+            buffer.append( " at "
+                  + violations.get( 0 ).getBeginLine() + ":" + violations.get( 0 ).getEndLine() );
+         }
+         buffer.append( ")\n" );
+      }
+      return buffer;
+   }
+
+   /**
+    * Test case which contains non-concerned files by the given rule
+    * 
+    * @throws TokenException
+    * @throws IOException
+    */
+   @Test
+   public final void testProcessNonViolatingFiles() throws IOException,
+                                                   TokenException
+   {
+      final Map< String, List< IFlexViolation >> violatedFiles = extractActualViolatedFiles();
+      final StringBuffer buffer = buildMessageName( violatedFiles );
+
+      if ( !violatedFiles.isEmpty() )
+      {
+         fail( buffer.toString() );
+      }
+   }
+
+   /**
+    * Test case which contains violating files
+    */
+   @Test
+   public final void testProcessViolatingFiles()
+   {
+      final Map< String, ViolationPosition[] > expectedPositions = computeExpectedViolations( getExpectedViolatingFiles() );
+
+      for ( final String fileName : expectedPositions.keySet() )
+      {
+         assertViolations( fileName,
+                           expectedPositions.get( fileName ) );
+      }
+   }
+
+   protected abstract ExpectedViolation[] getExpectedViolatingFiles();
+
+   protected List< String > getIgnoreFiles()
+   {
+      return new ArrayList< String >();
+   }
+
+   protected abstract AbstractFlexRule getRule();
+
+   protected List< IFlexViolation > processFile( final String resourcePath ) throws IOException,
+                                                                            TokenException
+   {
+      if ( !getIgnoreFiles().contains( resourcePath ) )
+      {
+         return getRule().processFile( getTestFiles().get( resourcePath ),
+                                       null,
+                                       getTestFiles() );
+      }
+      return new ArrayList< IFlexViolation >();
+   }
+
+   private void assertViolations( final String resourcePath,
+                                  final ViolationPosition[] expectedPositions )
+   {
+      try
+      {
+         final List< IFlexViolation > violations = processFile( resourcePath );
+
+         assertEquals( VIOLATIONS_NUMBER_NOT_CORRECT
+                             + " for " + resourcePath,
+                       expectedPositions.length,
+                       violations.size() );
+
+         if ( expectedPositions.length != 0 )
+         {
+            printFailures( buildFailureViolations( resourcePath,
+                                                   expectedPositions,
+                                                   violations ) );
+         }
+      }
+      catch ( final IOException e )
+      {
+         fail( e.getMessage() );
+      }
+      catch ( final TokenException e )
+      {
+         fail( e.getMessage() );
+      }
+   }
+
+   private Map< String, ViolationPosition[] > computeExpectedViolations( final ExpectedViolation[] expectedViolatingFiles )
+   {
+      final Map< String, ViolationPosition[] > expectedViolations = new LinkedHashMap< String, ViolationPosition[] >();
+
+      for ( final ExpectedViolation expectedViolatingFile : expectedViolatingFiles )
+      {
+         expectedViolations.put( expectedViolatingFile.file,
+                                 expectedViolatingFile.positions );
+      }
+      return expectedViolations;
+   }
+
+   private Map< String, List< IFlexViolation >> extractActualViolatedFiles() throws IOException,
+                                                                            TokenException
+   {
+      final Map< String, List< IFlexViolation > > violatedFiles = new LinkedHashMap< String, List< IFlexViolation > >();
+      final Map< String, ViolationPosition[] > expectedPositions = computeExpectedViolations( getExpectedViolatingFiles() );
+
+      for ( final Map.Entry< String, IFlexFile > fileNameEntry : getTestFiles().entrySet() )
+      {
+         if ( !expectedPositions.containsKey( fileNameEntry.getKey() ) )
+         {
+            final List< IFlexViolation > violations = processFile( fileNameEntry.getKey() );
+
+            if ( !violations.isEmpty() )
+            {
+               violatedFiles.put( fileNameEntry.getKey(),
+                                  violations );
+            }
+         }
+      }
+      return violatedFiles;
+   }
+
+   private void printFailures( final List< AssertPosition > failures )
+   {
+      if ( !failures.isEmpty() )
+      {
+         fail( buildFailuresMessage( failures ).toString() );
+      }
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractForbiddenImportRule.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractForbiddenImportRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractForbiddenImportRule.java
new file mode 100644
index 0000000..5c54876
--- /dev/null
+++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractForbiddenImportRule.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.adobe.ac.pmd.rules.core;
+
+import com.adobe.ac.pmd.nodes.IPackage;
+import com.adobe.ac.pmd.parser.IParserNode;
+
+/**
+ * @author xagnetti
+ */
+public abstract class AbstractForbiddenImportRule extends AbstractAstFlexRule
+{
+
+   /**
+    * 
+    */
+   public AbstractForbiddenImportRule()
+   {
+      super();
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see
+    * com.adobe.ac.pmd.rules.core.AbstractAstFlexRule#findViolations(com.adobe
+    * .ac.pmd.nodes.IPackage)
+    */
+   @Override
+   protected final void findViolations( final IPackage packageNode )
+   {
+      for ( final IParserNode importNode : packageNode.getImports() )
+      {
+         if ( importNode.getStringValue().contains( getForbiddenImport() ) )
+         {
+            addViolation( importNode );
+         }
+      }
+   }
+
+   /**
+    * @return
+    */
+   protected abstract String getForbiddenImport();
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractPrimaryAstRule.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractPrimaryAstRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractPrimaryAstRule.java
new file mode 100644
index 0000000..7479a2a
--- /dev/null
+++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractPrimaryAstRule.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.adobe.ac.pmd.rules.core;
+
+import java.util.List;
+
+import com.adobe.ac.pmd.nodes.IFunction;
+import com.adobe.ac.pmd.parser.IParserNode;
+
+/**
+ * Abstract rule which find a primary (or a couple of primaries) in a body
+ * function.
+ * 
+ * @author xagnetti
+ */
+public abstract class AbstractPrimaryAstRule extends AbstractAstFlexRule
+{
+   /**
+    * @param statement
+    * @param function
+    */
+   protected abstract void addViolation( IParserNode statement,
+                                         IFunction function );
+
+   /*
+    * (non-Javadoc)
+    * @see
+    * com.adobe.ac.pmd.rules.core.AbstractAstFlexRule#findViolations(com.adobe
+    * .ac.pmd.nodes.IFunction)
+    */
+   @Override
+   protected final void findViolations( final IFunction function )
+   {
+      final List< IParserNode > firstStatements = function.findPrimaryStatementsInBody( getFirstPrimaryToFind() );
+      if ( !firstStatements.isEmpty() )
+      {
+         for ( final IParserNode firstStatement : firstStatements )
+         {
+            if ( getSecondPrimaryToFind() == null )
+            {
+               addViolation( firstStatement,
+                             function );
+            }
+            else
+            {
+               final List< IParserNode > secondStatements = function.findPrimaryStatementsInBody( getSecondPrimaryToFind() );
+               if ( !secondStatements.isEmpty() )
+               {
+                  for ( final IParserNode secondStatement : secondStatements )
+                  {
+                     addViolation( secondStatement,
+                                   function );
+                  }
+               }
+            }
+         }
+      }
+   }
+
+   /**
+    * @return
+    */
+   protected abstract String getFirstPrimaryToFind();
+
+   /**
+    * @return
+    */
+   protected String getSecondPrimaryToFind()
+   {
+      return null;
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegExpBasedRuleTest.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegExpBasedRuleTest.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegExpBasedRuleTest.java
new file mode 100644
index 0000000..527e1cf
--- /dev/null
+++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegExpBasedRuleTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.adobe.ac.pmd.rules.core;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import junit.framework.Assert;
+
+import org.junit.Test;
+
+public abstract class AbstractRegExpBasedRuleTest extends AbstractFlexRuleTest
+{
+   @Test
+   public void testDoesCurrentLineMacthCorrectLine()
+   {
+      final AbstractRegexpBasedRule rule = getRegexpBasedRule();
+
+      if ( getMatchableLines().length == 0 )
+      {
+         Assert.fail( "the getMatchableLines() is empty" );
+      }
+      for ( int i = 0; i < getMatchableLines().length; i++ )
+      {
+         final String correctLine = getMatchableLines()[ i ];
+
+         assertTrue( "This line (\""
+                           + correctLine + "\") should be matched",
+                     rule.doesCurrentLineMacthes( correctLine ) );
+      }
+   }
+
+   @Test
+   public void testDoesCurrentLineMacthIncorrectLine()
+   {
+      final AbstractRegexpBasedRule rule = getRegexpBasedRule();
+
+      if ( getUnmatchableLines().length == 0 )
+      {
+         Assert.fail( "the getUnmatchableLines() is empty" );
+      }
+      for ( int i = 0; i < getUnmatchableLines().length; i++ )
+      {
+         final String incorrectLine = getUnmatchableLines()[ i ];
+
+         assertFalse( "This line  (\""
+                            + incorrectLine + "\") should not be matched",
+                      rule.doesCurrentLineMacthes( incorrectLine ) );
+      }
+   }
+
+   protected abstract String[] getMatchableLines();
+
+   protected abstract AbstractRegexpBasedRule getRegexpBasedRule();
+
+   @Override
+   protected AbstractFlexRule getRule()
+   {
+      return getRegexpBasedRule();
+   }
+
+   protected abstract String[] getUnmatchableLines();
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegexpBasedRule.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegexpBasedRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegexpBasedRule.java
new file mode 100644
index 0000000..cfc71de
--- /dev/null
+++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractRegexpBasedRule.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.adobe.ac.pmd.rules.core;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.adobe.ac.pmd.IFlexViolation;
+
+/**
+ * @author xagnetti
+ */
+public abstract class AbstractRegexpBasedRule extends AbstractFlexRule
+{
+   private Pattern pattern;
+
+   /**
+    * 
+    */
+   public AbstractRegexpBasedRule()
+   {
+      super();
+      compilePattern();
+   }
+
+   /**
+    * 
+    */
+   public final void compilePattern()
+   {
+      pattern = Pattern.compile( getRegexp() );
+   }
+
+   /*
+    * (non-Javadoc)
+    * @see
+    * com.adobe.ac.pmd.rules.core.AbstractFlexRule#findViolationsInCurrentFile()
+    */
+   @Override
+   public final List< IFlexViolation > findViolationsInCurrentFile()
+   {
+      final List< IFlexViolation > violations = new ArrayList< IFlexViolation >();
+
+      if ( "".compareTo( getRegexp() ) != 0 )
+      {
+         for ( int i = 1; i <= getCurrentFile().getLinesNb(); i++ )
+         {
+            final String line = getCurrentFile().getLineAt( i );
+
+            if ( isCurrentLineConcerned( line )
+                  && doesCurrentLineMacthes( line ) && isViolationDetectedOnThisMatchingLine( line )
+                  && !line.contains( "/*" ) && !line.contains( "//" ) )
+            {
+               addViolation( violations,
+                             ViolationPosition.create( i,
+                                                       i,
+                                                       0,
+                                                       line.length() ) );
+            }
+         }
+      }
+      return violations;
+   }
+
+   /**
+    * @param line
+    * @return
+    */
+   final boolean doesCurrentLineMacthes( final String line )
+   {
+      return getMatcher( line ).matches();
+   }
+
+   /**
+    * @param line
+    * @return
+    */
+   protected final Matcher getMatcher( final String line )
+   {
+      final Matcher matcher = pattern.matcher( line );
+
+      return matcher;
+   }
+
+   /**
+    * @return
+    */
+   protected abstract String getRegexp();
+
+   protected boolean isCurrentLineConcerned( final String line )
+   {
+      return true;
+   }
+
+   /**
+    * @param line
+    * @return
+    */
+   protected abstract boolean isViolationDetectedOnThisMatchingLine( final String line );
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractXpathRelatedRule.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractXpathRelatedRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractXpathRelatedRule.java
new file mode 100644
index 0000000..72dadfb
--- /dev/null
+++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/AbstractXpathRelatedRule.java
@@ -0,0 +1,244 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.adobe.ac.pmd.rules.core;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import com.adobe.ac.pmd.IFlexViolation;
+import com.adobe.ac.utils.StackTraceUtils;
+
+/**
+ * @author xagnetti
+ */
+public abstract class AbstractXpathRelatedRule extends AbstractFlexRule
+{
+   /**
+    * @author xagnetti
+    */
+   public class NamespaceContextMap implements NamespaceContext
+   {
+      private final Map< String, String > prefixMap;
+
+      /**
+       * Constructor that takes a map of XML prefix-namespaceURI values. A
+       * defensive copy is made of the map. An IllegalArgumentException will be
+       * thrown if the map attempts to remap the standard prefixes defined in
+       * the NamespaceContext contract.
+       * 
+       * @param prefixMappings a map of prefix:namespaceURI values
+       */
+      public NamespaceContextMap( final Map< String, String > prefixMappings )
+      {
+         prefixMap = createPrefixMap( prefixMappings );
+      }
+
+      /**
+       * Convenience constructor.
+       * 
+       * @param mappingPairs pairs of prefix-namespaceURI values
+       */
+      public NamespaceContextMap( final String... mappingPairs )
+      {
+         this( toMap( mappingPairs ) );
+      }
+
+      /*
+       * (non-Javadoc)
+       * @see
+       * javax.xml.namespace.NamespaceContext#getNamespaceURI(java.lang.String)
+       */
+      public String getNamespaceURI( final String prefix )
+      {
+         prefixMap.get( prefix );
+         return prefixMap.get( prefix );
+      }
+
+      /*
+       * (non-Javadoc)
+       * @see javax.xml.namespace.NamespaceContext#getPrefix(java.lang.String)
+       */
+      public String getPrefix( final String namespaceURI )
+      {
+         return null;
+      }
+
+      /*
+       * (non-Javadoc)
+       * @see javax.xml.namespace.NamespaceContext#getPrefixes(java.lang.String)
+       */
+      public Iterator< String > getPrefixes( final String namespaceURI )
+      {
+         return null;
+      }
+
+      private void addConstant( final Map< String, String > map,
+                                final String prefix,
+                                final String nsURI )
+      {
+         map.put( prefix,
+                  nsURI );
+      }
+
+      private Map< String, String > createPrefixMap( final Map< String, String > prefixMappings )
+      {
+         final Map< String, String > map = new LinkedHashMap< String, String >( prefixMappings );
+         addConstant( map,
+                      XMLConstants.XML_NS_PREFIX,
+                      XMLConstants.XML_NS_URI );
+         addConstant( map,
+                      XMLConstants.XMLNS_ATTRIBUTE,
+                      XMLConstants.XMLNS_ATTRIBUTE_NS_URI );
+         return Collections.unmodifiableMap( map );
+      }
+
+   }
+
+   protected static final Logger LOGGER = Logger.getLogger( AbstractXpathRelatedRule.class.getName() );
+
+   private static Map< String, String > toMap( final String... mappingPairs )
+   {
+      final Map< String, String > prefixMappings = new LinkedHashMap< String, String >( mappingPairs.length / 2 );
+      for ( int i = 0; i < mappingPairs.length; i++ )
+      {
+         prefixMappings.put( mappingPairs[ i ],
+                             mappingPairs[ ++i ] );
+      }
+      return prefixMappings;
+   }
+
+   /**
+    * @param doc
+    * @param xPath
+    * @return
+    * @throws XPathExpressionException
+    */
+   protected abstract Object evaluate( final Document doc,
+                                       final XPath xPath ) throws XPathExpressionException;
+
+   /*
+    * (non-Javadoc)
+    * @see
+    * com.adobe.ac.pmd.rules.core.AbstractFlexRule#findViolationsInCurrentFile()
+    */
+   @Override
+   protected List< IFlexViolation > findViolationsInCurrentFile()
+   {
+      final ArrayList< IFlexViolation > violations = new ArrayList< IFlexViolation >();
+
+      try
+      {
+         final Document doc = buildDocument();
+         final XPath xPath = buildXPath();
+
+         onEvaluated( violations,
+                      doc,
+                      xPath );
+      }
+      catch ( final XPathExpressionException e )
+      {
+         LOGGER.warning( StackTraceUtils.print( getCurrentFile().getFilename(),
+                                                e ) );
+      }
+      catch ( final FileNotFoundException e )
+      {
+         LOGGER.warning( StackTraceUtils.print( getCurrentFile().getFilename(),
+                                                e ) );
+      }
+      catch ( final ParserConfigurationException e )
+      {
+         LOGGER.warning( StackTraceUtils.print( getCurrentFile().getFilename(),
+                                                e ) );
+      }
+      catch ( final SAXException e )
+      {
+         LOGGER.warning( StackTraceUtils.print( getCurrentFile().getFilename(),
+                                                e ) );
+      }
+      catch ( final IOException e )
+      {
+         LOGGER.warning( StackTraceUtils.print( getCurrentFile().getFilename(),
+                                                e ) );
+      }
+
+      return violations;
+   }
+
+   /**
+    * @return
+    */
+   protected abstract String getXPathExpression();
+
+   /*
+    * (non-Javadoc)
+    * @see
+    * com.adobe.ac.pmd.rules.core.AbstractFlexRule#isConcernedByTheCurrentFile()
+    */
+   @Override
+   protected boolean isConcernedByTheCurrentFile()
+   {
+      return getCurrentFile().isMxml();
+   }
+
+   /**
+    * @param violations
+    * @param doc
+    * @param xPath
+    * @throws XPathExpressionException
+    */
+   protected abstract void onEvaluated( final List< IFlexViolation > violations,
+                                        final Document doc,
+                                        final XPath xPath ) throws XPathExpressionException;
+
+   private Document buildDocument() throws ParserConfigurationException,
+                                   SAXException,
+                                   IOException
+   {
+      final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+      factory.setNamespaceAware( true );
+      final DocumentBuilder builder = factory.newDocumentBuilder();
+      return builder.parse( getCurrentFile().getFilePath() );
+   }
+
+   private XPath buildXPath()
+   {
+      final XPathFactory xPathFactory = XPathFactory.newInstance();
+      final XPath xPath = xPathFactory.newXPath();
+      xPath.setNamespaceContext( new NamespaceContextMap( "mx", "http://www.adobe.com/2006/mxml" ) );
+      return xPath;
+   }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexAstRule.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexAstRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexAstRule.java
new file mode 100644
index 0000000..7cfcee4
--- /dev/null
+++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexAstRule.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.adobe.ac.pmd.rules.core;
+
+/**
+ * @author xagnetti
+ */
+public interface IFlexAstRule extends IFlexRule
+{
+   /**
+    * @return true if the current file is concerned
+    */
+   boolean isConcernedByTheCurrentFile();
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/flex-utilities/blob/e43b7a87/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexRule.java
----------------------------------------------------------------------
diff --git a/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexRule.java b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexRule.java
new file mode 100644
index 0000000..3eb94e4
--- /dev/null
+++ b/FlexPMD/flex-pmd-java/flex-pmd-ruleset-api/src/main/java/com/adobe/ac/pmd/rules/core/IFlexRule.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.adobe.ac.pmd.rules.core;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import net.sourceforge.pmd.Rule;
+
+import com.adobe.ac.pmd.IFlexViolation;
+import com.adobe.ac.pmd.files.IFlexFile;
+import com.adobe.ac.pmd.nodes.IPackage;
+
+/**
+ * @author xagnetti
+ */
+public interface IFlexRule extends Rule
+{
+   /**
+    * @return ruleName
+    */
+   String getRuleName();
+
+   /**
+    * @param file
+    * @param rootNode
+    * @param files
+    * @return
+    */
+   List< IFlexViolation > processFile( final IFlexFile file,
+                                       final IPackage rootNode,
+                                       final Map< String, IFlexFile > files );
+
+   /**
+    * @param excludes
+    */
+   void setExcludes( final Set< String > excludes );
+}
\ No newline at end of file