<?xml version="1.0" encoding="UTF-8"?>
<test-data
    xmlns="http://pmd.sourceforge.net/rule-tests"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">

    <test-code>
        <description>ok</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
}
        ]]></code>
    </test-code>

    <test-code>
        <description>ok, default constructor</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    public void bar() {}
}
        ]]></code>
    </test-code>

    <test-code>
        <description>simple failure</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>1</expected-linenumbers>
        <code><![CDATA[
public class Foo {
    private Foo() {}
    public void bar() {}
}
        ]]></code>
    </test-code>

    <test-code>
        <description>failure with multiple constructors</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>1</expected-linenumbers>
        <code><![CDATA[
public class Foo {
    private Foo(){}
    private Foo(Object o){}
    public void bar() {}
}
        ]]></code>
    </test-code>

    <test-code>
        <description>protected constructor is ok</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private Foo(){}
    protected Foo(Object o){}
    public void bar() {}
}
        ]]></code>
    </test-code>
    
  	<test-code>
        <description>package constructor is ok</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    /* default */ Foo(){}
    public void bar() {}
}
        ]]></code>
    </test-code>

    <test-code>
        <description>ok, one static method</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private Foo(){}
    private Foo(Object o){}
    public static void bar() {}
}
        ]]></code>
    </test-code>

    <test-code>
        <description>nested class</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private static class Bar {
        private Bar() {}
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>ok, public static field</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    public static int BUZ = 2;
    private Foo() {}
}
        ]]></code>
    </test-code>

    <test-code>
        <description>not ok, non-public static field</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>1</expected-linenumbers>
        <code><![CDATA[
public class Foo {
    private static int BUZ = 2;
    private Foo() {}
}
        ]]></code>
    </test-code>

    <test-code>
        <description>ok, protected static field</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    protected static Foo INSTANCE = new Foo();
    private Foo() {}
}
        ]]></code>
    </test-code>

    <test-code>
        <description>ok, package private static field</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    static Foo INSTANCE = new Foo();
    private Foo() {}
}
        ]]></code>
    </test-code>

    <test-code>
        <description>ok, checking for bug 1432595</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Suit {
    private final String name;
        private Suit(String name) {
        this.name = name;
    }
    public String toString() {
        return name;
    }
    public static final Suit CLUBS = new Suit("Clubs");
    public static final Suit DIAMONDS = new Suit("Diamonds");
    public static final Suit HEARTS = new Suit("Hearts");
    public static final Suit SPADES = new Suit("Spades");
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1125 Missing Static Method In Non Instantiatable Class / Factory</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import java.awt.Frame;
import java.awt.event.ActionListener;

public class AccountSelectionSubForm extends Frame implements ActionListener
{
    public static class Factory
    {
        public Factory()
        {
            // do
        }
        // factory method which creates the outer class
        public AccountSelectionSubForm create( Frame parent, boolean supportAllAccountsSelection )
        {
            return new AccountSelectionSubForm();
        }
    }

    private AccountSelectionSubForm()
    {
        super( parent, null );
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Check Builder pattern</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public final class BacklogElementParameters {
    private final Long backlogId;
    private final String name;

    private BacklogElementParameters(final BacklogElementParameters.Builder builder) {
        this.backlogId = builder.backlogId;
        this.name = builder.name;
    }

    public static class Builder {
        public Builder backlogId(final Long backlogId) {
            this.backlogId = backlogId;
            return this;
        }

        public Builder name(final String name) {
            this.name = name;
            return this;
        }

        public BacklogElementParameters build() {
            return new BacklogElementParameters(this);
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#590 Check Builder pattern alternative</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public final class BacklogElementParameters {
    private final Long backlogId;
    private final String name;

    private BacklogElementParameters(Long backlogId, String name) {
        this.backlogId = backlogId;
        this.name = name;
    }

    public static class Builder {
        public Builder backlogId(final Long backlogId) {
            this.backlogId = backlogId;
            return this;
        }

        public Builder name(final String name) {
            this.name = name;
            return this;
        }

        public BacklogElementParameters build() {
            return new BacklogElementParameters(backlogId, name);
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1832 Check constructor injection with @Autowired or @Inject</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import javax.inject.Inject;
import org.springframework.beans.factory.annotation.Autowired;

public class Foo {

    private String arg;

    @Autowired
    private Foo() {}

    @Inject
    private Foo(String arg) {
        this.arg = arg;
    }

    public void bar() {}
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1832 fine with a least one constructor annotated with "Autowired</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.PersistenceConstructor;

public class Foo {

    private String arg;

    @PersistenceConstructor
    private Foo() {}

    @Autowired
    private Foo(String arg) {
        this.arg = arg;
    }

    public void bar() {}
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1832 but fail with both private constructors annotated with @PersistenceConstructor</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>3</expected-linenumbers>
        <code><![CDATA[
import org.springframework.data.annotation.PersistenceConstructor;

public class Foo {

    private String arg;

    @PersistenceConstructor
    private Foo() {}

    @PersistenceConstructor
    private Foo(String arg) {
        this.arg = arg;
    }

    public void bar() {}
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#2102 [java] False positive MissingStaticMethodInNonInstantiatableClass when inheritors are instantiable</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import java.util.Function;

public abstract class MyADT {
    private MyADT() {
    }

    public abstract <R> R map(
            Function<String, ? extends R> onString,
            Function<Integer, ? extends R> onInt
    );

    public static final class StringHolder extends MyADT {
        private final String string;

        public StringHolder(String string) {
            this.string = string;
        }

        @Override
        public <R> R map(Function<String, ? extends R> onString, Function<Integer, ? extends R> onInt) {
            return onString.apply(string);
        }
    }

    public static final class IntHolder extends MyADT {
        private final Integer integer;

        public IntHolder(Integer integer) {
            this.integer = integer;
        }

        @Override
        public <R> R map(Function<String, ? extends R> onString, Function<Integer, ? extends R> onInt) {
            return onInt.apply(integer);
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#3701 - false positive with method inner class</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Scratch {

    public static void main(String[] args) {
        Scratch scratch = new Scratch();

        scratch.callMethod();
    }

    void callMethod() {

        class InnerClass {
            private InnerClass() {
            }

            void display() {
                System.out.println("Works OK!");
            }
        }

        InnerClass innerClass = new InnerClass();
        innerClass.display();
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#4224 [java] MissingStaticMethodInNonInstantiatableClass should considers lombok's UtilityClass</description>
        <expected-problems>1</expected-problems>
        <code><![CDATA[
import lombok.experimental.UtilityClass;

@UtilityClass
public final class Test {
   private int x;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#4224 [java] MissingStaticMethodInNonInstantiatableClass should considers lombok's UtilityClass</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.experimental.UtilityClass;

@UtilityClass
public final class Test {
    public int test(){
        return 0;
    }
   private int x;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#4224 [java] MissingStaticMethodInNonInstantiatableClass should consider lombok's UtilityClass</description>
        <expected-problems>1</expected-problems>
        <code><![CDATA[
import lombok.experimental.UtilityClass;

@UtilityClass
public final class Test {
    private int test(){
        return 0;
    }
   private int x;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#4224 [java] MissingStaticMethodInNonInstantiatableClass should consider lombok's UtilityClass</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.experimental.UtilityClass;

@UtilityClass
public final class Test {
    private int test(){
        return 0;
    }
    public int test0(){
        return 0;
    }
   private int x;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#4393 [java] MissingStaticMethodInNonInstantiatableClass should consider lombok's UtilityClass</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.experimental.UtilityClass;

@UtilityClass
public final class Test {
   int x;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#4393 [java] MissingStaticMethodInNonInstantiatableClass should consider lombok's UtilityClass</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.experimental.UtilityClass;

@UtilityClass
public final class Test {
   public static final String CONSTANT = "Constant";
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#4393 [java] MissingStaticMethodInNonInstantiatableClass should consider lombok's UtilityClass</description>
        <expected-problems>1</expected-problems>
        <code><![CDATA[
import lombok.experimental.UtilityClass;

@UtilityClass
public final class Test {
   private static final String CONSTANT = "Constant";
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#4225 [java] MissingStaticMethodInNonInstantiatableClass should consider Lombok's @NoArgsConstructor</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.NoArgsConstructor;

@NoArgsConstructor
public class Test {
    private int a;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#4225 [java] MissingStaticMethodInNonInstantiatableClass should consider Lombok's @RequiredArgsConstructor</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class Test {
    private int a;
    private final int b;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#4225 [java] MissingStaticMethodInNonInstantiatableClass should consider Lombok's @AllArgsConstructor</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.AllArgsConstructor;

@AllArgsConstructor
public class Test {
    private int a;
    private final int b;
}
        ]]></code>
    </test-code>

    <test-code>
        <description>[java] MissingStaticMethodInNonInstantiatableClass does not consider nested builder class #4174</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public final class TestPrivateClassWithFactory implements GenericTest {
  private final boolean shouldFail;

  private TestPrivateClassWithFactory(TestStep step) {
    this.shouldFail = step.shouldFail;
  }

  public void run() {
    if (shouldFail) {
      throw new AssertionError("fail");
    }
  }

  public static final class TestStep {
    private boolean shouldFail = false;

    public TestStep shouldFail() {
      this.shouldFail = true;
      return this;
    }

    public GenericTest newTest() {
      return new TestPrivateClassWithFactory(this);
    }
  }
}
]]></code>
    </test-code>

    <test-code>
        <description>#4493:[java]false-positive about MissingStaticMethodInNonInstantiatableClass and @Inject </description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import com.google.inject.Inject;
public class Foo {  
   @Inject
   private Foo() {}
}

public class Bar extends Foo {
   public Bar() {}
}
]]></code>
    </test-code>

    <test-code>
        <description>#1488:[java]false-positive about MissingStaticMethodInNonInstantiatableClass and @lombok.Builder on constructor</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.Builder;
public class Foo {
   @Builder
   private Foo() {}
}
]]></code>
    </test-code>

    <test-code>
        <description>#1488:[java]false-positive about MissingStaticMethodInNonInstantiatableClass and @lombok.Builder on class</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import lombok.Builder;
@Builder
public class Foo {
   private Foo() {}
}
]]></code>
    </test-code>

</test-data>
