--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco 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.mdsal.binding2.spec;
+
+public interface Action<I extends Input<I> & Instantiable<I>, O extends Output<O> & Instantiable<O>> {
+
+ void invoke(I input, RpcCallback<O> callback);
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ClassToInstanceMap;
+
+/**
+ * Augmentable (extensible) object which could carry additional data defined by third-party
+ * extension, without introducing conflict between various extension.
+ *
+ * This interface uses extended version of ExtensibleInterface pattern which also adds marker
+ * interface for augmentations (extensions) - {@link Augmentable}
+ *
+ * @author Tony Tkacik
+ * @param <T> Base class which should implements this interface and is target for augmentation.
+ */
+@Beta
+public interface Augmentable<T> {
+
+ /**
+ * Returns instance of augmentation based on class
+ *
+ * @param augment Type of augmentation to be returned.
+ * @return instance of augmentation.
+ */
+ default <E extends Augmentation<? super T>> E getAugmentation(Class<E> augment) {
+ return augments().getInstance(augment);
+ }
+
+ /**
+ *
+ * Returns map of all instantiated augmentations.
+ *
+ * @return Class to Instance Map
+ */
+ // REPLACES: BindingReflections#getAugmentations()
+ ClassToInstanceMap<Augmentation<? super T>> augments();
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.util.ClassLoaderUtils;
+
+@Beta
+public interface Augmentation<T> {
+
+ // REPLACES: BindingReflections#findAugmentationTarget
+ default Class<T> augmentTarget() {
+ return ClassLoaderUtils.findFirstGenericArgument(getClass(), Augmentation.class);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+
+/**
+ * Binding Namespace is structure of Java packages designed to prevent conflicts in YANG Java
+ * Binding, since Java does have only one namespace.
+ *
+ *
+ */
+@Beta
+public enum BindingNamespaceType {
+
+ /**
+ *
+ * Namespace containing all derived types, defined from grouping and data namespaces
+ *
+ */
+ Typedef("type"), Identity("ident"), Key("key"), Data("data"), Grouping("grp"), Builder("dto"),;
+
+ private final String packagePrefix;
+
+ private BindingNamespaceType(String packagePrefix) {
+ this.packagePrefix = Preconditions.checkNotNull(packagePrefix);
+ }
+
+ public String getPackagePrefix() {
+ return packagePrefix;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+
+/**
+ * An IdentifiableItem represents a object that is usually present in a collection and can be
+ * identified uniquely by a key. In YANG terms this would probably represent an item in a list.
+ *
+ * @param <I> An object that is identifiable by an identifier
+ * @param <T> The identifier of the object
+ */
+@Beta
+public final class IdentifiableItem<I extends TreeNode, T> extends TreeArgument<I> {
+ private final Class<I> type;
+ private final T key;
+
+ public IdentifiableItem(final Class<I> type, final T key) {
+ this.type = Preconditions.checkNotNull(type);
+ this.key = Preconditions.checkNotNull(key, "Key may not be null.");
+ }
+
+ @Override
+ public Class<I> getType() {
+ return type;
+ }
+
+ public T getKey() {
+ return this.key;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ return super.equals(obj) && key.equals(((IdentifiableItem<?, ?>) obj).getKey());
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() * 31 + key.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return type.getName() + "[key=" + key + "]";
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+
+@Beta
+public interface Input<T extends Input<T>> {
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 - 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.util.HashCodeBuilder;
+
+/**
+ *
+ * This instance identifier uniquely identifies a specific TreeNode in the data tree modeled by
+ * YANG.
+ *
+ * For Example let's say you were trying to refer to a node in inventory which was modeled in YANG
+ * as follows,
+ *
+ * <pre>
+ * module opendaylight-inventory {
+ * ....
+ *
+ * container nodes {
+ * list node {
+ * key "id";
+ * ext:context-instance "node-context";
+ *
+ * uses node;
+ * }
+ * }
+ *
+ * }
+ * </pre>
+ *
+ * You could create an instance identifier as follows to get to a node with id "openflow:1"
+ *
+ * InstanceIdentifierBuilder.builder(Nodes.class).child(Node.class, new NodeKey(new
+ * NodeId("openflow:1")).build();
+ *
+ * This would be the same as using a path like so, "/nodes/node/openflow:1" to refer to the
+ * openflow:1 node
+ *
+ */
+@Beta
+public class InstanceIdentifier<T extends TreeNode> implements Immutable, Serializable {
+ private static final Field PATHARGUMENTS_FIELD;
+ private static final long serialVersionUID = 2L;
+ /*
+ * Protected to differentiate internal and external access. Internal
+ * access is required never to modify the contents. References passed
+ * to outside entities have to be wrapped in an unmodifiable view.
+ */
+ protected transient final Iterable<TreeArgument> pathArguments;
+ private final Class<T> targetType;
+ private final boolean wildcarded;
+ private final int hash;
+
+ static {
+ final Field f;
+ try {
+ f = InstanceIdentifier.class.getDeclaredField("pathArguments");
+ } catch (NoSuchFieldException | SecurityException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ f.setAccessible(true);
+ PATHARGUMENTS_FIELD = f;
+ }
+
+ InstanceIdentifier(final Class<T> type, final Iterable<TreeArgument> pathArguments, final boolean wildcarded, final int hash) {
+ this.pathArguments = Preconditions.checkNotNull(pathArguments);
+ this.targetType = Preconditions.checkNotNull(type);
+ this.wildcarded = wildcarded;
+ this.hash = hash;
+ }
+
+ /**
+ * Return the type of data which this InstanceIdentifier identifies.
+ *
+ * @return Target type
+ */
+ public final Class<T> getTargetType() {
+ return targetType;
+ }
+
+ /**
+ * Return the path argument chain which makes up this instance identifier.
+ *
+ * @return Path argument chain. Immutable and does not contain nulls.
+ */
+ public final Iterable<TreeArgument> getPathArguments() {
+ return Iterables.unmodifiableIterable(pathArguments);
+ }
+
+ /**
+ * Check whether an instance identifier contains any wildcards. A wildcard
+ * is an path argument which has a null key.
+ *
+ * @return true if any of the path arguments has a null key.
+ */
+ public final boolean isWildcarded() {
+ return wildcarded;
+ }
+
+ @Override
+ public final int hashCode() {
+ return hash;
+ }
+
+ @Override
+ public final boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ final InstanceIdentifier<?> other = (InstanceIdentifier<?>) obj;
+ if (pathArguments == other.pathArguments) {
+ return true;
+ }
+
+ /*
+ * We could now just go and compare the pathArguments, but that
+ * can be potentially expensive. Let's try to avoid that by
+ * checking various things that we have cached from pathArguments
+ * and trying to prove the identifiers are *not* equal.
+ */
+ if (hash != other.hash) {
+ return false;
+ }
+ if (wildcarded != other.wildcarded) {
+ return false;
+ }
+ if (targetType != other.targetType) {
+ return false;
+ }
+ if (fastNonEqual(other)) {
+ return false;
+ }
+
+ // Everything checks out so far, so we have to do a full equals
+ return Iterables.elementsEqual(pathArguments, other.pathArguments);
+ }
+
+ /**
+ * Perform class-specific fast checks for non-equality. This allows
+ * subclasses to avoid iterating over the pathArguments by performing
+ * quick checks on their specific fields.
+ *
+ * @param other The other identifier, guaranteed to be the same class
+ * @return true if the other identifier cannot be equal to this one.
+ */
+ protected boolean fastNonEqual(final InstanceIdentifier<?> other) {
+ return false;
+ }
+
+ @Override
+ public final String toString() {
+ return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
+ }
+
+ /**
+ * Add class-specific toString attributes.
+ *
+ * @param toStringHelper ToStringHelper instance
+ * @return ToStringHelper instance which was passed in
+ */
+ protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+ return toStringHelper.add("targetType", targetType).add("path", Iterables.toString(pathArguments));
+ }
+
+ /**
+ * Return an instance identifier trimmed at the first occurrence of a
+ * specific component type.
+ *
+ * For example let's say an instance identifier was built like so,
+ * <pre>
+ * identifier = InstanceIdentifierBuilder.builder(Nodes.class).child(Node.class, new NodeKey(new NodeId("openflow:1")).build();
+ * </pre>
+ *
+ * And you wanted to obtain the Instance identifier which represented Nodes you would do it like so,
+ *
+ * <pre>
+ * identifier.firstIdentifierOf(Nodes.class)
+ * </pre>
+ *
+ * @param type component type
+ * @return trimmed instance identifier, or null if the component type
+ * is not present.
+ */
+ public final <I extends TreeNode> InstanceIdentifier<I> firstIdentifierOf(final Class<I> type) {
+ int i = 1;
+ for (final TreeArgument a : pathArguments) {
+ if (type.equals(a.getType())) {
+ @SuppressWarnings("unchecked")
+ final InstanceIdentifier<I> ret = (InstanceIdentifier<I>) internalCreate(Iterables.limit(pathArguments, i));
+ return ret;
+ }
+
+ ++i;
+ }
+
+ return null;
+ }
+
+ /**
+ * Return the key associated with the first component of specified type in
+ * an identifier.
+ *
+ * @param listItem component type
+ * @param listKey component key type
+ * @return key associated with the component, or null if the component type
+ * is not present.
+ *
+ * @deprecated Use {@link #firstKeyOf(Class)} instead.
+ */
+ @Deprecated
+ public final <N extends TreeNode, K> K firstKeyOf(final Class<N> listItem,
+ final Class<K> listKey) {
+ return firstKeyOf(listItem);
+ }
+
+ /**
+ * Return the key associated with the first component of specified type in
+ * an identifier.
+ *
+ * @param listItem component type
+ * @return key associated with the component, or null if the component type
+ * is not present.
+ */
+
+ public final <N extends TreeNode, K> K firstKeyOf(final Class<N> listItem) {
+ for (final TreeArgument i : pathArguments) {
+ if (listItem.equals(i.getType())) {
+ @SuppressWarnings("unchecked")
+ final K ret = ((IdentifiableItem<N, K>)i).getKey();
+ return ret;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Check whether an identifier is contained in this identifier. This is a strict subtree check, which requires all
+ * PathArguments to match exactly, e.g.
+ *
+ *
+ * The contains method checks if the other identifier is fully contained within the current identifier. It does this
+ * by looking at only the types of the path arguments and not by comparing the path arguments themselves.
+ *
+ * To illustrate here is an example which explains the working of this API.
+ *
+ * Let's say you have two instance identifiers as follows,
+ *
+ * this = /nodes/node/openflow:1
+ * other = /nodes/node/openflow:2
+ *
+ * then this.contains(other) will return false.
+ *
+ * @param other
+ * @return
+ */
+ public final boolean contains(final InstanceIdentifier<? extends TreeNode> other) {
+ Preconditions.checkNotNull(other, "other should not be null");
+
+ final Iterator<?> lit = pathArguments.iterator();
+ final Iterator<?> oit = other.pathArguments.iterator();
+
+ while (lit.hasNext()) {
+ if (!oit.hasNext()) {
+ return false;
+ }
+
+ if (!lit.next().equals(oit.next())) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Check whether this instance identifier contains the other identifier after wildcard expansion. This is similar
+ * to {@link #contains(InstanceIdentifier)}, with the exception that a wildcards are assumed to match the their
+ * non-wildcarded PathArgument counterpart.
+ *
+ * @param other Identifier which should be checked for inclusion.
+ * @return true if this identifier contains the other object
+ */
+ public final boolean containsWildcarded(final InstanceIdentifier<?> other) {
+ Preconditions.checkNotNull(other, "other should not be null");
+
+ final Iterator<TreeArgument> lit = pathArguments.iterator();
+ final Iterator<TreeArgument> oit = other.pathArguments.iterator();
+
+ while (lit.hasNext()) {
+ if (!oit.hasNext()) {
+ return false;
+ }
+
+ final TreeArgument la = lit.next();
+ final TreeArgument oa = oit.next();
+
+ if (!la.getType().equals(oa.getType())) {
+ return false;
+ }
+ if (la instanceof IdentifiableItem<?, ?> && oa instanceof IdentifiableItem<?, ?> && !la.equals(oa)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Create a builder rooted at this key.
+ *
+ * @return A builder instance
+ */
+ public InstanceIdentifierBuilder<T> builder() {
+ return new InstanceIdentifierBuilderImpl<T>(new Item<T>(targetType), pathArguments, hash, isWildcarded());
+ }
+
+ private InstanceIdentifier<?> childIdentifier(final TreeArgument arg) {
+ return trustedCreate(arg, Iterables.concat(pathArguments, Collections.singleton(arg)), HashCodeBuilder.nextHashCode(hash, arg), isWildcarded());
+ }
+
+ @SuppressWarnings("unchecked")
+ public final <N extends TreeChildNode<? super T, ?>> InstanceIdentifier<N> child(final Class<N> container) {
+ final TreeArgument arg = new Item<>(container);
+ return (InstanceIdentifier<N>) childIdentifier(arg);
+ }
+
+ @SuppressWarnings("unchecked")
+ public final <N extends TreeChildNode<? super T, ?>, K> KeyedInstanceIdentifier<N, K> child(
+ final Class<N> listItem, final K listKey) {
+ final TreeArgument arg = new IdentifiableItem<>(listItem, listKey);
+ return (KeyedInstanceIdentifier<N, K>) childIdentifier(arg);
+ }
+
+ @SuppressWarnings("unchecked")
+ public final <N extends TreeNode & Augmentation<? super T>> InstanceIdentifier<N> augmentation(
+ final Class<N> container) {
+ final TreeArgument arg = new Item<>(container);
+ return (InstanceIdentifier<N>) childIdentifier(arg);
+ }
+
+ @Deprecated
+ private List<TreeArgument> legacyCache;
+
+ /**
+ * @deprecated Use {@link #getPathArguments()} instead.
+ */
+ @Deprecated
+ public final List<TreeArgument> getPath() {
+ if (legacyCache == null) {
+ legacyCache = ImmutableList.<TreeArgument>copyOf(pathArguments);
+ }
+
+ return legacyCache;
+ }
+
+ /**
+ * Create a new InstanceIdentifierBuilder given a base InstanceIdentifier
+ *
+ * @param base
+ * @param <T>
+ * @return
+ *
+ * @deprecated Use {@link #builder()} instead.
+ */
+ @Deprecated
+ public static <T extends TreeNode> InstanceIdentifierBuilder<T> builder(final InstanceIdentifier<T> base) {
+ return base.builder();
+ }
+
+ /**
+ * Create an InstanceIdentifierBuilder for a specific type of InstanceIdentifier as specified by container
+ *
+ * @param container
+ * @param <T>
+ * @return
+ */
+ public static <T extends TreeChildNode<? extends TreeRoot, ?>> InstanceIdentifierBuilder<T> builder(
+ final Class<T> container) {
+ return new InstanceIdentifierBuilderImpl<T>().addNode(container);
+ }
+
+ /**
+ * Create an InstanceIdentifierBuilder for a specific type of InstanceIdentifier which represents an IdentifiableItem
+ *
+ * @param listItem
+ * @param listKey
+ * @param <N>
+ * @param <K>
+ * @return
+ */
+
+ public static <N extends TreeChildNode<? extends TreeRoot, ?>, K> InstanceIdentifierBuilder<N> builder(
+ final Class<N> listItem, final K listKey) {
+ return new InstanceIdentifierBuilderImpl<N>().addNode(listItem, listKey);
+ }
+
+ /**
+ * Create an instance identifier for a very specific object type. This method
+ * implements {@link #create(Iterable)} semantics, except it is used by internal
+ * callers, which have assured that the argument is an immutable Iterable.
+ *
+ *
+ * @param pathArguments The path to a specific node in the data tree
+ * @return InstanceIdentifier instance
+ * @throws IllegalArgumentException if pathArguments is empty or
+ * contains a null element.
+ */
+ private static InstanceIdentifier<?> internalCreate(final Iterable<TreeArgument> pathArguments) {
+ final Iterator<? extends TreeArgument> it = Preconditions.checkNotNull(pathArguments, "pathArguments may not be null").iterator();
+ final HashCodeBuilder<TreeArgument> hashBuilder = new HashCodeBuilder<>();
+ boolean wildcard = false;
+ TreeArgument a = null;
+
+ while (it.hasNext()) {
+ a = it.next();
+ Preconditions.checkArgument(a != null, "pathArguments may not contain null elements");
+
+ // TODO: sanity check ChildTreeNode<>;
+ hashBuilder.addArgument(a);
+
+ if (Identifiable.class.isAssignableFrom(a.getType()) && !(a instanceof IdentifiableItem<?, ?>)) {
+ wildcard = true;
+ }
+ }
+ Preconditions.checkArgument(a != null, "pathArguments may not be empty");
+
+ return trustedCreate(a, pathArguments, hashBuilder.build(), wildcard);
+ }
+
+ /**
+ * Create an instance identifier for a very specific object type.
+ *
+ * Example
+ * <pre>
+ * List<PathArgument> path = Arrays.asList(new Item(Nodes.class))
+ * new InstanceIdentifier(path);
+ * </pre>
+ *
+ * @param pathArguments The path to a specific node in the data tree
+ * @return InstanceIdentifier instance
+ * @throws IllegalArgumentException if pathArguments is empty or
+ * contains a null element.
+ */
+ public static InstanceIdentifier<?> create(final Iterable<? extends TreeArgument> pathArguments) {
+ if (pathArguments instanceof ImmutableCollection<?>) {
+ @SuppressWarnings("unchecked")
+ final Iterable<TreeArgument> immutableArguments = (Iterable<TreeArgument>) pathArguments;
+ return internalCreate(immutableArguments);
+ } else {
+ return internalCreate(ImmutableList.copyOf(pathArguments));
+ }
+ }
+
+ /**
+ * Create an instance identifier for a very specific object type.
+ *
+ * For example
+ * <pre>
+ * new InstanceIdentifier(Nodes.class)
+ * </pre>
+ * would create an InstanceIdentifier for an object of type Nodes
+ *
+ * @param type The type of the object which this instance identifier represents
+ * @return InstanceIdentifier instance
+ */
+ @SuppressWarnings("unchecked")
+ public static <T extends TreeNode> InstanceIdentifier<T> create(final Class<T> type) {
+ return (InstanceIdentifier<T>) create(Collections.<TreeArgument> singletonList(new Item<>(type)));
+ }
+
+ /**
+ * Return the key associated with the last component of the specified identifier.
+ *
+ * @param id instance identifier
+ * @return key associated with the last component
+ * @throws IllegalArgumentException if the supplied identifier type cannot have a key.
+ * @throws NullPointerException if id is null.
+ */
+
+ public static <N extends TreeNode, K> K keyOf(
+ final InstanceIdentifier<N> id) {
+ Preconditions.checkNotNull(id);
+ Preconditions.checkArgument(id instanceof KeyedInstanceIdentifier, "%s does not have a key", id);
+
+ @SuppressWarnings("unchecked")
+ final K ret = ((KeyedInstanceIdentifier<N, K>)id).getKey();
+ return ret;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ static InstanceIdentifier<?> trustedCreate(final TreeArgument arg, final Iterable<TreeArgument> pathArguments, final int hash, boolean wildcarded) {
+ if (Identifiable.class.isAssignableFrom(arg.getType()) && !(wildcarded)) {
+ Object key = null;
+ if (arg instanceof IdentifiableItem<?, ?>) {
+ key = ((IdentifiableItem<?, ?>) arg).getKey();
+ } else {
+ wildcarded = true;
+ }
+
+ return new KeyedInstanceIdentifier(arg.getType(), pathArguments, wildcarded, hash, key);
+ } else {
+ return new InstanceIdentifier(arg.getType(), pathArguments, wildcarded, hash);
+ }
+ }
+
+ private void writeObject(final java.io.ObjectOutputStream out) throws IOException {
+ out.defaultWriteObject();
+ out.writeInt(Iterables.size(pathArguments));
+ for (Object o : pathArguments) {
+ out.writeObject(o);
+ }
+ }
+
+ private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+
+ final int size = in.readInt();
+ final List<TreeArgument> args = new ArrayList<>(size);
+ for (int i = 0; i < size; ++i) {
+ args.add((TreeArgument) in.readObject());
+ }
+
+ try {
+ PATHARGUMENTS_FIELD.set(this, ImmutableList.copyOf(args));
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ throw new IOException(e);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 - 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.concepts.Builder;
+
+@Beta
+public interface InstanceIdentifierBuilder<T extends TreeNode> extends Builder<InstanceIdentifier<T>> {
+ /**
+ * Append the specified container as a child of the current InstanceIdentifier referenced by the
+ * builder.
+ *
+ * This method should be used when you want to build an instance identifier by appending
+ * top-level elements
+ *
+ * Example,
+ *
+ * <pre>
+ * InstanceIdentifier.builder().child(Nodes.class).build();
+ *
+ * </pre>
+ *
+ * NOTE :- The above example is only for illustration purposes InstanceIdentifier.builder() has
+ * been deprecated and should not be used. Use InstanceIdentifier.builder(Nodes.class) instead
+ *
+ * @param container
+ * @param <N>
+ * @return
+ */
+ // FIXME: Why TreeNode needs to be explicitly mentioned, whern ChildTreeNode is derived from
+ // TreeNode?
+ <N extends TreeNode & TreeChildNode<? super T, Item<N>>> InstanceIdentifierBuilder<N> child(Class<N> container);
+
+ /**
+ * Append the specified listItem as a child of the current InstanceIdentifier referenced by the
+ * builder.
+ *
+ * This method should be used when you want to build an instance identifier by appending a
+ * specific list element to the identifier
+ *
+ * @param listItem
+ * @param listKey
+ * @param <N>
+ * @param <K>
+ * @return
+ */
+ <N extends TreeChildNode<? super T, ?>, K> InstanceIdentifierBuilder<N> child(Class<N> listItem, K listKey);
+
+ /**
+ * Build an identifier which refers to a specific augmentation of the current InstanceIdentifier
+ * referenced by the builder
+ *
+ * @param container
+ * @param <N>
+ * @return
+ */
+ <N extends TreeNode & Augmentation<? super T>> InstanceIdentifierBuilder<N> augmentation(Class<N> container);
+
+ /**
+ * Build the instance identifier.
+ *
+ * @return
+ */
+ @Override
+ InstanceIdentifier<T> build();
+
+ /*
+ * @deprecated use #build()
+ */
+ @Deprecated
+ InstanceIdentifier<T> toInstance();
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2013 - 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.util.HashCodeBuilder;
+
+@Beta
+final class InstanceIdentifierBuilderImpl<T extends TreeNode>
+ implements InstanceIdentifierBuilder<T> {
+ private final ImmutableList.Builder<TreeArgument> pathBuilder = ImmutableList.builder();
+ private final HashCodeBuilder<TreeArgument> hashBuilder;
+ private final Iterable<? extends TreeArgument> basePath;
+ private boolean wildcard = false;
+ private TreeArgument arg = null;
+
+ InstanceIdentifierBuilderImpl() {
+ this.hashBuilder = new HashCodeBuilder<>();
+ this.basePath = null;
+ }
+
+ InstanceIdentifierBuilderImpl(final TreeArgument item, final Iterable<? extends TreeArgument> pathArguments, final int hash, final boolean wildcard) {
+ this.hashBuilder = new HashCodeBuilder<>(hash);
+ this.basePath = pathArguments;
+ this.wildcard = wildcard;
+ this.arg = item;
+ }
+
+ @Override
+ public int hashCode() {
+ return hashBuilder.build();
+ }
+
+ @SuppressWarnings("unchecked")
+ <N extends TreeNode> InstanceIdentifierBuilderImpl<N> addNode(final Class<N> container) {
+ arg = new Item<N>(container);
+ hashBuilder.addArgument(arg);
+ pathBuilder.add(arg);
+
+ if (Identifiable.class.isAssignableFrom(container)) {
+ wildcard = true;
+ }
+
+ return (InstanceIdentifierBuilderImpl<N>) this;
+ }
+
+ @SuppressWarnings("unchecked")
+ <N extends TreeNode, K> InstanceIdentifierBuilderImpl<N> addNode(
+ final Class<N> listItem, final K listKey) {
+ arg = new IdentifiableItem<N, K>(listItem, listKey);
+ hashBuilder.addArgument(arg);
+ pathBuilder.add(arg);
+ return (InstanceIdentifierBuilderImpl<N>) this;
+ }
+
+ @Override
+ public <N extends TreeNode & TreeChildNode<? super T, Item<N>>> InstanceIdentifierBuilderImpl<N> child(
+ final Class<N> container) {
+ return addNode(container);
+ }
+
+ @Override
+ public <N extends TreeChildNode<? super T, ?>, K> InstanceIdentifierBuilderImpl<N> child(
+ final Class<N> listItem, final K listKey) {
+ return addNode(listItem, listKey);
+ }
+
+ /**
+ * Build an identifier which refers to a specific augmentation of the current InstanceIdentifier referenced by
+ * the builder
+ *
+ * @param container
+ * @param <N>
+ * @return
+ */
+ @Override
+ public <N extends TreeNode & Augmentation<? super T>> InstanceIdentifierBuilderImpl<N> augmentation(
+ final Class<N> container) {
+ return addNode(container);
+ }
+
+ @Override
+ public InstanceIdentifier<T> build() {
+ Preconditions.checkState(arg != null, "No path arguments present");
+
+ final Iterable<TreeArgument> pathArguments;
+ if (basePath == null) {
+ pathArguments = pathBuilder.build();
+ } else {
+ pathArguments = Iterables.concat(basePath, pathBuilder.build());
+ }
+
+ @SuppressWarnings("unchecked")
+ final InstanceIdentifier<T> ret = (InstanceIdentifier<T>) InstanceIdentifier.trustedCreate(arg, pathArguments, hashBuilder.build(), wildcard);
+ return ret;
+ }
+
+ /*
+ * @deprecated Use #build() instead.
+ */
+ @Override
+ @Deprecated
+ public InstanceIdentifier<T> toInstance() {
+ return build();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Represents instantiable data object such as input / output, data tree items.
+ *
+ * @param <T> Final interface which is instantiable and extends this interface
+ */
+
+@Beta
+public interface Instantiable<T extends Instantiable<T>> {
+
+ // REPLACES: DataObject#getImplementedInterface()
+ Class<T> implementedInterface();
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+
+/**
+ * An Item represents an object that probably is only one of it's kind. For example a Nodes object
+ * is only one of a kind. In YANG terms this would probably represent a container.
+ *
+ * @param <T>
+ */
+
+@Beta
+public final class Item<T extends TreeNode> extends TreeArgument<T> {
+ private final Class<T> type;
+
+ public Item(final Class<T> type) {
+ this.type = Preconditions.checkNotNull(type);
+ }
+
+ @Override
+ public Class<T> getType() {
+ return type;
+ }
+
+ @Override
+ public String toString() {
+ return type.getName();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * An {@link InstanceIdentifier}, which has a list key attached at its last path
+ * element.
+ *
+ * @param <T> Target data type
+ * @param <K> Target key type
+ */
+
+@Beta
+public class KeyedInstanceIdentifier<T extends TreeNode, K> extends InstanceIdentifier<T> {
+ private static final long serialVersionUID = 1L;
+ private final K key;
+
+ KeyedInstanceIdentifier(final Class<T> type, final Iterable<TreeArgument> pathArguments, final boolean wildcarded, final int hash, final K key) {
+ super(type, pathArguments, wildcarded, hash);
+ this.key = key;
+ }
+
+ /**
+ * Return the key attached to this identifier. This method is equivalent to
+ * calling {@link InstanceIdentifier#keyOf(InstanceIdentifier)}.
+ *
+ * @return Key associated with this instance identifier.
+ */
+ public final K getKey() {
+ return key;
+ }
+
+ @Override
+ public final InstanceIdentifierBuilder<T> builder() {
+ return new InstanceIdentifierBuilderImpl<T>(new IdentifiableItem<T, K>(getTargetType(), key), pathArguments,
+ hashCode(), isWildcarded());
+ }
+
+ @Override
+ protected boolean fastNonEqual(final InstanceIdentifier<?> other) {
+ final KeyedInstanceIdentifier<?, ?> kii = (KeyedInstanceIdentifier<?, ?>) other;
+
+ /*
+ * We could do an equals() here, but that may actually be expensive.
+ * equals() in superclass falls back to a full compare, which will
+ * end up running that equals anyway, so do not bother here.
+ */
+ return (key == null) != (kii.key == null);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Marker interface for YANG-defined notifications
+ *
+ *
+ */
+@Beta
+public interface Notification<T extends Notification<T>> {
+
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+
+@Beta
+public interface Output<T extends Output<T>> {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+
+@Beta
+public interface RpcCallback<O> {
+
+ void onSuccess(O output);
+
+ void onFailure(Throwable e);
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+
+@Beta
+public abstract class TreeArgument<T> {
+
+ static TreeArgument<TreeRoot> root() {
+ throw new UnsupportedOperationException();
+ }
+
+ static <T extends TreeChildNode<?, ?>> Item<T> singular(Class<T> implementedInterface) {
+ throw new UnsupportedOperationException();
+ }
+
+ TreeArgument() {
+ // Intentionally package-visible & noop
+ }
+
+ public abstract Class<T> getType();
+
+ @Override
+ public int hashCode() {
+ return getType().hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final TreeArgument<?> other = (TreeArgument<?>) obj;
+ return getType().equals(other.getType());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.util.ClassLoaderUtils;
+
+@Beta
+public interface TreeChildNode<P extends TreeNode, I extends TreeArgument<?>> extends TreeNode {
+
+ I treeIdentifier();
+
+
+ // REPLACES: BindingReflections#findHierarchicalParent()
+ default Class<P> treeParent() {
+ return ClassLoaderUtils.findFirstGenericArgument(getClass(), TreeChildNode.class);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+
+/**
+ *
+ *
+ * @see TreeRoot
+ * @see TreeChildNode
+ *
+ */
+
+@Beta
+public interface TreeNode {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco 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.mdsal.binding2.spec;
+
+import com.google.common.annotations.Beta;
+
+@Beta
+public interface TreeRoot extends TreeNode {
+
+}
=== Binding Specification v2 Concepts
-<<Instantiated>>::
- Represent node, which is instantiated
+<<Instantiable>>::
+ Represent node, which is instantiable by users as a part of notification,
+ rpc, action or data tree.
<<TreeNode>>::
Represents node, which is part of instantiated data tree, this interface
is not used directly, but rather via <<TreeChildNode>>. See <<instantiated-data-tree-rules>>
Unique identifier of node / subtree in data tree, which provides unambiguous
information, how to reference node / subtree in Instantiated Data Tree.
+
+[cols="6"]
+|===
+.2+|Statement .2+| In groupings 3+| Instantiable .2+| Augmentable
+| In Data | In RPC | In Notification
+
+| `grouping` | Yes | No | No | No | No
+
+| `container` | Yes | Yes | Yes | Yes | Yes
+
+| `leaf` | Yes | Yes | Yes | Yes | No
+
+| `leaf-list` | Yes | Yes | Yes | Yes | No
+
+| `list` | Yes | Yes | Yes | Yes | Yes
+
+| `anydata` | Yes | Yes | Yes | Yes | No
+
+| `anyxml` | Yes | Yes | Yes | Yes | No
+
+| `choice` | Yes | Yes | Yes | Yes | Yes
+
+| `case` | Yes | Yes | Yes | Yes | Yes
+
+| `input` | Yes | No | Yes | No | Yes
+
+| `output` | Yes | No | Yes | No | Yes
+
+| `notification` | Yes | No | No | Yes | Yes
+
+|===
+
== Namespaces
YANG defines several namespaces and naming space of YANG is wider then applicable