Merge changes Icd18348e,I0e642b1b,I304bec5e
[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<Feature>();
44
45     /*
46      * @param holder - FeatureConfigSnapshotHolder that we
47      * @param feature - new
48      */
49     public FeatureConfigSnapshotHolder(final FeatureConfigSnapshotHolder holder, final Feature feature) throws JAXBException {
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 {
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         try {
73             XMLStreamReader xsr = xif.createXMLStreamReader(new StreamSource(new File(fileInfo.getFinalname())));
74             unmarshalled = ((ConfigSnapshot) um.unmarshal(xsr));
75         } catch (final XMLStreamException e) {
76             throw new JAXBException(e);
77         }
78     }
79     /*
80      * (non-Javadoc)
81      * @see java.lang.Object#hashCode()
82      *
83      * We really care most about the underlying ConfigShapshot, so compute hashcode on that
84      */
85     @Override
86     public int hashCode() {
87         final int prime = 31;
88         int result = 1;
89         result = prime * result + ((unmarshalled != null && unmarshalled.getConfigSnapshot() == null) ? 0 : unmarshalled.getConfigSnapshot().hashCode());
90         return result;
91     }
92     /*
93      * (non-Javadoc)
94      * @see java.lang.Object#equals(java.lang.Object)
95      * *
96      * We really care most about the underlying ConfigShapshot, so compute equality on that
97      */
98     @Override
99     public boolean equals(Object obj) {
100         if (this == obj) {
101             return true;
102         }
103         if (obj == null) {
104             return false;
105         }
106         if (getClass() != obj.getClass()) {
107             return false;
108         }
109         FeatureConfigSnapshotHolder fcsh = (FeatureConfigSnapshotHolder)obj;
110         if(this.unmarshalled.getConfigSnapshot().equals(fcsh.unmarshalled.getConfigSnapshot())) {
111             return true;
112         }
113         return false;
114     }
115
116     @Override
117     public String toString() {
118         StringBuilder b = new StringBuilder();
119         Path p = Paths.get(fileInfo.getFinalname());
120         b.append(p.getFileName())
121             .append("(")
122             .append(getCauseFeature())
123             .append(",")
124             .append(getFeature())
125             .append(")");
126         return b.toString();
127     }
128
129     @Override
130     public String getConfigSnapshot() {
131         return unmarshalled.getConfigSnapshot();
132     }
133
134     @Override
135     public SortedSet<String> getCapabilities() {
136         return unmarshalled.getCapabilities();
137     }
138
139     public ConfigFileInfo getFileInfo() {
140         return fileInfo;
141     }
142
143     /*
144      * @returns The original feature to which the ConfigFileInfo was attached
145      * Example:
146      * A -> B -> C, ConfigFileInfo Foo is attached to C.
147      * feature:install A
148      * thus C is the 'Feature' Foo was attached.
149      */
150     public Feature getFeature() {
151         return featureChain.get(0);
152     }
153
154     /*
155      * @return The dependency chain of the features that caused the ConfigFileInfo to be pushed in reverse order.
156      * Example:
157      * A -> B -> C, ConfigFileInfo Foo is attached to C.
158      * The returned list is
159      * [C,B,A]
160      */
161     public ImmutableList<Feature> getFeatureChain() {
162         return ImmutableList.copyOf(Lists.reverse(featureChain));
163     }
164
165     /*
166      * @return The feature the installation of which was the root cause
167      * of this pushing of the ConfigFileInfo.
168      * Example:
169      * A -> B -> C, ConfigFileInfo Foo is attached to C.
170      * feature:install A
171      * this A is the 'Cause' of the installation of Foo.
172      */
173     public Feature getCauseFeature() {
174         return Iterables.getLast(featureChain);
175     }
176 }