diff --git a/README.md b/README.md
index 390ec9a..7650414 100755
--- a/README.md
+++ b/README.md
@@ -38,6 +38,7 @@ To use this product, please configure your findbugs-maven-plugin like below.
- added ImplicitLengthDetector
- added ImplicitNullnessDetector
- added ColumnDefinitionDetector
+- added NullablePrimitiveDetector
## 0.0.1
diff --git a/src/main/java/jp/co/worksap/oss/findbugs/jpa/NullablePrimitiveDetector.java b/src/main/java/jp/co/worksap/oss/findbugs/jpa/NullablePrimitiveDetector.java
new file mode 100644
index 0000000..6aeaac3
--- /dev/null
+++ b/src/main/java/jp/co/worksap/oss/findbugs/jpa/NullablePrimitiveDetector.java
@@ -0,0 +1,58 @@
+package jp.co.worksap.oss.findbugs.jpa;
+
+import java.util.Map;
+
+import org.apache.bcel.classfile.ElementValue;
+import org.apache.bcel.generic.ObjectType;
+import org.apache.bcel.generic.Type;
+
+import edu.umd.cs.findbugs.BugInstance;
+import edu.umd.cs.findbugs.BugReporter;
+
+public class NullablePrimitiveDetector extends AbstractColumnDetector {
+
+ public NullablePrimitiveDetector(BugReporter bugReporter) {
+ super(bugReporter);
+ }
+
+ @Override
+ protected void verifyColumn(Type columnType,
+ Map elements) {
+ if (! isPrimitive(columnType)) {
+ return;
+ }
+
+ boolean isNullableColumn = detectNullability(elements);
+ if (isNullableColumn) {
+ reportNullablePrimitive(columnType);
+ }
+ }
+
+ private void reportNullablePrimitive(Type columnType) {
+ BugInstance bug = new BugInstance(this, "NULLABLE_PRIMITIVE", NORMAL_PRIORITY);
+ if (visitingMethod()) {
+ bug.addMethod(this);
+ }
+ getBugReporter().reportBug(bug);
+
+ }
+
+ private boolean detectNullability(Map elements) {
+ if (! elements.containsKey("nullable")) {
+ // in JPA 1.0 specification, default value of 'nullable' parameter is true
+ // note that this case will be reported by ImplicitNullnessDetector.
+ return true;
+ }
+
+ String nullability = elements.get("nullable").stringifyValue();
+ return "true".equals(nullability);
+ }
+
+ /**
+ * @return true if column type is primitive value (not reference type).
+ */
+ private boolean isPrimitive(Type columnType) {
+ return ! (columnType instanceof ObjectType); // looks bad, but simple way to check primitive or not.
+ }
+
+}
diff --git a/src/main/meta/bugrank.txt b/src/main/meta/bugrank.txt
index 832ee33..5bbbeb5 100755
--- a/src/main/meta/bugrank.txt
+++ b/src/main/meta/bugrank.txt
@@ -11,3 +11,4 @@
0 BugPattern IMPLICIT_LENGTH
0 BugPattern ILLEGAL_LENGTH
0 BugPattern USE_COLUMN_DEFINITION
+0 BugPattern NULLABLE_PRIMITIVE
diff --git a/src/main/meta/findbugs.xml b/src/main/meta/findbugs.xml
index 15afa6d..0b8b881 100755
--- a/src/main/meta/findbugs.xml
+++ b/src/main/meta/findbugs.xml
@@ -54,6 +54,11 @@
+
+
+
we can not use System.out and System.err, please use log to
output information
-
+
System.out and System.err are forbidden, please use log
]]>
@@ -39,7 +39,7 @@
To prevent from bad extending, immutable class should be final.
-
+
To prevent from bad extending, immutable class should be final.
]]>
@@ -52,7 +52,7 @@
Field ({1}) in class ({2}) should be final to make a class ({3}) immutable.
-
+
Field of immutable class should be final.
]]>
@@ -70,7 +70,7 @@
Nullness of this parameter is unknown.
-
+
Nullness of this parameter is unknown.
]]>
@@ -83,7 +83,7 @@
Nullness of this returned value is unknown.
-
+
Nullness of this returned value is unknown.
]]>
@@ -103,7 +103,7 @@
Index name should be shorter than or equal to 30 bytes.
-
+
Index name should be shorter than or equal to 30 bytes.
]]>
@@ -123,7 +123,7 @@
Table name should be shorter than or equal to 30 bytes.
-
+
Table name should be shorter than or equal to 30 bytes.
]]>
@@ -143,7 +143,7 @@
Column name should be shorter than or equal to 30 bytes.
-
+
Column name should be shorter than or equal to 30 bytes.
]]>
@@ -163,7 +163,7 @@
Specify length of column, its default (255) might be not enough.
-
+
Specify length of column, its default (255) might be not enough.
]]>
@@ -197,7 +197,7 @@
It is good to specify the value of nullable element clear, it tells that you have considered about it.
-
+
It is good to specify the value of nullable element clear, it tells that you have considered about it.
]]>
@@ -217,13 +217,34 @@
@Column annotation has columnDefinition property, it might break RDBMS portability.
-
+
@Column annotation has columnDefinition property, it might break RDBMS portability.
]]>
+
+
+ This detector will find illegal nullable property of primitive type.
+ When developer changes type of field from primitive type to reference type (ex. from int to Integer),
+ he/she might forget to care about this property. This detector helps developer to find this human-error.
+
+
+
+
+ Nullable property of primitive type should be false.
+
+
+ Nullable property of primitive type should be false.
+
+
+ Nullable property of primitive type should be false.
+ ]]>
+
+
+
This detector will find ignored test case which has no explanation about why it is ignored.
@@ -236,7 +257,7 @@
To tell why test case is ignored, put explanation as a parameter.
-
+
To tell why test case is ignored, put explanation as a parameter.
]]>
diff --git a/src/test/java/jp/co/worksap/oss/findbugs/jpa/NonNullablePrimitiveColumn.java b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NonNullablePrimitiveColumn.java
new file mode 100644
index 0000000..c1a6bd4
--- /dev/null
+++ b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NonNullablePrimitiveColumn.java
@@ -0,0 +1,28 @@
+package jp.co.worksap.oss.findbugs.jpa;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+
+@Entity
+public class NonNullablePrimitiveColumn {
+ @Column(nullable = false)
+ private boolean booleanValue;
+
+ @Column(nullable = false)
+ private byte byteValue;
+
+ @Column(nullable = false)
+ private short shortValue;
+
+ @Column(nullable = false)
+ private int intValue;
+
+ @Column(nullable = false)
+ private long longValue;
+
+ @Column(nullable = false)
+ private float floatValue;
+
+ @Column(nullable = false)
+ private double doubleValue;
+}
diff --git a/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableBooleanColumn.java b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableBooleanColumn.java
new file mode 100644
index 0000000..88c678f
--- /dev/null
+++ b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableBooleanColumn.java
@@ -0,0 +1,10 @@
+package jp.co.worksap.oss.findbugs.jpa;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+
+@Entity
+public class NullableBooleanColumn {
+ @Column(nullable = true)
+ private boolean booleanValue;
+}
diff --git a/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableByteColumn.java b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableByteColumn.java
new file mode 100644
index 0000000..bfb1525
--- /dev/null
+++ b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableByteColumn.java
@@ -0,0 +1,10 @@
+package jp.co.worksap.oss.findbugs.jpa;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+
+@Entity
+public class NullableByteColumn {
+ @Column(nullable = true)
+ private byte byteValue;
+}
diff --git a/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableDoubleColumn.java b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableDoubleColumn.java
new file mode 100644
index 0000000..a5690f0
--- /dev/null
+++ b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableDoubleColumn.java
@@ -0,0 +1,10 @@
+package jp.co.worksap.oss.findbugs.jpa;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+
+@Entity
+public class NullableDoubleColumn {
+ @Column(nullable = true)
+ private double doubleValue;
+}
diff --git a/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableFloatColumn.java b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableFloatColumn.java
new file mode 100644
index 0000000..75bc874
--- /dev/null
+++ b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableFloatColumn.java
@@ -0,0 +1,10 @@
+package jp.co.worksap.oss.findbugs.jpa;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+
+@Entity
+public class NullableFloatColumn {
+ @Column(nullable = true)
+ private float floatValue;
+}
diff --git a/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableIntColumn.java b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableIntColumn.java
new file mode 100644
index 0000000..e783975
--- /dev/null
+++ b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableIntColumn.java
@@ -0,0 +1,10 @@
+package jp.co.worksap.oss.findbugs.jpa;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+
+@Entity
+public class NullableIntColumn {
+ @Column(nullable = true)
+ private int intValue;
+}
diff --git a/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableLongColumn.java b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableLongColumn.java
new file mode 100644
index 0000000..4aaed77
--- /dev/null
+++ b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableLongColumn.java
@@ -0,0 +1,10 @@
+package jp.co.worksap.oss.findbugs.jpa;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+
+@Entity
+public class NullableLongColumn {
+ @Column(nullable = true)
+ private long longValue;
+}
diff --git a/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullablePrimitiveDetectorTest.java b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullablePrimitiveDetectorTest.java
new file mode 100644
index 0000000..1f9c8dc
--- /dev/null
+++ b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullablePrimitiveDetectorTest.java
@@ -0,0 +1,56 @@
+package jp.co.worksap.oss.findbugs.jpa;
+
+import static com.youdevise.fbplugins.tdd4fb.DetectorAssert.assertBugReported;
+import static com.youdevise.fbplugins.tdd4fb.DetectorAssert.assertNoBugsReported;
+import static com.youdevise.fbplugins.tdd4fb.DetectorAssert.bugReporterForTesting;
+import static com.youdevise.fbplugins.tdd4fb.DetectorAssert.ofType;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import edu.umd.cs.findbugs.BugReporter;
+
+public class NullablePrimitiveDetectorTest {
+ private BugReporter bugReporter;
+ private NullablePrimitiveDetector detector;
+
+ @Before
+ public void before() {
+ this.bugReporter = bugReporterForTesting();
+ this.detector = new NullablePrimitiveDetector(bugReporter);
+ }
+
+ @Test
+ public void testNullableObject() throws Exception {
+ assertNoBugsReported(UseColumnDefinition.class, detector, bugReporter);
+ }
+
+ @Test
+ public void testNullableInt() throws Exception {
+ assertBugReported(NullableBooleanColumn.class, detector,
+ bugReporter, ofType("NULLABLE_PRIMITIVE"));
+ assertBugReported(NullableByteColumn.class, detector,
+ bugReporter, ofType("NULLABLE_PRIMITIVE"));
+ assertBugReported(NullableShortColumn.class, detector,
+ bugReporter, ofType("NULLABLE_PRIMITIVE"));
+ assertBugReported(NullableIntColumn.class, detector,
+ bugReporter, ofType("NULLABLE_PRIMITIVE"));
+ assertBugReported(NullableLongColumn.class, detector,
+ bugReporter, ofType("NULLABLE_PRIMITIVE"));
+ assertBugReported(NullableFloatColumn.class, detector,
+ bugReporter, ofType("NULLABLE_PRIMITIVE"));
+ assertBugReported(NullableDoubleColumn.class, detector,
+ bugReporter, ofType("NULLABLE_PRIMITIVE"));
+ }
+
+ @Test
+ public void testNonNullableObject() throws Exception {
+ assertNoBugsReported(ColumnWithNullable.class, detector, bugReporter);
+ }
+
+ @Test
+ public void testNonNullableInt() throws Exception {
+ assertNoBugsReported(NonNullablePrimitiveColumn.class, detector, bugReporter);
+ }
+
+}
diff --git a/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableShortColumn.java b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableShortColumn.java
new file mode 100644
index 0000000..59a29a9
--- /dev/null
+++ b/src/test/java/jp/co/worksap/oss/findbugs/jpa/NullableShortColumn.java
@@ -0,0 +1,10 @@
+package jp.co.worksap.oss.findbugs.jpa;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+
+@Entity
+public class NullableShortColumn {
+ @Column(nullable = true)
+ private short shortValue;
+}