Currently, SADIS caches Subscriber records defining Subscriber Tagging requirements, authentication data and other service flow information. The OF Flow Table ID used to reference a Technology Profile for a given Subscriber needs to be able to be added to the Subscriber Record and a Reference to an Upstream and Downstream OF Meter also supported.

Change-Id: I2951d777e557c5354eb7ef0d9d8645c22b763740
diff --git a/api/src/main/java/org/opencord/sadis/BandwidthProfileInformation.java b/api/src/main/java/org/opencord/sadis/BandwidthProfileInformation.java
new file mode 100644
index 0000000..94835b9
--- /dev/null
+++ b/api/src/main/java/org/opencord/sadis/BandwidthProfileInformation.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.opencord.sadis;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.Objects;
+
+/**
+ * Represents bandwidth profile details such as PIR, CIR, AIR values.
+ */
+public class BandwidthProfileInformation extends BaseInformation {
+
+    @JsonProperty(value = "cir")
+    long committedInformationRate;
+
+    @JsonProperty(value = "cbs")
+    Long committedBurstSize;
+
+    @JsonProperty(value = "eir")
+    long exceededInformationRate;
+
+    @JsonProperty(value = "ebs")
+    Long exceededBurstSize;
+
+    @JsonProperty(value = "air")
+    long assuredInformationRate;
+
+    //note that: the burst size of assured bandwidth will be always 0
+    //the rate information must be in Kbps and burst must be in Kbits
+
+    protected BandwidthProfileInformation() {
+    }
+
+    public final long committedInformationRate() {
+        return this.committedInformationRate;
+    }
+
+    public final void setCommittedInformationRate(final long committedInformationRate) {
+        this.committedInformationRate = committedInformationRate;
+    }
+
+    public final Long committedBurstSize() {
+        return this.committedBurstSize;
+    }
+
+    public final void setCommittedBurstSize(final Long committedBurstSize) {
+        this.committedBurstSize = committedBurstSize;
+    }
+
+    public final long exceededInformationRate() {
+        return this.exceededInformationRate;
+    }
+
+    public final void setExceededInformationRate(final long exceededInformationRate) {
+        this.exceededInformationRate = exceededInformationRate;
+    }
+
+    public final Long exceededBurstSize() {
+        return this.exceededBurstSize;
+    }
+
+    public final void setExceededBurstSize(final Long exceededBurstSize) {
+        this.exceededBurstSize = exceededBurstSize;
+    }
+
+    public final long assuredInformationRate() {
+        return this.assuredInformationRate;
+    }
+
+    public final void setAssuredInformationRate(final long assuredInformationRate) {
+        this.assuredInformationRate = assuredInformationRate;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        BandwidthProfileInformation that = (BandwidthProfileInformation) o;
+        return committedInformationRate == that.committedInformationRate &&
+                exceededInformationRate == that.exceededInformationRate &&
+                assuredInformationRate == that.assuredInformationRate &&
+                Objects.equals(committedBurstSize, that.committedBurstSize) &&
+                Objects.equals(exceededBurstSize, that.exceededBurstSize);
+    }
+
+    @Override
+    public int hashCode() {
+
+        return Objects.hash(committedInformationRate, committedBurstSize, exceededInformationRate, exceededBurstSize,
+                assuredInformationRate);
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("BandwidthProfileInformation{");
+        sb.append("id=").append(id);
+        sb.append(", committedInformationRate=").append(committedInformationRate);
+        sb.append(", committedBurstSize=").append(committedBurstSize);
+        sb.append(", exceededInformationRate=").append(exceededInformationRate);
+        sb.append(", exceededBurstSize=").append(exceededBurstSize);
+        sb.append(", assuredInformationRate=").append(assuredInformationRate);
+        sb.append('}');
+        return sb.toString();
+    }
+}
diff --git a/api/src/main/java/org/opencord/sadis/BaseConfig.java b/api/src/main/java/org/opencord/sadis/BaseConfig.java
new file mode 100644
index 0000000..75951f7
--- /dev/null
+++ b/api/src/main/java/org/opencord/sadis/BaseConfig.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.opencord.sadis;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.config.Config;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.time.Duration;
+import java.util.List;
+
+public abstract class BaseConfig<T extends BaseInformation> extends Config<ApplicationId> {
+
+    private final Logger log = LoggerFactory.getLogger(this.getClass());
+
+    protected static final String INTEGRATION = "integration";
+    protected static final String CACHE = "cache";
+    protected static final String CACHE_SIZE = "maxsize";
+    protected static final String CACHE_TTL = "ttl";
+    protected static final String URL = "url";
+    protected static final String ENTRIES = "entries";
+    protected static final String DEFAULT_CACHE_TTL = "PT0S";
+    protected static final String ID_SUB_PATTERN = "%s";
+
+    /**
+     * Returns Integration URL.
+     *
+     * @return configured URL or null
+     * @throws MalformedURLException specified URL not valid
+     */
+    public final URL getUrl() throws MalformedURLException {
+        final JsonNode integration = this.object.path(INTEGRATION);
+        if (integration.isMissingNode()) {
+            return null;
+        }
+
+        final JsonNode url = integration.path(URL);
+        if (url.isMissingNode()) {
+            return null;
+        }
+        StringBuilder buf = new StringBuilder(ID_SUB_PATTERN);
+        if (!url.asText().contains(buf)) {
+            log.error("Error in url, missing {}", ID_SUB_PATTERN);
+            return null;
+        }
+        return new URL(url.asText());
+    }
+
+    /**
+     * Returns Cache Maximum Size.
+     *
+     * @return configured cache max size or -1
+     */
+    public final int getCacheMaxSize() {
+        final JsonNode integration = this.object.path(INTEGRATION);
+        if (integration.isMissingNode()) {
+            return -1;
+        }
+
+        final JsonNode cache = integration.path(CACHE);
+        if (cache.isMissingNode()) {
+            return -1;
+        }
+
+        return cache.path(CACHE_SIZE).asInt(-1);
+    }
+
+    public final Duration getCacheTtl() {
+        final JsonNode integration = this.object.path(INTEGRATION);
+        if (integration.isMissingNode()) {
+            return Duration.parse(DEFAULT_CACHE_TTL);
+        }
+
+        final JsonNode cache = integration.path(CACHE);
+        if (cache.isMissingNode()) {
+            return Duration.parse(DEFAULT_CACHE_TTL);
+        }
+
+        return Duration.parse(cache.path(CACHE_TTL).asText(DEFAULT_CACHE_TTL));
+    }
+
+    public abstract List<T> getEntries();
+
+}
diff --git a/api/src/main/java/org/opencord/sadis/BaseInformation.java b/api/src/main/java/org/opencord/sadis/BaseInformation.java
new file mode 100644
index 0000000..d8d8876
--- /dev/null
+++ b/api/src/main/java/org/opencord/sadis/BaseInformation.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.opencord.sadis;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class BaseInformation {
+
+    @JsonProperty(value = "id")
+    String id;
+
+    public final String id() {
+        return this.id;
+    }
+
+    public final void setId(final String id) {
+        this.id = id;
+    }
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/opencord/sadis/SubscriberAndDeviceInformationService.java b/api/src/main/java/org/opencord/sadis/BaseInformationService.java
similarity index 65%
rename from api/src/main/java/org/opencord/sadis/SubscriberAndDeviceInformationService.java
rename to api/src/main/java/org/opencord/sadis/BaseInformationService.java
index be0a42e..9d2896b 100644
--- a/api/src/main/java/org/opencord/sadis/SubscriberAndDeviceInformationService.java
+++ b/api/src/main/java/org/opencord/sadis/BaseInformationService.java
@@ -15,39 +15,35 @@
  */
 package org.opencord.sadis;
 
-/**
- * Subscriber And Device Information Service.
- */
-public interface SubscriberAndDeviceInformationService {
+public interface BaseInformationService<T extends BaseInformation> {
 
     /**
      * Removes all cached entries.
      */
-    public void invalidateAll();
+    void invalidateAll();
 
     /**
-      * Removes the information associated with the given ID.
-      * @param id
-      *           key to information
-      */
-    public void invalidateId(String id);
+     * Removes the information associated with the given ID.
+     *
+     * @param id key to information
+     */
+    void invalidateId(String id);
 
     /**
      * Return the information associated with the given ID.
      *
-     * @param id
-     *            key to information
+     * @param id key to information
      * @return information associated with ID, if available, else null
      */
-    public SubscriberAndDeviceInformation get(String id);
+    T get(String id);
 
     /**
      * Return the information associated with the given ID from the cache.
      *
-     * @param id
-     *            key to information
+     * @param id key to information
      * @return information associated with ID, if available in the cache, else null
      */
-    public SubscriberAndDeviceInformation getfromCache(String id);
+    T getfromCache(String id);
+
 
 }
diff --git a/api/src/main/java/org/opencord/sadis/SadisService.java b/api/src/main/java/org/opencord/sadis/SadisService.java
new file mode 100644
index 0000000..ff98273
--- /dev/null
+++ b/api/src/main/java/org/opencord/sadis/SadisService.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.opencord.sadis;
+
+/**
+ * Subscriber And Device Information Service.
+ */
+public interface SadisService {
+
+
+    /**
+     * Gets the subscriber service.
+     *
+     * @return the service related to the subscribers and access devices
+     */
+    BaseInformationService<SubscriberAndDeviceInformation> getSubscriberInfoService();
+
+    /**
+     * Gets the bandwidth profile service.
+     *
+     * @return the service related to bandwidth profiles
+     */
+    BaseInformationService<BandwidthProfileInformation> getBandwidthProfileService();
+
+}
diff --git a/api/src/main/java/org/opencord/sadis/SubscriberAndDeviceInformation.java b/api/src/main/java/org/opencord/sadis/SubscriberAndDeviceInformation.java
index 6b64ce7..28540a0 100644
--- a/api/src/main/java/org/opencord/sadis/SubscriberAndDeviceInformation.java
+++ b/api/src/main/java/org/opencord/sadis/SubscriberAndDeviceInformation.java
@@ -24,10 +24,8 @@
 /**
  * Represents a unit of information about a subscriber or access device.
  */
-public class SubscriberAndDeviceInformation {
+public class SubscriberAndDeviceInformation extends BaseInformation {
 
-    @JsonProperty(value = "id")
-    String id;
 
     @JsonProperty(value = "sTag")
     VlanId sTag;
@@ -59,17 +57,18 @@
     @JsonProperty(value = "remoteId")
     String remoteId;
 
+    @JsonProperty(value = "technologyProfileId")
+    int technologyProfileId = -1;
+
+    @JsonProperty(value = "upstreamBandwidthProfile")
+    String upstreamBandwidthProfile;
+
+    @JsonProperty(value = "downstreamBandwidthProfile")
+    String downstreamBandwidthProfile;
+
     protected SubscriberAndDeviceInformation() {
     }
 
-    public final String id() {
-        return this.id;
-    }
-
-    public final void setId(final String id) {
-        this.id = id;
-    }
-
     public final VlanId sTag() {
         return this.sTag;
     }
@@ -150,6 +149,30 @@
         this.remoteId = remoteId;
     }
 
+    public final int technologyProfileId() {
+        return this.technologyProfileId;
+    }
+
+    public final void setTechnologyProfileId(final int technologyProfileId) {
+        this.technologyProfileId = technologyProfileId;
+    }
+
+    public final String upstreamBandwidthProfile() {
+        return this.upstreamBandwidthProfile;
+    }
+
+    public final void setUpstreamBandwidthProfile(final String upstreamBandwidthProfile) {
+        this.upstreamBandwidthProfile = upstreamBandwidthProfile;
+    }
+
+    public final String downstreamBandwidthProfile() {
+        return this.downstreamBandwidthProfile;
+    }
+
+    public final void setDownstreamBandwidthProfile(final String downstreamBandwidthProfile) {
+        this.downstreamBandwidthProfile = downstreamBandwidthProfile;
+    }
+
     /*
      * (non-Javadoc)
      *
@@ -170,6 +193,11 @@
         result = prime * result + (this.nasId == null ? 0 : this.nasId.hashCode());
         result = prime + result + (this.circuitId == null ? 0 : this.circuitId.hashCode());
         result = prime + result + (this.remoteId == null ? 0 : this.remoteId.hashCode());
+        result = prime + result + this.technologyProfileId;
+        result = prime + result +
+                (this.upstreamBandwidthProfile == null ? 0 : this.upstreamBandwidthProfile.hashCode());
+        result = prime + result +
+                (this.downstreamBandwidthProfile == null ? 0 : this.downstreamBandwidthProfile.hashCode());
         return result;
     }
 
@@ -259,6 +287,23 @@
         } else if (!this.remoteId.equals(other.remoteId)) {
             return false;
         }
+        if (this.technologyProfileId != other.technologyProfileId) {
+            return false;
+        }
+        if (this.upstreamBandwidthProfile == null) {
+            if (other.upstreamBandwidthProfile != null) {
+                return false;
+            }
+        } else if (!this.upstreamBandwidthProfile.equals(other.upstreamBandwidthProfile)) {
+            return false;
+        }
+        if (this.downstreamBandwidthProfile == null) {
+            if (other.downstreamBandwidthProfile != null) {
+                return false;
+            }
+        } else if (!this.downstreamBandwidthProfile.equals(other.downstreamBandwidthProfile)) {
+            return false;
+        }
         return true;
     }
 
@@ -293,6 +338,12 @@
         buf.append(this.circuitId);
         buf.append(",remoteId:");
         buf.append(this.remoteId);
+        buf.append(",technologyProfileId:");
+        buf.append(this.technologyProfileId);
+        buf.append(",upstreamBandwidthProfile:");
+        buf.append(this.upstreamBandwidthProfile);
+        buf.append(",downstreamBandwidthProfile:");
+        buf.append(this.downstreamBandwidthProfile);
         buf.append(']');
 
         return buf.toString();