config-persister-feature-adapter to push configs from karaf features
[controller.git] / opendaylight / config / config-persister-feature-adapter / src / main / java / org / opendaylight / controller / configpusherfeature / internal / FeatureConfigSnapshotHolder.java
diff --git a/opendaylight/config/config-persister-feature-adapter/src/main/java/org/opendaylight/controller/configpusherfeature/internal/FeatureConfigSnapshotHolder.java b/opendaylight/config/config-persister-feature-adapter/src/main/java/org/opendaylight/controller/configpusherfeature/internal/FeatureConfigSnapshotHolder.java
new file mode 100644 (file)
index 0000000..d1a92eb
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.configpusherfeature.internal;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.SortedSet;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.karaf.features.ConfigFileInfo;
+import org.apache.karaf.features.Feature;
+import org.opendaylight.controller.config.persist.api.ConfigSnapshotHolder;
+import org.opendaylight.controller.config.persist.storage.file.xml.model.ConfigSnapshot;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+/*
+ * A ConfigSnapshotHolder that can track all the additional information
+ * relavent to the fact we are getting these from a Feature.
+ *
+ * Includes tracking the 'featureChain' - an reverse ordered list of the dependency
+ * graph of features that caused us to push this FeatureConfigSnapshotHolder.
+ * So if A -> B -> C, then the feature chain would be C -> B -> A
+ */
+public class FeatureConfigSnapshotHolder implements ConfigSnapshotHolder {
+    private ConfigSnapshot unmarshalled = null;
+    private ConfigFileInfo fileInfo = null;
+    private List<Feature> featureChain = new ArrayList<Feature>();
+
+    /*
+     * @param holder - FeatureConfigSnapshotHolder that we
+     * @param feature - new
+     */
+    public FeatureConfigSnapshotHolder(final FeatureConfigSnapshotHolder holder, final Feature feature) throws JAXBException {
+        this(holder.fileInfo,holder.getFeature());
+        this.featureChain.add(feature);
+    }
+
+    /*
+     * Create a FeatureConfigSnapshotHolder for a given ConfigFileInfo and record the associated
+     * feature we are creating it from.
+     * @param fileInfo - ConfigFileInfo to read into the ConfigSnapshot
+     * @param feature - Feature the ConfigFileInfo was attached to
+     */
+    public FeatureConfigSnapshotHolder(final ConfigFileInfo fileInfo, final Feature feature) throws JAXBException {
+        Preconditions.checkNotNull(fileInfo);
+        Preconditions.checkNotNull(fileInfo.getFinalname());
+        Preconditions.checkNotNull(feature);
+        this.fileInfo = fileInfo;
+        this.featureChain.add(feature);
+        JAXBContext jaxbContext = JAXBContext.newInstance(ConfigSnapshot.class);
+        Unmarshaller um = jaxbContext.createUnmarshaller();
+        File file = new File(fileInfo.getFinalname());
+        unmarshalled = ((ConfigSnapshot) um.unmarshal(file));
+    }
+    /*
+     * (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     *
+     * We really care most about the underlying ConfigShapshot, so compute hashcode on that
+     */
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((unmarshalled != null && unmarshalled.getConfigSnapshot() == null) ? 0 : unmarshalled.getConfigSnapshot().hashCode());
+        return result;
+    }
+    /*
+     * (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     * *
+     * We really care most about the underlying ConfigShapshot, so compute equality on that
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        FeatureConfigSnapshotHolder fcsh = (FeatureConfigSnapshotHolder)obj;
+        if(this.unmarshalled.getConfigSnapshot().equals(fcsh.unmarshalled.getConfigSnapshot())) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+       StringBuilder b = new StringBuilder();
+       Path p = Paths.get(fileInfo.getFinalname());
+       b.append(p.getFileName())
+           .append("(")
+           .append(getCauseFeature())
+           .append(",")
+           .append(getFeature())
+           .append(")");
+       return b.toString();
+
+    }
+
+    @Override
+    public String getConfigSnapshot() {
+        return unmarshalled.getConfigSnapshot();
+    }
+
+    @Override
+    public SortedSet<String> getCapabilities() {
+        return unmarshalled.getCapabilities();
+    }
+
+    public ConfigFileInfo getFileInfo() {
+        return fileInfo;
+    }
+
+    /*
+     * @returns The original feature to which the ConfigFileInfo was attached
+     * Example:
+     * A -> B -> C, ConfigFileInfo Foo is attached to C.
+     * feature:install A
+     * thus C is the 'Feature' Foo was attached.
+     */
+    public Feature getFeature() {
+        return featureChain.get(0);
+    }
+
+    /*
+     * @return The dependency chain of the features that caused the ConfigFileInfo to be pushed in reverse order.
+     * Example:
+     * A -> B -> C, ConfigFileInfo Foo is attached to C.
+     * The returned list is
+     * [C,B,A]
+     */
+    public ImmutableList<Feature> getFeatureChain() {
+        return ImmutableList.copyOf(Lists.reverse(featureChain));
+    }
+
+    /*
+     * @return The feature the installation of which was the root cause
+     * of this pushing of the ConfigFileInfo.
+     * Example:
+     * A -> B -> C, ConfigFileInfo Foo is attached to C.
+     * feature:install A
+     * this A is the 'Cause' of the installation of Foo.
+     */
+    public Feature getCauseFeature() {
+        return Iterables.getLast(featureChain);
+    }
+}