Sketching out component configuration model & API.
Added initial cut of implementation.
Finished implementation; ready for merge.

Change-Id: I385181c0591604a5c44986b97fb881eba7e0528e
diff --git a/core/api/src/main/java/org/onosproject/cfg/ComponentConfigEvent.java b/core/api/src/main/java/org/onosproject/cfg/ComponentConfigEvent.java
new file mode 100644
index 0000000..0f5a2ee
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/cfg/ComponentConfigEvent.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfg;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes a component configuration event.
+ */
+public class ComponentConfigEvent extends AbstractEvent<ComponentConfigEvent.Type, String> {
+
+    private final String name;
+    private final String value;
+
+    public enum Type {
+        /**
+         * Signifies that a configuration property has set.
+         */
+        PROPERTY_SET,
+
+        /**
+         * Signifies that a configuration property has been unset.
+         */
+        PROPERTY_UNSET
+    }
+
+    /**
+     * Creates an event of a given type and for the specified app and the
+     * current time.
+     *
+     * @param type          config property event type
+     * @param componentName component name event subject
+     * @param name          config property name
+     * @param value         config property value
+     */
+    public ComponentConfigEvent(Type type, String componentName,
+                                String name, String value) {
+        super(type, componentName);
+        this.name = name;
+        this.value = value;
+    }
+
+    /**
+     * Returns the property name.
+     *
+     * @return property name
+     */
+    public String name() {
+        return name;
+    }
+
+    /**
+     * Returns the property value as a string.
+     *
+     * @return string value
+     */
+    public String value() {
+        return value;
+    }
+
+}
diff --git a/core/api/src/main/java/org/onosproject/cfg/ComponentConfigService.java b/core/api/src/main/java/org/onosproject/cfg/ComponentConfigService.java
new file mode 100644
index 0000000..a311002
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/cfg/ComponentConfigService.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfg;
+
+import java.util.Set;
+
+/**
+ * Service for tracking system-wide configurations for various software components.
+ */
+public interface ComponentConfigService {
+
+    /**
+     * Returns names of all components that have registered their
+     * configuration properties.
+     *
+     * @return set of component names
+     */
+    Set<String> getComponentNames();
+
+    /**
+     * Registers configuration properties for the specified component.
+     *
+     * @param componentClass class of configurable component
+     */
+    void registerProperties(Class<?> componentClass);
+
+    /**
+     * Unregisters configuration properties for the specified component.
+     *
+     * @param componentClass class of configurable component
+     * @param clear          true indicates any settings should be cleared
+     */
+    void unregisterProperties(Class<?> componentClass, boolean clear);
+
+    /**
+     * Returns configuration properties of the named components.
+     *
+     * @param componentName component name
+     * @return set of configuration properties
+     */
+    Set<ConfigProperty> getProperties(String componentName);
+
+    /**
+     * Sets the value of the specified configuration property.
+     *
+     * @param componentName component name
+     * @param name          property name
+     * @param value         new property value
+     */
+    void setProperty(String componentName, String name, String value);
+
+    /**
+     * Clears the value of the specified configuration property thus making
+     * the property take on its default value.
+     *
+     * @param componentName component name
+     * @param name          property name
+     */
+    void unsetProperty(String componentName, String name);
+
+}
diff --git a/core/api/src/main/java/org/onosproject/cfg/ComponentConfigStore.java b/core/api/src/main/java/org/onosproject/cfg/ComponentConfigStore.java
new file mode 100644
index 0000000..05f58a4
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/cfg/ComponentConfigStore.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfg;
+
+import org.onosproject.store.Store;
+
+/**
+ * Service for storing and distributing system-wide configurations for various
+ * software components.
+ */
+public interface ComponentConfigStore
+        extends Store<ComponentConfigEvent, ComponentConfigStoreDelegate> {
+
+    /**
+     * Sets the value of the specified configuration property.
+     *
+     * @param componentName component name
+     * @param name          property name
+     * @param value         new property value
+     */
+    void setProperty(String componentName, String name, String value);
+
+    /**
+     * Clears the value of the specified configuration property thus making
+     * the property take on its default value.
+     *
+     * @param componentName component name
+     * @param name          property name
+     */
+    void unsetProperty(String componentName, String name);
+
+}
diff --git a/core/api/src/main/java/org/onosproject/cfg/ComponentConfigStoreDelegate.java b/core/api/src/main/java/org/onosproject/cfg/ComponentConfigStoreDelegate.java
new file mode 100644
index 0000000..da26278
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/cfg/ComponentConfigStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfg;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Configuration property store delegate abstraction.
+ */
+public interface ComponentConfigStoreDelegate extends StoreDelegate<ComponentConfigEvent> {
+}
diff --git a/core/api/src/main/java/org/onosproject/cfg/ConfigProperty.java b/core/api/src/main/java/org/onosproject/cfg/ConfigProperty.java
new file mode 100644
index 0000000..36cd22b
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/cfg/ConfigProperty.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cfg;
+
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Component configuration property.
+ */
+public final class ConfigProperty {
+
+    private final String name;
+    private final Type type;
+    private final String value;
+    private final String defaultValue;
+    private final String description;
+    private final boolean isSet;
+
+    /**
+     * Representation of the type of property value.
+     */
+    public enum Type {
+        /**
+         * Indicates the value is a string.
+         */
+        STRING,
+
+        /**
+         * Indicates the value is an integer.
+         */
+        INTEGER,
+
+        /**
+         * Indicates the value is a long.
+         */
+        LONG,
+
+        /**
+         * Indicates the value is a float.
+         */
+        FLOAT,
+
+        /**
+         * Indicates the value is a double.
+         */
+        DOUBLE,
+
+        /**
+         * Indicates the value is a boolean.
+         */
+        BOOLEAN
+    }
+
+    /**
+     * Creates a new configuration property with its default value.
+     *
+     * @param name         property name
+     * @param type         value type
+     * @param defaultValue default value as a string
+     * @param description  property description
+     * @return newly defined property
+     */
+    public static ConfigProperty defineProperty(String name, Type type,
+                                                String defaultValue,
+                                                String description) {
+        return new ConfigProperty(name, type, description, defaultValue, defaultValue, false);
+    }
+
+    /**
+     * Creates a new configuration property as a copy of an existing one, but
+     * with a new value.
+     *
+     * @param property property to be changed
+     * @param newValue new value as a string
+     * @return newly updated property
+     */
+    public static ConfigProperty setProperty(ConfigProperty property, String newValue) {
+        return new ConfigProperty(property.name, property.type, property.description,
+                                  property.defaultValue, newValue, true);
+    }
+
+    /**
+     * Creates a new configuration property as a copy of an existing one, but
+     * without a specific value, thus making it take its default value.
+     *
+     * @param property property to be reset
+     * @return newly reset property
+     */
+    public static ConfigProperty resetProperty(ConfigProperty property) {
+        return new ConfigProperty(property.name, property.type, property.description,
+                                  property.defaultValue, property.defaultValue, false);
+    }
+
+    /**
+     * Creates a new configuration property with its default value.
+     *
+     * @param name         property name
+     * @param type         value type
+     * @param defaultValue default value as a string
+     * @param description  property description
+     * @param value        property value
+     * @param isSet        indicates whether the property is set or not
+     */
+    private ConfigProperty(String name, Type type, String description,
+                           String defaultValue, String value, boolean isSet) {
+        this.name = checkNotNull(name, "Property name cannot be null");
+        this.type = checkNotNull(type, "Property type cannot be null");
+        this.description = checkNotNull(description, "Property description cannot be null");
+        this.defaultValue = defaultValue;
+        this.value = value;
+        this.isSet = isSet;
+    }
+
+    /**
+     * Returns the property name.
+     *
+     * @return property name
+     */
+    public String name() {
+        return name;
+    }
+
+    /**
+     * Returns the property type.
+     *
+     * @return property type
+     */
+    public Type type() {
+        return type;
+    }
+
+    /**
+     * Returns the property description.
+     *
+     * @return string value
+     */
+    public String description() {
+        return description;
+    }
+
+    /**
+     * Returns the property default value as a string.
+     *
+     * @return string default value
+     */
+    public String defaultValue() {
+        return defaultValue;
+    }
+
+    /**
+     * Returns the property value as a string.
+     *
+     * @return string value
+     */
+    public String value() {
+        return value;
+    }
+
+    /**
+     * Indicates whether the property is set or whether it assumes its
+     * default value.
+     *
+     * @return true if the property is set
+     */
+    public boolean isSet() {
+        return isSet;
+    }
+
+    /**
+     * Returns the property value as a string.
+     *
+     * @return string value
+     */
+    public String asString() {
+        return value;
+    }
+
+    /**
+     * Returns the property value as an integer.
+     *
+     * @return integer value
+     */
+    public int asInteger() {
+        checkState(type == Type.INTEGER, "Value is not an integer");
+        return Integer.parseInt(value);
+    }
+
+    /**
+     * Returns the property value as a long.
+     *
+     * @return long value
+     */
+    public long asLong() {
+        checkState(type == Type.INTEGER || type == Type.LONG, "Value is not a long or integer");
+        return Long.parseLong(value);
+    }
+
+    /**
+     * Returns the property value as a float.
+     *
+     * @return float value
+     */
+    public float asFloat() {
+        checkState(type == Type.FLOAT, "Value is not a float");
+        return Float.parseFloat(value);
+    }
+
+    /**
+     * Returns the property value as a double.
+     *
+     * @return double value
+     */
+    public double asDouble() {
+        checkState(type == Type.FLOAT || type == Type.DOUBLE, "Value is not a float or double");
+        return Double.parseDouble(value);
+    }
+
+    /**
+     * Returns the property value as a boolean.
+     *
+     * @return string value
+     */
+    public boolean asBoolean() {
+        checkState(type == Type.BOOLEAN, "Value is not a boolean");
+        return Boolean.parseBoolean(value);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * Equality is considered only on the basis of property name.
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof ConfigProperty) {
+            final ConfigProperty other = (ConfigProperty) obj;
+            return Objects.equals(this.name, other.name);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+                .add("name", name)
+                .add("type", type)
+                .add("value", value)
+                .add("defaultValue", defaultValue)
+                .add("description", description)
+                .add("isSet", isSet)
+                .toString();
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/cfg/package-info.java b/core/api/src/main/java/org/onosproject/cfg/package-info.java
new file mode 100644
index 0000000..99fd5be
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/cfg/package-info.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Set of abstractions for centrally managing component configurations.
+ * Configuration properties are registered for a component resource which is
+ * auto-generated during the build process based on information specified in
+ * the @Property annotations. This provides an overall inventory of all
+ * supported component configurations.
+ */
+package org.onosproject.cfg;
\ No newline at end of file