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