import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Verify.verifyNotNull;
import static java.util.Objects.requireNonNull;
import static org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil.computeDefaultSUID;
import static org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil.packageNameForAugmentedGeneratedType;
import static org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil.packageNameForGeneratedType;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.BASE_IDENTITY;
import static org.opendaylight.mdsal.binding.model.util.BindingTypes.DATA_OBJECT;
import static org.opendaylight.mdsal.binding.model.util.BindingTypes.DATA_ROOT;
-import static org.opendaylight.mdsal.binding.model.util.BindingTypes.IDENTIFIABLE;
-import static org.opendaylight.mdsal.binding.model.util.BindingTypes.IDENTIFIER;
import static org.opendaylight.mdsal.binding.model.util.BindingTypes.NOTIFICATION;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.NOTIFICATION_LISTENER;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.ROUTING_CONTEXT;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.RPC_SERVICE;
import static org.opendaylight.mdsal.binding.model.util.BindingTypes.augmentable;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.childOf;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.choiceIn;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.identifiable;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.identifier;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.rpcResult;
import static org.opendaylight.mdsal.binding.model.util.Types.BOOLEAN;
import static org.opendaylight.mdsal.binding.model.util.Types.FUTURE;
-import static org.opendaylight.mdsal.binding.model.util.Types.VOID;
import static org.opendaylight.mdsal.binding.model.util.Types.typeForClass;
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findNodeInSchemaContext;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
-import java.util.ArrayDeque;
+import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
-import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.opendaylight.mdsal.binding.model.api.ParameterizedType;
import org.opendaylight.mdsal.binding.model.api.Restrictions;
import org.opendaylight.mdsal.binding.model.api.Type;
+import org.opendaylight.mdsal.binding.model.api.type.builder.AnnotableTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.AnnotationTypeBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.EnumBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedPropertyBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder;
import org.opendaylight.mdsal.binding.model.api.type.builder.TypeMemberBuilder;
import org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil;
-import org.opendaylight.mdsal.binding.model.util.BindingTypes;
import org.opendaylight.mdsal.binding.model.util.ReferencedTypeImpl;
import org.opendaylight.mdsal.binding.model.util.TypeConstants;
import org.opendaylight.mdsal.binding.model.util.Types;
import org.opendaylight.mdsal.binding.yang.types.AbstractTypeProvider;
import org.opendaylight.mdsal.binding.yang.types.BaseYangTypes;
import org.opendaylight.mdsal.binding.yang.types.GroupingDefinitionDependencySort;
-import org.opendaylight.yangtools.yang.binding.BaseIdentity;
import org.opendaylight.yangtools.yang.binding.BindingMapping;
-import org.opendaylight.yangtools.yang.binding.DataContainer;
-import org.opendaylight.yangtools.yang.binding.RpcService;
-import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
-import org.opendaylight.yangtools.yang.common.RpcResult;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.api.UsesNode;
-import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementSource;
import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
abstract class AbstractTypeGenerator {
private static final Logger LOG = LoggerFactory.getLogger(BindingGeneratorImpl.class);
private static final Splitter COLON_SPLITTER = Splitter.on(':');
+ private static final JavaTypeName DEPRECATED_ANNOTATION = JavaTypeName.create(Deprecated.class);
+ private static final JavaTypeName OVERRIDE_ANNOTATION = JavaTypeName.create(Override.class);
/**
* Comparator based on augment target path.
final List<String> listKeys = listKeys(node);
final GeneratedTOBuilder genTOBuilder = resolveListKeyTOBuilder(context, node);
if (genTOBuilder != null) {
- final Type identifierMarker = Types.parameterizedTypeFor(IDENTIFIER, genType);
- final Type identifiableMarker = Types.parameterizedTypeFor(IDENTIFIABLE, genTOBuilder);
+ final Type identifierMarker = identifier(genType);
+ final Type identifiableMarker = identifiable(genTOBuilder);
genTOBuilder.addImplementsType(identifierMarker);
genType.addImplementsType(identifiableMarker);
}
}
final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(context, "Service");
- interfaceBuilder.addImplementsType(Types.typeForClass(RpcService.class));
+ interfaceBuilder.addImplementsType(RPC_SERVICE);
addCodegenInformation(interfaceBuilder, module, "RPCs", rpcDefinitions);
final String rpcName = BindingMapping.getClassName(rpc.getQName());
final String rpcMethodName = BindingMapping.getPropertyName(rpcName);
final MethodSignatureBuilder method = interfaceBuilder.addMethod(rpcMethodName);
- final ContainerSchemaNode input = rpc.getInput();
- final ContainerSchemaNode output = rpc.getOutput();
// Do not refer to annotation class, as it may not be available at runtime
method.addAnnotation("javax.annotation", "CheckReturnValue");
-
- //in case of implicit RPC input (StatementSource.CONTEXT),
- // stay compatible (no input argument generated)
- if (input != null && isExplicitStatement(input)) {
- final Type inTypeInstance = createRpcContainer(context, rpcName, rpc, input);
- method.addParameter(inTypeInstance, "input");
- }
-
- final Type outTypeInstance;
- //in case of implicit RPC output (StatementSource.CONTEXT),
- //stay compatible (Future<RpcResult<Void>> return type generated)
- if (output != null && isExplicitStatement(output)) {
- outTypeInstance = createRpcContainer(context, rpcName, rpc, output);
- } else {
- outTypeInstance = VOID;
- }
-
- final Type rpcRes = Types.parameterizedTypeFor(Types.typeForClass(RpcResult.class), outTypeInstance);
addComment(method, rpc);
- method.setReturnType(Types.parameterizedTypeFor(FUTURE, rpcRes));
+ method.addParameter(
+ createRpcContainer(context, rpcName, rpc, verifyNotNull(rpc.getInput())), "input");
+ method.setReturnType(Types.parameterizedTypeFor(FUTURE,
+ rpcResult(createRpcContainer(context, rpcName, rpc, verifyNotNull(rpc.getOutput())))));
}
}
context.addTopLevelNodeType(interfaceBuilder);
}
- private static boolean isExplicitStatement(final ContainerSchemaNode node) {
- return node instanceof EffectiveStatement
- && ((EffectiveStatement<?, ?>) node).getDeclared().getStatementSource() == StatementSource.DECLARATION;
- }
-
private Type createRpcContainer(final ModuleContext context, final String rpcName, final RpcDefinition rpc,
final ContainerSchemaNode schema) {
processUsesAugments(schema, context);
}
final GeneratedTypeBuilder listenerInterface = moduleTypeBuilder(context, "Listener");
- listenerInterface.addImplementsType(BindingTypes.NOTIFICATION_LISTENER);
+ listenerInterface.addImplementsType(NOTIFICATION_LISTENER);
for (final NotificationDefinition notification : notifications) {
if (notification != null) {
packageNameForGeneratedType(context.modulePackageName(), identity.getPath()),
BindingMapping.getClassName(identity.getQName())));
final Set<IdentitySchemaNode> baseIdentities = identity.getBaseIdentities();
- if (baseIdentities.isEmpty()) {
- final GeneratedTOBuilder gto = typeProvider.newGeneratedTOBuilder(JavaTypeName.create(BaseIdentity.class));
- newType.addImplementsType(gto.build());
- } else {
+ if (!baseIdentities.isEmpty()) {
for (IdentitySchemaNode baseIdentity : baseIdentities) {
final QName qname = baseIdentity.getQName();
final GeneratedTransferObject gto = typeProvider.newGeneratedTOBuilder(JavaTypeName.create(
BindingMapping.getRootPackageName(qname.getModule()), BindingMapping.getClassName(qname))).build();
newType.addImplementsType(gto);
}
+ } else {
+ newType.addImplementsType(BASE_IDENTITY);
}
final Module module = context.module();
newType.setModuleName(module.getName());
newType.setSchemaPath(identity.getPath());
- qnameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, identity.getQName());
+ qnameConstant(newType, JavaTypeName.create(context.modulePackageName(), BindingMapping.MODULE_INFO_CLASS_NAME),
+ identity.getQName().getLocalName());
context.addIdentityType(identity.getQName(), newType);
}
-
- private static Constant qnameConstant(final GeneratedTypeBuilderBase<?> toBuilder, final String constantName,
- final QName name) {
- return toBuilder.addConstant(typeForClass(QName.class), constantName, name);
+ private static Constant qnameConstant(final GeneratedTypeBuilderBase<?> toBuilder,
+ final JavaTypeName yangModuleInfo, final String localName) {
+ return toBuilder.addConstant(typeForClass(QName.class), BindingMapping.QNAME_STATIC_FIELD_NAME,
+ new SimpleImmutableEntry<>(yangModuleInfo, localName));
}
/**
SchemaNode result = targetGrouping;
for (final QName node : targetPath.getPathFromRoot()) {
if (result instanceof DataNodeContainer) {
- final QName resultNode = QName.create(result.getQName().getModule(), node.getLocalName());
+ final QName resultNode = node.withModule(result.getQName().getModule());
result = ((DataNodeContainer) result).getDataChildByName(resultNode);
} else if (result instanceof ChoiceSchemaNode) {
result = findNamedCase((ChoiceSchemaNode) result, node.getLocalName());
final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition(
JavaTypeName.create(packageNameForGeneratedType(context.modulePackageName(), choiceNode.getPath()),
BindingMapping.getClassName(choiceNode.getQName())), choiceNode);
- constructGetter(parent, choiceTypeBuilder, choiceNode);
- choiceTypeBuilder.addImplementsType(typeForClass(DataContainer.class));
+ choiceTypeBuilder.addImplementsType(choiceIn(parent));
annotateDeprecatedIfNecessary(choiceNode.getStatus(), choiceTypeBuilder);
context.addChildNodeType(choiceNode, choiceTypeBuilder);
- generateTypesFromChoiceCases(context, choiceTypeBuilder.build(), choiceNode);
+
+ final GeneratedType choiceType = choiceTypeBuilder.build();
+ generateTypesFromChoiceCases(context, choiceType, choiceNode);
+
+ constructGetter(parent, choiceType, choiceNode);
}
}
final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(context, caseNode);
caseTypeBuilder.addImplementsType(targetType);
- SchemaNode parent;
- final SchemaPath nodeSp = targetNode.getPath();
- parent = findDataSchemaNode(schemaContext, nodeSp.getParent());
-
- GeneratedTypeBuilder childOfType = null;
- if (parent instanceof Module) {
- childOfType = moduleContext(((Module) parent).getQNameModule()).getModuleNode();
- } else if (parent instanceof CaseSchemaNode) {
- childOfType = findCaseByPath(parent.getPath());
- } else if (parent instanceof DataSchemaNode || parent instanceof NotificationDefinition) {
- childOfType = findChildNodeByPath(parent.getPath());
- } else if (parent instanceof GroupingDefinition) {
- childOfType = findGroupingByPath(parent.getPath());
- }
-
- if (childOfType == null) {
- throw new IllegalArgumentException("Failed to find parent type of choice " + targetNode);
- }
-
+ GeneratedTypeBuilder childOfType = findChildOfType(targetNode);
CaseSchemaNode node = null;
final String caseLocalName = caseNode.getQName().getLocalName();
if (caseNode instanceof CaseSchemaNode) {
}
}
+ private GeneratedTypeBuilder findChildOfType(final ChoiceSchemaNode targetNode) {
+ final SchemaPath nodePath = targetNode.getPath();
+ final SchemaPath parentSp = nodePath.getParent();
+ if (parentSp.getParent() == null) {
+ return moduleContext(nodePath.getLastComponent().getModule()).getModuleNode();
+ }
+
+ final SchemaNode parent = findDataSchemaNode(schemaContext, parentSp);
+ GeneratedTypeBuilder childOfType = null;
+ if (parent instanceof CaseSchemaNode) {
+ childOfType = findCaseByPath(parent.getPath());
+ } else if (parent instanceof DataSchemaNode || parent instanceof NotificationDefinition) {
+ childOfType = findChildNodeByPath(parent.getPath());
+ } else if (parent instanceof GroupingDefinition) {
+ childOfType = findGroupingByPath(parent.getPath());
+ }
+
+ if (childOfType == null) {
+ throw new IllegalArgumentException("Failed to find parent type of choice " + targetNode);
+ }
+
+ return childOfType;
+ }
+
private static CaseSchemaNode findNamedCase(final ChoiceSchemaNode choice, final String caseName) {
final List<CaseSchemaNode> cases = choice.findCaseNodes(caseName);
return cases.isEmpty() ? null : cases.get(0);
+ nodeParam);
}
- final AnnotationTypeBuilder rc = getter.addAnnotation(JavaTypeName.create(RoutingContext.class));
+ final AnnotationTypeBuilder rc = getter.addAnnotation(ROUTING_CONTEXT);
final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath());
final String genTypeName = BindingMapping.getClassName(identity.getQName().getLocalName());
rc.addParameter("value", packageName + "." + genTypeName + ".class");
private GeneratedTOBuilder createUnionBuilder(final GeneratedTOBuilder genTOBuilder,
final GeneratedTypeBuilder typeBuilder) {
- final StringBuilder sb = new StringBuilder();
-
// Append enclosing path hierarchy without dots
- // TODO: JavaTypeName could be giving us a Stream<String> or similar, but there is no sense in generalizing
- // unless there is another caller.
- Optional<JavaTypeName> outerClass = genTOBuilder.getIdentifier().immediatelyEnclosingClass();
- if (outerClass.isPresent()) {
- final Deque<String> enclosingPath = new ArrayDeque<>();
- do {
- final JavaTypeName outerName = outerClass.get();
- enclosingPath.push(outerName.simpleName());
- outerClass = outerName.immediatelyEnclosingClass();
- } while (outerClass.isPresent());
-
- while (!enclosingPath.isEmpty()) {
- sb.append(enclosingPath.pop());
- }
- }
-
- sb.append(genTOBuilder.getName()).append("Builder");
+ final StringBuilder sb = new StringBuilder();
+ genTOBuilder.getIdentifier().localNameComponents().forEach(sb::append);
final GeneratedTOBuilder unionBuilder = typeProvider.newGeneratedTOBuilder(
- JavaTypeName.create(typeBuilder.getPackageName(), sb.toString()));
+ JavaTypeName.create(typeBuilder.getPackageName(), sb.append("Builder").toString()));
unionBuilder.setIsUnionBuilder(true);
return unionBuilder;
}
final Type parent, final ModuleContext context) {
final GeneratedTypeBuilder it = addRawInterfaceDefinition(
JavaTypeName.create(packageName, BindingMapping.getClassName(schemaNode.getQName())), schemaNode);
- if (parent == null) {
- it.addImplementsType(DATA_OBJECT);
- } else {
- it.addImplementsType(BindingTypes.childOf(parent));
- }
+
+ it.addImplementsType(parent == null ? DATA_OBJECT : childOf(parent));
if (!(schemaNode instanceof GroupingDefinition)) {
it.addImplementsType(augmentable(it));
}
-
if (schemaNode instanceof DataNodeContainer) {
- groupingsToGenTypes(context, ((DataNodeContainer) schemaNode).getGroupings());
- addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, it);
+ final DataNodeContainer containerSchema = (DataNodeContainer) schemaNode;
+ groupingsToGenTypes(context, containerSchema.getGroupings());
+ addImplementedInterfaceFromUses(containerSchema, it);
}
return it;
// FIXME: Validation of name conflict
final GeneratedTypeBuilder newType = typeProvider.newGeneratedTypeBuilder(identifier);
final Module module = findParentModule(schemaContext, schemaNode);
- qnameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, schemaNode.getQName());
+ qnameConstant(newType, JavaTypeName.create(BindingMapping.getRootPackageName(module.getQNameModule()),
+ BindingMapping.MODULE_INFO_CLASS_NAME), schemaNode.getQName().getLocalName());
addCodegenInformation(newType, module, schemaNode);
newType.setSchemaPath(schemaNode.getPath());
getterMethodName(node.getQName().getLocalName(), returnType));
getMethod.setReturnType(returnType);
- if (node.getStatus() == Status.DEPRECATED) {
- getMethod.addAnnotation("java.lang", "Deprecated");
+ annotateDeprecatedIfNecessary(node.getStatus(), getMethod);
+ if (!returnType.getPackageName().isEmpty()) {
+ // The return type has a package, so it's not a primitive type
+ getMethod.addAnnotation("javax.annotation", "Nullable");
}
addComment(getMethod, node);
if (genTOBuilder != null) {
final GeneratedTransferObject genTO = genTOBuilder.build();
-
- // Fake the 'getKey()' for items, this is equivalent to constructGetter()
- final MethodSignatureBuilder getMethod = typeBuilder.addMethod(getterMethodName("key", genTO));
- getMethod.setReturnType(genTO);
- getMethod.setComment("Returns Primary Key of Yang List Type");
+ // Add Identifiable.getKey() for items
+ typeBuilder.addMethod(BindingMapping.IDENTIFIABLE_KEY_NAME).setReturnType(genTO)
+ .addAnnotation(OVERRIDE_ANNOTATION);
context.addGeneratedTOBuilder(genTOBuilder);
}
}
return null;
}
- private static void annotateDeprecatedIfNecessary(final Status status, final GeneratedTypeBuilder builder) {
+ private static void annotateDeprecatedIfNecessary(final Status status, final AnnotableTypeBuilder builder) {
if (status == Status.DEPRECATED) {
- builder.addAnnotation("java.lang", "Deprecated");
+ builder.addAnnotation(DEPRECATED_ANNOTATION);
}
}
}