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, boolean config) {
155 long startTime = System.nanoTime();
157 DataSchemaNode node = schemaNodeFor(path);
158 return YangDataOperations.merge(node,stored,modified,config);
160 //System.out.println("Merge time: " + ((System.nanoTime() - startTime) / 1000.0d));
165 private DataSchemaNode schemaNodeFor(InstanceIdentifier path) {
166 checkState(schema != null,"YANG Schema is not available");
167 return YangSchemaUtils.getSchemaNode(schema, path);
170 private NormalizedDataModification prepareMergedTransaction(
171 DataModification<InstanceIdentifier, CompositeNode> original) {
173 NormalizedDataModification normalized = new NormalizedDataModification(original);
174 for (Entry<InstanceIdentifier,CompositeNode> entry : original.getUpdatedConfigurationData().entrySet()) {
175 normalized.putConfigurationData(entry.getKey(), entry.getValue());
177 for (Entry<InstanceIdentifier,CompositeNode> entry : original.getUpdatedOperationalData().entrySet()) {
178 normalized.putOperationalData(entry.getKey(), entry.getValue());
180 for (InstanceIdentifier entry : original.getRemovedConfigurationData()) {
181 normalized.removeConfigurationData(entry);
183 for(InstanceIdentifier entry : original.getRemovedOperationalData()) {
184 normalized.removeOperationalData(entry);
189 private final Comparator<Entry<InstanceIdentifier, CompositeNode>> preparationComparator = new Comparator<Entry<InstanceIdentifier, CompositeNode>>() {
191 public int compare(Entry<InstanceIdentifier, CompositeNode> o1, Entry<InstanceIdentifier, CompositeNode> o2) {
192 InstanceIdentifier o1Key = o1.getKey();
193 InstanceIdentifier o2Key = o2.getKey();
194 return Integer.compare(o1Key.getPath().size(), o2Key.getPath().size());
198 private class MergeFirstLevelReader implements DataReader<InstanceIdentifier, CompositeNode> {
201 public CompositeNode readConfigurationData(final InstanceIdentifier path) {
202 getDelegateReadLock().lock();
204 if (path.getPath().isEmpty()) {
208 CompositeNode original = getDelegate().readConfigurationData(path);
209 ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
210 if (original != null) {
211 childNodes.addAll(original.getChildren());
212 qname = original.getNodeType();
214 qname = path.getPath().get(path.getPath().size() - 1).getNodeType();
217 FluentIterable<InstanceIdentifier> directChildren = FluentIterable.from(getStoredConfigurationPaths())
218 .filter(new Predicate<InstanceIdentifier>() {
220 public boolean apply(InstanceIdentifier input) {
221 if (path.contains(input)) {
222 int nesting = input.getPath().size() - path.getPath().size();
230 for (InstanceIdentifier instanceIdentifier : directChildren) {
231 childNodes.add(getDelegate().readConfigurationData(instanceIdentifier));
233 if (original == null && childNodes.isEmpty()) {
237 return new CompositeNodeTOImpl(qname, null, childNodes);
239 getDelegateReadLock().unlock();
244 public CompositeNode readOperationalData(final InstanceIdentifier path) {
245 getDelegateReadLock().lock();
247 if (path.getPath().isEmpty()) {
251 CompositeNode original = getDelegate().readOperationalData(path);
252 ArrayList<Node<?>> childNodes = new ArrayList<Node<?>>();
253 if (original != null) {
254 childNodes.addAll(original.getChildren());
255 qname = original.getNodeType();
257 qname = path.getPath().get(path.getPath().size() - 1).getNodeType();
260 FluentIterable<InstanceIdentifier> directChildren = FluentIterable.from(getStoredOperationalPaths())
261 .filter(new Predicate<InstanceIdentifier>() {
263 public boolean apply(InstanceIdentifier input) {
264 if (path.contains(input)) {
265 int nesting = input.getPath().size() - path.getPath().size();
274 for (InstanceIdentifier instanceIdentifier : directChildren) {
275 childNodes.add(getDelegate().readOperationalData(instanceIdentifier));
277 if (original == null && childNodes.isEmpty()) {
281 return new CompositeNodeTOImpl(qname, null, childNodes);
283 getDelegateReadLock().unlock();
288 private class NormalizedDataModification extends AbstractDataModification<InstanceIdentifier, CompositeNode> {
290 private Object identifier;
291 private TransactionStatus status;
293 public NormalizedDataModification(DataModification<InstanceIdentifier, CompositeNode> original) {
294 super(getDelegate());
295 identifier = original;
296 status = TransactionStatus.NEW;
300 public Object getIdentifier() {
301 return this.identifier;
305 public TransactionStatus getStatus() {
310 public Future<RpcResult<TransactionStatus>> commit() {
311 throw new UnsupportedOperationException("Commit should not be invoked on this");
315 protected CompositeNode mergeConfigurationData(InstanceIdentifier path,CompositeNode stored, CompositeNode modified) {
316 return mergeData(path,stored, modified,true);
320 protected CompositeNode mergeOperationalData(InstanceIdentifier path,CompositeNode stored, CompositeNode modified) {
321 // TODO Auto-generated method stub
322 return mergeData(path,stored,modified,false);