import com.google.common.collect.Iterables;
import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeNode.ChildAddressabilitySummary;
import org.opendaylight.yangtools.binding.data.codec.impl.NodeCodecContext.CodecContextFactory;
import org.opendaylight.yangtools.yang.binding.DataRoot;
import org.opendaylight.yangtools.yang.binding.Identifiable;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.AnyDataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.TypedSchemaNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
final class DataContainerCodecPrototype<T> implements NodeContextSupplier {
+ private static final Logger LOG = LoggerFactory.getLogger(DataContainerCodecPrototype.class);
private final T schema;
private final QNameModule namespace;
private final Class<?> bindingClass;
private final InstanceIdentifier.Item<?> bindingArg;
private final YangInstanceIdentifier.PathArgument yangArg;
- private volatile DataContainerCodecContext<?,T> instance = null;
+ private final ChildAddressabilitySummary childAddressabilitySummary;
+
+ private volatile DataContainerCodecContext<?, T> instance = null;
@SuppressWarnings({"rawtypes", "unchecked"})
private DataContainerCodecPrototype(final Class<?> cls, final YangInstanceIdentifier.PathArgument arg, final T nodeSchema,
} else {
this.namespace = arg.getNodeType().getModule();
}
+
+ this.childAddressabilitySummary = computeChildAddressabilitySummary(nodeSchema);
+ }
+
+ private static ChildAddressabilitySummary computeChildAddressabilitySummary(final Object nodeSchema) {
+ if (nodeSchema instanceof DataNodeContainer) {
+ boolean haveAddressable = false;
+ boolean haveUnaddressable = false;
+ for (DataSchemaNode child : ((DataNodeContainer) nodeSchema).getChildNodes()) {
+ if (child instanceof ContainerSchemaNode || child instanceof AugmentationSchema) {
+ haveAddressable = true;
+ } else if (child instanceof ListSchemaNode) {
+ if (((ListSchemaNode) child).getKeyDefinition().isEmpty()) {
+ haveUnaddressable = true;
+ } else {
+ haveAddressable = true;
+ }
+ } else if (child instanceof AnyDataSchemaNode || child instanceof AnyXmlSchemaNode
+ || child instanceof TypedSchemaNode) {
+ haveUnaddressable = true;
+ } else if (child instanceof ChoiceSchemaNode) {
+ switch (computeChildAddressabilitySummary(child)) {
+ case ADDRESSABLE:
+ haveAddressable = true;
+ break;
+ case MIXED:
+ haveAddressable = true;
+ haveUnaddressable = true;
+ break;
+ case UNADDRESSABLE:
+ haveUnaddressable = true;
+ break;
+ default:
+ throw new IllegalStateException("Unhandled accessibility summary for " + child);
+ }
+ } else {
+ LOG.warn("Unhandled child node {}", child);
+ }
+ }
+
+ if (!haveAddressable) {
+ // Empty or all are unaddressable
+ return ChildAddressabilitySummary.UNADDRESSABLE;
+ }
+
+ return haveUnaddressable ? ChildAddressabilitySummary.MIXED : ChildAddressabilitySummary.ADDRESSABLE;
+ } else if (nodeSchema instanceof ChoiceSchemaNode) {
+ boolean haveAddressable = false;
+ boolean haveUnaddressable = false;
+ for (ChoiceCaseNode child : ((ChoiceSchemaNode) nodeSchema).getCases()) {
+ switch (computeChildAddressabilitySummary(child)) {
+ case ADDRESSABLE:
+ haveAddressable = true;
+ break;
+ case UNADDRESSABLE:
+ haveUnaddressable = true;
+ break;
+ case MIXED:
+ // A child is mixed, which means we are mixed, too
+ return ChildAddressabilitySummary.MIXED;
+ default:
+ throw new IllegalStateException("Unhandled accessibility summary for " + child);
+ }
+ }
+
+ if (!haveAddressable) {
+ // Empty or all are unaddressable
+ return ChildAddressabilitySummary.UNADDRESSABLE;
+ }
+
+ return haveUnaddressable ? ChildAddressabilitySummary.MIXED : ChildAddressabilitySummary.ADDRESSABLE;
+ }
+
+ // No child nodes possible: return unaddressable
+ return ChildAddressabilitySummary.UNADDRESSABLE;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
static DataContainerCodecPrototype<SchemaContext> rootPrototype(final CodecContextFactory factory) {
final SchemaContext schema = factory.getRuntimeContext().getSchemaContext();
final NodeIdentifier arg = NodeIdentifier.create(schema.getQName());
- return new DataContainerCodecPrototype<SchemaContext>(DataRoot.class, arg, schema, factory);
+ return new DataContainerCodecPrototype<>(DataRoot.class, arg, schema, factory);
}
static DataContainerCodecPrototype<NotificationDefinition> from(final Class<?> augClass, final NotificationDefinition schema, final CodecContextFactory factory) {
final PathArgument arg = NodeIdentifier.create(schema.getQName());
- return new DataContainerCodecPrototype<NotificationDefinition>(augClass,arg, schema, factory);
+ return new DataContainerCodecPrototype<>(augClass,arg, schema, factory);
}
protected T getSchema() {
return schema;
}
+ ChildAddressabilitySummary getChildAddressabilitySummary() {
+ return childAddressabilitySummary;
+ }
+
protected QNameModule getNamespace() {
return namespace;
}