2 * Copyright (c) 2017 Pantheon Technologies, s.r.o. 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.controller.clustering.it.provider.impl;
10 import static com.google.common.base.Preconditions.checkNotNull;
12 import com.google.common.base.MoreObjects;
13 import com.google.common.base.MoreObjects.ToStringHelper;
14 import com.google.common.base.Optional;
15 import java.util.ArrayList;
16 import java.util.Collections;
17 import java.util.List;
18 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
19 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
20 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode;
21 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
23 public abstract class DataListenerState {
24 private static final class Initial extends DataListenerState {
26 super(new ArrayList<>(1));
30 public long changeCount() {
35 public Optional<NormalizedNode<?, ?>> lastData() {
36 throw new UnsupportedOperationException();
40 Optional<DataListenerViolation> validate(final long sequence, final ModificationType type,
41 final Optional<NormalizedNode<?, ?>> beforeOpt, final Optional<NormalizedNode<?, ?>> afterOpt) {
42 return beforeOpt.transform(before -> new DataListenerViolation(sequence, null, before));
47 private abstract static class Subsequent extends DataListenerState {
48 private final long changeCount;
50 Subsequent(final List<DataListenerViolation> violations, final long changeCount) {
52 this.changeCount = changeCount;
56 public final long changeCount() {
61 private static final class Absent extends Subsequent {
62 Absent(final List<DataListenerViolation> violations, final long changeCount) {
63 super(violations, changeCount);
67 public Optional<NormalizedNode<?, ?>> lastData() {
68 return Optional.absent();
72 Optional<DataListenerViolation> validate(final long sequence, final ModificationType type,
73 final Optional<NormalizedNode<?, ?>> beforeOpt, final Optional<NormalizedNode<?, ?>> afterOpt) {
74 return beforeOpt.transform(before -> new DataListenerViolation(sequence, null, before));
78 private static final class Present extends Subsequent {
79 private final NormalizedNode<?, ?> data;
81 Present(final List<DataListenerViolation> violations, final long changeCount, final NormalizedNode<?, ?> data) {
82 super(violations, changeCount);
83 this.data = checkNotNull(data);
87 public Optional<NormalizedNode<?, ?>> lastData() {
88 return Optional.of(data);
92 Optional<DataListenerViolation> validate(final long sequence, final ModificationType type,
93 final Optional<NormalizedNode<?, ?>> beforeOpt, final Optional<NormalizedNode<?, ?>> afterOpt) {
94 if (!beforeOpt.isPresent()) {
95 return Optional.of(new DataListenerViolation(sequence, data, null));
98 final NormalizedNode<?, ?> before = beforeOpt.get();
99 // Identity check to keep things fast. We'll run a diff to eliminate false positives later
100 if (data != before) {
101 return Optional.of(new DataListenerViolation(sequence, data, before));
104 return Optional.absent();
108 private final List<DataListenerViolation> violations;
110 DataListenerState(final List<DataListenerViolation> violations) {
111 this.violations = checkNotNull(violations);
114 static DataListenerState initial() {
115 return new Initial();
118 final DataListenerState append(final DataTreeCandidate change) {
119 final DataTreeCandidateNode root = change.getRootNode();
120 final Optional<NormalizedNode<?, ?>> beforeOpt = root.getDataBefore();
121 final Optional<NormalizedNode<?, ?>> afterOpt = root.getDataAfter();
122 final long count = changeCount() + 1;
124 final Optional<DataListenerViolation> opt = validate(count, root.getModificationType(), beforeOpt, afterOpt);
125 if (opt.isPresent()) {
126 violations.add(opt.get());
129 return afterOpt.isPresent() ? new Present(violations, count, afterOpt.get()) : new Absent(violations, count);
132 public final List<DataListenerViolation> violations() {
133 return Collections.unmodifiableList(violations);
137 public abstract long changeCount();
139 public abstract Optional<NormalizedNode<?, ?>> lastData();
141 abstract Optional<DataListenerViolation> validate(final long sequence, final ModificationType type,
142 final Optional<NormalizedNode<?, ?>> beforeOpt, final Optional<NormalizedNode<?, ?>> afterOpt);
145 public final String toString() {
146 return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
149 ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
150 return toStringHelper.add("changeCount", changeCount());