BUG-8733: refactor IdInts listeners
[controller.git] / opendaylight / md-sal / samples / clustering-test-app / provider / src / main / java / org / opendaylight / controller / clustering / it / provider / impl / DataListenerState.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.clustering.it.provider.impl;
9
10 import static com.google.common.base.Preconditions.checkNotNull;
11
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;
22
23 public abstract class DataListenerState {
24     private static final class Initial extends DataListenerState {
25         Initial() {
26             super(new ArrayList<>(1));
27         }
28
29         @Override
30         public long changeCount() {
31             return 0;
32         }
33
34         @Override
35         public Optional<NormalizedNode<?, ?>> lastData() {
36             throw new UnsupportedOperationException();
37         }
38
39         @Override
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));
43         }
44
45     }
46
47     private abstract static class Subsequent extends DataListenerState {
48         private final long changeCount;
49
50         Subsequent(final List<DataListenerViolation> violations, final long changeCount) {
51             super(violations);
52             this.changeCount = changeCount;
53         }
54
55         @Override
56         public final long changeCount() {
57             return changeCount;
58         }
59     }
60
61     private static final class Absent extends Subsequent {
62         Absent(final List<DataListenerViolation> violations, final long changeCount) {
63             super(violations, changeCount);
64         }
65
66         @Override
67         public Optional<NormalizedNode<?, ?>> lastData() {
68             return Optional.absent();
69         }
70
71         @Override
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));
75         }
76     }
77
78     private static final class Present extends Subsequent {
79         private final NormalizedNode<?, ?> data;
80
81         Present(final List<DataListenerViolation> violations, final long changeCount, final NormalizedNode<?, ?> data) {
82             super(violations, changeCount);
83             this.data = checkNotNull(data);
84         }
85
86         @Override
87         public Optional<NormalizedNode<?, ?>> lastData() {
88             return Optional.of(data);
89         }
90
91         @Override
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));
96             }
97
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));
102             }
103
104             return Optional.absent();
105         }
106     }
107
108     private final List<DataListenerViolation> violations;
109
110     DataListenerState(final List<DataListenerViolation> violations) {
111         this.violations = checkNotNull(violations);
112     }
113
114     static DataListenerState initial() {
115         return new Initial();
116     }
117
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;
123
124         final Optional<DataListenerViolation> opt = validate(count, root.getModificationType(), beforeOpt, afterOpt);
125         if (opt.isPresent()) {
126             violations.add(opt.get());
127         }
128
129         return afterOpt.isPresent() ? new Present(violations, count, afterOpt.get()) : new Absent(violations, count);
130     }
131
132     public final List<DataListenerViolation> violations() {
133         return Collections.unmodifiableList(violations);
134     }
135
136
137     public abstract long changeCount();
138
139     public abstract Optional<NormalizedNode<?, ?>> lastData();
140
141     abstract Optional<DataListenerViolation> validate(final long sequence, final ModificationType type,
142             final Optional<NormalizedNode<?, ?>> beforeOpt, final Optional<NormalizedNode<?, ?>> afterOpt);
143
144     @Override
145     public final String toString() {
146         return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
147     }
148
149     ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
150         return toStringHelper.add("changeCount", changeCount());
151     }
152 }