Merge "Bug 2267: Reuse leaf and leaf set entry builders in NormalizedNodeInputStreamR...
[controller.git] / opendaylight / config / config-persister-feature-adapter / src / main / java / org / opendaylight / controller / configpusherfeature / internal / FeatureConfigSnapshotHolder.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. 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.configpusherfeature.internal;
9
10 import com.google.common.base.Preconditions;
11 import com.google.common.collect.ImmutableList;
12 import com.google.common.collect.Iterables;
13 import com.google.common.collect.Lists;
14 import java.io.File;
15 import java.nio.file.Path;
16 import java.nio.file.Paths;
17 import java.util.ArrayList;
18 import java.util.List;
19 import java.util.SortedSet;
20 import javax.xml.bind.JAXBContext;
21 import javax.xml.bind.JAXBException;
22 import javax.xml.bind.Unmarshaller;
23 import org.apache.karaf.features.ConfigFileInfo;
24 import org.apache.karaf.features.Feature;
25 import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
26 import org.opendaylight.controller.config.persist.storage.file.xml.model.ConfigSnapshot;
27
28 /*
29  * A ConfigSnapshotHolder that can track all the additional information
30  * relavent to the fact we are getting these from a Feature.
31  *
32  * Includes tracking the 'featureChain' - an reverse ordered list of the dependency
33  * graph of features that caused us to push this FeatureConfigSnapshotHolder.
34  * So if A -> B -> C, then the feature chain would be C -> B -> A
35  */
36 public class FeatureConfigSnapshotHolder implements ConfigSnapshotHolder {
37     private ConfigSnapshot unmarshalled = null;
38     private ConfigFileInfo fileInfo = null;
39     private List<Feature> featureChain = new ArrayList<Feature>();
40
41     /*
42      * @param holder - FeatureConfigSnapshotHolder that we
43      * @param feature - new
44      */
45     public FeatureConfigSnapshotHolder(final FeatureConfigSnapshotHolder holder, final Feature feature) throws JAXBException {
46         this(holder.fileInfo,holder.getFeature());
47         this.featureChain.add(feature);
48     }
49
50     /*
51      * Create a FeatureConfigSnapshotHolder for a given ConfigFileInfo and record the associated
52      * feature we are creating it from.
53      * @param fileInfo - ConfigFileInfo to read into the ConfigSnapshot
54      * @param feature - Feature the ConfigFileInfo was attached to
55      */
56     public FeatureConfigSnapshotHolder(final ConfigFileInfo fileInfo, final Feature feature) throws JAXBException {
57         Preconditions.checkNotNull(fileInfo);
58         Preconditions.checkNotNull(fileInfo.getFinalname());
59         Preconditions.checkNotNull(feature);
60         this.fileInfo = fileInfo;
61         this.featureChain.add(feature);
62         JAXBContext jaxbContext = JAXBContext.newInstance(ConfigSnapshot.class);
63         Unmarshaller um = jaxbContext.createUnmarshaller();
64         File file = new File(fileInfo.getFinalname());
65         unmarshalled = ((ConfigSnapshot) um.unmarshal(file));
66     }
67     /*
68      * (non-Javadoc)
69      * @see java.lang.Object#hashCode()
70      *
71      * We really care most about the underlying ConfigShapshot, so compute hashcode on that
72      */
73     @Override
74     public int hashCode() {
75         final int prime = 31;
76         int result = 1;
77         result = prime * result + ((unmarshalled != null && unmarshalled.getConfigSnapshot() == null) ? 0 : unmarshalled.getConfigSnapshot().hashCode());
78         return result;
79     }
80     /*
81      * (non-Javadoc)
82      * @see java.lang.Object#equals(java.lang.Object)
83      * *
84      * We really care most about the underlying ConfigShapshot, so compute equality on that
85      */
86     @Override
87     public boolean equals(Object obj) {
88         if (this == obj) {
89             return true;
90         }
91         if (obj == null) {
92             return false;
93         }
94         if (getClass() != obj.getClass()) {
95             return false;
96         }
97         FeatureConfigSnapshotHolder fcsh = (FeatureConfigSnapshotHolder)obj;
98         if(this.unmarshalled.getConfigSnapshot().equals(fcsh.unmarshalled.getConfigSnapshot())) {
99             return true;
100         }
101         return false;
102     }
103
104     @Override
105     public String toString() {
106         StringBuilder b = new StringBuilder();
107         Path p = Paths.get(fileInfo.getFinalname());
108         b.append(p.getFileName())
109             .append("(")
110             .append(getCauseFeature())
111             .append(",")
112             .append(getFeature())
113             .append(")");
114         return b.toString();
115     }
116
117     @Override
118     public String getConfigSnapshot() {
119         return unmarshalled.getConfigSnapshot();
120     }
121
122     @Override
123     public SortedSet<String> getCapabilities() {
124         return unmarshalled.getCapabilities();
125     }
126
127     public ConfigFileInfo getFileInfo() {
128         return fileInfo;
129     }
130
131     /*
132      * @returns The original feature to which the ConfigFileInfo was attached
133      * Example:
134      * A -> B -> C, ConfigFileInfo Foo is attached to C.
135      * feature:install A
136      * thus C is the 'Feature' Foo was attached.
137      */
138     public Feature getFeature() {
139         return featureChain.get(0);
140     }
141
142     /*
143      * @return The dependency chain of the features that caused the ConfigFileInfo to be pushed in reverse order.
144      * Example:
145      * A -> B -> C, ConfigFileInfo Foo is attached to C.
146      * The returned list is
147      * [C,B,A]
148      */
149     public ImmutableList<Feature> getFeatureChain() {
150         return ImmutableList.copyOf(Lists.reverse(featureChain));
151     }
152
153     /*
154      * @return The feature the installation of which was the root cause
155      * of this pushing of the ConfigFileInfo.
156      * Example:
157      * A -> B -> C, ConfigFileInfo Foo is attached to C.
158      * feature:install A
159      * this A is the 'Cause' of the installation of Foo.
160      */
161     public Feature getCauseFeature() {
162         return Iterables.getLast(featureChain);
163     }
164 }