Merge "BUG-1275: Expose XmlStreamUtils.writeValue()"
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / ImmutableCompositeNode.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.yang.data.impl;
9
10 import com.google.common.collect.ImmutableList;
11 import com.google.common.collect.ImmutableMap;
12
13 import java.io.IOException;
14 import java.io.ObjectInputStream;
15 import java.io.ObjectOutputStream;
16 import java.io.Serializable;
17 import java.util.ArrayList;
18 import java.util.Collection;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Set;
24
25 import org.opendaylight.yangtools.concepts.Immutable;
26 import org.opendaylight.yangtools.yang.common.QName;
27 import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
28 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
29 import org.opendaylight.yangtools.yang.data.api.ModifyAction;
30 import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
31 import org.opendaylight.yangtools.yang.data.api.Node;
32 import org.opendaylight.yangtools.yang.data.api.SimpleNode;
33 import org.opendaylight.yangtools.yang.data.impl.util.AbstractCompositeNodeBuilder;
34 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
35
36 public final class ImmutableCompositeNode extends AbstractNodeTO<List<Node<?>>> implements //
37 Immutable, //
38 CompositeNode, //
39 AttributesContainer, //
40 Serializable {
41
42     private static final long serialVersionUID = 100L;
43
44     private Map<QName, List<Node<?>>> nodeMap = new HashMap<>();
45
46     private final Map<QName, String> attributes;
47
48
49
50     /**
51      * @param qname
52      * @param parent
53      *            use null to create top composite node (without parent)
54      * @param value
55      */
56     private ImmutableCompositeNode(final QName qname, final Map<QName,String> attributes,final List<Node<?>> value) {
57         super(qname, null, ImmutableList.copyOf(value));
58         if(attributes == null) {
59             this.attributes = ImmutableMap.<QName, String>of();
60         } else {
61             this.attributes = ImmutableMap.copyOf(attributes);
62         }
63         init();
64     }
65
66     /**
67      * @param qname
68      * @param parent
69      *            use null to create top composite node (without parent)
70      * @param value
71      * @param modifyAction
72      */
73     public ImmutableCompositeNode(final QName qname, final List<Node<?>> value, final ModifyAction modifyAction) {
74         super(qname, null, value, modifyAction);
75         attributes = ImmutableMap.of();
76         init();
77     }
78
79     protected void init() {
80         if (getValue() != null) {
81             nodeMap = NodeUtils.buildNodeMap(getValue());
82         }
83     }
84
85     protected Map<QName, List<Node<?>>> getNodeMap() {
86         return nodeMap;
87     }
88
89     @Override
90     public List<Node<?>> getChildren() {
91         return Collections.unmodifiableList(getValue() == null ? new ArrayList<Node<?>>() : getValue());
92     }
93
94     @Override
95     public SimpleNode<?> getFirstSimpleByName(final QName leafQName) {
96         List<SimpleNode<?>> list = getSimpleNodesByName(leafQName);
97         if (list.isEmpty()) {
98             return null;
99         }
100         return list.get(0);
101     }
102
103     @Override
104     public List<CompositeNode> getCompositesByName(final QName children) {
105         List<Node<?>> toFilter = getNodeMap().get(children);
106         if (toFilter == null) {
107             return Collections.emptyList();
108         }
109         List<CompositeNode> list = new ArrayList<CompositeNode>();
110         for (Node<?> node : toFilter) {
111             if (node instanceof CompositeNode) {
112                 list.add((CompositeNode) node);
113             }
114         }
115         return list;
116     }
117
118     @Override
119     public List<SimpleNode<?>> getSimpleNodesByName(final QName children) {
120         List<Node<?>> toFilter = getNodeMap().get(children);
121         if (toFilter == null) {
122             return Collections.emptyList();
123         }
124         List<SimpleNode<?>> list = new ArrayList<SimpleNode<?>>();
125
126         for (Node<?> node : toFilter) {
127             if (node instanceof SimpleNode<?>) {
128                 list.add((SimpleNode<?>) node);
129             }
130         }
131         return list;
132     }
133
134     @Override
135     public CompositeNode getFirstCompositeByName(final QName container) {
136         List<CompositeNode> list = getCompositesByName(container);
137         if (list.isEmpty()) {
138             return null;
139         }
140         return list.get(0);
141     }
142
143     @Override
144     public Map<QName, String> getAttributes() {
145         return attributes;
146     }
147
148     @Override
149     public String getAttributeValue(final QName key) {
150         return attributes.get(key);
151     }
152
153     /**
154      * @param leaf
155      * @return TODO:: do we need this method?
156      */
157     public SimpleNode<?> getFirstLeafByName(final QName leaf) {
158         List<SimpleNode<?>> list = getSimpleNodesByName(leaf);
159         if (list.isEmpty()) {
160             return null;
161         }
162         return list.get(0);
163     }
164
165     @Override
166     public List<CompositeNode> getCompositesByName(final String children) {
167         return getCompositesByName(QName.create(getNodeType(), children));
168     }
169
170     @Override
171     public List<SimpleNode<?>> getSimpleNodesByName(final String children) {
172         return getSimpleNodesByName(QName.create(getNodeType(), children));
173     }
174
175     @Override
176     public MutableCompositeNode asMutable() {
177         throw new IllegalAccessError("cast to mutable is not supported - " + getClass().getSimpleName());
178     }
179
180     @Override
181     public String toString() {
182         return super.toString() + ", children.size = " + (getChildren() != null ? getChildren().size() : "n/a");
183     }
184
185     @Override
186     public void clear() {
187         nodeMap.clear();
188     }
189
190     @Override
191     public boolean containsKey(final Object key) {
192         return nodeMap.containsKey(key);
193     }
194
195     @Override
196     public boolean containsValue(final Object value) {
197         return nodeMap.containsValue(value);
198     }
199
200     @Override
201     public Set<java.util.Map.Entry<QName, List<Node<?>>>> entrySet() {
202         return nodeMap.entrySet();
203     }
204
205     @Override
206     public int size() {
207         return nodeMap.size();
208     }
209
210     @Override
211     public boolean isEmpty() {
212         return nodeMap.isEmpty();
213     }
214
215     @Override
216     public List<Node<?>> get(final Object key) {
217         return nodeMap.get(key);
218     }
219
220     @Override
221     public List<Node<?>> put(final QName key, final List<Node<?>> value) {
222         return nodeMap.put(key, value);
223     }
224
225     @Override
226     public List<Node<?>> remove(final Object key) {
227         return nodeMap.remove(key);
228     }
229
230     @Override
231     public void putAll(final Map<? extends QName, ? extends List<Node<?>>> m) {
232         nodeMap.putAll(m);
233     }
234
235     @Override
236     public Set<QName> keySet() {
237         return nodeMap.keySet();
238     }
239
240     @Override
241     public Collection<List<Node<?>>> values() {
242         return nodeMap.values();
243     }
244
245     // Serialization related
246
247     private void readObject(final ObjectInputStream aStream) throws IOException, ClassNotFoundException {
248         aStream.defaultReadObject();
249         QName qName = (QName) aStream.readObject();
250         CompositeNode parent = (CompositeNode) aStream.readObject();
251         @SuppressWarnings("unchecked")
252         List<Node<?>> value = (List<Node<?>>) aStream.readObject();
253         ModifyAction modifyAction = (ModifyAction) aStream.readObject();
254
255         init(qName, parent, value, modifyAction);
256     }
257
258     private void writeObject(final ObjectOutputStream aStream) throws IOException {
259         aStream.defaultWriteObject();
260         // manually serialize superclass
261         aStream.writeObject(getQName());
262         aStream.writeObject(getParent());
263         aStream.writeObject(getValue());
264         aStream.writeObject(getModificationAction());
265     }
266
267     public static CompositeNodeBuilder<ImmutableCompositeNode> builder() {
268         return new ImmutableCompositeNodeBuilder();
269     }
270
271     private static class ImmutableCompositeNodeBuilder extends AbstractCompositeNodeBuilder<ImmutableCompositeNode> {
272
273         @Override
274         public AbstractCompositeNodeBuilder<ImmutableCompositeNode> addLeaf(final QName leafName, final Object leafValue) {
275             add(new SimpleNodeTOImpl<Object>(leafName, null, leafValue));
276             return this;
277         }
278
279         @Override
280         public ImmutableCompositeNode toInstance() {
281             return ImmutableCompositeNode.create(this.getQName(), this.getAttributes(), this.getChildNodes());
282         }
283
284     }
285
286     public static ImmutableCompositeNode create(final QName qName, final List<Node<?>> childNodes) {
287         return new ImmutableCompositeNode(qName, ImmutableMap.<QName, String>of(),childNodes);
288     }
289
290     public static ImmutableCompositeNode create(final QName qName, final Map<QName, String> attributes, final List<Node<?>> childNodes) {
291         return new ImmutableCompositeNode(qName, attributes,childNodes);
292     }
293
294     public static ImmutableCompositeNode create(final QName qName, final List<Node<?>> childNodes, final ModifyAction modifyAction) {
295         return new ImmutableCompositeNode(qName, childNodes, modifyAction);
296     }
297 }