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;
}
}
@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);
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);
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) {
}
@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();
}
}
-
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();
}
*/
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);
}
this.port = port;
}
+ /**
+ * Tries to start web socket server.
+ */
public void run(){
try {
startServer();
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)
*/
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;
*/
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();
*/
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);
}
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);
}
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);
}
<dependency>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
- <version>1.4</version>
+ <version>1.5</version>
<scope>test</scope>
</dependency>
<dependency>
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));
}
}
+ 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
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) {
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();
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) {
}
}
} 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("/");
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");
}
}
} 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));
}
}
}
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);
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())) {
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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();
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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);
+ }
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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);
+ }
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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);
+ }
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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");
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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();
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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();
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.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;
+ }
+}
--- /dev/null
+<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
--- /dev/null
+// 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
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;
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);
+ }
}
/**
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;
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());
+ }
+
}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+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 {
+ }
+ }
+ }
+
+}