From 20f741cbd833d31baa0dc7d7339a4df3cb90d28b Mon Sep 17 00:00:00 2001 From: VenomVendor Date: Thu, 2 Aug 2018 00:50:57 +0530 Subject: [PATCH] Fixes #18, Fixes #19 Added Support for class level annotation Removed restriction to be used only on JDK1.7 and above. Compiled with JDK-6 Refactored package name --- .codeclimate.yml | 3 +- .codecov.yml | 11 ---- README.md | 4 +- RELEASE.md | 10 +++ .../gson/NullDefenseTypeAdapterFactory.java | 64 +++++++++++-------- .../{library => }/gson/BaseTest.java | 6 +- .../NullDefenseTypeAdapterFactoryTest.java | 8 +-- .../gson/annotation/MandatoryTest.java | 4 +- .../{library => }/gson/model/ChildTest.java | 9 ++- .../gson/model/LanguageTest.java | 13 +++- .../{library => }/gson/model/ParentTest.java | 6 +- .../gson/util/CustomListTest.java | 2 +- .../gson/util/ResourceHelperTest.java | 2 +- version.gradle.kts | 4 +- 14 files changed, 81 insertions(+), 65 deletions(-) rename src/main/java/com/venomvendor/{library => }/gson/NullDefenseTypeAdapterFactory.java (82%) rename src/test/java/com/venomvendor/{library => }/gson/BaseTest.java (91%) rename src/test/java/com/venomvendor/{library => }/gson/NullDefenseTypeAdapterFactoryTest.java (97%) rename src/test/java/com/venomvendor/{library => }/gson/annotation/MandatoryTest.java (90%) rename src/test/java/com/venomvendor/{library => }/gson/model/ChildTest.java (88%) rename src/test/java/com/venomvendor/{library => }/gson/model/LanguageTest.java (76%) rename src/test/java/com/venomvendor/{library => }/gson/model/ParentTest.java (87%) rename src/test/java/com/venomvendor/{library => }/gson/util/CustomListTest.java (94%) rename src/test/java/com/venomvendor/{library => }/gson/util/ResourceHelperTest.java (97%) diff --git a/.codeclimate.yml b/.codeclimate.yml index a4ee0f4..07c3f29 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -6,7 +6,6 @@ plugins: - "java-basic" - "java-braces" - "java-codesize" - - "java-codesize" - "java-design" - "java-naming" sonar-java: @@ -14,4 +13,4 @@ plugins: config: tests_patterns: - src/test/** - sonar.java.source: 8 + sonar.java.source: 1.6 diff --git a/.codecov.yml b/.codecov.yml index ca2f019..7ea9723 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -1,18 +1,7 @@ -# Team Yaml -coverage: - round: down - precision: 5 - # Repository Yaml coverage: round: up range: 0..10 -# Used in Codecov after updating -coverage: - round: up - range: 0..10 - precision: 5 - codecov: branch: master diff --git a/README.md b/README.md index ee28987..9966734 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ > Removes invalid objects during Gson parsing which are marked as required, yet null/empty. [![Build Status](https://img.shields.io/travis/VenomVendor/NullDefense/master.svg?logo=travis)](https://travis-ci.org/VenomVendor/NullDefense) -[![Apache License v2.0](https://img.shields.io/badge/License-Apache%202.0-brightgreen.svg)](https://github.com/VenomVendor/NullDefense/blob/master/LICENSE) -[![Latest Version](https://img.shields.io/maven-metadata/v/https/jcenter.bintray.com/com/venomvendor/gson-nulldefense/maven-metadata.xml.svg)](https://bintray.com/bintray/jcenter/NullDefense) +[![Apache License v2.0](https://img.shields.io/badge/license-Apache--2.0-brightgreen.svg)](https://github.com/VenomVendor/NullDefense/blob/master/LICENSE) +[![Latest Version](https://img.shields.io/maven-metadata/v/https/jcenter.bintray.com/com/venomvendor/gson-nulldefense/maven-metadata.xml.svg)](https://bintray.com/venomvendor/maven/NullDefense/_latestVersion) # Code Quality [![Codecov](https://codecov.io/gh/VenomVendor/NullDefense/branch/master/graph/badge.svg)](https://codecov.io/gh/VenomVendor/NullDefense) diff --git a/RELEASE.md b/RELEASE.md index d9520d9..e079cb6 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -12,6 +12,16 @@ New Line is created by adding TWO whitespace at EOL # Release Notes +## [v2.0.0](https://github.com/VenomVendor/NullDefense/releases/tag/v2.0.0) +**Date**: 02-Aug-2018 +**Fixes**: [#18](https://github.com/VenomVendor/NullDefense/issues/18), + [#19](https://github.com/VenomVendor/NullDefense/issues/19) +**Notes** + - Breaking Changes + - Renamed package + - Added support for class level annotation + - Removed Restriction to use JDK 1.7+ + ## [v1.0.1](https://github.com/VenomVendor/NullDefense/releases/tag/v1.0.1) **Date**: 27-Jul-2018 **Fixes**: [#16](https://github.com/VenomVendor/NullDefense/issues/16) diff --git a/src/main/java/com/venomvendor/library/gson/NullDefenseTypeAdapterFactory.java b/src/main/java/com/venomvendor/gson/NullDefenseTypeAdapterFactory.java similarity index 82% rename from src/main/java/com/venomvendor/library/gson/NullDefenseTypeAdapterFactory.java rename to src/main/java/com/venomvendor/gson/NullDefenseTypeAdapterFactory.java index 7d81778..5612373 100644 --- a/src/main/java/com/venomvendor/library/gson/NullDefenseTypeAdapterFactory.java +++ b/src/main/java/com/venomvendor/gson/NullDefenseTypeAdapterFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.venomvendor.library.gson; +package com.venomvendor.gson; import com.google.gson.Gson; import com.google.gson.TypeAdapter; @@ -30,16 +30,15 @@ import java.lang.reflect.Type; import java.util.Collection; import java.util.Collections; -import java.util.Objects; /** - * Adapter for removing null objects & empty Collection once the object is created. + * Adapter for removing null objects & empty CollectionS, once object is created. *

* Incase of {@link Collection}, empty collection is invalid unless {@link #retainEmptyCollection()} - * is called explicility to retain empty collection. This can be useful incase of search results. + * is called explicitly to retain empty collection. This can be useful incase of search results. *

- * This also processess all collection & finally removes {@code null} from Collection, + * This also processes all collection & finally removes {@code null} from Collection, * further processes collection to remove all {@code null} from results.

  *   public class Parent {
  *        @Mandatory
@@ -76,7 +75,7 @@
  *         .create();
  * 
*/ -@SuppressWarnings("All") +@SuppressWarnings("WeakerAccess") public final class NullDefenseTypeAdapterFactory implements TypeAdapterFactory { /* Annotation by which variables are marked mandatory */ @@ -98,7 +97,9 @@ public final class NullDefenseTypeAdapterFactory implements TypeAdapterFactory { * @throws NullPointerException if annotated class is null */ public NullDefenseTypeAdapterFactory(Class annotatedType) { - Objects.requireNonNull(annotatedType, "Annotation class cannot be null"); + if (annotatedType == null) { + throw new NullPointerException("Annotation class cannot be null"); + } this.annotatedType = annotatedType; removeEmptyCollection(); } @@ -124,15 +125,18 @@ public NullDefenseTypeAdapterFactory retainEmptyCollection() { return this; } + /** + * {@inheritDoc} + */ @Override public TypeAdapter create(Gson gson, TypeToken type) { TypeAdapter author = gson.getDelegateAdapter(this, type); - return new DefensiveAdapter<>(author, discardEmpty, annotatedType); + return new DefensiveAdapter(author, discardEmpty, annotatedType); } /** * Adapter that removes null objects. - * A callback is recieved from Gson to read & write. + * A callback is received from Gson to read & write. * During {@link #read(JsonReader)} if return value is null, then this is ignored. * * @param Type of object. @@ -149,8 +153,6 @@ private static final class DefensiveAdapter extends TypeAdapter { DefensiveAdapter(TypeAdapter author, boolean discardEmpty, Class annotatedType) { - Objects.requireNonNull(author, "TypeAdapter cannot be null"); - Objects.requireNonNull(annotatedType, "Annotation cannot be null"); this.author = author; this.discardEmpty = discardEmpty; this.annotatedType = annotatedType; @@ -163,11 +165,12 @@ public void write(JsonWriter out, T value) throws IOException { @Override public T read(JsonReader reader) throws IOException { - // Usually never null + // Usually non-null if (reader == null) { return null; } // Get read value, after processing with gson + // This is where Object is created from json T result = author.read(reader); // if null, return it. @@ -186,12 +189,18 @@ public T read(JsonReader reader) throws IOException { * @return same result if not null or conditional empty, else {@code null} */ private T getFilteredData(T result) { - for (Field field : result.getClass().getDeclaredFields()) { + Class clz = result.getClass(); + boolean isMarkedInClz = clz.isAnnotationPresent(annotatedType); + + for (Field field : clz.getDeclaredFields()) { if (field.getType().isPrimitive()) { // Skip primitives continue; } - if (containsInvalidData(result, field)) { + + boolean isMarked = isMarkedInClz || field.isAnnotationPresent(annotatedType); + if (containsInvalidData(result, field, isMarked)) { + // Discard result & return null. return null; } } @@ -203,21 +212,21 @@ private T getFilteredData(T result) { /** * Check if data contains null or empty objects only on annotated fields * - * @param result data to process - * @param field declared variable in current object + * @param result data to process + * @param field declared variable in current object + * @param isMarked represents if current field is annotated * @return {@code true} if data is invalid */ - private boolean containsInvalidData(T result, Field field) { + private boolean containsInvalidData(T result, Field field, boolean isMarked) { // Check if current field is marked - if (field.isAnnotationPresent(annotatedType)) { + if (isMarked) { // To read private fields field.setAccessible(true); - if (hasInvalidData(result, field)) { - return true; - } + // Validate data + return hasInvalidData(result, field); } - // Data is valid + // Consider data as valid return false; } @@ -234,10 +243,11 @@ private boolean hasInvalidData(T result, Field field) { // Lil, costly operation. value = field.get(result); } catch (IllegalAccessException ex) { + // Can't help ex.printStackTrace(); } - // Check of emptyness + // Check for emptiness return isEmpty(value); } @@ -258,14 +268,14 @@ private boolean isEmpty(Object value) { * @param value data to process * @return {@code true} if data is invalid */ + @SuppressWarnings("SuspiciousMethodCalls") private boolean isEmptyCollection(Object value) { if (value instanceof Collection) { - Collection subCollection = ((Collection) value); + Collection subCollection = ((Collection) value); // Cost is O(N^2), due to rearrangement subCollection.removeAll(NULL_COLLECTION); - if (discardEmpty && subCollection.isEmpty()) { - return true; - } + // Remove object if collection is empty. + return discardEmpty && subCollection.isEmpty(); } return false; } diff --git a/src/test/java/com/venomvendor/library/gson/BaseTest.java b/src/test/java/com/venomvendor/gson/BaseTest.java similarity index 91% rename from src/test/java/com/venomvendor/library/gson/BaseTest.java rename to src/test/java/com/venomvendor/gson/BaseTest.java index 4424683..1464af8 100644 --- a/src/test/java/com/venomvendor/library/gson/BaseTest.java +++ b/src/test/java/com/venomvendor/gson/BaseTest.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package com.venomvendor.library.gson; +package com.venomvendor.gson; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.TypeAdapterFactory; -import com.venomvendor.library.gson.annotation.MandatoryTest; -import com.venomvendor.library.gson.util.ResourceHelperTest; +import com.venomvendor.gson.annotation.MandatoryTest; +import com.venomvendor.gson.util.ResourceHelperTest; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.TestInstance; diff --git a/src/test/java/com/venomvendor/library/gson/NullDefenseTypeAdapterFactoryTest.java b/src/test/java/com/venomvendor/gson/NullDefenseTypeAdapterFactoryTest.java similarity index 97% rename from src/test/java/com/venomvendor/library/gson/NullDefenseTypeAdapterFactoryTest.java rename to src/test/java/com/venomvendor/gson/NullDefenseTypeAdapterFactoryTest.java index ec569e8..5b9f210 100644 --- a/src/test/java/com/venomvendor/library/gson/NullDefenseTypeAdapterFactoryTest.java +++ b/src/test/java/com/venomvendor/gson/NullDefenseTypeAdapterFactoryTest.java @@ -14,15 +14,15 @@ * limitations under the License. */ -package com.venomvendor.library.gson; +package com.venomvendor.gson; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.TypeAdapterFactory; import com.google.gson.reflect.TypeToken; -import com.venomvendor.library.gson.annotation.MandatoryTest; -import com.venomvendor.library.gson.model.ChildTest; -import com.venomvendor.library.gson.model.ParentTest; +import com.venomvendor.gson.annotation.MandatoryTest; +import com.venomvendor.gson.model.ChildTest; +import com.venomvendor.gson.model.ParentTest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Tag; diff --git a/src/test/java/com/venomvendor/library/gson/annotation/MandatoryTest.java b/src/test/java/com/venomvendor/gson/annotation/MandatoryTest.java similarity index 90% rename from src/test/java/com/venomvendor/library/gson/annotation/MandatoryTest.java rename to src/test/java/com/venomvendor/gson/annotation/MandatoryTest.java index 0843bd3..5ed524f 100644 --- a/src/test/java/com/venomvendor/library/gson/annotation/MandatoryTest.java +++ b/src/test/java/com/venomvendor/gson/annotation/MandatoryTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.venomvendor.library.gson.annotation; +package com.venomvendor.gson.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -22,7 +22,7 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD}) +@Target({ElementType.FIELD, ElementType.TYPE}) public @interface MandatoryTest { } diff --git a/src/test/java/com/venomvendor/library/gson/model/ChildTest.java b/src/test/java/com/venomvendor/gson/model/ChildTest.java similarity index 88% rename from src/test/java/com/venomvendor/library/gson/model/ChildTest.java rename to src/test/java/com/venomvendor/gson/model/ChildTest.java index 444ea10..3905914 100644 --- a/src/test/java/com/venomvendor/library/gson/model/ChildTest.java +++ b/src/test/java/com/venomvendor/gson/model/ChildTest.java @@ -14,18 +14,17 @@ * limitations under the License. */ -package com.venomvendor.library.gson.model; +package com.venomvendor.gson.model; -import com.venomvendor.library.gson.annotation.MandatoryTest; +import com.venomvendor.gson.annotation.MandatoryTest; + +@MandatoryTest public class ChildTest { - @MandatoryTest private String name; private boolean isMale; - @MandatoryTest private int age; - @MandatoryTest private LanguageTest language; public String getName() { diff --git a/src/test/java/com/venomvendor/library/gson/model/LanguageTest.java b/src/test/java/com/venomvendor/gson/model/LanguageTest.java similarity index 76% rename from src/test/java/com/venomvendor/library/gson/model/LanguageTest.java rename to src/test/java/com/venomvendor/gson/model/LanguageTest.java index 7441b2c..0ee5b10 100644 --- a/src/test/java/com/venomvendor/library/gson/model/LanguageTest.java +++ b/src/test/java/com/venomvendor/gson/model/LanguageTest.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.venomvendor.library.gson.model; +package com.venomvendor.gson.model; -import com.venomvendor.library.gson.annotation.MandatoryTest; +import com.venomvendor.gson.annotation.MandatoryTest; import java.util.ArrayList; import java.util.List; @@ -25,6 +25,7 @@ public class LanguageTest { @MandatoryTest private List knownLanguages = new ArrayList<>(); + private List learning; public List getKnownLanguages() { return knownLanguages; @@ -33,4 +34,12 @@ public List getKnownLanguages() { public void setKnownLanguages(List knownLanguages) { this.knownLanguages = knownLanguages; } + + public List getLearning() { + return learning; + } + + public void setLearning(List learning) { + this.learning = learning; + } } diff --git a/src/test/java/com/venomvendor/library/gson/model/ParentTest.java b/src/test/java/com/venomvendor/gson/model/ParentTest.java similarity index 87% rename from src/test/java/com/venomvendor/library/gson/model/ParentTest.java rename to src/test/java/com/venomvendor/gson/model/ParentTest.java index 54c58a4..309042b 100644 --- a/src/test/java/com/venomvendor/library/gson/model/ParentTest.java +++ b/src/test/java/com/venomvendor/gson/model/ParentTest.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package com.venomvendor.library.gson.model; +package com.venomvendor.gson.model; import com.google.gson.annotations.SerializedName; -import com.venomvendor.library.gson.annotation.MandatoryTest; -import com.venomvendor.library.gson.util.CustomListTest; +import com.venomvendor.gson.annotation.MandatoryTest; +import com.venomvendor.gson.util.CustomListTest; public class ParentTest { diff --git a/src/test/java/com/venomvendor/library/gson/util/CustomListTest.java b/src/test/java/com/venomvendor/gson/util/CustomListTest.java similarity index 94% rename from src/test/java/com/venomvendor/library/gson/util/CustomListTest.java rename to src/test/java/com/venomvendor/gson/util/CustomListTest.java index 799d16c..5e985ab 100644 --- a/src/test/java/com/venomvendor/library/gson/util/CustomListTest.java +++ b/src/test/java/com/venomvendor/gson/util/CustomListTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.venomvendor.library.gson.util; +package com.venomvendor.gson.util; import java.util.ArrayList; diff --git a/src/test/java/com/venomvendor/library/gson/util/ResourceHelperTest.java b/src/test/java/com/venomvendor/gson/util/ResourceHelperTest.java similarity index 97% rename from src/test/java/com/venomvendor/library/gson/util/ResourceHelperTest.java rename to src/test/java/com/venomvendor/gson/util/ResourceHelperTest.java index d80b7b7..9b57063 100644 --- a/src/test/java/com/venomvendor/library/gson/util/ResourceHelperTest.java +++ b/src/test/java/com/venomvendor/gson/util/ResourceHelperTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.venomvendor.library.gson.util; +package com.venomvendor.gson.util; import java.io.File; import java.io.IOException; diff --git a/version.gradle.kts b/version.gradle.kts index a63ea7c..0189c33 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -1,6 +1,6 @@ -extra["major"] = 1 +extra["major"] = 2 extra["minor"] = 0 -extra["patch"] = 1 +extra["patch"] = 0 val suffix = "" val version = "${extra["major"]}.${extra["minor"]}.${extra["patch"]}"