1 package org.opendaylight.controller.sal.dom.broker.impl;
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.Iterator;
11 import java.util.Map.Entry;
13 import java.util.concurrent.Future;
14 import java.util.concurrent.atomic.AtomicLong;
16 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
17 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
18 import org.opendaylight.controller.md.sal.common.api.data.DataReader;
19 import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification;
20 import org.opendaylight.controller.md.sal.common.impl.util.AbstractLockableDelegator;
21 import org.opendaylight.controller.sal.core.api.data.DataStore;
22 import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
23 import org.opendaylight.yangtools.yang.common.QName;
24 import org.opendaylight.yangtools.yang.common.RpcResult;
25 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
26 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
27 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
28 import org.opendaylight.yangtools.yang.data.api.Node;
29 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
30 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
31 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
32 import org.opendaylight.yangtools.yang.model.api.Module;
33 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
34 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
35 import org.opendaylight.yangtools.yang.util.YangDataOperations;
36 import org.opendaylight.yangtools.yang.util.YangSchemaUtils;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
40 import com.google.common.base.Predicate;
41 import com.google.common.collect.FluentIterable;
43 import static com.google.common.base.Preconditions.*;
44 import org.opendaylight.yangtools.yang.util.YangDataOperations;
46 public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataStore> implements //
48 SchemaServiceListener, //
51 private final static Logger LOG = LoggerFactory.getLogger(SchemaAwareDataStoreAdapter.class);
53 private SchemaContext schema = null;
54 private boolean validationEnabled = false;
55 private DataReader<InstanceIdentifier, CompositeNode> reader = new MergeFirstLevelReader();
58 public boolean containsConfigurationPath(InstanceIdentifier path) {
60 getDelegateReadLock().lock();
61 return getDelegate().containsConfigurationPath(path);
64 getDelegateReadLock().unlock();
69 public boolean containsOperationalPath(InstanceIdentifier path) {
71 getDelegateReadLock().lock();
72 return getDelegate().containsOperationalPath(path);
75 getDelegateReadLock().unlock();
80 public Iterable<InstanceIdentifier> getStoredConfigurationPaths() {
82 getDelegateReadLock().lock();
83 return getDelegate().getStoredConfigurationPaths();
86 getDelegateReadLock().unlock();
91 public Iterable<InstanceIdentifier> getStoredOperationalPaths() {
93 getDelegateReadLock().lock();
94 return getDelegate().getStoredOperationalPaths();
97 getDelegateReadLock().unlock();
102 public CompositeNode readConfigurationData(InstanceIdentifier path) {
103 return reader.readConfigurationData(path);
107 public CompositeNode readOperationalData(InstanceIdentifier path) {
108 return reader.readOperationalData(path);
112 public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction<InstanceIdentifier, CompositeNode> requestCommit(
113 DataModification<InstanceIdentifier, CompositeNode> modification) {
114 validateAgainstSchema(modification);
115 NormalizedDataModification cleanedUp = prepareMergedTransaction(modification);
116 cleanedUp.status = TransactionStatus.SUBMITED;
117 return retrieveDelegate().requestCommit(cleanedUp);
120 public boolean isValidationEnabled() {
121 return validationEnabled;
124 public void setValidationEnabled(boolean validationEnabled) {
125 this.validationEnabled = validationEnabled;
128 private void validateAgainstSchema(DataModification<InstanceIdentifier, CompositeNode> modification) {
129 if (!validationEnabled) {
133 if (schema == null) {
134 LOG.info("Validation not performed for {}. Reason: YANG Schema not present.", modification.getIdentifier());
140 protected void onDelegateChanged(DataStore oldDelegate, DataStore newDelegate) {
145 public void onGlobalContextUpdated(SchemaContext context) {
146 this.schema = context;
150 public void close() throws Exception {
154 protected CompositeNode mergeData(InstanceIdentifier path, CompositeNode stored, CompositeNode modified,
156 long startTime = System.nanoTime();
158 DataSchemaNode node = schemaNodeFor(path);
159 return YangDataOperations.merge(node, stored, modified, config);
161 // System.out.println("Merge time: " + ((System.nanoTime() -
162 // startTime) / 1000.0d));
166 private DataSchemaNode schemaNodeFor(InstanceIdentifier path) {
167 checkState(schema != null, "YANG Schema is not available");
168 return YangSchemaUtils.getSchemaNode(schema, path);
171 private NormalizedDataModification prepareMergedTransaction(
172 DataModification<InstanceIdentifier, CompositeNode> original) {
174 NormalizedDataModification normalized = new NormalizedDataModification(original);
175 for (Entry<InstanceIdentifier, CompositeNode> entry : original.getUpdatedConfigurationData().entrySet()) {
176 normalized.putConfigurationData(entry.getKey(), entry.getValue());
178 for (Entry<InstanceIdentifier, CompositeNode> entry : original.getUpdatedOperationalData().entrySet()) {
179 normalized.putOperationalData(entry.getKey(), entry.getValue());
181 for (InstanceIdentifier entry : original.getRemovedConfigurationData()) {
182 normalized.removeConfigurationData(entry);
184 for (InstanceIdentifier entry : original.getRemovedOperationalData()) {
185 normalized.removeOperationalData(entry);
190 private final Comparator<Entry<InstanceIdentifier, CompositeNode>> preparationComparator = new Comparator<Entry<InstanceIdentifier, CompositeNode>>() {
192 public int compare(Entry<InstanceIdentifier, CompositeNode> o1, Entry<InstanceIdentifier, CompositeNode> o2) {
193 InstanceIdentifier o1Key = o1.getKey();
194 InstanceIdentifier o2Key = o2.getKey();
195 return Integer.compare(o1Key.getPath().size(), o2Key.getPath().size());
199 private class MergeFirstLevelReader implements DataReader<InstanceIdentifier, CompositeNode> {
202 public CompositeNode readConfigurationData(final InstanceIdentifier path) {
203 getDelegateReadLock().lock();
205 if (path.getPath().isEmpty()) {
209 CompositeNode original = getDelegate().readConfigurationData(path);
210 ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
211 if (original != null) {
212 childNodes.addAll(original.getChildren());
213 qname = original.getNodeType();
215 qname = path.getPath().get(path.getPath().size() - 1).getNodeType();
218 FluentIterable<InstanceIdentifier> directChildren = FluentIterable.from(getStoredConfigurationPaths())
219 .filter(new Predicate<InstanceIdentifier>() {
221 public boolean apply(InstanceIdentifier input) {
222 if (path.contains(input)) {
223 int nesting = input.getPath().size() - path.getPath().size();
231 for (InstanceIdentifier instanceIdentifier : directChildren) {
232 childNodes.add(getDelegate().readConfigurationData(instanceIdentifier));
234 if (original == null && childNodes.isEmpty()) {
238 return new CompositeNodeTOImpl(qname, null, childNodes);
240 getDelegateReadLock().unlock();
245 public CompositeNode readOperationalData(final InstanceIdentifier path) {
246 getDelegateReadLock().lock();
248 if (path.getPath().isEmpty()) {
252 CompositeNode original = getDelegate().readOperationalData(path);
253 ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
254 if (original != null) {
255 childNodes.addAll(original.getChildren());
256 qname = original.getNodeType();
258 qname = path.getPath().get(path.getPath().size() - 1).getNodeType();
261 FluentIterable<InstanceIdentifier> directChildren = FluentIterable.from(getStoredOperationalPaths())
262 .filter(new Predicate<InstanceIdentifier>() {
264 public boolean apply(InstanceIdentifier input) {
265 if (path.contains(input)) {
266 int nesting = input.getPath().size() - path.getPath().size();
275 for (InstanceIdentifier instanceIdentifier : directChildren) {
276 childNodes.add(getDelegate().readOperationalData(instanceIdentifier));
278 if (original == null && childNodes.isEmpty()) {
282 return new CompositeNodeTOImpl(qname, null, childNodes);
284 getDelegateReadLock().unlock();
289 private class NormalizedDataModification extends AbstractDataModification<InstanceIdentifier, CompositeNode> {
291 private Object identifier;
292 private TransactionStatus status;
294 public NormalizedDataModification(DataModification<InstanceIdentifier, CompositeNode> original) {
295 super(getDelegate());
296 identifier = original;
297 status = TransactionStatus.NEW;
301 public Object getIdentifier() {
302 return this.identifier;
306 public TransactionStatus getStatus() {
311 public Future<RpcResult<TransactionStatus>> commit() {
312 throw new UnsupportedOperationException("Commit should not be invoked on this");
316 protected CompositeNode mergeConfigurationData(InstanceIdentifier path, CompositeNode stored,
317 CompositeNode modified) {
318 return mergeData(path, stored, modified, true);
322 protected CompositeNode mergeOperationalData(InstanceIdentifier path, CompositeNode stored,
323 CompositeNode modified) {
324 // TODO Auto-generated method stub
325 return mergeData(path, stored, modified, false);