<?xml version="1.0"?>

<ruleset name="Optimization"
    xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
  <description>
These rules deal with different optimizations that generally apply to best practices.
  </description>

    <rule name="LocalVariableCouldBeFinal"
    	 since="2.2"
	    message="Local variable ''{0}'' could be declared final"
          class="net.sourceforge.pmd.lang.java.rule.optimizations.LocalVariableCouldBeFinalRule"
          externalInfoUrl="${pmd.website.baseurl}/rules/java/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 txtA = "a"; 		// if txtA will not be assigned again it is better to do this:
		final String txtB = "b";
	}
}
  ]]>
      </example>
      </rule>

    <rule name="MethodArgumentCouldBeFinal"
    		 since="2.2"
          message="Parameter ''{0}'' is not assigned and could be declared final"
          class="net.sourceforge.pmd.lang.java.rule.optimizations.MethodArgumentCouldBeFinalRule"
          externalInfoUrl="${pmd.website.baseurl}/rules/java/optimizations.html#MethodArgumentCouldBeFinal">
      <description>
A method argument that is never re-assigned within the method can be declared final.
      </description>
        <priority>3</priority>
      <example>
  <![CDATA[
public void foo1 (String param) {	// do stuff with param never assigning it
  
}

public void foo2 (final String param) {	// better, do stuff with param never assigning it
  
}
  ]]>
      </example>
      </rule>

  <rule name="AvoidInstantiatingObjectsInLoops"
  		  since="2.2"
        message="Avoid instantiating new objects inside loops"
        class="net.sourceforge.pmd.lang.java.rule.optimizations.AvoidInstantiatingObjectsInLoopsRule"
          externalInfoUrl="${pmd.website.baseurl}/rules/java/optimizations.html#AvoidInstantiatingObjectsInLoops">
    <description>
New objects created within loops should be checked to see if they can created outside them and reused.
    </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"
   		language="java"
    		 since="3.0"
          message="Use ArrayList instead of Vector"
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/rules/java/optimizations.html#UseArrayListInsteadOfVector">
      <description>
ArrayList is a much better Collection implementation than Vector if thread-safe operation is not required.
      </description>
      <priority>3</priority>
      <properties>
          <property name="xpath">
              <value>
<![CDATA[
//CompilationUnit[count(ImportDeclaration) = 0 or count(ImportDeclaration/Name[@Image='java.util.Vector']) > 0]
  //AllocationExpression/ClassOrInterfaceType
    [@Image='Vector' or @Image='java.util.Vector']
]]>
              </value>
          </property>
      </properties>
      <example>
<![CDATA[
public class SimpleTest extends TestCase {
	public void testX() {
		Collection c1 = new Vector();		
		Collection c2 = new ArrayList();	// achieves the same with much better performance
	}
}
]]>
          </example>
    </rule>

    <rule name="SimplifyStartsWith"
   		language="java"
    		 since="3.1"
          message="This call to String.startsWith can be rewritten using String.charAt(0)"
          class="net.sourceforge.pmd.lang.rule.XPathRule"
          externalInfoUrl="${pmd.website.baseurl}/rules/java/optimizations.html#SimplifyStartsWith">
      <description>
Since it passes in a literal of length 1, calls to (string).startsWith can be rewritten using (string).charAt(0)
at the expense of some readability.
      </description>
      <priority>3</priority>
    <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>
      <example>
  <![CDATA[
public class Foo {

	boolean checkIt(String x) {
		return x.startsWith("a");	// suboptimal
	}
  
	boolean fasterCheckIt(String x) {
		return x.charAt(0) == 'a';	//	faster approach
	}
}
]]>
      </example>
    </rule>

    <rule name="UseStringBufferForStringAppends"
    		 since="3.1"
          message="Prefer StringBuffer over += for concatenating strings"
          class="net.sourceforge.pmd.lang.java.rule.optimizations.UseStringBufferForStringAppendsRule"
          externalInfoUrl="${pmd.website.baseurl}/rules/java/optimizations.html#UseStringBufferForStringAppends">
           <description>
The use of the '+=' operator for appending strings causes the JVM to create and use an internal StringBuffer.
If a non-trivial number of these concatenations are being used then the explicit use of a StringBuilder or 
threadsafe StringBuffer is recommended to avoid this.
           </description>
            <priority>3</priority>
           <example>
      <![CDATA[
public class Foo {
  void bar() {
    String a;
    a = "foo";
    a += " bar";
   // better would be:
   // StringBuilder a = new StringBuilder("foo");
   // a.append(" bar);
  }
}
      ]]>
           </example>
        </rule>

  <rule name="UseArraysAsList"
   		language="java"
     since="3.5"
     message="Use asList instead of tight loops"
      class="net.sourceforge.pmd.lang.rule.XPathRule"
      externalInfoUrl="${pmd.website.baseurl}/rules/java/optimizations.html#UseArraysAsList">
     <description>
The java.util.Arrays class has a "asList" method that should be used when you want to create a new List from
an array of objects. It is faster than executing a loop to copy all the elements of the array one by one.
     </description>
     <priority>3</priority>
     <properties>
       <property name="xpath">
       <value>
   <![CDATA[
//Statement[
    (ForStatement) and (ForStatement//VariableInitializer//Literal[@IntLiteral='true' and @Image='0']) and (count(.//IfStatement)=0)
   ]
   //StatementExpression[
    PrimaryExpression/PrimaryPrefix/Name[
     substring-before(@Image,'.add') = ancestor::MethodDeclaration//LocalVariableDeclaration[
      ./Type//ClassOrInterfaceType[
       @Image = 'Collection' or 
       @Image = 'List' or @Image='ArrayList'
      ]
     ]
     /VariableDeclarator/VariableDeclaratorId[
      count(..//AllocationExpression/ClassOrInterfaceType[
       @Image="ArrayList"
      ]
      )=1
     ]/@Image
    ]
   and
   PrimaryExpression/PrimarySuffix/Arguments/ArgumentList/Expression/PrimaryExpression/PrimaryPrefix/Name
   [
     @Image = ancestor::MethodDeclaration//LocalVariableDeclaration[@Array="true"]/VariableDeclarator/VariableDeclaratorId/@Image
     or
     @Image = ancestor::MethodDeclaration//FormalParameter/VariableDeclaratorId/@Image
   ]
   /../..[count(.//PrimarySuffix)
   =1]/PrimarySuffix/Expression/PrimaryExpression/PrimaryPrefix
   /Name
   ]
   ]]>
       </value>
       </property>
     </properties>
     <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"
   		language="java"
      since="3.5"
      message="System.arraycopy is more efficient"
      class="net.sourceforge.pmd.lang.rule.XPathRule"
      externalInfoUrl="${pmd.website.baseurl}/rules/java/optimizations.html#AvoidArrayLoops">
      <description>
Instead of manually copying data between two arrays, use the efficient System.arraycopy method instead.
      </description>
      <priority>3</priority>
      <properties>
        <property name="xpath">
        <value>
    <![CDATA[
//Statement[(ForStatement or WhileStatement) and
count(*//AssignmentOperator[@Image = '='])=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>
      <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>

    <rule name="UnnecessaryWrapperObjectCreation"
          since="3.8"
          message="Unnecessary wrapper object creation"
          class="net.sourceforge.pmd.lang.java.rule.optimizations.UnnecessaryWrapperObjectCreationRule"
          externalInfoUrl="${pmd.website.baseurl}/rules/java/optimizations.html#UnnecessaryWrapperObjectCreation">
      <description>
Most wrapper classes provide static conversion methods that avoid the need to create intermediate objects
just to create the primitive forms. Using these avoids the cost of creating objects that also need to be 
garbage-collected later.
      </description>
      <priority>3</priority>
      <example>
<![CDATA[
public int convert(String s) {
  int i, i2;

  i = Integer.valueOf(s).intValue(); // this wastes an object
  i = Integer.parseInt(s); 			 // this is better

  i2 = Integer.valueOf(i).intValue(); // this wastes an object
  i2 = i; // this is better

  String s3 = Integer.valueOf(i2).toString(); // this wastes an object
  s3 = Integer.toString(i2); 		// this is better

  return i2;
}
]]>
          </example>
    </rule>

    <rule name="AddEmptyString"
   		language="java"
        since="4.0"
        message="Do not add empty strings"
        class="net.sourceforge.pmd.lang.rule.XPathRule"
        externalInfoUrl="${pmd.website.baseurl}/rules/java/optimizations.html#AddEmptyString">
        <description>
The conversion of literals to strings by concatenating them with empty strings is inefficient.
It is much better to use one of the type-specific toString() methods instead.
        </description>
        <priority>3</priority>
        <properties>
            <property name="xpath">
                <value>
                    <![CDATA[ 
//AdditiveExpression/PrimaryExpression/PrimaryPrefix/Literal[@Image='""']
                ]]>
                </value>
            </property>
        </properties>
        <example>
            <![CDATA[ 
String s = "" + 123; 				// inefficient 
String t = Integer.toString(456); 	// preferred approach
            ]]>
        </example>
    </rule>

	<rule name="RedundantFieldInitializer"
			language="java"
			since="5.0"
			message="Avoid using redundant field initializer for ''${variableName}''"
			class="net.sourceforge.pmd.lang.java.rule.optimizations.RedundantFieldInitializerRule"
			externalInfoUrl="${pmd.website.baseurl}/rules/java/optimizations.html#RedundantFieldInitializer">
		<description>
Java will initialize fields with known default values so any explicit initialization of those same defaults
is redundant and results in a larger class file (approximately three additional bytecode instructions per field).
		</description>
              <priority>3</priority>
              <example>
              <![CDATA[
public class C {
	boolean b	= false;	// examples of redundant initializers
	byte by		= 0;
	short s		= 0;
	char c		= 0;
	int i		= 0;
	long l		= 0;
	
	float f		= .0f;    // all possible float literals
	doable d	= 0d;     // all possible double literals
	Object o	= null;
	
	MyClass mca[] = null;
	int i1 = 0, ia1[] = null;
	
	class Nested {
		boolean b = false;
	}
}
              ]]>
              </example>
            </rule>

	<rule name="PrematureDeclaration"
			language="java"
			since="5.0"
			message="Avoid declaring a variable if it is unreferenced before a possible exit point."
			class="net.sourceforge.pmd.lang.java.rule.optimizations.PrematureDeclarationRule"
			externalInfoUrl="${pmd.website.baseurl}/rules/java/optimizations.html#PrematureDeclaration">
		<description>
Checks for variables that are defined before they might be used. A reference is deemed to be premature if it is created right before a block of code that doesn't use it that also has the ability to return or throw an exception.
		</description>
              <priority>3</priority>
              <example>
              <![CDATA[
public int getLength(String[] strings) {
  
  int length = 0;	// declared prematurely

  if (strings == null || strings.length == 0) return 0;
  
  for (String str : strings) {
    length += str.length();
    }

  return length;
}
              ]]>
              </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>