diff --git a/src/main/java/com/jmethods/catatumbo/OverrideKind.java b/src/main/java/com/jmethods/catatumbo/OverrideKind.java new file mode 100644 index 0000000..29cb76f --- /dev/null +++ b/src/main/java/com/jmethods/catatumbo/OverrideKind.java @@ -0,0 +1,35 @@ +/* + * Copyright 2016 Sai Pullabhotla. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jmethods.catatumbo; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * A class annotated with OverrideKind specifies a new kind for the enclosing @{@link Entity} + * when using within an @{@link Embedded} field. + * Only @{@link Embeddable} classes can be annotated with this annotation. + * + * @author Aurelien Thieriot + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface OverrideKind { + + String kind(); +} diff --git a/src/main/java/com/jmethods/catatumbo/impl/EntityIntrospector.java b/src/main/java/com/jmethods/catatumbo/impl/EntityIntrospector.java index 079ea29..f72f790 100644 --- a/src/main/java/com/jmethods/catatumbo/impl/EntityIntrospector.java +++ b/src/main/java/com/jmethods/catatumbo/impl/EntityIntrospector.java @@ -15,24 +15,16 @@ */ package com.jmethods.catatumbo.impl; -import java.lang.reflect.Field; -import java.time.OffsetDateTime; -import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.List; - import com.jmethods.catatumbo.CreatedTimestamp; import com.jmethods.catatumbo.DatastoreKey; +import com.jmethods.catatumbo.Embeddable; import com.jmethods.catatumbo.Embedded; import com.jmethods.catatumbo.Entity; import com.jmethods.catatumbo.EntityManagerException; import com.jmethods.catatumbo.Identifier; import com.jmethods.catatumbo.Key; import com.jmethods.catatumbo.MappedSuperClass; +import com.jmethods.catatumbo.OverrideKind; import com.jmethods.catatumbo.ParentKey; import com.jmethods.catatumbo.ProjectedEntity; import com.jmethods.catatumbo.Property; @@ -41,6 +33,16 @@ import com.jmethods.catatumbo.UpdatedTimestamp; import com.jmethods.catatumbo.Version; +import java.lang.reflect.Field; +import java.time.OffsetDateTime; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.List; + /** * Introspector for model classes with the annotation of {@link Entity} or * {@link ProjectedEntity}. The introspect method gathers metadata about the @@ -228,6 +230,7 @@ private void processFields() { processParentKeyField(field); } else if (field.isAnnotationPresent(Embedded.class)) { processEmbeddedField(field); + processOverrideKind(field); } else { processField(field); } @@ -421,6 +424,30 @@ private void processEmbeddedField(Field field) { entityMetadata.putEmbeddedMetadata(embeddedMetadata); } + /** + * Process an OverrideKind annotation on an embedded field and + * update the current entity metadata if needs be + * + * @param field + * the embedded field + */ + private void processOverrideKind(Field field) { + OverrideKind overrideKind = field.getType().getAnnotation(OverrideKind.class); + Embeddable embeddable = field.getType().getAnnotation(Embeddable.class); + + if (overrideKind != null) { + if (embeddable == null) { + String message = String.format("A class annotated with %s must also be annotated with %s", + OverrideKind.class.getName(), + Embeddable.class.getName() + ); + throw new EntityManagerException(message); + } + + entityMetadata.setKind(overrideKind.kind()); + } + } + /** * Convenient method for getting the metadata of the field used for * optimistic locking. diff --git a/src/main/java/com/jmethods/catatumbo/impl/EntityMetadata.java b/src/main/java/com/jmethods/catatumbo/impl/EntityMetadata.java index 2040c23..10ca65e 100644 --- a/src/main/java/com/jmethods/catatumbo/impl/EntityMetadata.java +++ b/src/main/java/com/jmethods/catatumbo/impl/EntityMetadata.java @@ -166,6 +166,16 @@ public String getKind() { return kind; } + /** + * Sets the metadata Kind. + * + * @param kind + * entity kind parameter + */ + public void setKind(String kind) { + this.kind = kind; + } + /** * Returns the metadata of the identifier. * diff --git a/src/test/java/com/jmethods/catatumbo/entities/WrappedZipCode.java b/src/test/java/com/jmethods/catatumbo/entities/WrappedZipCode.java new file mode 100644 index 0000000..a1700c1 --- /dev/null +++ b/src/test/java/com/jmethods/catatumbo/entities/WrappedZipCode.java @@ -0,0 +1,115 @@ +/* + * Copyright 2016 Sai Pullabhotla. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.jmethods.catatumbo.entities; + +import com.jmethods.catatumbo.Embeddable; +import com.jmethods.catatumbo.Embedded; +import com.jmethods.catatumbo.OverrideKind; +import com.jmethods.catatumbo.Property; + +import java.util.Objects; + +/** + * @author Aurelien Thieriot + * + */ +@Embeddable +@OverrideKind(kind = "wrapped") +public class WrappedZipCode { + + @Property(name = "zip") + private String fiveDigits; + + @Property(name = "zipx", indexed = false, optional = true) + private String fourDigits; + + @Embedded(name = "useless", indexed = true) + private AnotherEmbeddable anotherEmbeddable = new AnotherEmbeddable(); + + /** + * + */ + public WrappedZipCode() { + // TODO Auto-generated constructor stub + } + + /** + * @return the fiveDigits + */ + public String getFiveDigits() { + return fiveDigits; + } + + /** + * @param fiveDigits + * the fiveDigits to set + */ + public void setFiveDigits(String fiveDigits) { + this.fiveDigits = fiveDigits; + } + + /** + * @return the fourDigits + */ + public String getFourDigits() { + return fourDigits; + } + + /** + * @param fourDigits + * the fourDigits to set + */ + public void setFourDigits(String fourDigits) { + this.fourDigits = fourDigits; + } + + @Override + public String toString() { + return fiveDigits + "-" + fourDigits; + } + + @Override + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof ZipCode)) { + return false; + } + WrappedZipCode that = (WrappedZipCode) obj; + return Objects.equals(this.fiveDigits, that.fiveDigits) && Objects.equals(this.fourDigits, that.fourDigits) + && Objects.equals(this.anotherEmbeddable, that.anotherEmbeddable); + } + + @Override + public int hashCode() { + return Objects.hash(fiveDigits, fourDigits, anotherEmbeddable); + } + + /** + * @return the anotherEmbeddable + */ + public AnotherEmbeddable getAnotherEmbeddable() { + return anotherEmbeddable; + } + + /** + * @param anotherEmbeddable + * the anotherEmbeddable to set + */ + public void setAnotherEmbeddable(AnotherEmbeddable anotherEmbeddable) { + this.anotherEmbeddable = anotherEmbeddable; + } + +} diff --git a/src/test/java/com/jmethods/catatumbo/entities/ZipCodeWrapper.java b/src/test/java/com/jmethods/catatumbo/entities/ZipCodeWrapper.java new file mode 100644 index 0000000..402a575 --- /dev/null +++ b/src/test/java/com/jmethods/catatumbo/entities/ZipCodeWrapper.java @@ -0,0 +1,67 @@ +/* + * Copyright 2016 Sai Pullabhotla. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.jmethods.catatumbo.entities; + +import com.jmethods.catatumbo.Embedded; +import com.jmethods.catatumbo.Entity; +import com.jmethods.catatumbo.Identifier; + +/** + * @author Aurelien Thieriot + * + */ +@Entity(kind = "generic") +public class ZipCodeWrapper { + + @Identifier + private long id; + + @Embedded + private WrappedZipCode wrappedZipCode; + + public ZipCodeWrapper() { + + } + + public ZipCodeWrapper(long id, WrappedZipCode wrappedZipCode) { + this.id = id; + this.wrappedZipCode = wrappedZipCode; + } + + /** + * @return the id + */ + public long getId() { + return id; + } + + /** + * @param id + * the id to set + */ + public void setId(long id) { + this.id = id; + } + + public WrappedZipCode getWrappedZipCode() { + return wrappedZipCode; + } + + public void setWrappedZipCode(WrappedZipCode wrappedZipCode) { + this.wrappedZipCode = wrappedZipCode; + } +} diff --git a/src/test/java/com/jmethods/catatumbo/impl/EntityIntrospectorTest.java b/src/test/java/com/jmethods/catatumbo/impl/EntityIntrospectorTest.java index d06f0ef..11905f6 100644 --- a/src/test/java/com/jmethods/catatumbo/impl/EntityIntrospectorTest.java +++ b/src/test/java/com/jmethods/catatumbo/impl/EntityIntrospectorTest.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.Objects; +import com.jmethods.catatumbo.entities.ZipCodeWrapper; import org.junit.Test; import com.jmethods.catatumbo.EntityManagerException; @@ -153,6 +154,12 @@ public void testIntrospect_TaskName() { assertEquals(1, entityMetadata.getPropertyMetadataCollection().size()); } + @Test + public void testIntrospect_ZipCodeWrapper() { + EntityMetadata entityMetadata = EntityIntrospector.introspect(ZipCodeWrapper.class); + assertEquals("wrapped", entityMetadata.getKind()); + } + @Test(expected = EntityManagerException.class) public void testIntrospect_Button() { try {