Groovy の Canonical アノテーションっぽいのを Xtend で
@Data が使えたら楽なんですが mutable な物の場合 @Data が使えません。とりあえず equals, hashCode, toString を追加したいなーという時用の Active Annotation 書いてみました。
適当なので、commons-lang に思いっきり依存してます。
import java.lang.annotation.ElementType import java.lang.annotation.Retention import java.lang.annotation.RetentionPolicy import java.lang.annotation.Target import org.eclipse.xtend.lib.macro.AbstractClassProcessor import org.eclipse.xtend.lib.macro.Active import org.eclipse.xtend.lib.macro.TransformationContext import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) @Active(CanonitalProcessor) annotation Canonical { } class CanonitalProcessor extends AbstractClassProcessor { override doTransform(MutableClassDeclaration annotatedClass, extension TransformationContext context) { annotatedClass.addMethod("toString") [ returnType = string body = ['''return «toJavaCode(newTypeReference("org.apache.commons.lang3.builder.ToStringBuilder"))».reflectionToString(this);'''] addAnnotation(Override.findTypeGlobally) ] annotatedClass.addMethod("equals") [ returnType = primitiveBoolean addParameter("value", object) body = ['''return «toJavaCode(newTypeReference("org.apache.commons.lang3.builder.EqualsBuilder"))».reflectionEquals(this, value, false);'''] addAnnotation(Override.findTypeGlobally) ] annotatedClass.addMethod("hashCode") [ returnType = primitiveInt body = ['''return «toJavaCode(newTypeReference("org.apache.commons.lang3.builder.HashCodeBuilder"))».reflectionHashCode(this, false);'''] addAnnotation(Override.findTypeGlobally) ] // .java には Canonical アノテーションを残さない annotatedClass.findAnnotation(Canonical.findTypeGlobally).remove } }
使う方は、
@Canonical class User { @Property int id @Property String name }
これでこんな .java を吐きます。
import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; @SuppressWarnings("all") public class User { private int _id; public int getId() { return this._id; } public void setId(final int id) { this._id = id; } private String _name; public String getName() { return this._name; } public void setName(final String name) { this._name = name; } @Override public String toString() { return ToStringBuilder.reflectionToString(this); } @Override public boolean equals(final Object value) { return EqualsBuilder.reflectionEquals(this, value, false); } @Override public int hashCode() { return HashCodeBuilder.reflectionHashCode(this, false); } }