import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
-import org.opendaylight.yangtools.yang.common.QName\r
-\r
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl
+
public class BindingGeneratorImpl implements BindingGenerator {
private final Map<Module, ModuleContext> genCtx = new HashMap()
processUsesAugments(node, module)
val List<String> listKeys = listKeys(node);
- val genTOBuilder = resolveListKeyTOBuilder(packageName, node);
+ val genTOBuilder = resolveListKeyTOBuilder(packageName, node);\r
- if (genTOBuilder !== null) {
+ if (genTOBuilder !== null) {\r
+ val GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");\r
+ prop.setValue(Long.toString(computeDefaultSUID(genTOBuilder as GeneratedTOBuilderImpl)));\r
+ genTOBuilder.setSUID(prop);
val identifierMarker = IDENTIFIER.parameterizedTypeFor(genType);
val identifiableMarker = IDENTIFIABLE.parameterizedTypeFor(genTOBuilder);
genTOBuilder.addImplementsType(identifierMarker);
private def GeneratedTOBuilder resolveListKeyTOBuilder(String packageName, ListSchemaNode list) {
var GeneratedTOBuilder genTOBuilder = null;
if ((list.keyDefinition !== null) && (!list.keyDefinition.isEmpty())) {
- if (list !== null) {
- val listName = list.QName.localName + "Key";
- val String genTOName = parseToClassName(listName);
- genTOBuilder = new GeneratedTOBuilderImpl(packageName, genTOName);
- }
+ val listName = list.QName.localName + "Key";
+ val String genTOName = parseToClassName(listName);
+ genTOBuilder = new GeneratedTOBuilderImpl(packageName, genTOName);
}
return genTOBuilder;
}
package org.opendaylight.yangtools.binding.generator.util;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.TypeMemberBuilder;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
return sb.toString();
}
+ public static long computeDefaultSUID(GeneratedTOBuilderImpl to) {
+ try {
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ DataOutputStream dout = new DataOutputStream(bout);
+
+ dout.writeUTF(to.getName());
+ dout.writeInt(to.isAbstract() ? 3 : 7);
+
+ List<Type> impl = to.getImplementsTypes();
+ Collections.sort(impl, new Comparator<Type>() {
+ @Override
+ public int compare(Type o1, Type o2) {
+ return o1.getFullyQualifiedName().compareTo(o2.getFullyQualifiedName());
+ }
+ });
+ for (Type ifc : impl) {
+ dout.writeUTF(ifc.getFullyQualifiedName());
+ }
+
+ Comparator<TypeMemberBuilder<?>> comparator = new Comparator<TypeMemberBuilder<?>>() {
+ @Override
+ public int compare(TypeMemberBuilder<?> o1, TypeMemberBuilder<?> o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ };
+
+ List<GeneratedPropertyBuilder> props = to.getProperties();
+ Collections.sort(props, comparator);
+ for (GeneratedPropertyBuilder gp : props) {
+ dout.writeUTF(gp.getName());
+ }
+
+ List<MethodSignatureBuilder> methods = to.getMethodDefinitions();
+ Collections.sort(methods, comparator);
+ for (MethodSignatureBuilder m : methods) {
+ if (!(m.getAccessModifier().equals(AccessModifier.PRIVATE))) {
+ dout.writeUTF(m.getName());
+ dout.write(m.getAccessModifier().ordinal());
+ }
+ }
+
+ dout.flush();
+
+ MessageDigest md = MessageDigest.getInstance("SHA");
+ byte[] hashBytes = md.digest(bout.toByteArray());
+ long hash = 0;
+ for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
+ hash = (hash << 8) | (hashBytes[i] & 0xFF);
+ }
+ return hash;
+ } catch (IOException ex) {
+ throw new InternalError();
+ } catch (NoSuchAlgorithmException ex) {
+ throw new SecurityException(ex.getMessage());
+ }
+ }
+
public static Restrictions getRestrictions(TypeDefinition<?> type) {
final List<LengthConstraint> length = new ArrayList<>();
final List<PatternConstraint> pattern = new ArrayList<>();
*/
package org.opendaylight.yangtools.binding.generator.util.generated.type.builder;
+import java.util.ArrayList;
+import java.util.List;
+
import org.opendaylight.yangtools.binding.generator.util.AbstractBaseType;
import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
import org.opendaylight.yangtools.sal.binding.model.api.Constant;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
-import org.opendaylight.yangtools.sal.binding.model.api.type.builder.*;
-
-import java.util.ArrayList;
-import java.util.List;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.EnumBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
abstract class AbstractGeneratedTypeBuilder<T extends GeneratedTypeBuilderBase<T>> extends AbstractBaseType implements
GeneratedTypeBuilderBase<T> {
return annotationBuilders;
}
- protected boolean isAbstract() {
+ public boolean isAbstract() {
return isAbstract;
}
- protected List<Type> getImplementsTypes() {
+ public List<Type> getImplementsTypes() {
return implementsTypes;
}
return constants;
}
- protected List<MethodSignatureBuilder> getMethodDefinitions() {
+ public List<MethodSignatureBuilder> getMethodDefinitions() {
return methodDefinitions;
}
return null;
}
- protected List<GeneratedPropertyBuilder> getProperties() {
+ public List<GeneratedPropertyBuilder> getProperties() {
return properties;
}
}
package org.opendaylight.yangtools.binding.generator.util.generated.type.builder;\r
\r
\r
+import java.util.Collections;\r
+import java.util.List;\r
+\r
import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;\r
import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;\r
import org.opendaylight.yangtools.sal.binding.model.api.Type;\r
import org.opendaylight.yangtools.sal.binding.model.api.TypeMember;\r
\r
-import java.util.Collections;\r
-import java.util.List;\r
-\r
abstract class AbstractTypeMember implements TypeMember {\r
\r
private final String name;\r
private final Type returnType;\r
private final List<AnnotationType> annotations;\r
private final boolean isFinal;\r
+ private final boolean isStatic;\r
private final AccessModifier accessModifier;\r
\r
public AbstractTypeMember(final Type definingType, final String name, final List<AnnotationType> annotations,\r
final String comment, final AccessModifier accessModifier, final Type returnType,\r
- boolean isFinal) {\r
+ boolean isFinal, boolean isStatic) {\r
super();\r
this.definingType = definingType;\r
this.name = name;\r
this.accessModifier = accessModifier;\r
this.returnType = returnType;\r
this.isFinal = isFinal;\r
+ this.isStatic = isStatic;\r
}\r
\r
@Override\r
return isFinal;\r
}\r
\r
+ @Override\r
+ public boolean isStatic() {\r
+ return isStatic;\r
+ }\r
+\r
@Override\r
public int hashCode() {\r
final int prime = 31;\r
*/
package org.opendaylight.yangtools.binding.generator.util.generated.type.builder;
+import java.util.ArrayList;
+import java.util.List;
+
import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder;
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.TypeMemberBuilder;
-import java.util.ArrayList;
-import java.util.List;
-
abstract class AbstractTypeMemberBuilder<T extends TypeMemberBuilder<T>> implements TypeMemberBuilder<T> {
private final String name;
private Type returnType;
private final List<AnnotationTypeBuilder> annotationBuilders;
private String comment = "";
private boolean isFinal;
+ private boolean isStatic;
private AccessModifier accessModifier;
public AbstractTypeMemberBuilder(final String name) {
return isFinal;
}
- protected AccessModifier getAccessModifier() {
+ protected boolean isStatic() {
+ return isStatic;
+ }
+
+ @Override
+ public AccessModifier getAccessModifier() {
return accessModifier;
}
}
protected abstract T thisInstance();
-
+
@Override
public T setReturnType(Type returnType) {
if (returnType == null) {
return thisInstance();
}
+ @Override
+ public T setStatic(boolean isStatic) {
+ this.isStatic = isStatic;
+ return thisInstance();
+ }
+
protected List<AnnotationType> toAnnotationTypes() {
final List<AnnotationType> annotations = new ArrayList<>();
for (final AnnotationTypeBuilder annotBuilder : getAnnotationBuilders()) {
*/
package org.opendaylight.yangtools.binding.generator.util.generated.type.builder;
+import java.util.List;
+
import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
-import java.util.List;
-
-final class GeneratedPropertyBuilderImpl extends AbstractTypeMemberBuilder<GeneratedPropertyBuilder> implements GeneratedPropertyBuilder {
-
+public final class GeneratedPropertyBuilderImpl extends AbstractTypeMemberBuilder<GeneratedPropertyBuilder> implements GeneratedPropertyBuilder {
+ private String value;
private boolean isReadOnly;
public GeneratedPropertyBuilderImpl(String name) {
this.isReadOnly = true;
}
+ @Override
+ public GeneratedPropertyBuilderImpl setValue(String value) {
+ this.value = value;
+ return this;
+ }
+
@Override
public GeneratedPropertyBuilderImpl setReadOnly(boolean isReadOnly) {
this.isReadOnly = isReadOnly;
protected GeneratedPropertyBuilderImpl thisInstance() {
return this;
}
-
+
@Override
public GeneratedProperty toInstance(Type definingType) {
final List<AnnotationType> annotations = toAnnotationTypes();
return new GeneratedPropertyImpl(definingType, getName(), annotations, getComment(), getAccessModifier(),
- getReturnType(), isFinal(), isReadOnly);
+ getReturnType(), isFinal(), isStatic(), isReadOnly, value);
}
@Override
*/
package org.opendaylight.yangtools.binding.generator.util.generated.type.builder;
+import java.util.List;
+
import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
-import java.util.List;
-
final class GeneratedPropertyImpl extends AbstractTypeMember implements GeneratedProperty {
-
+ private String value;
private boolean isReadOnly;
public GeneratedPropertyImpl(Type definingType, String name, List<AnnotationType> annotations, String comment,
- AccessModifier accessModifier, Type returnType, boolean isFinal, boolean isReadOnly) {
- super(definingType, name, annotations, comment, accessModifier, returnType, isFinal);
+ AccessModifier accessModifier, Type returnType, boolean isFinal, boolean isStatic, boolean isReadOnly, String value) {
+ super(definingType, name, annotations, comment, accessModifier, returnType, isFinal, isStatic);
+ this.value = value;
this.isReadOnly = isReadOnly;
}
+ @Override
+ public String getValue() {
+ return value;
+ }
+
@Override
public boolean isReadOnly() {
return isReadOnly;
private final List<GeneratedPropertyBuilder> toStringProperties = new ArrayList<>();\r
private boolean isUnionType = false;\r
private Restrictions restrictions;\r
+ private GeneratedPropertyBuilder SUID;\r
\r
public GeneratedTOBuilderImpl(String packageName, String name) {\r
super(packageName, name);\r
this.restrictions = restrictions;\r
}\r
\r
+ @Override\r
+ public void setSUID(GeneratedPropertyBuilder suid) {\r
+ this.SUID = suid;\r
+ }\r
+\r
@Override\r
public GeneratedTransferObject toInstance() {\r
return new GeneratedTransferObjectImpl(this);\r
private final GeneratedTransferObject extendsType;\r
private final boolean isUnionType;\r
private final Restrictions restrictions;\r
+ private final GeneratedProperty SUID;\r
\r
public GeneratedTransferObjectImpl(GeneratedTOBuilderImpl builder) {\r
super(builder);\r
this.stringProperties = toUnmodifiableProperties(builder.toStringProperties);\r
this.isUnionType = builder.isUnionType;\r
this.restrictions = builder.restrictions;\r
+ if (builder.SUID == null) {\r
+ this.SUID = null;\r
+ } else {\r
+ this.SUID = builder.SUID.toInstance(GeneratedTransferObjectImpl.this);\r
+ }\r
}\r
\r
@Override\r
return restrictions;\r
}\r
\r
+ @Override\r
+ public GeneratedProperty getSUID() {\r
+ return SUID;\r
+ }\r
+\r
@Override\r
public String toString() {\r
StringBuilder builder = new StringBuilder();\r
protected MethodSignatureBuilder thisInstance() {
return this;
}
-
+
@Override
public MethodSignature toInstance(Type definingType) {
final List<AnnotationType> annotations = toAnnotationTypes();
return new MethodSignatureImpl(definingType, getName(), annotations, getComment(), getAccessModifier(),
- getReturnType(), parameters, isFinal(), isAbstract);
+ getReturnType(), parameters, isFinal(), isAbstract, isStatic());
}
@Override
*/
package org.opendaylight.yangtools.binding.generator.util.generated.type.builder;
+import java.util.Collections;
+import java.util.List;
+
import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
-import java.util.Collections;
-import java.util.List;
-
class MethodSignatureImpl extends AbstractTypeMember implements MethodSignature {
private final List<Parameter> params;
final List<AnnotationType> annotations,
final String comment, final AccessModifier accessModifier,
final Type returnType, final List<Parameter> params, boolean isFinal,
- boolean isAbstract) {
- super(definingType, name, annotations, comment, accessModifier, returnType, isFinal);
+ boolean isAbstract, boolean isStatic) {
+ super(definingType, name, annotations, comment, accessModifier, returnType, isFinal, isStatic);
this.params = Collections.unmodifiableList(params);
this.isAbstract = isAbstract;
}
this.consts = genType.constantDefinitions\r
this.enclosedGeneratedTypes = genType.enclosedTypes\r
}\r
- \r
\r
- \r
- \r
- \r
+\r
/**\r
* Generates JAVA class source code (class body only).\r
* \r
def CharSequence generateAsInnerClass() {\r
return generateBody(true)\r
}\r
- \r
\r
- \r
+\r
override protected body() {\r
generateBody(false);\r
}\r
def protected generateBody(boolean isInnerClass) '''\r
«type.comment.asJavadoc»\r
«generateClassDeclaration(isInnerClass)» {\r
- «innerClassesDeclarations»\r
+ «suidDeclaration»\r
+ «innerClassesDeclarations»\r
«enumDeclarations»\r
«constantsDeclarations»\r
«generateFields»\r
\r
}\r
'''\r
- \r
- \r
+\r
+\r
/**\r
* Template method which generates inner classes inside this interface.\r
* \r
«ENDFOR»\r
«ENDIF»\r
'''\r
- \r
+\r
+ def protected suidDeclaration() '''\r
+ «IF genTO.SUID != null»\r
+ private static final long serialVersionUID = «genTO.SUID.value»L; \r
+ «ENDIF»\r
+ '''\r
+\r
/**\r
* Template method wich generates JAVA constants.\r
* \r
import java.io.File;
import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.WildcardType;
// test generated 'list links'
assertTrue(linksClass.isInterface());
- // FIXME: anyxml
+ // TODO: anyxml
assertEquals(5, linksClass.getDeclaredMethods().length);
testImplementsIfc(linksClass, keyArgsClass);
// Test list key constructor arguments ordering
assertContainsConstructor(linksKeyClass, Byte.class, String.class, Integer.class);
+ // Test serialVersionUID generation
+ Field suid = assertContainsField(linksKeyClass, "serialVersionUID", Long.TYPE);
+ suid.setAccessible(true);
+ assertEquals(9028898643007565383L, suid.getLong(null));
cleanUp(sourcesOutputDir, compiledOutputDir);
}
}
}
- static void assertContainsField(Class<?> clazz, String name, Class<?> type) {
+ static Field assertContainsField(Class<?> clazz, String name, Class<?> type) {
try {
Field f = clazz.getDeclaredField(name);
assertEquals(type, f.getType());
+ return f;
} catch (NoSuchFieldException e) {
throw new AssertionError("Field " + name + " does not exists in class " + clazz.getSimpleName());
}
* The Generated Property interface is designed to store information of fields
* (or members) declared in Java Transfer Objects (or any java classes) and
* their access counterparts (getters and setters).
- *
+ *
* @see MethodSignature
*/
public interface GeneratedProperty extends TypeMember {
+ String getValue();
+
/**
* Returns <code>true</code> if the property si declared as read-only. <br>
* If the property has flag <code>isReadOnly == true</code> the property
* SHOULD be generated as getter only.
- *
+ *
* @return <code>true</code> if the property si declared as read-only.
*/
boolean isReadOnly();
*/
public interface GeneratedTransferObject extends GeneratedType {
+ GeneratedProperty getSUID();
+
/**
* Returns the extending Generated Transfer Object or <code>null</code> if
* there is no extending Generated Transfer Object.
import java.util.List;
+/**
+ * Common interface for variables and methods in class.
+ */
public interface TypeMember {
+ /**
+ * Returns comment string associated with member.
+ *
+ * @return comment string associated with member.
+ */
+ String getComment();
+
/**
* Returns List of annotation definitions associated with generated type.
- *
+ *
* @return List of annotation definitions associated with generated type.
*/
List<AnnotationType> getAnnotations();
/**
- * Returns the name of method.
- *
- * @return the name of method.
+ * Returns the access modifier of member.
+ *
+ * @return the access modifier of member.
*/
- String getName();
+ AccessModifier getAccessModifier();
/**
- * Returns comment string associated with method.
- *
- * @return comment string associated with method.
+ * Returns <code>true</code> if member is declared as static.
+ *
+ * @return <code>true</code> if member is declared as static.
*/
- String getComment();
+ boolean isStatic();
/**
- * Returns the Type that declares method.
- *
- * @return the Type that declares method.
+ * Returns <code>true</code> if member is declared as final.
+ *
+ * @return <code>true</code> if member is declared as final.
*/
- Type getDefiningType();
+ boolean isFinal();
/**
- * Returns the access modifier of method.
- *
- * @return the access modifier of method.
+ * Get the returning Type of member.
+ *
+ * @return the returning Type of member.
*/
- AccessModifier getAccessModifier();
+ Type getReturnType();
/**
- * Returns the returning Type that methods returns.
- *
- * @return the returning Type that methods returns.
+ * Returns the name of member.
+ *
+ * @return the name of member.
*/
- Type getReturnType();
+ String getName();
/**
- * Returns <code>true</code> if method is declared as final.
- *
- * @return <code>true</code> if method is declared as final.
+ * Returns the Type that declares member.
+ *
+ * @return the Type that declares member.
*/
- boolean isFinal();
+ Type getDefiningType();
+
}
/**
* Generated Property Builder is interface that contains methods to build and
* instantiate Generated Property definition.
- *
+ *
* @see GeneratedProperty
*/
public interface GeneratedPropertyBuilder extends TypeMemberBuilder<GeneratedPropertyBuilder> {
+ GeneratedPropertyBuilder setValue(String value);
+
/**
* Sets isReadOnly flag for property. If property is marked as read only it
* is the same as set property in java as final.
- *
+ *
* @param isReadOnly
* Read Only property flag.
*/
* <code>class</code> definition. In case that defining Type will be passed
* as <code>null</code> reference the method SHOULD thrown
* {@link IllegalArgumentException}.
- *
+ *
* @param definingType
* Defining Type of Generated Property
* @return <code>new</code> <i>immutable</i> instance of Generated Property.
* @param isUnion
*/
void setIsUnion(boolean isUnion);
+
+ void setSUID(GeneratedPropertyBuilder suid);
}
* Neither the package name or annotation name can contain <code>null</code>
* references. In case that any of parameters contains <code>null</code> the
* method SHOULD thrown {@link IllegalArgumentException}
- *
+ *
* @param packageName
* Package Name of Annotation Type
* @param name
/**
* Returns the name of property.
- *
+ *
* @return the name of property.
*/
String getName();
* Adds return Type into Builder definition for Generated Property. <br>
* The return Type MUST NOT be <code>null</code>, otherwise the method
* SHOULD throw {@link IllegalArgumentException}
- *
+ *
* @param returnType
* Return Type of property.
*/
T setReturnType(final Type returnType);
+ AccessModifier getAccessModifier();
+
/**
* Sets the access modifier of property.
- *
+ *
* @param modifier
* Access Modifier value.
*/
* Adds String definition of comment into Method Signature definition. <br>
* The comment String MUST NOT contain anny comment specific chars (i.e.
* "/**" or "//") just plain String text description.
- *
+ *
* @param comment
* Comment String.
*/
* be prohibited from overriding. <br>
* This setting is irrelevant for methods designated to be defined in
* interface definitions because interface can't have final method.
- *
+ *
* @param isFinal
* Is Final
*/
T setFinal(final boolean isFinal);
+
+ T setStatic(final boolean isStatic);
}