1f908140b0ba60ca286095e4c693804609ec3472
[controller.git] / opendaylight / md-sal / sal-dom-broker / src / main / java / org / opendaylight / controller / sal / dom / broker / impl / SchemaAwareDataStoreAdapter.java
1 package org.opendaylight.controller.sal.dom.broker.impl;
2
3 import java.awt.PageAttributes.OriginType;
4 import java.util.ArrayList;
5 import java.util.Collections;
6 import java.util.Comparator;
7 import java.util.HashSet;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Map.Entry;
11 import java.util.Set;
12 import java.util.concurrent.atomic.AtomicLong;
13
14 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
15 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
16 import org.opendaylight.controller.md.sal.common.impl.util.AbstractLockableDelegator;
17 import org.opendaylight.controller.sal.core.api.data.DataStore;
18 import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
21 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.Node;
23 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
24 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 import com.google.common.base.Predicate;
29 import com.google.common.collect.FluentIterable;
30
31 import static com.google.common.base.Preconditions.*;
32
33 public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataStore> implements //
34         DataStore, //
35         SchemaServiceListener, //
36         AutoCloseable {
37
38     private final static Logger LOG = LoggerFactory.getLogger(SchemaAwareDataStoreAdapter.class);
39
40     private SchemaContext schema = null;
41     private boolean validationEnabled = false;
42     private SchemaAwareDataMerger dataMerger = null;
43     private DataReader<InstanceIdentifier, CompositeNode> reader = new MergeFirstLevelReader();
44
45     @Override
46     public boolean containsConfigurationPath(InstanceIdentifier path) {
47         try {
48             getDelegateReadLock().lock();
49             return getDelegate().containsConfigurationPath(path);
50
51         } finally {
52             getDelegateReadLock().unlock();
53         }
54     }
55
56     @Override
57     public boolean containsOperationalPath(InstanceIdentifier path) {
58         try {
59             getDelegateReadLock().lock();
60             return getDelegate().containsOperationalPath(path);
61
62         } finally {
63             getDelegateReadLock().unlock();
64         }
65     }
66
67     @Override
68     public Iterable<InstanceIdentifier> getStoredConfigurationPaths() {
69         try {
70             getDelegateReadLock().lock();
71             return getDelegate().getStoredConfigurationPaths();
72
73         } finally {
74             getDelegateReadLock().unlock();
75         }
76     }
77
78     @Override
79     public Iterable<InstanceIdentifier> getStoredOperationalPaths() {
80         try {
81             getDelegateReadLock().lock();
82             return getDelegate().getStoredOperationalPaths();
83
84         } finally {
85             getDelegateReadLock().unlock();
86         }
87     }
88
89     @Override
90     public CompositeNode readConfigurationData(InstanceIdentifier path) {
91         return reader.readConfigurationData(path);
92     }
93
94     @Override
95     public CompositeNode readOperationalData(InstanceIdentifier path) {
96         return reader.readOperationalData(path);
97     }
98
99     @Override
100     public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(
101             DataModification<InstanceIdentifier, CompositeNode> modification) {
102         validateAgainstSchema(modification);
103         DataModification<InstanceIdentifier, CompositeNode> cleanedUp = prepareMergedTransaction(modification);
104         return retrieveDelegate().requestCommit(cleanedUp);
105     }
106
107     public boolean isValidationEnabled() {
108         return validationEnabled;
109     }
110
111     public void setValidationEnabled(boolean validationEnabled) {
112         this.validationEnabled = validationEnabled;
113     }
114
115     private void validateAgainstSchema(DataModification<InstanceIdentifier, CompositeNode> modification) {
116         if (!validationEnabled) {
117             return;
118         }
119
120         if (schema == null) {
121             LOG.info("Validation not performed for {}. Reason: YANG Schema not present.", modification.getIdentifier());
122             return;
123         }
124     }
125
126     @Override
127     protected void onDelegateChanged(DataStore oldDelegate, DataStore newDelegate) {
128         // NOOP
129     }
130
131     @Override
132     public void onGlobalContextUpdated(SchemaContext context) {
133         this.schema = context;
134     }
135
136     @Override
137     public void close() throws Exception {
138         this.schema = null;
139     }
140
141     private DataModification<InstanceIdentifier, CompositeNode> prepareMergedTransaction(
142             DataModification<InstanceIdentifier, CompositeNode> original) {
143         // NOOP for now
144         return original;
145     }
146
147     private final Comparator<Entry<InstanceIdentifier, CompositeNode>> preparationComparator = new Comparator<Entry<InstanceIdentifier, CompositeNode>>() {
148         @Override
149         public int compare(Entry<InstanceIdentifier, CompositeNode> o1, Entry<InstanceIdentifier, CompositeNode> o2) {
150             InstanceIdentifier o1Key = o1.getKey();
151             InstanceIdentifier o2Key = o2.getKey();
152             return Integer.compare(o1Key.getPath().size(), o2Key.getPath().size());
153         }
154     };
155
156     private class MergeFirstLevelReader implements DataReader<InstanceIdentifier, CompositeNode> {
157
158         @Override
159         public CompositeNode readConfigurationData(final InstanceIdentifier path) {
160             getDelegateReadLock().lock();
161             try {
162                 if (path.getPath().isEmpty()) {
163                     return null;
164                 }
165                 QName qname = null;
166                 CompositeNode original = getDelegate().readConfigurationData(path);
167                 ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
168                 if (original != null) {
169                     childNodes.addAll(original.getChildren());
170                     qname = original.getNodeType();
171                 } else {
172                     qname = path.getPath().get(path.getPath().size() - 1).getNodeType();
173                 }
174
175                 FluentIterable<InstanceIdentifier> directChildren = FluentIterable.from(getStoredConfigurationPaths())
176                         .filter(new Predicate<InstanceIdentifier>() {
177                             @Override
178                             public boolean apply(InstanceIdentifier input) {
179                                 if (path.contains(input)) {
180                                     int nesting = input.getPath().size() - path.getPath().size();
181                                     if (nesting == 1) {
182                                         return true;
183                                     }
184                                 }
185                                 return false;
186                             }
187                         });
188                 for (InstanceIdentifier instanceIdentifier : directChildren) {
189                     childNodes.add(getDelegate().readConfigurationData(instanceIdentifier));
190                 }
191                 if (original == null && childNodes.isEmpty()) {
192                     return null;
193                 }
194
195                 return new CompositeNodeTOImpl(qname, null, childNodes);
196             } finally {
197                 getDelegateReadLock().unlock();
198             }
199         }
200
201         @Override
202         public CompositeNode readOperationalData(final InstanceIdentifier path) {
203             getDelegateReadLock().lock();
204             try {
205                 if (path.getPath().isEmpty()) {
206                     return null;
207                 }
208                 QName qname = null;
209                 CompositeNode original = getDelegate().readOperationalData(path);
210                 ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
211                 if (original != null) {
212                     childNodes.addAll(original.getChildren());
213                     qname = original.getNodeType();
214                 } else {
215                     qname = path.getPath().get(path.getPath().size() - 1).getNodeType();
216                 }
217
218                 FluentIterable<InstanceIdentifier> directChildren = FluentIterable.from(getStoredOperationalPaths())
219                         .filter(new Predicate<InstanceIdentifier>() {
220                             @Override
221                             public boolean apply(InstanceIdentifier input) {
222                                 if (path.contains(input)) {
223                                     int nesting = input.getPath().size() - path.getPath().size();
224                                     if (nesting == 1) {
225                                         return true;
226                                     }
227                                 }
228                                 return false;
229                             }
230                         });
231
232                 for (InstanceIdentifier instanceIdentifier : directChildren) {
233                     childNodes.add(getDelegate().readOperationalData(instanceIdentifier));
234                 }
235                 if (original == null && childNodes.isEmpty()) {
236                     return null;
237                 }
238
239                 return new CompositeNodeTOImpl(qname, null, childNodes);
240             } finally {
241                 getDelegateReadLock().unlock();
242             }
243         }
244     }
245 }