Merge "Fix for Bug 511 (concepts)"
authorTony Tkacik <ttkacik@cisco.com>
Tue, 18 Mar 2014 11:04:04 +0000 (11:04 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 18 Mar 2014 11:04:04 +0000 (11:04 +0000)
42 files changed:
websocket/websocket-client/src/main/java/org/opendaylight/yangtools/websocket/client/WebSocketClientHandler.java
websocket/websocket-client/src/main/java/org/opendaylight/yangtools/websocket/client/WebSocketIClient.java
websocket/websocket-client/src/main/java/org/opendaylight/yangtools/websocket/client/callback/ClientMessageCallback.java
websocket/websocket-client/src/test/java/org/opendaylight/yangtools/websocket/server/WebSocketServer.java
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/AugmentationNode.java
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ChoiceNode.java
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ContainerNode.java
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/DataContainerNode.java
yang/yang-data-impl/pom.xml
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/Builders.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/CollectionNodeBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/DataContainerNodeBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/ListNodeBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/NormalizedNodeBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableNormalizedNodeBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableAugmentationNodeBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableAugmentationNodeSchemaAwareBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeSchemaAwareBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableContainerNodeBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableContainerNodeSchemaAwareBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafNodeBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafNodeSchemaAwareBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetEntryNodeBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetEntryNodeSchemaAwareBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetNodeBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetNodeSchemaAwareBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapEntryNodeBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapEntryNodeSchemaAwareBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapNodeBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapNodeSchemaAwareBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/valid/DataNodeContainerValidator.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerNode.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedNode.java [new file with mode: 0644]
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/NormalizedDataBuilderTest.java [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple.xml [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/test.yang [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangParserImpl.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/impl/AugmentTest.java
yang/yang-parser-impl/src/test/resources/augment-test/augment-in-uses/foo.yang [new file with mode: 0644]

index e81831ba58f935ec8054976ba5871bc31b5d279f..d2392a4fd394685ed796c6074d87e3bd69a148b9 100644 (file)
@@ -23,19 +23,39 @@ import org.opendaylight.yangtools.websocket.client.callback.ClientMessageCallbac
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * {@link WebSocketClientHandler} is implementation of
+ * {@link SimpleChannelInboundHandler} which handle {@link TextWebSocketFrame},
+ * {@link PongWebSocketFrame} and {@link CloseWebSocketFrame} messages.
+ */
 public class WebSocketClientHandler extends SimpleChannelInboundHandler<Object> {
 
-    private static final Logger logger = LoggerFactory.getLogger(WebSocketClientHandler.class.toString());
+    private static final Logger logger = LoggerFactory
+            .getLogger(WebSocketClientHandler.class.toString());
     private final WebSocketClientHandshaker handshaker;
     private ChannelPromise handshakeFuture;
     private ClientMessageCallback messageListener;
 
-
-    public WebSocketClientHandler(WebSocketClientHandshaker handshaker,ClientMessageCallback listener) {
+    /**
+     * Create new Web Socket Client Handler.
+     * 
+     * @param handshaker
+     *            manages handshake process
+     * @param listener
+     * 
+     * 
+     */
+    public WebSocketClientHandler(WebSocketClientHandshaker handshaker,
+            ClientMessageCallback listener) {
         this.handshaker = handshaker;
         this.messageListener = listener;
     }
 
+    /**
+     * Notifies by Future when handshake process succeeds or fails.
+     * 
+     * @return information about the completation of the handshake
+     */
     public ChannelFuture handshakeFuture() {
         return handshakeFuture;
     }
@@ -56,7 +76,8 @@ public class WebSocketClientHandler extends SimpleChannelInboundHandler<Object>
     }
 
     @Override
-    public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
+    public void channelRead0(ChannelHandlerContext ctx, Object msg)
+            throws Exception {
         Channel ch = ctx.channel();
         if (!handshaker.isHandshakeComplete()) {
             handshaker.finishHandshake(ch, (FullHttpResponse) msg);
@@ -67,8 +88,11 @@ public class WebSocketClientHandler extends SimpleChannelInboundHandler<Object>
 
         if (msg instanceof FullHttpResponse) {
             FullHttpResponse response = (FullHttpResponse) msg;
-            throw new RuntimeException("Unexpected FullHttpResponse (getStatus=" + response.getStatus() + ", content="
-                    + response.content().toString(CharsetUtil.UTF_8) + ')');
+            throw new RuntimeException(
+                    "Unexpected FullHttpResponse (getStatus="
+                            + response.getStatus() + ", content="
+                            + response.content().toString(CharsetUtil.UTF_8)
+                            + ')');
         }
 
         messageListener.onMessageReceived(msg);
@@ -76,7 +100,8 @@ public class WebSocketClientHandler extends SimpleChannelInboundHandler<Object>
 
         if (frame instanceof TextWebSocketFrame) {
             TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
-            logger.info("WebSocket Client received message: " + textFrame.text());
+            logger.info("WebSocket Client received message: "
+                    + textFrame.text());
         } else if (frame instanceof PongWebSocketFrame) {
             logger.info("WebSocket Client received pong");
         } else if (frame instanceof CloseWebSocketFrame) {
@@ -86,11 +111,11 @@ public class WebSocketClientHandler extends SimpleChannelInboundHandler<Object>
     }
 
     @Override
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
+            throws Exception {
         if (!handshakeFuture.isDone()) {
             handshakeFuture.setFailure(cause);
         }
         ctx.close();
     }
 }
-
index 9091b211d116444797df3a3f1a97fbd614d7052a..1a16487b7483a579f47e612f008dfbd413078f79 100644 (file)
@@ -20,71 +20,123 @@ import io.netty.handler.codec.http.HttpClientCodec;
 import io.netty.handler.codec.http.HttpObjectAggregator;
 import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
 import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
+import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
 import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
 import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
 import io.netty.handler.codec.http.websocketx.WebSocketVersion;
+
 import java.net.URI;
+
 import org.opendaylight.yangtools.websocket.client.callback.ClientMessageCallback;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class WebSocketIClient  {
+/**
+ * Implementation of web socket client that supports WS and HTTP protocols.
+ */
+public class WebSocketIClient {
 
     private final URI uri;
     private Bootstrap bootstrap = new Bootstrap();;
     private final WebSocketClientHandler clientHandler;
-    private static final Logger logger = LoggerFactory.getLogger(WebSocketIClient.class);
+    private static final Logger logger = LoggerFactory
+            .getLogger(WebSocketIClient.class);
     private Channel clientChannel;
     private final EventLoopGroup group = new NioEventLoopGroup();
 
-
-    public WebSocketIClient(URI uri,ClientMessageCallback clientMessageCallback) {
+    /**
+     * Creates new web socket client
+     * 
+     * @param uri
+     *            URI
+     * @param clientMessageCallback
+     *            ClientMessageCallback
+     */
+    public WebSocketIClient(URI uri, ClientMessageCallback clientMessageCallback) {
         this.uri = uri;
         clientHandler = new WebSocketClientHandler(
-                WebSocketClientHandshakerFactory.newHandshaker(
-                        uri, WebSocketVersion.V13, null, false,null),clientMessageCallback); // last null could be replaced with DefaultHttpHeaders
+                WebSocketClientHandshakerFactory.newHandshaker(uri,
+                        WebSocketVersion.V13, null, false, null),
+                clientMessageCallback); // last null could be replaced with
+                                        // DefaultHttpHeaders
         initialize();
     }
-    private void initialize(){
+
+    /**
+     * Initializes {@link Channel} one when it was registered to its
+     * {@link EventLoop}.
+     */
+    private void initialize() {
 
         String protocol = uri.getScheme();
         if (!"ws".equals(protocol) && !"http".equals(protocol)) {
-            throw new IllegalArgumentException("Unsupported protocol: " + protocol);
+            throw new IllegalArgumentException("Unsupported protocol: "
+                    + protocol);
         }
 
-        bootstrap.group(group)
-                .channel(NioSocketChannel.class)
+        bootstrap.group(group).channel(NioSocketChannel.class)
                 .handler(new ChannelInitializer<SocketChannel>() {
                     @Override
                     public void initChannel(SocketChannel ch) throws Exception {
                         ChannelPipeline pipeline = ch.pipeline();
                         pipeline.addLast("http-codec", new HttpClientCodec());
-                        pipeline.addLast("aggregator", new HttpObjectAggregator(8192));
+                        pipeline.addLast("aggregator",
+                                new HttpObjectAggregator(8192));
                         pipeline.addLast("ws-handler", clientHandler);
                     }
                 });
     }
-    public void connect() throws InterruptedException{
-        clientChannel  = bootstrap.connect(uri.getHost(), uri.getPort()).sync().channel();
+
+    /**
+     * Makes the connection attempt and notifies when the handshake process
+     * succeeds or fail.
+     */
+    public void connect() throws InterruptedException {
+        clientChannel = bootstrap.connect(uri.getHost(), uri.getPort()).sync()
+                .channel();
         clientHandler.handshakeFuture().sync();
     }
 
-    public void writeAndFlush(String message){
+    /**
+     * Writes a String message via {@link ChannelOutboundInvoker} through the
+     * {@link ChannelPipeline} and request to actual {@link #flush()} to flush
+     * all pending data to the actual transport.
+     * 
+     * @param message
+     *            a message to write
+     */
+    public void writeAndFlush(String message) {
         clientChannel.writeAndFlush(new TextWebSocketFrame(message));
     }
-    public void writeAndFlush(Object message){
+
+    /**
+     * Writes a Object message via {@link ChannelOutboundInvoker} through the
+     * {@link ChannelPipeline} and request to actual {@link #flush()} to flush
+     * all pending data to the actual transport.
+     * 
+     * @param message
+     *            a message to write
+     */
+    public void writeAndFlush(Object message) {
         clientChannel.writeAndFlush(message);
     }
 
-    public void ping(){
-        clientChannel.writeAndFlush(new PingWebSocketFrame(Unpooled.copiedBuffer(new byte[]{1, 2, 3, 4, 5, 6})));
+    /**
+     * Writes {@link PingWebSocketFrame} via {@link ChannelOutboundInvoker}
+     * through the {@link ChannelPipeline} and request to actual
+     * {@link #flush()} to flush all pending data to the actual transport.
+     */
+    public void ping() {
+        clientChannel.writeAndFlush(new PingWebSocketFrame(Unpooled
+                .copiedBuffer(new byte[] { 1, 2, 3, 4, 5, 6 })));
     }
 
+    /**
+     * Closes the connection when the server responds to the
+     * {@link CloseWebSocketFrame}.
+     */
     public void close() throws InterruptedException {
         clientChannel.writeAndFlush(new CloseWebSocketFrame());
-
-        // WebSocketClientHandler will close the connection when the server
-        // responds to the CloseWebSocketFrame.
         clientChannel.closeFuture().sync();
         group.shutdownGracefully();
     }
index b416e811b214848c7ff72e648274a38bef975da3..0766d1a4e13f1c7175516fb0b4d018ce1bfcebce 100644 (file)
@@ -7,7 +7,16 @@
  */
 package org.opendaylight.yangtools.websocket.client.callback;
 
+/**
+ * {@link ClientMessageCallback} notifies client that some event has occurred.
+ */
 public interface ClientMessageCallback {
 
+    /**
+     * Notifies client that some event has occurred.
+     * 
+     * @param message
+     *            the message which aid to will be client notified
+     */
     public void onMessageReceived(Object message);
 }
index fb6b8ca78e70246e7e3c5ae9fc63c84751583074..08d51b3f6815972620b3e37470472d2355be9f99 100644 (file)
@@ -54,6 +54,9 @@ public class WebSocketServer implements Runnable {
         this.port = port;
     }
 
+    /**
+     * Tries to start web socket server. 
+     */
     public void run(){
         try {
             startServer();
@@ -61,6 +64,11 @@ public class WebSocketServer implements Runnable {
             logger.info("Exception occured while starting webSocket server {}",e);
         }
     }
+    
+    /**
+     * Start web socket server at {@link #port}.
+     * @throws Exception
+     */
     public void startServer() throws Exception {
         try {
             bootstrap.group(bossGroup, workerGroup)
index babba071fb5e10ad9b9d55699918dca5ec86dfc2..ef9d6b9918ed5c7090e98788d245c7f48a70fbf1 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.data.api.schema;
 
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 
@@ -22,15 +23,15 @@ import com.google.common.base.Optional;
  */
 public interface AugmentationNode extends //
     MixinNode, //
-    DataContainerNode<AugmentationIdentifier> {
-
+    DataContainerNode<AugmentationIdentifier>,
+    DataContainerChild<InstanceIdentifier.AugmentationIdentifier, Iterable<DataContainerChild<? extends PathArgument, ?>>> {
 
     @Override
-    public Iterable<DataContainerChild<?, ?>> getValue();
+    public Iterable<DataContainerChild<? extends PathArgument, ?>> getValue();
 
 
     @Override
-    public Optional<DataContainerChild<?, ?>> getChild(PathArgument child);
+    public Optional<DataContainerChild<? extends PathArgument, ?>> getChild(PathArgument child);
 
     @Override
     public AugmentationIdentifier getIdentifier();
index d1dd33bd88c99252795d4b731b60cd5bca762951..f0f0aed6860d6966b86d8befc6275ae03c887994 100644 (file)
@@ -21,12 +21,13 @@ import com.google.common.base.Optional;
  */
 public interface ChoiceNode extends //
         MixinNode, //
-        DataContainerNode<NodeIdentifier> {
+        DataContainerNode<NodeIdentifier>,
+        DataContainerChild<NodeIdentifier, Iterable<DataContainerChild<? extends PathArgument, ?>>> {
 
     @Override
     public NodeIdentifier getIdentifier();
 
     @Override
-    public Optional<DataContainerChild<?, ?>> getChild(PathArgument child);
+    public Optional<DataContainerChild<? extends PathArgument, ?>> getChild(PathArgument child);
 
 }
index e1acb551ff59c85928f3dcaf13f7eddee311b6f3..8ddcf6899668903117507322ad49871411ac7d4e 100644 (file)
@@ -13,12 +13,13 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import com.google.common.base.Optional;
 
 public interface ContainerNode extends //
-        DataContainerNode<NodeIdentifier> {
+        DataContainerNode<NodeIdentifier>,
+        DataContainerChild<NodeIdentifier, Iterable<DataContainerChild<? extends PathArgument, ?>>> {
 
     @Override
     public NodeIdentifier getIdentifier();
 
     @Override
-    public Optional<DataContainerChild<?, ?>> getChild(PathArgument child);
+    public Optional<DataContainerChild<? extends PathArgument, ?>> getChild(PathArgument child);
 
 }
index 683f815bf1af5ddfa0bbeaeb6cb56c7368e6a510..ce73d1c93e49052863bb10784cf1501007b07686 100644 (file)
@@ -18,9 +18,9 @@ public interface DataContainerNode<K extends PathArgument> extends //
     public K getIdentifier();
 
     @Override
-    public Iterable<DataContainerChild<?, ?>> getValue();
+    public Iterable<DataContainerChild<? extends PathArgument, ?>> getValue();
 
     @Override
-    public Optional<DataContainerChild<?, ?>> getChild(PathArgument child);
+    public Optional<DataContainerChild<? extends PathArgument, ?>> getChild(PathArgument child);
 
 }
index db13970068fd4559d48fb67a282e725d17dd81e2..a4e2ef8a82d9688e664e5f7b32e1772b4f721cd3 100644 (file)
         <dependency>
             <groupId>xmlunit</groupId>
             <artifactId>xmlunit</artifactId>
-            <version>1.4</version>
+            <version>1.5</version>
             <scope>test</scope>
         </dependency>
       <dependency>
index b16ff3664e9480fbc3eda96972540897cfe007fa..9f034543d7c659ff7dcc8999bf0914c341c03a7f 100644 (file)
@@ -87,15 +87,7 @@ public class XmlDocumentUtils {
         Preconditions.checkNotNull(data);
         Preconditions.checkNotNull(schema);
 
-        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-        dbf.setNamespaceAware(true);
-        Document doc = null;
-        try {
-            DocumentBuilder bob = dbf.newDocumentBuilder();
-            doc = bob.newDocument();
-        } catch (ParserConfigurationException e) {
-            return null;
-        }
+        Document doc = getDocument();
 
         if (schema instanceof ContainerSchemaNode || schema instanceof ListSchemaNode) {
             doc.appendChild(createXmlRootElement(doc, data, (SchemaNode) schema, codecProvider));
@@ -106,6 +98,18 @@ public class XmlDocumentUtils {
         }
     }
 
+    public static Document getDocument() {
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        Document doc = null;
+        try {
+            DocumentBuilder bob = dbf.newDocumentBuilder();
+            doc = bob.newDocument();
+        } catch (ParserConfigurationException e) {
+            throw new RuntimeException(e);
+        }
+        return doc;
+    }
+
     /**
      * Converts Data DOM structure to XML Document for specified XML Codec Provider. The CompositeNode
      * data parameter enters as root of Data DOM tree and will be transformed to root in XML Document. The child
@@ -169,7 +173,7 @@ public class XmlDocumentUtils {
         return itemEl;
     }
 
-    private static Element createElementFor(Document doc, Node<?> data) {
+    public static Element createElementFor(Document doc, Node<?> data) {
         QName dataType = data.getNodeType();
         Element ret;
         if (dataType.getNamespace() != null) {
@@ -189,11 +193,17 @@ public class XmlDocumentUtils {
 
     public static void writeValueByType(Element element, SimpleNode<?> node, TypeDefinition<?> type,
             DataSchemaNode schema, XmlCodecProvider codecProvider) {
-        TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
 
+        Object nodeValue = node.getValue();
+
+        writeValueByType(element, type, codecProvider, nodeValue);
+    }
+
+    public static void writeValueByType(Element element, TypeDefinition<?> type, XmlCodecProvider codecProvider, Object nodeValue) {
+        TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
         if (baseType instanceof IdentityrefTypeDefinition) {
-            if (node.getValue() instanceof QName) {
-                QName value = (QName) node.getValue();
+            if (nodeValue instanceof QName) {
+                QName value = (QName) nodeValue;
                 String prefix = "x";
                 if (value.getPrefix() != null && !value.getPrefix().isEmpty()) {
                     prefix = value.getPrefix();
@@ -201,7 +211,7 @@ public class XmlDocumentUtils {
                 element.setAttribute("xmlns:" + prefix, value.getNamespace().toString());
                 element.setTextContent(prefix + ":" + value.getLocalName());
             } else {
-                Object value = node.getValue();
+                Object value = nodeValue;
                 logger.debug("Value of {}:{} is not instance of QName but is {}", baseType.getQName().getNamespace(),
                         baseType.getQName().getLocalName(), value != null ? value.getClass() : "null");
                 if (value != null) {
@@ -209,10 +219,10 @@ public class XmlDocumentUtils {
                 }
             }
         } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
-            if (node.getValue() instanceof InstanceIdentifier) {
+            if (nodeValue instanceof InstanceIdentifier) {
                 // Map< key = namespace, value = prefix>
                 Map<String, String> prefixes = new HashMap<>();
-                InstanceIdentifier instanceIdentifier = (InstanceIdentifier) node.getValue();
+                InstanceIdentifier instanceIdentifier = (InstanceIdentifier) nodeValue;
                 StringBuilder textContent = new StringBuilder();
                 for (PathArgument pathArgument : instanceIdentifier.getPath()) {
                     textContent.append("/");
@@ -239,7 +249,7 @@ public class XmlDocumentUtils {
                 element.setTextContent(textContent.toString());
 
             } else {
-                Object value = node.getValue();
+                Object value = nodeValue;
                 logger.debug("Value of {}:{} is not instance of InstanceIdentifier but is {}", baseType.getQName()
                         .getNamespace(), //
                         baseType.getQName().getLocalName(), value != null ? value.getClass() : "null");
@@ -248,19 +258,19 @@ public class XmlDocumentUtils {
                 }
             }
         } else {
-            if (node.getValue() != null) {
+            if (nodeValue != null) {
                 final TypeDefinitionAwareCodec<Object, ?> codec = codecProvider.codecFor(baseType);
                 if (codec != null) {
                     try {
-                        final String text = codec.serialize(node.getValue());
+                        final String text = codec.serialize(nodeValue);
                         element.setTextContent(text);
                     } catch (ClassCastException e) {
-                        logger.error("Provided node {} did not have type {} required by mapping. Using stream instead.", node, baseType, e);
-                        element.setTextContent(String.valueOf(node.getValue()));
+                        logger.error("Provided node value {} did not have type {} required by mapping. Using stream instead.", nodeValue, baseType, e);
+                        element.setTextContent(String.valueOf(nodeValue));
                     }
                 } else {
                     logger.error("Failed to find codec for {}, falling back to using stream", baseType);
-                    element.setTextContent(String.valueOf(node.getValue()));
+                    element.setTextContent(String.valueOf(nodeValue));
                 }
             }
         }
@@ -340,7 +350,7 @@ public class XmlDocumentUtils {
         return node.toInstance();
     }
 
-    private static QName qNameFromElement(Element xmlElement) {
+    public static QName qNameFromElement(Element xmlElement) {
         String namespace = xmlElement.getNamespaceURI();
         String localName = xmlElement.getLocalName();
         return QName.create(namespace != null ? URI.create(namespace) : null, null, localName);
@@ -416,7 +426,7 @@ public class XmlDocumentUtils {
         checkState(qName.getLocalName().equals(xmlElement.getLocalName()));
     }
 
-    private static final Optional<DataSchemaNode> findFirstSchema(QName qname, Set<DataSchemaNode> dataSchemaNode) {
+    public static final Optional<DataSchemaNode> findFirstSchema(QName qname, Set<DataSchemaNode> dataSchemaNode) {
         if (dataSchemaNode != null && !dataSchemaNode.isEmpty() && qname != null) {
             for (DataSchemaNode dsn : dataSchemaNode) {
                 if (qname.isEqualWithoutRevision(dsn.getQName())) {
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/Builders.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/Builders.java
new file mode 100644 (file)
index 0000000..0982382
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * 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.yangtools.yang.data.impl.schema;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.*;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.*;
+import org.opendaylight.yangtools.yang.model.api.*;
+
+public class Builders {
+
+    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> leafBuilder() {
+        return ImmutableLeafNodeBuilder.create();
+    }
+
+    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> leafBuilder(
+            LeafSchemaNode schema) {
+        return ImmutableLeafNodeSchemaAwareBuilder.create(schema);
+    }
+
+    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> leafSetEntryBuilder() {
+        return ImmutableLeafSetEntryNodeBuilder.create();
+    }
+
+    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> leafSetEntryBuilder(
+            LeafListSchemaNode schema) {
+        return ImmutableLeafSetEntryNodeSchemaAwareBuilder.create(schema);
+    }
+
+    public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> leafSetBuilder() {
+        return ImmutableLeafSetNodeBuilder.create();
+    }
+
+    public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> leafSetBuilder(LeafListSchemaNode schema) {
+        return ImmutableLeafSetNodeSchemaAwareBuilder.create(schema);
+    }
+
+    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> containerBuilder() {
+        return ImmutableContainerNodeBuilder.create();
+    }
+
+    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> containerBuilder(
+            ContainerSchemaNode schema) {
+        return ImmutableContainerNodeSchemaAwareBuilder.create(schema);
+    }
+
+    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder() {
+        return ImmutableMapEntryNodeBuilder.create();
+    }
+
+    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder(
+            ListSchemaNode schema) {
+        return ImmutableMapEntryNodeSchemaAwareBuilder.create(schema);
+    }
+
+    public static CollectionNodeBuilder<MapEntryNode, MapNode> mapBuilder() {
+        return ImmutableMapNodeBuilder.create();
+    }
+
+    public static CollectionNodeBuilder<MapEntryNode, MapNode> mapBuilder(ListSchemaNode schema) {
+        return ImmutableMapNodeSchemaAwareBuilder.create(schema);
+    }
+
+    public static DataContainerNodeBuilder<InstanceIdentifier.AugmentationIdentifier, AugmentationNode> augmentationBuilder() {
+        return ImmutableAugmentationNodeBuilder.create();
+    }
+
+    public static DataContainerNodeBuilder<InstanceIdentifier.AugmentationIdentifier, AugmentationNode> augmentationBuilder(AugmentationSchema schema) {
+        return ImmutableAugmentationNodeSchemaAwareBuilder.create(schema);
+    }
+
+    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> choiceBuilder() {
+        return ImmutableChoiceNodeBuilder.create();
+    }
+
+    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> choiceBuilder(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
+        return ImmutableChoiceNodeSchemaAwareBuilder.create(schema);
+    }
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/CollectionNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/CollectionNodeBuilder.java
new file mode 100644 (file)
index 0000000..2dc68a9
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.api;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public interface CollectionNodeBuilder<V, R extends NormalizedNode<InstanceIdentifier.NodeIdentifier, ?>>
+        extends NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, List<V>, R> {
+
+    //TODO might be list to keep ordering and map internal
+    @Override
+    CollectionNodeBuilder<V, R> withValue(List<V> value);
+
+    @Override
+    CollectionNodeBuilder<V, R> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier);
+
+    CollectionNodeBuilder<V, R> withChild(V child);
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/DataContainerNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/DataContainerNodeBuilder.java
new file mode 100644 (file)
index 0000000..9c39b87
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.api;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
+
+public interface DataContainerNodeBuilder<I extends InstanceIdentifier.PathArgument, R extends DataContainerNode<I>>
+        extends NormalizedNodeBuilder<I, List<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>>, R> {
+
+    @Override
+    DataContainerNodeBuilder<I, R> withValue(List<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value);
+
+    @Override
+    DataContainerNodeBuilder<I, R> withNodeIdentifier(I nodeIdentifier);
+
+    DataContainerNodeBuilder<I, R> withChild(DataContainerChild<?, ?> child);
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/ListNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/ListNodeBuilder.java
new file mode 100644 (file)
index 0000000..41aeae3
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.api;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+
+public interface ListNodeBuilder<T, V>
+        extends CollectionNodeBuilder<V, LeafSetNode<T>> {
+
+    @Override
+    ListNodeBuilder<T, V> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier);
+
+    @Override
+    ListNodeBuilder<T, V> withValue(List<V> value);
+
+    @Override
+    ListNodeBuilder<T, V> withChild(V child);
+
+    ListNodeBuilder<T, V> withChildValue(T child);
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/NormalizedNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/NormalizedNodeBuilder.java
new file mode 100644 (file)
index 0000000..2db9d63
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.api;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public interface NormalizedNodeBuilder<I extends InstanceIdentifier.PathArgument, V, R extends NormalizedNode<I, ?>> {
+
+    NormalizedNodeBuilder<I, V, R> withValue(V value);
+
+    NormalizedNodeBuilder<I, V, R> withNodeIdentifier(I nodeIdentifier);
+
+    R build();
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeBuilder.java
new file mode 100644 (file)
index 0000000..39032ad
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+
+import com.google.common.collect.Maps;
+
+abstract class AbstractImmutableDataContainerNodeBuilder<I extends InstanceIdentifier.PathArgument, R extends DataContainerNode<I>>
+        implements DataContainerNodeBuilder<I, R> {
+
+    protected Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value;
+    protected I nodeIdentifier;
+
+    protected AbstractImmutableDataContainerNodeBuilder() {
+        this.value = Maps.newLinkedHashMap();
+    }
+
+    @Override
+    public DataContainerNodeBuilder<I, R> withValue(List<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value) {
+        // TODO Replace or putAll ?
+        for (DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild : value) {
+            withChild(dataContainerChild);
+        }
+        return this;
+    }
+
+    @Override
+    public DataContainerNodeBuilder<I, R> withChild(DataContainerChild<?, ?> child) {
+        this.value.put(child.getIdentifier(), child);
+        return this;
+    }
+
+
+    @Override
+    public DataContainerNodeBuilder<I, R> withNodeIdentifier(I nodeIdentifier) {
+        this.nodeIdentifier = nodeIdentifier;
+        return this;
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableNormalizedNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableNormalizedNodeBuilder.java
new file mode 100644 (file)
index 0000000..ff6a235
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
+
+abstract class AbstractImmutableNormalizedNodeBuilder<I extends InstanceIdentifier.PathArgument, V, R extends NormalizedNode<I, ?>>
+        implements NormalizedNodeBuilder<I,V,R> {
+
+    protected V value;
+    protected I nodeIdentifier;
+
+    @Override
+    public NormalizedNodeBuilder<I,V,R> withValue(V value) {
+        this.value = value;
+        return this;
+    }
+
+
+    @Override
+    public NormalizedNodeBuilder<I,V,R> withNodeIdentifier(I nodeIdentifier) {
+        this.nodeIdentifier = nodeIdentifier;
+        return this;
+    }
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableAugmentationNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableAugmentationNodeBuilder.java
new file mode 100644 (file)
index 0000000..481ddb0
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerNode;
+
+import com.google.common.base.Preconditions;
+
+public class ImmutableAugmentationNodeBuilder
+        extends AbstractImmutableDataContainerNodeBuilder<InstanceIdentifier.AugmentationIdentifier, AugmentationNode> {
+
+    public static DataContainerNodeBuilder<InstanceIdentifier.AugmentationIdentifier, AugmentationNode> create() {
+        return new ImmutableAugmentationNodeBuilder();
+    }
+
+    @Override
+    public DataContainerNodeBuilder<InstanceIdentifier.AugmentationIdentifier, AugmentationNode> withChild(
+            DataContainerChild<?, ?> child) {
+        // Check nested augments
+        Preconditions.checkArgument(child instanceof AugmentationNode == false,
+                "Unable to add: %s, as a child for: %s, Nested augmentations are not permitted", child.getNodeType(),
+                nodeIdentifier == null ? this : nodeIdentifier);
+
+        return super.withChild(child);
+    }
+
+    @Override
+    public AugmentationNode build() {
+        return new ImmutableAugmentationNode(nodeIdentifier, value);
+    }
+
+    static final class ImmutableAugmentationNode
+            extends AbstractImmutableDataContainerNode<InstanceIdentifier.AugmentationIdentifier>
+            implements AugmentationNode {
+
+        ImmutableAugmentationNode(InstanceIdentifier.AugmentationIdentifier nodeIdentifier, Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children) {
+            super(children, nodeIdentifier);
+        }
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableAugmentationNodeSchemaAwareBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableAugmentationNodeSchemaAwareBuilder.java
new file mode 100644 (file)
index 0000000..1f07eb5
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataNodeContainerValidator;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+
+public class ImmutableAugmentationNodeSchemaAwareBuilder extends ImmutableAugmentationNodeBuilder {
+
+    private final DataNodeContainerValidator validator;
+
+    protected ImmutableAugmentationNodeSchemaAwareBuilder(AugmentationSchema schema) {
+        super();
+        this.validator = new DataNodeContainerValidator(schema);
+        // TODO no QName for augmentation
+        super.withNodeIdentifier(new InstanceIdentifier.AugmentationIdentifier(null, getChildQNames(schema)));
+    }
+
+    // TODO move somewhere to UTIL
+    public static Set<QName> getChildQNames(AugmentationSchema schema) {
+        Set<QName> qnames = Sets.newHashSet();
+
+        for (DataSchemaNode dataSchemaNode : schema.getChildNodes()) {
+            qnames.add(dataSchemaNode.getQName());
+        }
+
+        return qnames;
+    }
+
+    @Override
+    public DataContainerNodeBuilder<InstanceIdentifier.AugmentationIdentifier, AugmentationNode> withNodeIdentifier(InstanceIdentifier.AugmentationIdentifier nodeIdentifier) {
+        throw new UnsupportedOperationException("Node identifier created from schema");
+    }
+
+    @Override
+    public DataContainerNodeBuilder<InstanceIdentifier.AugmentationIdentifier, AugmentationNode> withChild(DataContainerChild<?, ?> child) {
+        validator.validateChild(child.getIdentifier());
+        return super.withChild(child);
+    }
+
+    public static DataContainerNodeBuilder<InstanceIdentifier.AugmentationIdentifier, AugmentationNode> create(AugmentationSchema schema) {
+        return new ImmutableAugmentationNodeSchemaAwareBuilder(schema);
+    }
+
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeBuilder.java
new file mode 100644 (file)
index 0000000..674ebba
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerNode;
+
+public class ImmutableChoiceNodeBuilder extends AbstractImmutableDataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> {
+
+    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> create() {
+        return new ImmutableChoiceNodeBuilder();
+    }
+
+    public ChoiceNode build() {
+        return new ImmutableChoiceNode(nodeIdentifier, value);
+    }
+
+    static final class ImmutableChoiceNode
+            extends AbstractImmutableDataContainerNode<InstanceIdentifier.NodeIdentifier>
+            implements ChoiceNode {
+
+        ImmutableChoiceNode(InstanceIdentifier.NodeIdentifier nodeIdentifier,
+                            Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children) {
+            super(children, nodeIdentifier);
+        }
+
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeSchemaAwareBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeSchemaAwareBuilder.java
new file mode 100644 (file)
index 0000000..ab73930
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataNodeContainerValidator;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+import com.google.common.base.Preconditions;
+
+public class ImmutableChoiceNodeSchemaAwareBuilder extends ImmutableChoiceNodeBuilder {
+
+    private final org.opendaylight.yangtools.yang.model.api.ChoiceNode schema;
+    private ChoiceCaseNode detectedCase;
+    private DataNodeContainerValidator validator;
+
+    protected ImmutableChoiceNodeSchemaAwareBuilder(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
+        super();
+        this.schema = schema;
+        super.withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(schema.getQName()));
+    }
+
+    @Override
+    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier) {
+        throw new UnsupportedOperationException("Node identifier created from schema");
+    }
+
+    @Override
+    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> withChild(DataContainerChild<?, ?> child) {
+        if(detectedCase == null) {
+            detectedCase = detectCase(child);
+            validator = new DataNodeContainerValidator(detectedCase);
+        }
+
+        validator.validateChild(child.getIdentifier());
+
+        return super.withChild(child);
+    }
+
+    @Override
+    public ChoiceNode build() {
+        // TODO validate when statement
+        return super.build();
+    }
+
+    private ChoiceCaseNode detectCase(DataContainerChild<?, ?> child) {
+        for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+            for (DataSchemaNode childFromCase : choiceCaseNode.getChildNodes()) {
+                if (childFromCase.getQName().equals(child.getNodeType())) {
+                    return choiceCaseNode;
+                }
+            }
+        }
+
+        throw new IllegalArgumentException(String.format("Unknown child node: %s, for choice: %s", child.getNodeType(),
+                schema.getQName()));
+    }
+
+    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> create(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
+        return new ImmutableChoiceNodeSchemaAwareBuilder(schema);
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableContainerNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableContainerNodeBuilder.java
new file mode 100644 (file)
index 0000000..c3cbf34
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerNode;
+
+public class ImmutableContainerNodeBuilder extends AbstractImmutableDataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> {
+
+    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> create() {
+        return new ImmutableContainerNodeBuilder();
+    }
+
+    @Override
+    public ContainerNode build() {
+        return new ImmutableContainerNode(nodeIdentifier, value);
+    }
+
+    final class ImmutableContainerNode
+            extends AbstractImmutableDataContainerNode<InstanceIdentifier.NodeIdentifier>
+            implements ContainerNode {
+
+        ImmutableContainerNode(
+                InstanceIdentifier.NodeIdentifier nodeIdentifier,
+                Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children) {
+            super(children, nodeIdentifier);
+        }
+
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableContainerNodeSchemaAwareBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableContainerNodeSchemaAwareBuilder.java
new file mode 100644 (file)
index 0000000..5f00539
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataNodeContainerValidator;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+
+public final class ImmutableContainerNodeSchemaAwareBuilder extends ImmutableContainerNodeBuilder {
+
+    private final DataNodeContainerValidator validator;
+
+    // TODO remove schema aware builders, replace by validator called at build()
+
+    private ImmutableContainerNodeSchemaAwareBuilder(ContainerSchemaNode schema) {
+        super();
+        this.validator = new DataNodeContainerValidator(schema);
+        super.withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(schema.getQName()));
+    }
+
+    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> create(ContainerSchemaNode schema) {
+        return new ImmutableContainerNodeSchemaAwareBuilder(schema);
+    }
+
+    @Override
+    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier) {
+        throw new UnsupportedOperationException("Node identifier created from schema");
+    }
+
+    @Override
+    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> withChild(DataContainerChild<?, ?> child) {
+        validator.validateChild(child.getIdentifier());
+        return super.withChild(child);
+    }
+
+    @Override
+    public ContainerNode build() {
+        // TODO check when statements... somewhere
+        return super.build();
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafNodeBuilder.java
new file mode 100644 (file)
index 0000000..f466ed3
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
+
+public class ImmutableLeafNodeBuilder<T> extends AbstractImmutableNormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> {
+
+    protected ImmutableLeafNodeBuilder() {
+    }
+
+    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> create() {
+        return new ImmutableLeafNodeBuilder<>();
+    }
+
+    @Override
+    public LeafNode<T> build() {
+        return new ImmutableLeafNode<>(nodeIdentifier, value);
+    }
+
+    static final class ImmutableLeafNode<T> extends AbstractImmutableNormalizedNode<InstanceIdentifier.NodeIdentifier, T> implements LeafNode<T> {
+
+        ImmutableLeafNode(InstanceIdentifier.NodeIdentifier nodeIdentifier, T value) {
+            super(nodeIdentifier, value);
+        }
+
+        @Override
+        public String toString() {
+            final StringBuffer sb = new StringBuffer("ImmutableLeafNode{");
+            sb.append("nodeIdentifier=").append(nodeIdentifier);
+            sb.append(", value=").append(value);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafNodeSchemaAwareBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafNodeSchemaAwareBuilder.java
new file mode 100644 (file)
index 0000000..097889a
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+
+public final class ImmutableLeafNodeSchemaAwareBuilder<T> extends ImmutableLeafNodeBuilder<T> {
+
+    private final LeafSchemaNode schema;
+
+    private ImmutableLeafNodeSchemaAwareBuilder(LeafSchemaNode schema) {
+        super();
+        this.schema = schema;
+        super.withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(schema.getQName()));
+    }
+
+    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> create(LeafSchemaNode schema) {
+        return new ImmutableLeafNodeSchemaAwareBuilder<>(schema);
+    }
+
+    @Override
+    public NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> withValue(T value) {
+//        TODO check value type
+        return super.withValue(value);
+    }
+
+    @Override
+    public NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier) {
+        throw new UnsupportedOperationException("Node identifier created from schema");
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetEntryNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetEntryNodeBuilder.java
new file mode 100644 (file)
index 0000000..77d23d8
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
+
+import com.google.common.base.Preconditions;
+
+public class ImmutableLeafSetEntryNodeBuilder<T> extends AbstractImmutableNormalizedNodeBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> {
+
+    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> create() {
+        return new ImmutableLeafSetEntryNodeBuilder<>();
+    }
+
+    @Override
+    public LeafSetEntryNode<T> build() {
+        return new ImmutableLeafSetEntryNode<>(nodeIdentifier, value);
+    }
+
+    static final class ImmutableLeafSetEntryNode<T> extends AbstractImmutableNormalizedNode<InstanceIdentifier.NodeWithValue, T> implements LeafSetEntryNode<T> {
+
+        ImmutableLeafSetEntryNode(InstanceIdentifier.NodeWithValue nodeIdentifier, T value) {
+            super(nodeIdentifier, value);
+            Preconditions.checkArgument(nodeIdentifier.getValue().equals(value),
+                    "Node identifier contains different value: %s than value itself: %s", nodeIdentifier, value);
+        }
+
+        @Override
+        public String toString() {
+            final StringBuffer sb = new StringBuffer("ImmutableLeafSetEntryNode{");
+            sb.append("nodeIdentifier=").append(nodeIdentifier);
+            sb.append(", value=").append(value);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetEntryNodeSchemaAwareBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetEntryNodeSchemaAwareBuilder.java
new file mode 100644 (file)
index 0000000..35fe299
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+public final class ImmutableLeafSetEntryNodeSchemaAwareBuilder<T> extends ImmutableLeafSetEntryNodeBuilder<T> {
+
+    private final LeafListSchemaNode schema;
+
+    private ImmutableLeafSetEntryNodeSchemaAwareBuilder(LeafListSchemaNode schema) {
+        super();
+        this.schema = schema;
+    }
+
+    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> create(LeafListSchemaNode schema) {
+        return new ImmutableLeafSetEntryNodeSchemaAwareBuilder<>(schema);
+    }
+
+    @Override
+    public NormalizedNodeBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> withValue(T value) {
+        super.withNodeIdentifier(new InstanceIdentifier.NodeWithValue(schema.getQName(), value));
+        // TODO check value type
+        return super.withValue(value);
+    }
+
+    @Override
+    public NormalizedNodeBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> withNodeIdentifier(InstanceIdentifier.NodeWithValue nodeIdentifier) {
+        throw new UnsupportedOperationException("Node identifier created from schema");
+    }
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetNodeBuilder.java
new file mode 100644 (file)
index 0000000..f352b98
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Maps;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+public class ImmutableLeafSetNodeBuilder<T>
+        implements ListNodeBuilder<T, LeafSetEntryNode<T>> {
+
+    protected Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> value;
+    protected InstanceIdentifier.NodeIdentifier nodeIdentifier;
+
+    public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> create() {
+        return new ImmutableLeafSetNodeBuilder<>();
+    }
+
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withChild(LeafSetEntryNode<T> child) {
+        if(this.value == null) {
+            this.value = Maps.newLinkedHashMap();
+        }
+
+        this.value.put(child.getIdentifier(), child);
+        return this;
+    }
+
+    @Override
+    public LeafSetNode<T> build() {
+        return new ImmutableLeafSetNode<>(nodeIdentifier, value);
+    }
+
+    @Override
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier) {
+        this.nodeIdentifier = nodeIdentifier;
+        return this;
+    }
+
+    @Override
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withValue(List<LeafSetEntryNode<T>> value) {
+        for (LeafSetEntryNode<T> leafSetEntry : value) {
+            withChild(leafSetEntry);
+        }
+
+        return this;
+    }
+
+    @Override
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withChildValue(T value) {
+        return withChild(new ImmutableLeafSetEntryNodeBuilder.ImmutableLeafSetEntryNode<>(new InstanceIdentifier.NodeWithValue(nodeIdentifier.getNodeType(), value), value));
+    }
+
+    final class ImmutableLeafSetNode<T> extends AbstractImmutableNormalizedNode<InstanceIdentifier.NodeIdentifier, Iterable<LeafSetEntryNode<T>>> implements LeafSetNode<T> {
+
+        private final Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> mappedChildren;
+
+        ImmutableLeafSetNode(InstanceIdentifier.NodeIdentifier nodeIdentifier, Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> children) {
+            super(nodeIdentifier, children.values());
+            this.mappedChildren = children;
+        }
+
+        @Override
+        public Optional<LeafSetEntryNode<T>> getChild(InstanceIdentifier.NodeWithValue child) {
+            return Optional.fromNullable(mappedChildren.get(child));
+        }
+
+        @Override
+        public String toString() {
+            final StringBuffer sb = new StringBuffer("ImmutableLeafSetNode{");
+            sb.append("nodeIdentifier=").append(nodeIdentifier);
+            sb.append(", children=").append(value);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetNodeSchemaAwareBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetNodeSchemaAwareBuilder.java
new file mode 100644 (file)
index 0000000..e1a4eda
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+import com.google.common.base.Preconditions;
+
+public final class ImmutableLeafSetNodeSchemaAwareBuilder<T> extends ImmutableLeafSetNodeBuilder<T> {
+
+    private final LeafListSchemaNode schema;
+
+    private ImmutableLeafSetNodeSchemaAwareBuilder(LeafListSchemaNode schema) {
+        super();
+        this.schema = schema;
+        super.withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(schema.getQName()));
+    }
+
+    public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> create(LeafListSchemaNode schema) {
+        return new ImmutableLeafSetNodeSchemaAwareBuilder<>(schema);
+    }
+
+    @Override
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withChildValue(T value) {
+        // TODO check value type
+        return super.withChildValue(value);
+    }
+
+    @Override
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withChild(LeafSetEntryNode<T> child) {
+        Preconditions.checkArgument(schema.getQName().equals(child.getNodeType()),
+                "Incompatible node type, should be: %s, is: %s", schema.getQName(), child.getNodeType());
+        return super.withChild(child);
+    }
+
+    @Override
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier) {
+        throw new UnsupportedOperationException("Node identifier created from schema");
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapEntryNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapEntryNodeBuilder.java
new file mode 100644 (file)
index 0000000..90e36f7
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataNodeContainerValidator;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerNode;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+
+public class ImmutableMapEntryNodeBuilder
+        extends AbstractImmutableDataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> {
+
+    protected final Map<QName, InstanceIdentifier.PathArgument> childrenQNamesToPaths;
+
+    protected ImmutableMapEntryNodeBuilder() {
+        this.childrenQNamesToPaths = Maps.newLinkedHashMap();
+    }
+
+    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> create() {
+        return new ImmutableMapEntryNodeBuilder();
+    }
+
+    // FIXME, find better solution than 2 maps (map from QName to Child ?)
+
+    @Override
+    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> withValue(List<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value) {
+        for (DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childId : value) {
+            this.childrenQNamesToPaths.put(childId.getNodeType(), childId.getIdentifier());
+        }
+        return super.withValue(value);
+    }
+
+    @Override
+    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> withChild(DataContainerChild<?, ?> child) {
+        childrenQNamesToPaths.put(child.getNodeType(), child.getIdentifier());
+        return super.withChild(child);
+    }
+
+    public MapEntryNode build() {
+        checkKeys();
+        return new ImmutableMapEntryNode(nodeIdentifier, value);
+    }
+
+    private void checkKeys() {
+        for (QName keyQName : nodeIdentifier.getKeyValues().keySet()) {
+
+            InstanceIdentifier.PathArgument childNodePath = childrenQNamesToPaths.get(keyQName);
+            DataContainerChild<?, ?> childNode = value.get(childNodePath);
+
+            Preconditions.checkNotNull(childNode, "Key child node: %s, not present", keyQName);
+
+            Object actualValue = nodeIdentifier.getKeyValues().get(keyQName);
+            Object expectedValue = childNode.getValue();
+            Preconditions.checkArgument(expectedValue.equals(actualValue),
+                    "Key child node with unexpected value, is: %s, should be: %s", actualValue, expectedValue);
+        }
+    }
+
+    static final class ImmutableMapEntryNode extends AbstractImmutableDataContainerNode<InstanceIdentifier.NodeIdentifierWithPredicates> implements MapEntryNode {
+
+        ImmutableMapEntryNode(InstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifier,
+                              Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children) {
+            super(children, nodeIdentifier);
+        }
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapEntryNodeSchemaAwareBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapEntryNodeSchemaAwareBuilder.java
new file mode 100644 (file)
index 0000000..4495910
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataNodeContainerValidator;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+
+public final class ImmutableMapEntryNodeSchemaAwareBuilder extends ImmutableMapEntryNodeBuilder{
+
+    private final ListSchemaNode schema;
+    private final DataNodeContainerValidator validator;
+
+    protected ImmutableMapEntryNodeSchemaAwareBuilder(ListSchemaNode schema) {
+        this.schema = schema;
+        this.validator = new DataNodeContainerValidator(schema);
+    }
+
+    @Override
+    public ImmutableMapEntryNodeBuilder withNodeIdentifier(InstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifier) {
+        throw new UnsupportedOperationException("Node identifier created from schema");
+    }
+
+    @Override
+    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> withChild(DataContainerChild<?, ?> child) {
+        validator.validateChild(child.getIdentifier());
+        return super.withChild(child);
+    }
+
+    @Override
+    public MapEntryNode build() {
+        super.withNodeIdentifier(constructNodeIdentifier());
+        return super.build();
+    }
+
+    /**
+     * Build map entry node identifier from schema, and provided children
+     */
+    private InstanceIdentifier.NodeIdentifierWithPredicates constructNodeIdentifier() {
+        Collection<QName> keys = schema.getKeyDefinition();
+
+        // If no keys defined, add all child elements as key
+        // FIXME should be all PRESENT child nodes, not all from schema
+        if(keys.isEmpty()) {
+            keys = childrenQNamesToPaths.keySet();
+        }
+
+        Map<QName, Object> keysToValues = Maps.newHashMap();
+        for (QName key : keys) {
+            // TODO two maps ? find better solution
+            DataContainerChild<?, ?> valueForKey = value.get(childrenQNamesToPaths.get(key));
+            Preconditions.checkState(valueForKey != null, "Key value: %s cannot be empty for: %s", key, schema.getQName());
+            keysToValues.put(key, valueForKey.getValue());
+        }
+
+        return new InstanceIdentifier.NodeIdentifierWithPredicates(schema.getQName(), keysToValues);
+    }
+
+    public static ImmutableMapEntryNodeSchemaAwareBuilder create(ListSchemaNode schema) {
+        return new ImmutableMapEntryNodeSchemaAwareBuilder(schema);
+    }
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapNodeBuilder.java
new file mode 100644 (file)
index 0000000..08380c7
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import java.util.List;
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Maps;
+
+public class ImmutableMapNodeBuilder
+        implements CollectionNodeBuilder<MapEntryNode, MapNode> {
+
+    protected Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> value;
+    protected InstanceIdentifier.NodeIdentifier nodeIdentifier;
+
+    public static CollectionNodeBuilder<MapEntryNode, MapNode> create() {
+        return new ImmutableMapNodeBuilder();
+    }
+
+    public CollectionNodeBuilder<MapEntryNode, MapNode> withChild(MapEntryNode child) {
+        if(this.value == null) {
+            this.value = Maps.newLinkedHashMap();
+        }
+
+        this.value.put(child.getIdentifier(), child);
+        return this;
+    }
+
+    @Override
+    public CollectionNodeBuilder<MapEntryNode, MapNode> withValue(List<MapEntryNode> value) {
+        // TODO replace or putAll ?
+        for (MapEntryNode mapEntryNode : value) {
+            withChild(mapEntryNode);
+        }
+
+        return this;
+    }
+
+    public CollectionNodeBuilder<MapEntryNode, MapNode> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier) {
+        this.nodeIdentifier = nodeIdentifier;
+        return this;
+    }
+
+    @Override
+    public MapNode build() {
+        return new ImmutableMapNode(nodeIdentifier, value);
+    }
+
+    static final class ImmutableMapNode extends AbstractImmutableNormalizedNode<InstanceIdentifier.NodeIdentifier, Iterable<MapEntryNode>> implements MapNode {
+
+        private final Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mappedChildren;
+
+        ImmutableMapNode(InstanceIdentifier.NodeIdentifier nodeIdentifier,
+                         Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> children) {
+            super(nodeIdentifier, children.values());
+            this.mappedChildren = children;
+        }
+
+        @Override
+        public Optional<MapEntryNode> getChild(InstanceIdentifier.NodeIdentifierWithPredicates child) {
+            return Optional.fromNullable(mappedChildren.get(child));
+        }
+
+        @Override
+        public String toString() {
+            final StringBuffer sb = new StringBuffer("ImmutableMapNode{");
+            sb.append("nodeIdentifier=").append(nodeIdentifier);
+            sb.append(", children=").append(mappedChildren);
+            sb.append('}');
+            return sb.toString();
+        }
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapNodeSchemaAwareBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapNodeSchemaAwareBuilder.java
new file mode 100644 (file)
index 0000000..77a0e49
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+import com.google.common.base.Preconditions;
+
+public class ImmutableMapNodeSchemaAwareBuilder extends ImmutableMapNodeBuilder {
+
+    private final ListSchemaNode schema;
+
+    protected ImmutableMapNodeSchemaAwareBuilder(ListSchemaNode schema) {
+        super();
+        this.schema = schema;
+        super.withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(schema.getQName()));
+    }
+
+    public static CollectionNodeBuilder<MapEntryNode, MapNode> create(ListSchemaNode schema) {
+        return new ImmutableMapNodeSchemaAwareBuilder(schema);
+    }
+
+    @Override
+    public CollectionNodeBuilder<MapEntryNode, MapNode> withChild(MapEntryNode child) {
+        Preconditions.checkArgument(schema.getQName().equals(child.getNodeType()),
+                "Incompatible node type, should be: %s, is: %s", schema.getQName(), child.getNodeType());
+        return super.withChild(child);
+    }
+
+    @Override
+    public CollectionNodeBuilder<MapEntryNode, MapNode> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier) {
+        throw new UnsupportedOperationException("Node identifier created from schema");
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/valid/DataNodeContainerValidator.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/valid/DataNodeContainerValidator.java
new file mode 100644 (file)
index 0000000..8e0c1d3
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.builder.impl.valid;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeSchemaAwareBuilder;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * General validator for container like statements, e.g. container, list-entry, choice, augment
+ */
+public class DataNodeContainerValidator {
+
+    private final DataNodeContainer schema;
+    private Collection<AugmentationSchema> augmentations;
+
+    public DataNodeContainerValidator(DataNodeContainer schema) {
+        this.schema = schema;
+        augmentations = schema instanceof AugmentationTarget ? ((AugmentationTarget) schema)
+                .getAvailableAugmentations() : Collections.<AugmentationSchema> emptyList();
+    }
+
+    private boolean isKnownChild(InstanceIdentifier.PathArgument child) {
+        // check augmentation by comparing all child nodes
+        if(child instanceof InstanceIdentifier.AugmentationIdentifier) {
+            for (AugmentationSchema augmentationSchema : augmentations) {
+                if(equalAugments(augmentationSchema, (InstanceIdentifier.AugmentationIdentifier) child)) {
+                    return true;
+                }
+            }
+            // check regular child node
+        } else {
+            return schema.getDataChildByName(child.getNodeType()) != null;
+        }
+
+        return false;
+    }
+
+    private Optional<AugmentationSchema> isAugmentChild(InstanceIdentifier.PathArgument child) {
+        for (AugmentationSchema augmentationSchema : augmentations) {
+            if(ImmutableAugmentationNodeSchemaAwareBuilder.getChildQNames(augmentationSchema).contains(child.getNodeType())) {
+                return Optional.of(augmentationSchema);
+            }
+        }
+
+        return Optional.absent();
+    }
+
+    // FIXME, need to compare Set of QNames(AugmentationIdentifier) with Set of DataSchemaNodes(AugmentationSchema)
+    // throw away set is created just to compare
+    // Or if augmentationSchemaNode had a QName, we would just compare a QName
+    private boolean equalAugments(AugmentationSchema augmentationSchema, InstanceIdentifier.AugmentationIdentifier identifier) {
+        return identifier.getPossibleChildNames().equals(ImmutableAugmentationNodeSchemaAwareBuilder.getChildQNames(augmentationSchema));
+    }
+
+    public void validateChild(InstanceIdentifier.PathArgument child) {
+        Preconditions.checkArgument(isKnownChild(child), "Unknown child node: %s, does not belong to: %s", child.getNodeType(), schema);
+
+        // FIXME make a cache for augmentation child sets in constructor
+        Optional<AugmentationSchema> augmentChild = isAugmentChild(child);
+        Preconditions.checkArgument(
+                    augmentChild.isPresent() == false,
+                    "Illegal node type, child nodes from augmentation are not permitted as direct children, must be wrapped in augmentation node, "
+                            + "node: %s, from augmentation: %s, in parent: %s", child.getNodeType(), augmentChild, schema);
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerNode.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerNode.java
new file mode 100644 (file)
index 0000000..7954d56
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.nodes;
+
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
+
+import com.google.common.base.Optional;
+
+public abstract class AbstractImmutableDataContainerNode<K extends InstanceIdentifier.PathArgument>
+        extends AbstractImmutableNormalizedNode<K, Iterable<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>>>
+        implements DataContainerNode<K> {
+
+    protected Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children;
+
+    public AbstractImmutableDataContainerNode(Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children, K nodeIdentifier) {
+        super(nodeIdentifier, children.values());
+        this.children = children;
+    }
+
+    @Override
+    public Optional<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> getChild(InstanceIdentifier.PathArgument child) {
+        return Optional.<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>>fromNullable(children.get(child));
+    }
+
+    @Override
+    public String toString() {
+        final StringBuffer sb = new StringBuffer("ImmutableContainerNode{");
+        sb.append("nodeIdentifier=").append(nodeIdentifier);
+        sb.append(", children=").append(children);
+        sb.append('}');
+        return sb.toString();
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedNode.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedNode.java
new file mode 100644 (file)
index 0000000..ceb2012
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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.yangtools.yang.data.impl.schema.nodes;
+
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractImmutableNormalizedNode<K extends InstanceIdentifier.PathArgument,V>
+        implements NormalizedNode<K, V>, Immutable {
+
+    protected final K nodeIdentifier;
+    protected V value;
+
+    protected AbstractImmutableNormalizedNode(K nodeIdentifier, V value) {
+        this.nodeIdentifier = Preconditions.checkNotNull(nodeIdentifier, "nodeIdentifier");
+        this.value = Preconditions.checkNotNull(value, "value");
+    }
+
+    @Override
+    public QName getNodeType() {
+        return getIdentifier().getNodeType();
+    }
+
+    @Override
+    public K getIdentifier() {
+        return nodeIdentifier;
+    }
+
+    @Override
+    public CompositeNode getParent() {
+        throw new UnsupportedOperationException("Deprecated");
+    }
+
+    @Override
+    public QName getKey() {
+        return getNodeType();
+    }
+
+    @Override
+    public V getValue() {
+        return value;
+    }
+
+    @Override
+    public V setValue(V value) {
+        throw new UnsupportedOperationException("Immutable");
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof AbstractImmutableNormalizedNode)) return false;
+
+        AbstractImmutableNormalizedNode that = (AbstractImmutableNormalizedNode) o;
+
+        if (!nodeIdentifier.equals(that.nodeIdentifier)) return false;
+        if (!value.equals(that.value)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = nodeIdentifier.hashCode();
+        result = 31 * result + value.hashCode();
+        return result;
+    }
+}
diff --git a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/NormalizedDataBuilderTest.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/NormalizedDataBuilderTest.java
new file mode 100644 (file)
index 0000000..60b93ce
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * 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.yangtools.yang.data.impl.schema;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.*;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeSchemaAwareBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeSchemaAwareBuilder;
+import org.opendaylight.yangtools.yang.model.api.*;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.*;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+public class NormalizedDataBuilderTest {
+
+    private ContainerSchemaNode containerNode;
+    private SchemaContext schema;
+
+    SchemaContext parseTestSchema() {
+        YangParserImpl yangParserImpl = new YangParserImpl();
+        Set<Module> modules = yangParserImpl.parseYangModelsFromStreams(getTestYangs());
+        return yangParserImpl.resolveSchemaContext(modules);
+    }
+
+    List<InputStream> getTestYangs() {
+
+        return Lists.newArrayList(Collections2.transform(Lists.newArrayList("test.yang"),
+                new Function<String, InputStream>() {
+                    @Override
+                    public InputStream apply(String input) {
+                        InputStream resourceAsStream = getClass().getResourceAsStream(input);
+                        Preconditions.checkNotNull(resourceAsStream, "File %s was null", resourceAsStream);
+                        return resourceAsStream;
+                    }
+                }));
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        schema = parseTestSchema();
+        containerNode = (ContainerSchemaNode) getSchemaNode(schema, "test", "container");
+    }
+
+    @Test
+    public void testSchemaUnaware() throws Exception {
+        // Container
+        DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> builder = Builders.containerBuilder().withNodeIdentifier(
+                getNodeIdentifier("container"));
+
+        // leaf
+        LeafNode<String> leafChild = Builders.<String>leafBuilder()
+                .withNodeIdentifier(getNodeIdentifier("leaf")).withValue("String").build();
+        builder.withChild(leafChild);
+
+        // leafList
+        LeafSetNode<Integer> leafList = Builders.<Integer>leafSetBuilder()
+                .withNodeIdentifier(getNodeIdentifier("leaf"))
+                .withChildValue(1)
+                .withChild(Builders.<Integer>leafSetEntryBuilder().withNodeIdentifier(getNodeWithValueIdentifier("leaf", 3)).withValue(3).build())
+                .build();
+        builder.withChild(leafList);
+
+        // list
+        MapEntryNode listChild1 = Builders.mapEntryBuilder()
+                .withChild(
+                        Builders.<Integer>leafBuilder()
+                                .withNodeIdentifier(getNodeIdentifier("uint32InList")).withValue(1).build())
+                .withChild(
+                        Builders.containerBuilder().withNodeIdentifier(
+                                getNodeIdentifier("containerInList"))
+                                .build())
+                .withNodeIdentifier(
+                        new InstanceIdentifier.NodeIdentifierWithPredicates(getNodeIdentifier("list").getNodeType(),
+                                Collections.singletonMap(getNodeIdentifier("uint32InList").getNodeType(), (Object) 1)))
+                .build();
+
+        MapNode list = Builders.mapBuilder().withChild(listChild1).withNodeIdentifier(getNodeIdentifier("list")).build();
+        builder.withChild(list);
+
+        AugmentationNode augmentation = Builders.augmentationBuilder()
+                .withNodeIdentifier(new InstanceIdentifier.AugmentationIdentifier(null, Sets.newHashSet(getQName("augmentUint32"))))
+                .withChild(
+                        Builders.<Integer>leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32")).withValue(11).build())
+                .build();
+
+        builder.withChild(augmentation);
+
+        // This works without schema (adding child from augment as a direct child)
+        builder.withChild(Builders.<Integer>leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32")).withValue(11).build());
+
+        System.out.println(builder.build());
+    }
+
+    @Test
+    public void testSchemaAware() throws Exception {
+        DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> builder =  Builders.containerBuilder(containerNode);
+
+        LeafSchemaNode schemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "uint32");
+        LeafNode<String> leafChild = Builders.<String>leafBuilder(schemaNode)
+                .withValue("String").build();
+        builder.withChild(leafChild);
+
+        LeafListSchemaNode leafListSchemaNode = (LeafListSchemaNode) getSchemaNode(schema, "test", "leafList");
+        LeafSetNode<Integer> leafList = Builders.<Integer>leafSetBuilder(leafListSchemaNode)
+                .withChildValue(1)
+                .withChild(Builders.<Integer>leafSetEntryBuilder(leafListSchemaNode).withValue(3).build())
+                .build();
+        builder.withChild(leafList);
+
+        ListSchemaNode listSchema = (ListSchemaNode) getSchemaNode(schema, "test", "list");
+        LeafSchemaNode uint32InListSchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "uint32InList");
+        ContainerSchemaNode containerInListSchemaNode = (ContainerSchemaNode) getSchemaNode(schema, "test", "containerInList");
+
+        MapEntryNode listChild1 = Builders.mapEntryBuilder(listSchema)
+                .withChild(
+                        Builders.<Integer>leafBuilder(uint32InListSchemaNode).withValue(1).build())
+                .withChild(
+                        Builders.containerBuilder(containerInListSchemaNode).build())
+                .build();
+
+        MapNode list = ImmutableMapNodeSchemaAwareBuilder.create(listSchema).withChild(listChild1).build();
+        builder.withChild(list);
+
+        LeafSchemaNode augmentUint32SchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "augmentUint32");
+        AugmentationSchema augmentationSchema = getAugmentationSchemaForChild(containerNode, augmentUint32SchemaNode.getQName());
+
+        AugmentationNode augmentation = Builders.augmentationBuilder(augmentationSchema).withChild(
+                Builders.<Integer>leafBuilder(augmentUint32SchemaNode).withValue(11).build())
+                .build();
+
+        builder.withChild(augmentation);
+
+        // This should fail with schema, since the leaf comes from augmentation
+//        builder.withChild(ImmutableLeafNodeSchemaAwareBuilder.<Integer>get(augmentUint32SchemaNode).withValue(11).build());
+
+        LeafSchemaNode augumentString1SchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "augmentString1");
+        LeafSchemaNode augumentString2SchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "augmentString2");
+
+        ChoiceNode choice1SchemaNode = (ChoiceNode) getSchemaNode(schema, "test", "choice");
+        org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode choice = ImmutableChoiceNodeSchemaAwareBuilder.create(choice1SchemaNode)
+                .withChild(Builders.<String>leafBuilder(augumentString1SchemaNode).withValue("case1")
+                        .build())
+                        // This should fail, since child node belongs to different case
+//                .withChild(Builders.<String>leafBuilder(augumentString2SchemaNode).withValue("case2")
+//                        .build())
+                .build();
+
+;        builder.withChild(choice);
+
+        // This should fail, child from case
+//        builder.withChild(Builders.<String>leafBuilder(augumentString1SchemaNode).withValue("case1")
+//                .build());
+
+        System.out.println(builder.build());
+    }
+
+    private AugmentationSchema getAugmentationSchemaForChild(ContainerSchemaNode containerNode, QName qName) {
+        for (AugmentationSchema augmentationSchema : containerNode.getAvailableAugmentations()) {
+            if(augmentationSchema.getDataChildByName(qName) != null) {
+                return augmentationSchema;
+            }
+        }
+        throw new IllegalStateException("Unable to find child augmentation in " + containerNode);
+    }
+
+    private InstanceIdentifier.NodeWithValue getNodeWithValueIdentifier(String localName, Object value) {
+        return new InstanceIdentifier.NodeWithValue(getQName(localName), value);
+    }
+
+    private QName getQName(String localName) {
+        String namespace = "namespace";
+        return new QName(URI.create(namespace), localName);
+    }
+
+    private InstanceIdentifier.NodeWithValue getNodeWithValueIdentifier(QName q, Object value) {
+        return new InstanceIdentifier.NodeWithValue(q, value);
+    }
+
+    private InstanceIdentifier.NodeIdentifier getNodeIdentifier(String localName) {
+        return new InstanceIdentifier.NodeIdentifier(getQName(localName));
+    }
+
+    private InstanceIdentifier.NodeIdentifier getNodeIdentifier(QName q) {
+        return new InstanceIdentifier.NodeIdentifier(q);
+    }
+
+    private Document loadDocument(String xmlPath) throws Exception {
+        InputStream resourceAsStream = getClass().getResourceAsStream(xmlPath);
+
+        Document currentConfigElement = readXmlToDocument(resourceAsStream);
+        Preconditions.checkNotNull(currentConfigElement);
+        return currentConfigElement;
+    }
+
+    private static final DocumentBuilderFactory BUILDERFACTORY;
+
+    static {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        factory.setCoalescing(true);
+        factory.setIgnoringElementContentWhitespace(true);
+        factory.setIgnoringComments(true);
+        BUILDERFACTORY = factory;
+    }
+
+    private Document readXmlToDocument(InputStream xmlContent) throws IOException, SAXException {
+        DocumentBuilder dBuilder;
+        try {
+            dBuilder = BUILDERFACTORY.newDocumentBuilder();
+        } catch (ParserConfigurationException e) {
+            throw new RuntimeException("Failed to parse XML document", e);
+        }
+        Document doc = dBuilder.parse(xmlContent);
+
+        doc.getDocumentElement().normalize();
+        return doc;
+    }
+
+    public static String toString(Element xml) {
+        try {
+            Transformer transformer = TransformerFactory.newInstance().newTransformer();
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+
+            StreamResult result = new StreamResult(new StringWriter());
+            DOMSource source = new DOMSource(xml);
+            transformer.transform(source, result);
+
+            return result.getWriter().toString();
+        } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) {
+            throw new RuntimeException("Unable to serialize xml element " + xml, e);
+        }
+    }
+
+    DataSchemaNode getSchemaNode(SchemaContext context, String moduleName, String childNodeName) {
+        for (Module module : context.getModules()) {
+            if (module.getName().equals(moduleName)) {
+                DataSchemaNode found = findChildNode(module.getChildNodes(), childNodeName);
+                Preconditions.checkState(found!=null, "Unable to find %s", childNodeName);
+                return found;
+            }
+        }
+        throw new IllegalStateException("Unable to find child node " + childNodeName);
+    }
+
+    DataSchemaNode findChildNode(Set<DataSchemaNode> children, String name) {
+        List<DataNodeContainer> containers = Lists.newArrayList();
+
+        for (DataSchemaNode dataSchemaNode : children) {
+            if (dataSchemaNode.getQName().getLocalName().equals(name))
+                return dataSchemaNode;
+            if(dataSchemaNode instanceof DataNodeContainer) {
+                containers.add((DataNodeContainer) dataSchemaNode);
+            } else if(dataSchemaNode instanceof ChoiceNode) {
+                containers.addAll(((ChoiceNode) dataSchemaNode).getCases());
+            }
+        }
+
+        for (DataNodeContainer container : containers) {
+            DataSchemaNode retVal = findChildNode(container.getChildNodes(), name);
+            if(retVal != null) {
+                return retVal;
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple.xml b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple.xml
new file mode 100644 (file)
index 0000000..014688e
--- /dev/null
@@ -0,0 +1,37 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <boolean>true</boolean>
+    <innerContainer>
+        <uint16>44</uint16>
+    </innerContainer>
+    <leafList>a</leafList>
+    <leafList>b</leafList>
+
+    <list>
+        <uint32InList>1</uint32InList>
+        <containerInList>
+            <uint32>32</uint32>
+            <uint16>16</uint16>
+        </containerInList>
+    </list>
+    <list>
+        <uint32InList>2</uint32InList>
+        <containerInList>
+            <uint32>32</uint32>
+            <uint16>16</uint16>
+        </containerInList>
+    </list>
+    <list>
+        <uint32InList>3</uint32InList>
+    </list>
+
+    <augmentUint32>999</augmentUint32>
+
+    <augmentString1>choice1Case1</augmentString1>
+    <augmentInt1>41</augmentInt1>
+
+    <augmentContainer>
+        <augmentStringInaugmentContainer>choice2Case1</augmentStringInaugmentContainer>
+    </augmentContainer>
+
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/test.yang b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/test.yang
new file mode 100644 (file)
index 0000000..4ad6e78
--- /dev/null
@@ -0,0 +1,152 @@
+// vi: set smarttab et sw=4 tabstop=4:
+module test {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:test";
+    prefix "test";
+
+    organization "Cisco Systems, Inc.";
+
+    revision "2013-2-21" {
+        description
+            "Initial revision";
+    }
+
+    grouping listGroup {
+        list list {
+            key "uint32InList";
+
+            leaf uint32InList {
+                type uint32;
+            }
+
+            container containerInList{
+                leaf uint32 {
+                    type uint32;
+                }
+                leaf uint16 {
+                    type uint16;
+                }
+            }
+        }
+     }
+
+     grouping innerContainerGrouping {
+        container innerContainer {
+            leaf uint16 {
+                type uint16;
+            }
+
+            container innerInnerContainer {
+
+                leaf uint16 {
+                    type uint16;
+                }
+
+                leaf uint32 {
+                    type uint32;
+                }
+            }
+        }
+     }
+
+    container container {
+        leaf uint32 {
+            type uint32;
+        }
+
+        leaf decimal64 {
+            type decimal64 {
+                fraction-digits 2;
+            }
+        }
+
+        leaf boolean {
+            type boolean;
+        }
+
+        leaf binary {
+            type binary;
+        }
+
+        leaf string {
+            type string;
+        }
+
+        uses listGroup;
+        uses innerContainerGrouping;
+
+        choice choice{}
+        choice choice2{}
+
+        leaf-list leafList {
+            type string;
+        }
+
+        leaf identityRef {
+            type identityref {
+                base test-identity;
+            }
+        }
+
+        /* TODO test modification with empty type
+        leaf empty {
+             type empty;
+         }
+         */
+    }
+
+    augment "/container/" {
+        leaf augmentUint32 {
+            type uint32;
+        }
+    }
+
+    augment "/container/choice/" {
+        case test-identity-augment {
+            when "/container/identityRef = 'test-identity'";
+            leaf augmentString1 {
+                type string;
+            }
+
+            leaf augmentInt1 {
+                type uint32;
+            }
+        }
+        case test-identity-augment2 {
+            when "/container/identityRef = 'test-identity2'";
+            leaf augmentString2 {
+                type string;
+            }
+
+            leaf augmentInt2 {
+                type uint32;
+            }
+        }
+    }
+
+    augment "/container/choice2/" {
+        case test-identity-augment {
+            when "/container/identityRef = 'test-identity'";
+            container augmentContainer {
+                leaf augmentStringInaugmentContainer {
+                    type string;
+                }
+            }
+        }
+        case test-identity-augment2 {
+            when "/container/identityRef = 'test-identity2'";
+            list augmentedList {
+                leaf augmentStringInaugmentList {
+                    type string;
+                }
+            }
+        }
+    }
+
+
+    identity test-identity {}
+    identity test-identity2 {
+        base test-identity;
+    }
+
+}
\ No newline at end of file
index fe57b76dab8ec87b515220e21435149f6e486992..1ad6ca37527984221c66d159b4e7166ee8abff0e 100644 (file)
@@ -30,6 +30,7 @@ import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationTargetBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
 import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
@@ -981,9 +982,15 @@ public final class YangParserImpl implements YangModelParser {
             targetNode = findSchemaNode(augment.getTargetPath().getPath(), (SchemaNodeBuilder) parentNode);
         }
 
-        fillAugmentTarget(augment, targetNode);
-        augment.setResolved(true);
-        return true;
+        if (targetNode instanceof AugmentationTargetBuilder) {
+            fillAugmentTarget(augment, targetNode);
+            ((AugmentationTargetBuilder) targetNode).addAugmentation(augment);
+            augment.setResolved(true);
+            return true;
+        } else {
+            throw new YangParseException(module.getName(), augment.getLine(),
+                    "Failed to resolve augment in uses. Invalid augment target: " + targetNode);
+        }
     }
 
     /**
index 011f4cd8c56123fbc7e61c6903b72fd2f78094ac..7d8f4ed66d2de2f06481c7c20508a868994190c7 100644 (file)
@@ -28,6 +28,7 @@ import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
 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.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
@@ -419,4 +420,21 @@ public class AugmentTest {
         assertEquals(1, destroyChildren.size());
     }
 
+    @Test
+    public void testAugmentInUsesResolving() throws Exception {
+        modules = TestUtils.loadModules(getClass().getResource("/augment-test/augment-in-uses").toURI());
+        assertEquals(1, modules.size());
+
+        Module test = modules.iterator().next();
+        DataNodeContainer links = (DataNodeContainer) test.getDataChildByName("links");
+        DataNodeContainer link = (DataNodeContainer) links.getDataChildByName("link");
+        DataNodeContainer nodes = (DataNodeContainer) link.getDataChildByName("nodes");
+        ContainerSchemaNode node = (ContainerSchemaNode) nodes.getDataChildByName("node");
+        Set<AugmentationSchema> augments = node.getAvailableAugmentations();
+        assertEquals(1, augments.size());
+        assertEquals(1, node.getChildNodes().size());
+        LeafSchemaNode id = (LeafSchemaNode) node.getDataChildByName("id");
+        assertTrue(id.isAugmenting());
+    }
+
 }
diff --git a/yang/yang-parser-impl/src/test/resources/augment-test/augment-in-uses/foo.yang b/yang/yang-parser-impl/src/test/resources/augment-test/augment-in-uses/foo.yang
new file mode 100644 (file)
index 0000000..0dca0bc
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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
+ */
+module foo {
+    yang-version 1;
+    namespace "urn:yang.foo";
+    prefix "f";
+
+    revision "2014-03-10" {
+    }
+
+    container links {
+        container link {
+            uses g1 {
+                augment nodes/node {
+                    leaf id {
+                        type string;
+                    }
+                }
+            }
+        }
+    }
+
+    grouping g1 {
+        list nodes {
+            container node {
+            }
+        }
+    }
+
+}