2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.data.impl.schema.tree;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.base.MoreObjects.ToStringHelper;
13 import com.google.common.collect.ImmutableMap;
14 import com.google.common.collect.ImmutableMap.Builder;
15 import java.util.Optional;
16 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
20 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
21 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
22 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
23 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * Base strategy for applying changes to a ContainerNode, irrespective of its
31 * @param <T> Type of the container node
33 class DataNodeContainerModificationStrategy<T extends DataNodeContainer>
34 extends AbstractNodeContainerModificationStrategy {
35 private static final Logger LOG = LoggerFactory.getLogger(DataNodeContainerModificationStrategy.class);
37 private final DataTreeConfiguration treeConfig;
38 private final T schema;
40 @SuppressWarnings("rawtypes")
41 private static final AtomicReferenceFieldUpdater<DataNodeContainerModificationStrategy, ImmutableMap> UPDATER =
42 AtomicReferenceFieldUpdater.newUpdater(DataNodeContainerModificationStrategy.class, ImmutableMap.class,
44 private volatile ImmutableMap<PathArgument, ModificationApplyOperation> children = ImmutableMap.of();
46 DataNodeContainerModificationStrategy(final NormalizedNodeContainerSupport<?, ?> support, final T schema,
47 final DataTreeConfiguration treeConfig) {
48 super(support, treeConfig);
49 this.schema = requireNonNull(schema, "schema");
50 this.treeConfig = requireNonNull(treeConfig, "treeConfig");
54 public final Optional<ModificationApplyOperation> getChild(final PathArgument identifier) {
55 final ImmutableMap<PathArgument, ModificationApplyOperation> local = children;
56 final ModificationApplyOperation existing = local.get(identifier);
57 if (existing != null) {
58 return Optional.of(existing);
61 final ModificationApplyOperation childOperation = resolveChild(identifier);
62 return childOperation != null ? appendChild(local, identifier, childOperation) : Optional.empty();
65 private ModificationApplyOperation resolveChild(final PathArgument identifier) {
66 if (identifier instanceof AugmentationIdentifier && schema instanceof AugmentationTarget) {
67 return SchemaAwareApplyOperation.from(schema, (AugmentationTarget) schema,
68 (AugmentationIdentifier) identifier, treeConfig);
71 final QName qname = identifier.getNodeType();
72 final Optional<DataSchemaNode> child = schema.findDataChildByName(qname);
73 if (!child.isPresent()) {
74 LOG.trace("Child {} not present in container schema {} children {}", identifier, this,
75 schema.getChildNodes());
80 return SchemaAwareApplyOperation.from(child.get(), treeConfig);
81 } catch (IllegalArgumentException e) {
82 LOG.trace("Failed to instantiate child {} in container schema {} children {}", identifier, this,
83 schema.getChildNodes(), e);
88 private Optional<ModificationApplyOperation> appendChild(
89 final ImmutableMap<PathArgument, ModificationApplyOperation> initial, final PathArgument identifier,
90 final ModificationApplyOperation computed) {
92 ImmutableMap<PathArgument, ModificationApplyOperation> previous = initial;
94 // Build up a new map based on observed snapshot and computed child
95 final Builder<PathArgument, ModificationApplyOperation> builder = ImmutableMap.builderWithExpectedSize(
97 builder.putAll(previous);
98 builder.put(identifier, computed);
99 final ImmutableMap<PathArgument, ModificationApplyOperation> updated = builder.build();
101 // Attempt to install the updated map
102 if (UPDATER.compareAndSet(this, previous, updated)) {
103 return Optional.of(computed);
106 // We have raced, acquire a new snapshot, recheck presence and retry if needed
108 final ModificationApplyOperation raced = previous.get(identifier);
110 return Optional.of(raced);
116 ToStringHelper addToStringAttributes(final ToStringHelper helper) {
117 return super.addToStringAttributes(helper).add("schema", schema);