From: Tony Tkacik Date: Mon, 21 Jul 2014 08:15:04 +0000 (+0000) Subject: Merge "BUG-1276: fixed generated union constructor" X-Git-Tag: release/helium~321 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=27311d19e3b2ea039726f512932022ce0184f418;hp=2b26351fad1af347c60c20762de92be8a5f229a1;p=yangtools.git Merge "BUG-1276: fixed generated union constructor" --- diff --git a/.gitignore b/.gitignore index d4bca56522..3e8b88f5c0 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,5 @@ target *.iml .idea bin -**/src/main/xtend-gen +xtend-gen target diff --git a/code-generator/binding-generator-impl/pom.xml b/code-generator/binding-generator-impl/pom.xml index fbf4098b05..39a98ad1ef 100644 --- a/code-generator/binding-generator-impl/pom.xml +++ b/code-generator/binding-generator-impl/pom.xml @@ -93,29 +93,6 @@ org.eclipse.xtend xtend-maven-plugin - - - - compile - - - ${basedir}/src/main/xtend-gen - - - - - - maven-clean-plugin - - - - ${basedir}/src/main/xtend-gen - - ** - - - - diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.java index b4837dc185..0e6a8e473c 100644 --- a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.java +++ b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.java @@ -11,7 +11,6 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.computeDefaultSUID; -import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.moduleNamespaceToPackageName; import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.packageNameForGeneratedType; import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.parseToValidParamName; import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.DATA_OBJECT; @@ -240,7 +239,7 @@ public class BindingGeneratorImpl implements BindingGenerator { if (!m.getChildNodes().isEmpty()) { final GeneratedTypeBuilder moduleType = moduleToDataType(m); genCtx.get(m).addModuleNode(moduleType); - final String basePackageName = moduleNamespaceToPackageName(m); + final String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule()); resolveDataSchemaNodes(m, basePackageName, moduleType, moduleType, m.getChildNodes()); } } @@ -336,7 +335,7 @@ public class BindingGeneratorImpl implements BindingGenerator { } private void processUsesAugments(final DataNodeContainer node, final Module module) { - final String basePackageName = moduleNamespaceToPackageName(module); + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); for (UsesNode usesNode : node.getUses()) { for (AugmentationSchema augment : usesNode.getAugmentations()) { usesAugmentationToGenTypes(basePackageName, augment, module, usesNode, node); @@ -365,7 +364,7 @@ public class BindingGeneratorImpl implements BindingGenerator { checkArgument(module.getName() != null, "Module name cannot be NULL."); checkState(module.getAugmentations() != null, "Augmentations Set cannot be NULL."); - final String basePackageName = moduleNamespaceToPackageName(module); + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); final List augmentations = resolveAugmentations(module); for (AugmentationSchema augment : augmentations) { augmentationToGenTypes(basePackageName, augment, module); @@ -442,7 +441,7 @@ public class BindingGeneratorImpl implements BindingGenerator { return; } - final String basePackageName = moduleNamespaceToPackageName(module); + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(module, "Service"); interfaceBuilder.addImplementsType(Types.typeForClass(RpcService.class)); for (RpcDefinition rpc : rpcDefinitions) { @@ -512,7 +511,7 @@ public class BindingGeneratorImpl implements BindingGenerator { final GeneratedTypeBuilder listenerInterface = moduleTypeBuilder(module, "Listener"); listenerInterface.addImplementsType(BindingTypes.NOTIFICATION_LISTENER); - final String basePackageName = moduleNamespaceToPackageName(module); + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); for (NotificationDefinition notification : notifications) { if (notification != null) { @@ -550,7 +549,7 @@ public class BindingGeneratorImpl implements BindingGenerator { */ private void allIdentitiesToGenTypes(final Module module, final SchemaContext context) { final Set schemaIdentities = module.getIdentities(); - final String basePackageName = moduleNamespaceToPackageName(module); + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); if (schemaIdentities != null && !schemaIdentities.isEmpty()) { for (IdentitySchemaNode identity : schemaIdentities) { @@ -593,7 +592,7 @@ public class BindingGeneratorImpl implements BindingGenerator { newType.setExtendsType(gto.toInstance()); } else { final Module baseIdentityParentModule = SchemaContextUtil.findParentModule(context, baseIdentity); - final String returnTypePkgName = moduleNamespaceToPackageName(baseIdentityParentModule); + final String returnTypePkgName = BindingMapping.getRootPackageName(baseIdentityParentModule.getQNameModule()); final String returnTypeName = BindingMapping.getClassName(baseIdentity.getQName()); final GeneratedTransferObject gto = new GeneratedTOBuilderImpl(returnTypePkgName, returnTypeName) .toInstance(); @@ -635,7 +634,7 @@ public class BindingGeneratorImpl implements BindingGenerator { * */ private void groupingsToGenTypes(final Module module, final Collection groupings) { - final String basePackageName = moduleNamespaceToPackageName(module); + final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); final List groupingsSortedByDependencies = new GroupingDefinitionDependencySort() .sort(groupings); for (GroupingDefinition grouping : groupingsSortedByDependencies) { @@ -711,7 +710,7 @@ public class BindingGeneratorImpl implements BindingGenerator { */ private GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix) { checkArgument(module != null, "Module reference cannot be NULL."); - final String packageName = moduleNamespaceToPackageName(module); + final String packageName = BindingMapping.getRootPackageName(module.getQNameModule()); final String moduleName = BindingMapping.getClassName(module.getName()) + postfix; return new GeneratedTypeBuilderImpl(packageName, moduleName); } @@ -1333,7 +1332,7 @@ public class BindingGeneratorImpl implements BindingGenerator { final int length = Iterables.size(splittedElement); if (length == 1) { identity = findIdentityByName(module.getIdentities(), iterator.next()); - basePackageName = moduleNamespaceToPackageName(module); + basePackageName = BindingMapping.getRootPackageName(module.getQNameModule()); } else if (length == 2) { String prefix = iterator.next(); final Module dependentModule = findModuleFromImports(module.getImports(), prefix); @@ -1342,7 +1341,7 @@ public class BindingGeneratorImpl implements BindingGenerator { + prefix); } identity = findIdentityByName(dependentModule.getIdentities(), iterator.next()); - basePackageName = moduleNamespaceToPackageName(dependentModule); + basePackageName = BindingMapping.getRootPackageName(dependentModule.getQNameModule()); } else { throw new IllegalArgumentException("Failed to process context-reference: unknown identity " + nodeParam); diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/LazyGeneratedCodecRegistry.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/LazyGeneratedCodecRegistry.java index 6868579259..c890252a3f 100644 --- a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/LazyGeneratedCodecRegistry.java +++ b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/LazyGeneratedCodecRegistry.java @@ -37,6 +37,7 @@ import org.opendaylight.yangtools.yang.binding.Augmentable; import org.opendaylight.yangtools.yang.binding.Augmentation; import org.opendaylight.yangtools.yang.binding.BaseIdentity; import org.opendaylight.yangtools.yang.binding.BindingCodec; +import org.opendaylight.yangtools.yang.binding.BindingMapping; import org.opendaylight.yangtools.yang.binding.DataContainer; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.Identifier; @@ -1292,9 +1293,14 @@ class LazyGeneratedCodecRegistry implements // @Override public Class deserialize(final QName input) { + if(input == null) { + return null; + } Type type = qnamesToIdentityMap.get(input); if (type == null) { - throw new IllegalArgumentException( "Invalid value \"" + input + "\"." ); + String packageName = BindingMapping.getRootPackageName(input); + String className = BindingMapping.getClassName(input); + type = new ReferencedTypeImpl(packageName, className); } ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName()); WeakReference softref = typeToClass.get(typeref); @@ -1348,8 +1354,7 @@ class LazyGeneratedCodecRegistry implements // if (qname != null) { return qname; } - ConcreteType typeref = Types.typeForClass(input); - qname = typeToQname.get(typeref); + qname = BindingReflections.findQName(input); if (qname != null) { identityQNames.put(input, qname); } diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/TransformerGenerator.xtend b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/TransformerGenerator.xtend index 5d127d6c15..ab6b734c0b 100644 --- a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/TransformerGenerator.xtend +++ b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/TransformerGenerator.xtend @@ -72,6 +72,9 @@ import static org.opendaylight.yangtools.sal.binding.generator.impl.CodecMapping import static extension org.opendaylight.yangtools.sal.binding.generator.util.YangSchemaUtils.* import java.util.ArrayList +import org.opendaylight.yangtools.sal.binding.generator.util.DefaultSourceCodeGenerator +import org.opendaylight.yangtools.sal.binding.generator.util.SourceCodeGeneratorFactory +import org.opendaylight.yangtools.sal.binding.generator.util.SourceCodeGenerator class TransformerGenerator extends AbstractTransformerGenerator { private static val LOG = LoggerFactory.getLogger(TransformerGenerator) @@ -90,6 +93,8 @@ class TransformerGenerator extends AbstractTransformerGenerator { val CtClass BINDING_CODEC val CtClass ctQName + val SourceCodeGeneratorFactory sourceCodeGeneratorFactory = new SourceCodeGeneratorFactory(); + public new(TypeResolver typeResolver, ClassPool pool) { super(typeResolver, pool) @@ -328,17 +333,19 @@ class TransformerGenerator extends AbstractTransformerGenerator { private def generateKeyTransformerFor(Class inputType, GeneratedType typeSpec, ListSchemaNode node) { try { + val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null ); + //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader) val properties = typeSpec.allProperties; val ctCls = createClass(inputType.codecClassName) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); - staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec) - staticField(it, IDENTITYREF_CODEC, BindingCodec) - staticQNameField(node.QName); + staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator) + staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator) + staticQNameField(node.QName, sourceGenerator); implementsType(BINDING_CODEC) method(Object, "toDomStatic", #[QName, Object]) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = ''' + val body = ''' { «QName.name» _resultName; if($1 != null) { @@ -357,10 +364,11 @@ class TransformerGenerator extends AbstractTransformerGenerator { return ($r) java.util.Collections.singletonMap(_resultName,_childNodes); } ''' + setBodyChecked(body, sourceGenerator) ] method(Object, "fromDomStatic", #[QName, Object]) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = ''' + val body = ''' { if($2 == null){ return null; @@ -379,9 +387,10 @@ class TransformerGenerator extends AbstractTransformerGenerator { return _value; } ''' + setBodyChecked(body, sourceGenerator) ] method(Object, "serialize", Object) [ - bodyChecked = ''' + val body = ''' { java.util.Map.Entry _input = (java.util.Map.Entry) $1; «QName.name» _localQName = («QName.name») _input.getKey(); @@ -389,9 +398,10 @@ class TransformerGenerator extends AbstractTransformerGenerator { return toDomStatic(_localQName,_keyValue); } ''' + setBodyChecked(body, sourceGenerator) ] method(Object, "deserialize", Object) [ - bodyChecked = ''' + val body = ''' { «QName.name» _qname = QNAME; if($1 instanceof java.util.Map.Entry) { @@ -400,9 +410,11 @@ class TransformerGenerator extends AbstractTransformerGenerator { return fromDomStatic(_qname,$1); } ''' + setBodyChecked(body, sourceGenerator) ] ] val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) + sourceGenerator.outputGeneratedSource( ctCls ) LOG.debug("DOM Codec for {} was generated {}", inputType, ret) return ret as Class, ?>>; } catch (Exception e) { @@ -414,17 +426,19 @@ class TransformerGenerator extends AbstractTransformerGenerator { private def Class> generateCaseCodec(Class inputType, GeneratedType type, ChoiceCaseNode node) { try { + val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null ); + //log.info("Generating DOM Codec for {} with {}, TCCL is: {}", inputType, inputType.classLoader,Thread.currentThread.contextClassLoader) val ctCls = createClass(type.codecClassName) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); implementsType(BINDING_CODEC) - staticQNameField(node.QName); - staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec) - staticField(it, AUGMENTATION_CODEC, BindingCodec) - staticField(it, IDENTITYREF_CODEC, BindingCodec) + staticQNameField(node.QName, sourceGenerator); + staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator) + staticField(it, AUGMENTATION_CODEC, BindingCodec, sourceGenerator) + staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator) method(Object, "toDomStatic", #[QName, Object]) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = ''' + val body = ''' { «QName.name» _resultName = «QName.name».create($1,QNAME.getLocalName()); java.util.List _childNodes = new java.util.ArrayList(); @@ -433,9 +447,10 @@ class TransformerGenerator extends AbstractTransformerGenerator { return ($r) _childNodes; } ''' + setBodyChecked( body, sourceGenerator) ] method(Object, "serialize", Object) [ - bodyChecked = ''' + val body = ''' { java.util.Map.Entry _input = (java.util.Map.Entry) $1; «QName.name» _localName = QNAME; @@ -445,23 +460,27 @@ class TransformerGenerator extends AbstractTransformerGenerator { return toDomStatic(_localName,_input.getValue()); } ''' + setBodyChecked( body, sourceGenerator) ] method(Object, "fromDomStatic", #[QName, Object, InstanceIdentifier]) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = deserializeBody(type, node, getBindingIdentifierByPath(node.path)) + setBodyChecked( deserializeBody(type, node, getBindingIdentifierByPath(node.path)), + sourceGenerator ) ] method(Object, "deserialize", #[Object, InstanceIdentifier]) [ - bodyChecked = ''' + val body = ''' { //System.out.println("«type.name»#deserialize: " +$1); java.util.Map.Entry _input = (java.util.Map.Entry) $1; return fromDomStatic((«QName.name»)_input.getKey(),_input.getValue(),$2); } ''' + setBodyChecked( body, sourceGenerator) ] ] val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class> + sourceGenerator.outputGeneratedSource( ctCls ) listener?.onDataContainerCodecCreated(inputType, ret); LOG.debug("DOM Codec for {} was generated {}", inputType, ret) return ret; @@ -475,21 +494,24 @@ class TransformerGenerator extends AbstractTransformerGenerator { Class inputType, GeneratedType typeSpec, SchemaNode node) { try { + val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null ); + //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader) val ctCls = createClass(typeSpec.codecClassName) [ + //staticField(Map,"AUGMENTATION_SERIALIZERS"); - staticQNameField(node.QName); - staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec) - staticField(it, IDENTITYREF_CODEC, BindingCodec) - staticField(it, AUGMENTATION_CODEC, BindingCodec) + staticQNameField(node.QName, sourceGenerator); + staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator) + staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator) + staticField(it, AUGMENTATION_CODEC, BindingCodec, sourceGenerator) implementsType(BINDING_CODEC) method(Object, "toDomStatic", #[QName, Object]) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = serializeBodyFacade(typeSpec, node) + setBodyChecked( serializeBodyFacade(typeSpec, node), sourceGenerator ) ] method(Object, "serialize", Object) [ - bodyChecked = ''' + val body = ''' { java.util.Map.Entry _input = (java.util.Map.Entry) $1; «QName.name» _localName = QNAME; @@ -499,15 +521,17 @@ class TransformerGenerator extends AbstractTransformerGenerator { return toDomStatic(_localName,_input.getValue()); } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "fromDomStatic", #[QName, Object, InstanceIdentifier]) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = deserializeBody(typeSpec, node, getBindingIdentifierByPath(node.path)) + setBodyChecked( deserializeBody(typeSpec, node, getBindingIdentifierByPath(node.path)), + sourceGenerator ) ] method(Object, "deserialize", #[Object, InstanceIdentifier]) [ - bodyChecked = ''' + val body = ''' { «QName.name» _qname = QNAME; if($1 instanceof java.util.Map.Entry) { @@ -516,10 +540,14 @@ class TransformerGenerator extends AbstractTransformerGenerator { return fromDomStatic(_qname,$1,$2); } ''' + setBodyChecked( body, sourceGenerator ) ] ] val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class, Object>> + + sourceGenerator.outputGeneratedSource( ctCls ) + listener?.onDataContainerCodecCreated(inputType, ret); LOG.debug("DOM Codec for {} was generated {}", inputType, ret) return ret; @@ -533,19 +561,21 @@ class TransformerGenerator extends AbstractTransformerGenerator { Class inputType, GeneratedType type, AugmentationSchema node) { try { + val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null ); + //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader) val properties = type.allProperties val ctCls = createClass(type.codecClassName) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); - staticQNameField(node.augmentationQName); - staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec) - staticField(it, AUGMENTATION_CODEC, BindingCodec) - staticField(it, IDENTITYREF_CODEC, BindingCodec) + staticQNameField(node.augmentationQName, sourceGenerator); + staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator) + staticField(it, AUGMENTATION_CODEC, BindingCodec, sourceGenerator) + staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator) implementsType(BINDING_CODEC) method(Object, "toDomStatic", #[QName, Object]) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = ''' + val body = ''' { ////System.out.println("Qname " + $1); ////System.out.println("Value " + $2); @@ -560,23 +590,25 @@ class TransformerGenerator extends AbstractTransformerGenerator { return ($r) _childNodes; } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "serialize", Object) [ - bodyChecked = ''' + val body = ''' { - java.util.Map.Entry _input = (java.util.Map.Entry) $1; - «QName.name» _localName = QNAME; - if(_input.getKey() != null) { - _localName = («QName.name») _input.getKey(); - } - return toDomStatic(_localName,_input.getValue()); + java.util.Map.Entry _input = (java.util.Map.Entry) $1; + «QName.name» _localName = QNAME; + if(_input.getKey() != null) { + _localName = («QName.name») _input.getKey(); + } + return toDomStatic(_localName,_input.getValue()); } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "fromDomStatic", #[QName, Object, InstanceIdentifier]) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = ''' + val body = ''' { «QName.name» _localQName = QNAME; @@ -598,16 +630,21 @@ class TransformerGenerator extends AbstractTransformerGenerator { return _builder.build(); } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "deserialize", #[Object, InstanceIdentifier]) [ - bodyChecked = ''' - return fromDomStatic(QNAME,$1,$2); + val body = ''' + { + return fromDomStatic(QNAME,$1,$2); + } ''' + setBodyChecked( body, sourceGenerator ) ] ] val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) as Class, Object>> + sourceGenerator.outputGeneratedSource( ctCls ) listener?.onDataContainerCodecCreated(inputType, ret); return ret; } catch (Exception e) { @@ -620,18 +657,20 @@ class TransformerGenerator extends AbstractTransformerGenerator { Class inputType, GeneratedType typeSpec, ChoiceNode node) { try { + val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null ); + //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader) val ctCls = createClass(typeSpec.codecClassName) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); //staticQNameField(inputType); - staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec) - staticField(it, IDENTITYREF_CODEC, BindingCodec) - staticField(it, DISPATCH_CODEC, BindingCodec) + staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator) + staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator) + staticField(it, DISPATCH_CODEC, BindingCodec, sourceGenerator) //staticField(it,QNAME_TO_CASE_MAP,BindingCodec) implementsType(BINDING_CODEC) method(List, "toDomStatic", #[QName, Object]) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = ''' + val body = ''' { if($2 == null) { return null; @@ -645,15 +684,19 @@ class TransformerGenerator extends AbstractTransformerGenerator { return («List.name») _ret; } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "serialize", Object) [ - bodyChecked = ''' - throw new «UnsupportedOperationException.name»("Direct invocation not supported."); + val body = ''' + { + throw new «UnsupportedOperationException.name»("Direct invocation not supported."); + } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "fromDomStatic", #[QName, Map, InstanceIdentifier]) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = ''' + val body = ''' { if («DISPATCH_CODEC» == null) { throw new «IllegalStateException.name»("Implementation of codec was not initialized."); @@ -661,15 +704,20 @@ class TransformerGenerator extends AbstractTransformerGenerator { return «DISPATCH_CODEC».deserialize($2,$3); } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "deserialize", #[Object, InstanceIdentifier]) [ - bodyChecked = ''' - throw new «UnsupportedOperationException.name»("Direct invocation not supported."); + val body = ''' + { + throw new «UnsupportedOperationException.name»("Direct invocation not supported."); + } ''' + setBodyChecked( body, sourceGenerator ) ] ] val rawRet = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) + sourceGenerator.outputGeneratedSource( ctCls ) val ret = rawRet as Class, Object>>; listener?.onChoiceCodecCreated(inputType, ret, node); LOG.debug("DOM Codec for {} was generated {}", inputType, ret) @@ -908,10 +956,13 @@ class TransformerGenerator extends AbstractTransformerGenerator { Class inputType, GeneratedTransferObject typeSpec, TypeDefinition typeDef) { try { + val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null ); + val returnType = typeSpec.valueReturnType; if (returnType == null) { - val ctCls = createDummyImplementation(inputType, typeSpec); + val ctCls = createDummyImplementation(inputType, typeSpec, sourceGenerator); val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) + sourceGenerator.outputGeneratedSource( ctCls ) return ret as Class, Object>>; } @@ -919,14 +970,14 @@ class TransformerGenerator extends AbstractTransformerGenerator { //staticField(Map,"AUGMENTATION_SERIALIZERS"); if (inputType.isYangBindingAvailable) { implementsType(BINDING_CODEC) - staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec) - staticField(it, IDENTITYREF_CODEC, BindingCodec) + staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator) + staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator) implementsType(BindingDeserializer.asCtClass) } method(Object, "toDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC val ctSpec = typeSpec.asCtClass; - bodyChecked = ''' + val body = ''' { ////System.out.println("«inputType.simpleName»#toDomValue: "+$1); @@ -941,17 +992,19 @@ class TransformerGenerator extends AbstractTransformerGenerator { return _domValue; } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "serialize", Object) [ - bodyChecked = ''' + val body = ''' { return toDomValue($1); } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "fromDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = ''' + val body = ''' { ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1); @@ -963,16 +1016,20 @@ class TransformerGenerator extends AbstractTransformerGenerator { return _value; } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "deserialize", Object) [ - bodyChecked = '''{ + val body = ''' + { return fromDomValue($1); - } + } ''' + setBodyChecked( body, sourceGenerator ) ] ] val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) + sourceGenerator.outputGeneratedSource( ctCls ) LOG.debug("DOM Codec for {} was generated {}", inputType, ret) return ret as Class, Object>>; } catch (Exception e) { @@ -986,20 +1043,22 @@ class TransformerGenerator extends AbstractTransformerGenerator { private def dispatch Class, Object>> generateValueTransformer( Class inputType, GeneratedTransferObject typeSpec, UnionTypeDefinition typeDef) { try { + val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null ); + val ctCls = createClass(typeSpec.codecClassName) [ val properties = typeSpec.allProperties; val getterToTypeDefinition = XtendHelper.getTypes(typeDef).toMap[type|type.QName.getterName]; //staticField(Map,"AUGMENTATION_SERIALIZERS"); if (inputType.isYangBindingAvailable) { implementsType(BINDING_CODEC) - staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec) - staticField(it, IDENTITYREF_CODEC, BindingCodec) + staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator) + staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator) implementsType(BindingDeserializer.asCtClass) } method(Object, "toDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC val ctSpec = inputType.asCtClass; - bodyChecked = ''' + val body = ''' { ////System.out.println("«inputType.simpleName»#toDomValue: "+$1); @@ -1021,17 +1080,19 @@ class TransformerGenerator extends AbstractTransformerGenerator { return null; } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "serialize", Object) [ - bodyChecked = ''' + val body = ''' { return toDomValue($1); } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "fromDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = ''' + val body = ''' { ////System.out.println("«inputType.simpleName»#fromDomValue: "+$1); @@ -1045,16 +1106,20 @@ class TransformerGenerator extends AbstractTransformerGenerator { return null; } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "deserialize", Object) [ - bodyChecked = '''{ + val body = ''' + { return fromDomValue($1); - } + } ''' + setBodyChecked( body, sourceGenerator ) ] ] val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) + sourceGenerator.outputGeneratedSource( ctCls ) LOG.debug("DOM Codec for {} was generated {}", inputType, ret) return ret as Class, Object>>; } catch (Exception e) { @@ -1068,18 +1133,20 @@ class TransformerGenerator extends AbstractTransformerGenerator { private def dispatch Class, Object>> generateValueTransformer( Class inputType, GeneratedTransferObject typeSpec, BitsTypeDefinition typeDef) { try { + val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null ); + val ctCls = createClass(typeSpec.codecClassName) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); if (inputType.isYangBindingAvailable) { implementsType(BINDING_CODEC) - staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec) - staticField(it, IDENTITYREF_CODEC, BindingCodec) + staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator) + staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator) implementsType(BindingDeserializer.asCtClass) } method(Object, "toDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC val ctSpec = typeSpec.asCtClass; - bodyChecked = ''' + val body = ''' { ////System.out.println("«inputType.simpleName»#toDomValue: "+$1); @@ -1102,21 +1169,20 @@ class TransformerGenerator extends AbstractTransformerGenerator { return _domValue; } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "serialize", Object) [ - bodyChecked = ''' + val body = ''' { return toDomValue($1); } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "fromDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC - val sortedBits = new ArrayList(typeDef.bits) - Collections.sort(sortedBits, [o1, o2| - o1.propertyName.compareTo(o2.propertyName) - ]) - bodyChecked = ''' + val sortedBits = typeDef.bits.sort[o1, o2|o1.propertyName.compareTo(o2.propertyName)] + val body = ''' { //System.out.println("«inputType.simpleName»#fromDomValue: "+$1); @@ -1131,16 +1197,20 @@ class TransformerGenerator extends AbstractTransformerGenerator { return new «inputType.resolvedName»(«FOR bit : sortedBits SEPARATOR ","»«bit.propertyName»«ENDFOR»); } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "deserialize", Object) [ - bodyChecked = '''{ + val body = ''' + { return fromDomValue($1); - } + } ''' + setBodyChecked( body, sourceGenerator ) ] ] val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) + sourceGenerator.outputGeneratedSource( ctCls ) LOG.debug("DOM Codec for {} was generated {}", inputType, ret) return ret as Class, Object>>; } catch (Exception e) { @@ -1170,42 +1240,48 @@ class TransformerGenerator extends AbstractTransformerGenerator { } } - private def createDummyImplementation(Class object, GeneratedTransferObject typeSpec) { + private def createDummyImplementation(Class object, GeneratedTransferObject typeSpec, + SourceCodeGenerator sourceGenerator ) { LOG.trace("Generating Dummy DOM Codec for {} with {}", object, object.classLoader) return createClass(typeSpec.codecClassName) [ if (object.isYangBindingAvailable) { implementsType(BINDING_CODEC) - staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec) - staticField(it, IDENTITYREF_CODEC, BindingCodec) + staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec, sourceGenerator) + staticField(it, IDENTITYREF_CODEC, BindingCodec, sourceGenerator) implementsType(BindingDeserializer.asCtClass) } //implementsType(BindingDeserializer.asCtClass) method(Object, "toDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = '''{ - if($1 == null) { - return null; - } - return $1.toString(); - + val body = ''' + { + if($1 == null) { + return null; + } + return $1.toString(); }''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "serialize", Object) [ - bodyChecked = ''' + val body = ''' { return toDomValue($1); } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "fromDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = '''return null;''' + val body = '''return null;''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "deserialize", Object) [ - bodyChecked = '''{ + val body = ''' + { return fromDomValue($1); } ''' + setBodyChecked( body, sourceGenerator ) ] ] } @@ -1233,13 +1309,16 @@ class TransformerGenerator extends AbstractTransformerGenerator { } val enumSchema = enumSchemaType; try { + val SourceCodeGenerator sourceGenerator = sourceCodeGeneratorFactory.getInstance( null ); + //log.info("Generating DOM Codec for {} with {}", inputType, inputType.classLoader) val ctCls = createClass(typeSpec.codecClassName) [ //staticField(Map,"AUGMENTATION_SERIALIZERS"); //implementsType(BINDING_CODEC) method(Object, "toDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = '''{ + val body = ''' + { if($1 == null) { return null; } @@ -1252,15 +1331,19 @@ class TransformerGenerator extends AbstractTransformerGenerator { return null; } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "serialize", Object) [ - bodyChecked = ''' - return toDomValue($1); + val body = ''' + { + return toDomValue($1); + } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "fromDomValue", Object) [ modifiers = PUBLIC + FINAL + STATIC - bodyChecked = ''' + val body = ''' { if($1 == null) { return null; @@ -1274,15 +1357,20 @@ class TransformerGenerator extends AbstractTransformerGenerator { return null; } ''' + setBodyChecked( body, sourceGenerator ) ] method(Object, "deserialize", Object) [ - bodyChecked = ''' - return fromDomValue($1); + val body = ''' + { + return fromDomValue($1); + } ''' + setBodyChecked( body, sourceGenerator ) ] ] val ret = ctCls.toClassImpl(inputType.classLoader, inputType.protectionDomain) + sourceGenerator.outputGeneratedSource( ctCls ) LOG.debug("DOM Codec for {} was generated {}", inputType, ret) return ret; } catch (CodeGenerationException e) { @@ -1347,11 +1435,13 @@ class TransformerGenerator extends AbstractTransformerGenerator { */ private def getBuilderName(GeneratedType type) '''«type.resolvedName»Builder''' - private def staticQNameField(CtClass it, QName node) { + private def staticQNameField(CtClass it, QName node, SourceCodeGenerator sourceGenerator) { val field = new CtField(ctQName, "QNAME", it); field.modifiers = PUBLIC + FINAL + STATIC; - addField(field, - '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")''') + val code = '''«QName.asCtClass.name».create("«node.namespace»","«node.formattedRevision»","«node.localName»")''' + addField(field, code ) + + sourceGenerator.appendField( field, code ); } private def String serializeBodyImpl(GeneratedType type, DataNodeContainer nodeContainer) ''' @@ -1605,9 +1695,11 @@ class TransformerGenerator extends AbstractTransformerGenerator { throw exception; } - private def setBodyChecked(CtMethod method, String body) { + private def setBodyChecked(CtMethod method, String body, SourceCodeGenerator sourceGenerator ) { try { method.setBody(body); + + sourceGenerator.appendMethod( method, body ); } catch (CannotCompileException e) { LOG.error("Cannot compile method: {}#{} {}, Reason: {} Body: {}", method.declaringClass, method.name, method.signature, e.message, body) diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/DefaultSourceCodeGenerator.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/DefaultSourceCodeGenerator.java new file mode 100644 index 0000000000..5df91cdc86 --- /dev/null +++ b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/DefaultSourceCodeGenerator.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.yangtools.sal.binding.generator.util; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javassist.CtClass; +import javassist.CtField; +import javassist.CtMethod; +import javassist.Modifier; +import javassist.NotFoundException; + +/** + * The default implementation of the SourceCodeGenerator interface that generates readable source code + * for a runtime generated class. The appendField/appendMethod methods output source code to a temporary + * StringBuilder. When outputGeneratedSource is called, the entire class source code is generated and + * written to a file under a specified directory. + * + * @author Thomas Pantelis + */ +public class DefaultSourceCodeGenerator implements SourceCodeGenerator { + private static final Logger LOG = LoggerFactory.getLogger(DefaultSourceCodeGenerator.class); + + private static final String GENERATED_SOURCE_DIR_PROP = "org.opendaylight.yangtools.sal.generatedCodecSourceDir"; + + private final StringBuilder builder = new StringBuilder(); + private final String generatedSourceDir; + + /** + * Constructor. + * + * @param generatedSourceDir the directory in which to put generated source files. If null, the directory + * is obtained from a system property (org.opendaylight.yangtools.sal.generatedCodecSourceDir) or + * defaults to "generated-codecs". + */ + public DefaultSourceCodeGenerator( String generatedSourceDir ) { + if( generatedSourceDir != null ) { + this.generatedSourceDir = generatedSourceDir; + } + else { + this.generatedSourceDir = System.getProperty( GENERATED_SOURCE_DIR_PROP, "generated-codecs" ); + } + } + + @Override + public void appendField(CtField field, String value) { + try { + builder.append('\n') + .append(Modifier.toString(field.getModifiers())) + .append(' ').append(field.getType().getName()).append(' ') + .append(field.getName()); + if (value != null) { + builder.append(" = ").append(value); + } + + builder.append(";\n"); + } catch (NotFoundException e) { + LOG.error("Error building field source for " + field.getName(), e); + } + } + + @Override + public void appendMethod(CtMethod method, String code) { + try { + builder.append('\n') + .append(Modifier.toString(method.getModifiers())) + .append(' ').append(method.getReturnType().getName()) + .append(' ').append(method.getName()).append("( "); + + CtClass[] paramTypes = method.getParameterTypes(); + if (paramTypes != null) { + for (int i = 0; i < paramTypes.length; i++) { + if (i > 0) + builder.append(", "); + builder.append(paramTypes[i].getName()).append(" $") + .append(i + 1); + } + } + + builder.append(" )\n").append(code).append("\n\n"); + } catch (NotFoundException e) { + LOG.error("Error building method source for " + method.getName(), e); + } + } + + @Override + public void outputGeneratedSource(CtClass ctClass) { + String name = ctClass.getName(); + + StringBuilder classBuilder = new StringBuilder(); + classBuilder.append(Modifier.toString(ctClass.getModifiers())) + .append(" class ").append(ctClass.getSimpleName()); + + try { + CtClass superClass = ctClass.getSuperclass(); + if (superClass != null) { + classBuilder.append(" extends ").append(superClass.getName()); + } + + CtClass[] interfaces = ctClass.getInterfaces(); + if (interfaces.length > 0) { + classBuilder.append(" implements "); + for (int i = 0; i < interfaces.length; i++) { + if (i > 0) { + classBuilder.append(", "); + } + + classBuilder.append(interfaces[i].getName()); + } + } + + classBuilder.append(" {\n").append(builder.toString()) + .append("\n}"); + } catch (NotFoundException e) { + LOG.error("Error building class source for " + name, e); + return; + } + + File dir = new File(generatedSourceDir); + dir.mkdir(); + try (FileWriter writer = new FileWriter(new File(dir, name + ".java"))) { + writer.append(classBuilder.toString()); + writer.flush(); + } catch (IOException e) { + LOG.error("Error writing class source for " + name, e); + } + } +} diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/JavassistUtils.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/JavassistUtils.java index 252fca7107..7f92e704ee 100644 --- a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/JavassistUtils.java +++ b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/JavassistUtils.java @@ -23,7 +23,6 @@ import javassist.CtMethod; import javassist.LoaderClassPath; import javassist.Modifier; import javassist.NotFoundException; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -149,9 +148,20 @@ public final class JavassistUtils { } public CtField staticField(final CtClass it, final String name, final Class returnValue) throws CannotCompileException { + return staticField(it, name, returnValue, null); + } + + public CtField staticField(final CtClass it, final String name, + final Class returnValue, + SourceCodeGenerator sourceGenerator) throws CannotCompileException { final CtField field = new CtField(asCtClass(returnValue), name, it); field.setModifiers(Modifier.PUBLIC + Modifier.STATIC); it.addField(field); + + if (sourceGenerator != null) { + sourceGenerator.appendField(field, null); + } + return field; } diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/NullSourceCodeGenerator.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/NullSourceCodeGenerator.java new file mode 100644 index 0000000000..f087d5469b --- /dev/null +++ b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/NullSourceCodeGenerator.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.yangtools.sal.binding.generator.util; + +import javassist.CtClass; +import javassist.CtField; +import javassist.CtMethod; + +/** + * Implementation of the SourceCodeGenerator interface that does nothing. + * + * @author Thomas Pantelis + */ +public class NullSourceCodeGenerator implements SourceCodeGenerator { + + @Override + public void appendField( CtField field, String value ) { + } + + @Override + public void appendMethod( CtMethod method, String code ) { + } + + @Override + public void outputGeneratedSource( CtClass ctClass ) { + } +} diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/SourceCodeGenerator.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/SourceCodeGenerator.java new file mode 100644 index 0000000000..bfbb031e49 --- /dev/null +++ b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/SourceCodeGenerator.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.yangtools.sal.binding.generator.util; + +import javassist.CtClass; +import javassist.CtField; +import javassist.CtMethod; + +/** + * Interface for a class that that generates readable source code for a runtime generated class. + * The appendField/appendMethod methods append source code to a temporary output. When outputGeneratedSource + * is called, the entire class source code is generated and outputted. + * + * @author Thomas Pantelis + */ +public interface SourceCodeGenerator { + + /** + * Appends the given class field and value to the temporary output. + */ + void appendField( CtField field, String value ); + + /** + * Appends the given method and source code body to the temporary output. + */ + void appendMethod( CtMethod method, String code ); + + /** + * Generates the full source code for the given class and outputs it. + */ + void outputGeneratedSource( CtClass ctClass ); +} \ No newline at end of file diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/SourceCodeGeneratorFactory.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/SourceCodeGeneratorFactory.java new file mode 100644 index 0000000000..23549c6bd4 --- /dev/null +++ b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/SourceCodeGeneratorFactory.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Brocade Communications Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.yangtools.sal.binding.generator.util; + +/** + * Factory class for creating SourceCodeGenerator instances. + * + * @author Thomas Pantelis + */ +public class SourceCodeGeneratorFactory { + + private static final String GENERATE_CODEC_SOURCE_PROP = "org.opendaylight.yangtools.sal.generateCodecSource"; + + private static final SourceCodeGenerator NULL_GENERATOR = new NullSourceCodeGenerator(); + + /** + * Gets a SourceCodeGenerator instance. + *

+ * Generation of source code is controlled by the org.opendaylight.yangtools.sal.generateCodecSource + * system property. If set to true, a DefaultSourceCodeGenerator instance is returned, otherwise a + * NullSourceCodeGenerator is returned. + * + * @param generatedSourceDir the directory in which to put generated source files. If null, + * a default is used (see DefaultSourceCodeGenerator). + */ + public SourceCodeGenerator getInstance( String generatedSourceDir ) { + + boolean generateSource = Boolean.valueOf( System.getProperty( GENERATE_CODEC_SOURCE_PROP, "false") ); + if( generateSource ) { + return new DefaultSourceCodeGenerator( generatedSourceDir ); + } + + return NULL_GENERATOR; + } +} diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/BindingGeneratorUtil.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/BindingGeneratorUtil.java index d5ec8b202f..0b7e071fa8 100644 --- a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/BindingGeneratorUtil.java +++ b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/BindingGeneratorUtil.java @@ -8,21 +8,20 @@ package org.opendaylight.yangtools.binding.generator.util; import com.google.common.base.CharMatcher; -import com.google.common.base.Splitter; import com.google.common.collect.Iterables; + import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; + 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; @@ -32,6 +31,7 @@ import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSigna import org.opendaylight.yangtools.sal.binding.model.api.type.builder.TypeMemberBuilder; import org.opendaylight.yangtools.yang.binding.BindingMapping; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaPath; import org.opendaylight.yangtools.yang.model.api.TypeDefinition; @@ -51,19 +51,6 @@ import org.opendaylight.yangtools.yang.model.util.ExtendedType; */ public final class BindingGeneratorUtil { - private static final ThreadLocal DATE_FORMAT = new ThreadLocal() { - - @Override - protected SimpleDateFormat initialValue() { - return new SimpleDateFormat("yyMMdd"); - } - - @Override - public void set(final SimpleDateFormat value) { - throw new UnsupportedOperationException(); - } - }; - /** * Impossible to instantiate this class. All of the methods or attributes * are static. @@ -74,45 +61,44 @@ public final class BindingGeneratorUtil { /** * Pre-compiled replacement pattern. */ - private static final Pattern COLON_SLASH_SLASH = Pattern.compile("://", Pattern.LITERAL); - private static final String QUOTED_DOT = Matcher.quoteReplacement("."); - private static final Splitter DOT_SPLITTER = Splitter.on('.'); private static final CharMatcher DOT_MATCHER = CharMatcher.is('.'); private static final CharMatcher DASH_COLON_MATCHER = CharMatcher.anyOf("-:"); - /** - * Converts string packageName to valid JAVA package name. - * - * If some words of package name are digits of JAVA reserved words they are - * prefixed with underscore character. - * - * @param packageName - * string which contains words separated by point. - * @return package name which contains words separated by point. - */ - private static String validateJavaPackage(final String packageName) { - if (packageName == null) { - return null; + private static final Restrictions EMPTY_RESTRICTIONS = new Restrictions() { + @Override + public List getLengthConstraints() { + return Collections.emptyList(); } - final StringBuilder builder = new StringBuilder(); - boolean first = true; + @Override + public List getPatternConstraints() { + return Collections.emptyList(); + } - for (String p : DOT_SPLITTER.split(packageName.toLowerCase())) { - if (first) { - first = false; - } else { - builder.append('.'); - } + @Override + public List getRangeConstraints() { + return Collections.emptyList(); + } - if (Character.isDigit(p.charAt(0)) || BindingMapping.JAVA_RESERVED_WORDS.contains(p)) { - builder.append('_'); - } - builder.append(p); + @Override + public boolean isEmpty() { + return true; } + }; - return builder.toString(); - } + private static final Comparator> SUID_MEMBER_COMPARATOR = new Comparator>() { + @Override + public int compare(final TypeMemberBuilder o1, final TypeMemberBuilder o2) { + return o1.getName().compareTo(o2.getName()); + } + }; + + private static final Comparator SUID_NAME_COMPARATOR = new Comparator() { + @Override + public int compare(final Type o1, final Type o2) { + return o1.getFullyQualifiedName().compareTo(o2.getFullyQualifiedName()); + } + }; /** * Converts parameterName to valid JAVA parameter name. @@ -149,43 +135,11 @@ public final class BindingGeneratorUtil { * @throws IllegalArgumentException * if the revision date of the module equals * null + * @deprecated USe {@link BindingMapping#getRootPackageName(QNameModule)} with {@link Module#getQNameModule()}. */ + @Deprecated public static String moduleNamespaceToPackageName(final Module module) { - final StringBuilder packageNameBuilder = new StringBuilder(); - - if (module.getRevision() == null) { - throw new IllegalArgumentException("Module " + module.getName() + " does not specify revision date!"); - } - packageNameBuilder.append(BindingMapping.PACKAGE_PREFIX); - packageNameBuilder.append('.'); - - String namespace = module.getNamespace().toString(); - namespace = COLON_SLASH_SLASH.matcher(namespace).replaceAll(QUOTED_DOT); - - final char[] chars = namespace.toCharArray(); - for (int i = 0; i < chars.length; ++i) { - switch (chars[i]) { - case '/': - case ':': - case '-': - case '@': - case '$': - case '#': - case '\'': - case '*': - case '+': - case ',': - case ';': - case '=': - chars[i] = '.'; - } - } - - packageNameBuilder.append(chars); - packageNameBuilder.append(".rev"); - packageNameBuilder.append(DATE_FORMAT.get().format(module.getRevision())); - - return validateJavaPackage(packageNameBuilder.toString()); + return BindingMapping.getRootPackageName(module.getQNameModule()); } public static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath) { @@ -230,10 +184,10 @@ public final class BindingGeneratorUtil { for (int i = 0; i < traversalSteps; ++i) { builder.append('.'); String nodeLocalName = iterator.next().getLocalName(); - + // FIXME: Collon ":" is invalid in node local name as per RFC6020, identifier statement. builder.append(DASH_COLON_MATCHER.replaceFrom(nodeLocalName, '.')); } - return validateJavaPackage(builder.toString()); + return BindingMapping.normalizePackageName(builder.toString()); } /** @@ -262,7 +216,7 @@ public final class BindingGeneratorUtil { final StringBuilder builder = new StringBuilder(); builder.append(basePackageName); - return validateJavaPackage(builder.toString()); + return BindingMapping.normalizePackageName(builder.toString()); } /** @@ -374,6 +328,16 @@ public final class BindingGeneratorUtil { return sb.toString(); } + private static Iterable sortedCollection(final Comparator comparator, final Collection input) { + if (input.size() > 1) { + final List ret = new ArrayList<>(input); + Collections.sort(ret, comparator); + return ret; + } else { + return input; + } + } + public static long computeDefaultSUID(final GeneratedTypeBuilderBase to) { try { ByteArrayOutputStream bout = new ByteArrayOutputStream(); @@ -382,33 +346,15 @@ public final class BindingGeneratorUtil { dout.writeUTF(to.getName()); dout.writeInt(to.isAbstract() ? 3 : 7); - List impl = to.getImplementsTypes(); - Collections.sort(impl, new Comparator() { - @Override - public int compare(final Type o1, final Type o2) { - return o1.getFullyQualifiedName().compareTo(o2.getFullyQualifiedName()); - } - }); - for (Type ifc : impl) { + for (Type ifc : sortedCollection(SUID_NAME_COMPARATOR, to.getImplementsTypes())) { dout.writeUTF(ifc.getFullyQualifiedName()); } - Comparator> comparator = new Comparator>() { - @Override - public int compare(final TypeMemberBuilder o1, final TypeMemberBuilder o2) { - return o1.getName().compareTo(o2.getName()); - } - }; - - List props = to.getProperties(); - Collections.sort(props, comparator); - for (GeneratedPropertyBuilder gp : props) { + for (GeneratedPropertyBuilder gp : sortedCollection(SUID_MEMBER_COMPARATOR, to.getProperties())) { dout.writeUTF(gp.getName()); } - List methods = to.getMethodDefinitions(); - Collections.sort(methods, comparator); - for (MethodSignatureBuilder m : methods) { + for (MethodSignatureBuilder m : sortedCollection(SUID_MEMBER_COMPARATOR, to.getMethodDefinitions())) { if (!(m.getAccessModifier().equals(AccessModifier.PRIVATE))) { dout.writeUTF(m.getName()); dout.write(m.getAccessModifier().ordinal()); @@ -417,42 +363,52 @@ public final class BindingGeneratorUtil { 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); + try { + 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 (NoSuchAlgorithmException ex) { + throw new SecurityException(ex.getMessage()); } - return hash; } catch (IOException ex) { throw new InternalError(); - } catch (NoSuchAlgorithmException ex) { - throw new SecurityException(ex.getMessage()); } } public static Restrictions getRestrictions(final TypeDefinition type) { - final List length = new ArrayList<>(); - final List pattern = new ArrayList<>(); - final List range = new ArrayList<>(); - - if (type instanceof ExtendedType) { - ExtendedType ext = (ExtendedType)type; - TypeDefinition base = ext.getBaseType(); - length.addAll(ext.getLengthConstraints()); - pattern.addAll(ext.getPatternConstraints()); - range.addAll(ext.getRangeConstraints()); - - if (base instanceof IntegerTypeDefinition && range.isEmpty()) { - range.addAll(((IntegerTypeDefinition)base).getRangeConstraints()); - } else if (base instanceof UnsignedIntegerTypeDefinition && range.isEmpty()) { - range.addAll(((UnsignedIntegerTypeDefinition)base).getRangeConstraints()); - } else if (base instanceof DecimalTypeDefinition && range.isEmpty()) { - range.addAll(((DecimalTypeDefinition)base).getRangeConstraints()); + // Base types have no constraints, so get over it quickly + if (!(type instanceof ExtendedType)) { + return EMPTY_RESTRICTIONS; + } + + // Take care of the extended types ... + final ExtendedType ext = (ExtendedType)type; + final List length = ext.getLengthConstraints(); + final List pattern = ext.getPatternConstraints(); + + List tmp = ext.getRangeConstraints(); + if (tmp.isEmpty()) { + final TypeDefinition base = ext.getBaseType(); + if (base instanceof IntegerTypeDefinition) { + tmp = ((IntegerTypeDefinition)base).getRangeConstraints(); + } else if (base instanceof UnsignedIntegerTypeDefinition) { + tmp = ((UnsignedIntegerTypeDefinition)base).getRangeConstraints(); + } else if (base instanceof DecimalTypeDefinition) { + tmp = ((DecimalTypeDefinition)base).getRangeConstraints(); } + } + // Now, this may have ended up being empty, too... + if (length.isEmpty() && pattern.isEmpty() && tmp.isEmpty()) { + return EMPTY_RESTRICTIONS; } + // Nope, not empty allocate a holder + final List range = tmp; return new Restrictions() { @Override public List getRangeConstraints() { @@ -468,7 +424,7 @@ public final class BindingGeneratorUtil { } @Override public boolean isEmpty() { - return range.isEmpty() && pattern.isEmpty() && length.isEmpty(); + return false; } }; } diff --git a/code-generator/binding-java-api-generator/pom.xml b/code-generator/binding-java-api-generator/pom.xml index 5b16fa7eec..871e57b7ac 100644 --- a/code-generator/binding-java-api-generator/pom.xml +++ b/code-generator/binding-java-api-generator/pom.xml @@ -41,9 +41,6 @@ org.eclipse.xtend xtend-maven-plugin - - maven-clean-plugin -