<?xml version="1.0"?>

<ruleset name="Optimization Rules" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="../etc/ruleset_xml_schema.xml">
  <description>
These rules deal with different optimizations that generally apply to performance best practices.
  </description>

<!-- jmv
    <rule name="LocalVariableCouldBeFinal"
          message="Local variable could be declared final"
          class="net.sourceforge.pmd.rules.optimization.LocalVariableCouldBeFinal"
          externalInfoUrl="http://pmd.sourceforge.net/rules/optimizations.html#LocalVariableCouldBeFinal">
      <description>
A local variable assigned only once can be declared final.
      </description>
        <priority>3</priority>
      <example>
  <![CDATA[
public class Bar {
 public void foo () {
  String a = "a"; //if a will not be assigned again it is better to do this:
  final String b = "b";
 }
}
  ]]>
      </example>
      </rule>

    <rule name="MethodArgumentCouldBeFinal"
          message="Parameter ''{0}'' is not assigned and could be declared final"
          class="net.sourceforge.pmd.rules.optimization.MethodArgumentCouldBeFinal"
          externalInfoUrl="http://pmd.sourceforge.net/rules/optimizations.html#MethodArgumentCouldBeFinal">
      <description>
A method argument that is never assigned can be declared final.
      </description>
        <priority>3</priority>
      <example>
  <![CDATA[
public void foo (String param) {
  // do stuff with param never assigning it
  // better: public void foo (final String param) {
}
  ]]>
      </example>
      </rule>

  <rule name="AvoidInstantiatingObjectsInLoops"
        message="Avoid instantiating new objects inside loops"
        class="net.sourceforge.pmd.rules.optimization.AvoidInstantiatingObjectsInLoops"
          externalInfoUrl="http://pmd.sourceforge.net/rules/optimizations.html#AvoidInstantiatingObjectsInLoops">
    <description>
Detects when a new object is created inside a loop
    </description>
      <priority>3</priority>
    <example>
<![CDATA[
public class Something {
  public static void main( String as[] ) {  
    for (int i = 0; i < 10; i++) {
      Foo f = new Foo(); //Avoid this whenever you can it's really expensive
    }
  }
}
]]>
    </example>
  </rule>
-->
  
    <rule name="UseArrayListInsteadOfVector"
          message="Use ArrayList instead of Vector"
          class="net.sourceforge.pmd.rules.XPathRule"
          externalInfoUrl="http://pmd.sourceforge.net/rules/optimizations.html#UseArrayListInsteadOfVector">
      <description>
ArrayList is a much better Collection implementation than Vector.
      </description>
      <properties>
          <property name="xpath">
              <value>
<![CDATA[
//AllocationExpression
 /ClassOrInterfaceType[@Image='Vector' or @Image='java.util.Vector']
]]>
              </value>
          </property>
      </properties>
        <priority>3</priority>
      <example>
<![CDATA[
public class SimpleTest extends TestCase {
 public void testX() {
  Collection c = new Vector();
  // This achieves the same with much better performance
  // Collection c = new ArrayList();
 }
}
]]>
          </example>
    </rule>

    <rule name="SimplifyStartsWith"
          message="This call to String.startsWith can be rewritten using String.charAt(0)"
          class="net.sourceforge.pmd.rules.XPathRule"
          externalInfoUrl="http://pmd.sourceforge.net/rules/optimizations.html#SimplifyStartsWith">
      <description>
Since it passes in a literal of length 1, this call to String.startsWith can be rewritten using String.charAt(0) to save some time.
      </description>
    <properties>
        <property name="xpath">
            <value>
<![CDATA[
//PrimaryExpression
 [PrimaryPrefix/Name
  [ends-with(@Image, '.startsWith')]]
 [PrimarySuffix/Arguments/ArgumentList
  /Expression/PrimaryExpression/PrimaryPrefix
  /Literal
   [string-length(@Image)=3]
   [starts-with(@Image, '"')]
   [ends-with(@Image, '"')]
 ]
 ]]>
            </value>
        </property>
    </properties>
        <priority>3</priority>
      <example>
  <![CDATA[
public class Foo {
  boolean checkIt(String x) {
      return x.startsWith("a");
  }
}
]]>
      </example>
    </rule>

    <rule name="UseStringBufferForStringAppends"
          message="Prefer StringBuffer over += for concatenating strings"
          class="net.sourceforge.pmd.rules.XPathRule"
          externalInfoUrl="http://pmd.sourceforge.net/rules/optimizations.html#UseStringBufferForStringAppends">
           <description>
Finds usages of += for appending strings.
           </description>
          <properties>
              <property name="xpath">
                  <value>
                      <![CDATA[
//StatementExpression
    [PrimaryExpression/PrimaryPrefix/Name
        [@Image = ancestor::MethodDeclaration//LocalVariableDeclaration
            [./Type//ClassOrInterfaceType[@Image =
'String']]/VariableDeclarator/VariableDeclaratorId/@Image]]
    //AssignmentOperator[@Compound='true']
                      ]]>
                  </value>
              </property>
          </properties>
            <priority>3</priority>
           <example>
      <![CDATA[
public class Foo {
 void bar() {
  String a;
  a = "foo";
  a += " bar";
  // better would be:
  // StringBuffer a = new StringBuffer("foo");
  // a.append(" bar);
 }
}
      ]]>
           </example>
        </rule>

  <rule name="UseArraysAsList"
     message="Use asList instead of tight loops"
      class="net.sourceforge.pmd.rules.XPathRule"
      externalInfoUrl="http://pmd.sourceforge.net/rules/optimizations.html#UseArraysAsList">
     <description>
   The class java.util.Arrays has a "asList" method that
   should be use when you want to create a new List from
   an array of objects. It is faster than executing a loop to
   cpy all the elements of the array one by one
     </description>
     <properties>
       <property name="xpath">
       <value>
   <![CDATA[
   //Statement[
    (ForStatement) and (count(.//IfStatement)=0)
   ]
   //StatementExpression[
    PrimaryExpression/PrimaryPrefix/Name[
     @Image = concat(ancestor::MethodDeclaration//LocalVariableDeclaration[
      ./Type//ClassOrInterfaceType[
       @Image = 'List' or @Image ='ArrayList'
      ]
     ]
     /VariableDeclarator/VariableDeclaratorId[
      count(..//AllocationExpression/ClassOrInterfaceType[
       @Image="ArrayList"
      ]
      )=1
     ]/@Image,".add")
    ]
   and
   PrimaryExpression/PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name
   [@Image = ancestor::MethodDeclaration//LocalVariableDeclaration
   [@Array="true"]/VariableDeclarator/VariableDeclaratorId/@Image]
   /../..[count(.//PrimarySuffix)
   =1]/PrimarySuffix/Expression/PrimaryExpression/PrimaryPrefix
   /Name
   ]
   ]]>
       </value>
       </property>
     </properties>
     <priority>3</priority>
     <example>
   <![CDATA[
   public class Test {
    public void foo(Integer[] ints) {
    // could just use Arrays.asList(ints)
     List l= new ArrayList(10);
     for (int i=0; i< 100; i++) {
      l.add(ints[i]);
     }
     for (int i=0; i< 100; i++) {
      l.add(a[i].toString()); // won't trigger the rule
     }
    }
   }
   ]]>
     </example>
   </rule>


    <rule name="AvoidArrayLoops"
      message="System.arrayCopy is more efficient"
      class="net.sourceforge.pmd.rules.XPathRule"
      externalInfoUrl="http://pmd.sourceforge.net/rules/optimizations.html#AvoidArrayLoops">
      <description>
    Instead of copying data between two arrays, use
    System.arrayCopy method
      </description>
      <properties>
        <property name="xpath">
        <value>
    <![CDATA[
//Statement[(ForStatement or WhileStatement) and
count(*//AssignmentOperator)=1
and
*/Statement
[
./Block/BlockStatement/Statement/StatementExpression/PrimaryExpression
/PrimaryPrefix/Name/../../PrimarySuffix/Expression
[(PrimaryExpression or AdditiveExpression) and count
(.//PrimaryPrefix/Name)=1]//PrimaryPrefix/Name/@Image
and
./Block/BlockStatement/Statement/StatementExpression/Expression/PrimaryExpression
/PrimaryPrefix/Name/../../PrimarySuffix[count
(..//PrimarySuffix)=1]/Expression[(PrimaryExpression
or AdditiveExpression) and count(.//PrimaryPrefix/Name)=1]
//PrimaryPrefix/Name/@Image
]]
    ]]>
        </value>
        </property>
      </properties>
      <priority>3</priority>
      <example>
    <![CDATA[
public class Test {
 public void bar() {
  int[] a = new int[10];
  int[] b = new int[10];
  for (int i=0;i<10;i++) {
   b[i]=a[i];
  }
 }
}
            // this will trigger the rule
            for (int i=0;i<10;i++) {
             b[i]=a[c[i]];
            }

        }
    }
    ]]>
      </example>
    </rule>



    <!--
    other optimization should be like avoiding
    "" + int
    or "" + (int) i
    and String.valueOf(int)
    
    and using Integer.toString(int)

    IntegerToStringShouldBeUsed
    LongToStringShouldBeUsed
    BooleanToStringShouldBeUsed    
    -->

</ruleset>



                                             
