You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by da...@apache.org on 2018/01/27 00:41:41 UTC

[6/7] atlas git commit: ATLAS-1095:final code drop for OCF

http://git-wip-us.apache.org/repos/asf/atlas/blob/cbfdd7fc/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/OCFErrorCode.java
----------------------------------------------------------------------
diff --git a/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/OCFErrorCode.java b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/OCFErrorCode.java
new file mode 100644
index 0000000..e6fad57
--- /dev/null
+++ b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/OCFErrorCode.java
@@ -0,0 +1,270 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.apache.atlas.ocf.ffdc;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.MessageFormat;
+import java.util.Arrays;
+
+/**
+ * The OCF error code is used to define first failure data capture (FFDC) for errors that occur when working with
+ * OCF Connectors.  It is used in conjunction with all OCF Exceptions, both Checked and Runtime (unchecked).
+ *
+ * The 5 fields in the enum are:
+ * <ul>
+ *     <li>HTTP Error Code - for translating between REST and JAVA - Typically the numbers used are:</li>
+ *     <li><ul>
+ *         <li>500 - internal error</li>
+ *         <li>400 - invalid parameters</li>
+ *         <li>404 - not found</li>
+ *         <li>409 - data conflict errors - eg item already defined</li>
+ *     </ul></li>
+ *     <li>Error Message Id - to uniquely identify the message</li>
+ *     <li>Error Message Text - includes placeholder to allow additional values to be captured</li>
+ *     <li>SystemAction - describes the result of the error</li>
+ *     <li>UserAction - describes how a user should correct the error</li>
+ * </ul>
+ */
+public enum OCFErrorCode
+{
+    NULL_CONNECTION(400, "OCF-CONNECTION-400-001 ",
+            "Null connection object passed on request for new connector instance",
+            "The system is unable to create the requested connector instance without the connection information that describes which type of connector is required.",
+            "Recode call to system to include a correctly formatted connection object and retry the request."),
+    UNNAMED_CONNECTION(400, "OCF-CONNECTION-400-002 ",
+            "Unnamed connection object passed to requested action {0}",
+            "The system is unable to perform the requested action without a connection name.",
+            "Update connection configuration to include a value for at least one of the following name properties: qualifiedName, displayName, guid. Then retry the request."),
+    NULL_CONNECTOR_TYPE(400, "OCF-CONNECTION-400-003 ",
+            "Null connectorType property passed in connection {0}",
+            "The system is unable to create the requested connector instance without information on the type of connection required.",
+            "Update the connection configuration to include a valid connectorType definition.  Then retry the request."),
+    NULL_CONNECTOR_PROVIDER(400, "OCF-CONNECTION-400-004 ",
+            "Null Connector Provider passed in connection {0}",
+            "The system is unable to create the requested connector instance without information on the type of connection required.",
+            "Update the connection configuration to include a valid Java class name for the connector provider in the connectorProviderClassName property of the connection's connectorType. Then retry the request."),
+    UNKNOWN_CONNECTOR_PROVIDER(400, "OCF-CONNECTION-400-005 ",
+            "Unknown Connector Provider class {0} passed in connection {1}",
+            "The system is unable to create the requested connector instance because the Connector Provider's class is not known to the JVM.  This may be because the Connector Provider's jar is not installed in the local JVM or the wrong Java class name has been configured in the connection. ",
+            "Verify that the Connector Provider and Connector jar files are properly configured in the process.  Update the connection configuration to include a valid Java class name for the connector provider in the connectorProviderClassName property of the connection's connectorType. Then retry the request."),
+    NOT_CONNECTOR_PROVIDER(400, "OCF-CONNECTION-400-006 ",
+            "Class {0} passed in connection {1} is not a Connector Provider",
+            "The system is unable to create the requested connector instance because the Connector Provider's class does not implement org.apache.atlas.ocf.ConnectorProvider. ",
+            "Update the connection configuration to include a valid Java class name for the connector provider in the connectorProviderClassName property of the connection's connectorType. Then retry the request."),
+    INCOMPLETE_CONNECTOR_PROVIDER(400, "OCF-CONNECTION-400-007 ",
+            "Unable to load Connector Provider class {0} passed in connection {1}",
+            "The system is unable to create the requested connector instance because the Connector Provider's class is failing to load in the JVM.  This has resulted in an exception in the class loader.",
+            "Verify that the Connector Provider and Connector jar files are properly configured in the process.  Update the connection configuration to include a valid Java class name for the connector provider in the connectorProviderClassName property of the connection's connectorType. Then retry the request."),
+    INVALID_CONNECTOR_PROVIDER(400, "OCF-CONNECTION-400-008 ",
+            "Invalid Connector Provider class {0} passed in connection {1}",
+            "The system is unable to create the requested connector instance because the Connector Provider's class is failing to initialize in the JVM.  This has resulted in an exception in the class loader.",
+            "Verify that the Connector Provider and Connector jar files are properly configured in the process.  Update the connection configuration to include a valid Java class name for the connector provider in the connectorProviderClassName property of the connection's connectorType. Then retry the request."),
+    NULL_ENDPOINT_IN_CONNECTION(400, "OCF-CONNECTION-400-009 ",
+            "Null endpoint detected in connection {0}",
+            "The system is unable to initialize the requested connector because the endpoint information in the connection is missing.",
+            "Add the endpoint information into the connection object and retry the request."),
+    MALFORMED_ENDPOINT(400, "OCF-CONNECTION-400-010 ",
+            "The endpoint attribute {0} in connection {1} is set to \"{2}\" which is invalid",
+            "The system is unable to initialize the requested connector because the endpoint information in the connection is not formatted correctly for this type of connection.",
+            "Correct the endpoint information into the connection object and retry the request."),
+    NULL_PROPERTY_NAME(400, "OCF-PROPERTIES-400-011 ",
+            "Null property name passed to entity {0} of type {1}",
+            "A request to set an additional property failed because the property name passed was null",
+            "Recode the call to the property object with a valid property name and retry."),
+    INVALID_PROPERTY_NAMES(400, "OCF-PROPERTIES-400-012 ",
+            "Non-string property names stored in entity {0} of type {1}",
+            "A request to retrieve additional properties failed because the properties have become corrupted.",
+            "Debug the calls to the properties object."),
+    NULL_SECURED_PROPERTY_NAME(400, "OCF-CONNECTION-400-013 ",
+            "Null securedProperty name passed to connection {0})",
+            "A request to set a secured property failed because the property name passed was null",
+            "Recode the call to the connection object with a valid property name and retry."),
+    NO_MORE_ELEMENTS(400, "OCF-PROPERTIES-400-014 ",
+            "No more elements in {0} iterator for entity {1} of type {2}",
+            "A caller stepping through an iterator has requested more elements when there are none left.",
+            "Recode the caller to use the hasNext() method to check for more elements before calling next() and then retry."),
+    NO_ITERATOR(400, "OCF-PROPERTIES-400-015 ",
+            "No type-specific iterator for {0} paging iterator for entity {1} of type {2}",
+            "A caller requesting a paging iterator has not supplied a type-specific iterator in the constructor.",
+            "Recode the caller to use the hasNext() method to check for more elements before calling next() and then retry."),
+    NULL_CLASSIFICATION_NAME(400, "OCF-PROPERTIES-400-016 ",
+            "No classification name for entity {0} of type {1}",
+            "A classification with a null name is assigned to an entity.   This value should come from a metadata repository, and always be filled in.",
+            "Look for other error messages to identify the source of the problem.  Identify the metadata repository where the asset came from.  Correct the cause of the error and then retry."),
+    NULL_TAG_NAME(400, "OCF-PROPERTIES-400-017 ",
+            "No tag name for entity {0} of type {1}",
+            "A tag with a null name is assigned to an entity.   This value should come from a metadata repository, and always be filled in.",
+            "Look for other error messages to identify the source of the problem.  Identify the metadata repository where the asset came from.  Correct the cause of the error and then retry."),
+    UNKNOWN_ENDPOINT(404, "OCF-CONNECTOR-404-001 ",
+            "Endpoint {0} in connection {1} for connector instance {2} is either unknown or unavailable",
+            "The requested action is not able to complete because the remote endpoint where the assets are located is not responding.  It may be unavailable or unknown.",
+            "Verify that the endpoint information is correct and the server that supports it is operational, then retry the request."),
+    PROPERTIES_NOT_AVAILABLE(404, "OCF-PROPERTIES-404-002 ",
+            "Exception with error message \"{0}\" was returned to object {1} resulted from a request for connected asset properties",
+            "The requested action is not able to complete which may mean that the server is not able to return all of the properties associated with the asset.",
+                     "Verify that the endpoint information is correct and the server that supports it is operational, then retry the request."),
+    CAUGHT_EXCEPTION(500, "OCF-CONNECTION-500-001 ",
+            "OCF method detected an unexpected exception",
+            "The system detected an error during connector processing.",
+            "The root cause of the error is captured in previous reported messages."),
+    CAUGHT_EXCEPTION_WITHMSG(500, "OCF-CONNECTION-500-002 ",
+            "OCF method {0} detected an unexpected exception, message was {1}",
+            "The system detected an error during connector processing.",
+            "The root cause of the error is captured in previous reported messages."),
+    NOT_IMPLEMENTED(500, "OCF-CONNECTION-500-003 ",
+            "OCF method {0} not yet implemented",
+            "The system is not able to process a request because a feature is not yet implemented.",
+            "Contact your support organization for help in discovering a workaround, fix or upgrade to the system."),
+    UNKNOWN_ERROR(500, "OCF-CONNECTION-500-004 ",
+            "Connection error detected",
+            "The system detected an error during connection processing.",
+            "The root cause of the error is captured in previous reported messages."),
+    INTERNAL_ERROR(500, "OCF-CONNECTION-500-005 ",
+            "Internal error in OCF method {0}",
+            "The system detected an error during connection processing.",
+            "The root cause of the error is captured in previous reported messages."),
+    NULL_CONNECTOR_CLASS(500, "OCF-CONNECTOR-500-006 ",
+            "The class name for the connector is not set up",
+            "The system is unable to create the requested connector instance without the name of the Java class for the connector.",
+            "Update the implementation of the connector provider to ensure the connector's java class is intitialized correctly"),
+    UNKNOWN_CONNECTOR(500,"OCF-CONNECTOR-500-007 ",
+            "Unknown Connector Java class {0}",
+            "The system is unable to create the requested connector instance because the Connector's class is not known to the JVM.  This may be because the Connector Provider's jar is not installed in the local JVM or the wrong Java class name has been configured in the connection. ",
+            "Verify that the Connector Provider and Connector jar files are properly configured in the process.  Update the connection configuration to include a valid Java class name for the connector provider in the connectorProviderClassName property of the connection's connectorType. Then retry the request."),
+    NOT_CONNECTOR(500,"OCF-CONNECTOR-500-008 ",
+            "Java class {0} is not a Connector",
+            "The system is unable to create the requested connector instance because the Connector's class does not implement org.apache.atlas.ocf.Connector. ",
+            "Update the connection configuration to include a valid Java class name for the connector provider in the connectorProviderClassName property of the connection's connectorType. Then retry the request."),
+    INCOMPLETE_CONNECTOR(500,"OCF-CONNECTOR-500-009 ",
+            "Unable to load Connector Java class {0}",
+            "The system is unable to create the requested connector instance because the Connector's class is failing to load in the JVM.  This has resulted in an exception in the class loader.",
+            "Verify that the Connector Provider and Connector jar files are properly configured in the process. Then retry the request."),
+    INVALID_CONNECTOR(500, "OCF-CONNECTION-500-010 ",
+            "Invalid Connector class {0}",
+            "The system is unable to create the requested connector instance because the Connector's class is failing to initialize in the JVM.  This has resulted in an exception in the class loader.",
+            "Verify that the Connector Provider and Connector jar files are properly configured in the process.  Then retry the request."),
+    NULL_CONNECTOR(500, "OCF-CONNECTION-500-011 ",
+            "Connector Provider {0} returned a null connector instance for connection {1}",
+            "The system detected an error during connector processing and was unable to create a connector.",
+            "The root cause of the error is captured in previous reported messages.");
+
+    private int    httpErrorCode;
+    private String errorMessageId;
+    private String errorMessage;
+    private String systemAction;
+    private String userAction;
+
+    private static final Logger log = LoggerFactory.getLogger(OCFErrorCode.class);
+
+
+    /**
+     * The constructor for OCFErrorCode expects to be passed one of the enumeration rows defined in
+     * OCFErrorCode above.   For example:
+     *
+     *     OCFErrorCode   errorCode = OCFErrorCode.UNKNOWN_ENDPOINT;
+     *
+     * This will expand out to the 5 parameters shown below.
+     *
+     * @param httpErrorCode - error code to use over REST calls
+     * @param errorMessageId - unique Id for the message
+     * @param errorMessage - text for the message
+     * @param systemAction - description of the action taken by the system when the error condition happened
+     * @param userAction - instructions for resolving the error
+     */
+    OCFErrorCode(int  httpErrorCode, String errorMessageId, String errorMessage, String systemAction, String userAction)
+    {
+        this.httpErrorCode = httpErrorCode;
+        this.errorMessageId = errorMessageId;
+        this.errorMessage = errorMessage;
+        this.systemAction = systemAction;
+        this.userAction = userAction;
+    }
+
+
+    public int getHTTPErrorCode()
+    {
+        return httpErrorCode;
+    }
+
+
+    /**
+     * Returns the unique identifier for the error message.
+     *
+     * @return errorMessageId
+     */
+    public String getErrorMessageId()
+    {
+        return errorMessageId;
+    }
+
+
+    /**
+     * Returns the error message with placeholders for specific details.
+     *
+     * @return errorMessage (unformatted)
+     */
+    public String getUnformattedErrorMessage()
+    {
+        return errorMessage;
+    }
+
+
+    /**
+     * Returns the error message with the placeholders filled out with the supplied parameters.
+     *
+     * @param params - strings that plug into the placeholders in the errorMessage
+     * @return errorMessage (formatted with supplied parameters)
+     */
+    public String getFormattedErrorMessage(String... params)
+    {
+        MessageFormat mf = new MessageFormat(errorMessage);
+        String result = mf.format(params);
+
+        if (log.isDebugEnabled())
+        {
+            log.debug(String.format("OCFErrorCode.getMessage(%s): %s", Arrays.toString(params), result));
+        }
+
+        return result;
+    }
+
+
+    /**
+     * Returns a description of the action taken by the system when the condition that caused this exception was
+     * detected.
+     *
+     * @return systemAction
+     */
+    public String getSystemAction()
+    {
+        return systemAction;
+    }
+
+
+    /**
+     * Returns instructions of how to resolve the issue reported in this exception.
+     *
+     * @return userAction
+     */
+    public String getUserAction()
+    {
+        return userAction;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/cbfdd7fc/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/OCFRuntimeException.java
----------------------------------------------------------------------
diff --git a/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/OCFRuntimeException.java b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/OCFRuntimeException.java
new file mode 100644
index 0000000..3d66271
--- /dev/null
+++ b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/OCFRuntimeException.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.apache.atlas.ocf.ffdc;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.UUID;
+
+/**
+ * OCFRuntimeException is used for all runtime exceptions generated by the OCF.  The OCFErrorCode provides
+ * first failure data capture information for this exception, although this information can also be provided
+ * using custom values.
+ */
+public class OCFRuntimeException extends RuntimeException
+{
+    private static final int      hashCode = UUID.randomUUID().hashCode();
+
+
+    /*
+     * These default values are only seen if this exception is initialized using one of its superclass constructors.
+     */
+    private int       reportedHTTPCode = 500;
+    private String    reportingClassName = "<Unknown>";
+    private String    reportingActionDescription = "<Unknown>";
+    private String    reportedErrorMessage = "<Unknown>";
+    private String    reportedSystemAction = "<Unknown>";
+    private String    reportedUserAction = "<Unknown>";
+    private Throwable reportedCaughtException = null;
+
+    private static final Logger log = LoggerFactory.getLogger(OCFRuntimeException.class);
+
+    /**
+     * This is the typical constructor used for creating an OCFRuntimeException.
+     *
+     * @param httpCode - http response code to use if this exception flows over a REST call
+     * @param className - name of class reporting error
+     * @param actionDescription - description of function it was performing when error detected
+     * @param errorMessage - description of error
+     * @param systemAction - actions of the system as a result of the error
+     * @param userAction - instructions for correcting the error
+     */
+    public OCFRuntimeException(int  httpCode, String className, String  actionDescription, String errorMessage, String systemAction, String userAction)
+    {
+        super(errorMessage);
+        this.reportedHTTPCode = httpCode;
+        this.reportingClassName = className;
+        this.reportingActionDescription = actionDescription;
+        this.reportedErrorMessage = errorMessage;
+        this.reportedSystemAction = systemAction;
+        this.reportedUserAction = userAction;
+
+
+        if (log.isDebugEnabled())
+        {
+            log.debug(httpCode + ", " + className + ", " + actionDescription);
+        }
+    }
+
+
+    /**
+     * This is the constructor used for creating a OCFRuntimeException that results from a previous error/exception
+     * being thrown.
+     *
+     * @param httpCode - http response code to use if this exception flows over a rest call
+     * @param className - name of class reporting error
+     * @param actionDescription - description of function it was performing when error detected
+     * @param errorMessage - description of error
+     * @param systemAction - actions of the system as a result of the error
+     * @param userAction - instructions for correcting the error
+     * @param caughtError - previous error causing this exception
+     */
+    public OCFRuntimeException(int  httpCode, String className, String  actionDescription, String errorMessage, String systemAction, String userAction, Throwable caughtError)
+    {
+        super(errorMessage, caughtError);
+        this.reportedHTTPCode = httpCode;
+        this.reportingClassName = className;
+        this.reportingActionDescription = actionDescription;
+        this.reportedErrorMessage = errorMessage;
+        this.reportedSystemAction = systemAction;
+        this.reportedUserAction = userAction;
+        this.reportedCaughtException = caughtError;
+
+        if (log.isDebugEnabled())
+        {
+            log.debug(httpCode + ", " + className + ", " + actionDescription + ", " + caughtError.toString());
+        }
+    }
+
+
+    /**
+     * Return the HTTP response code to use with this exception.
+     *
+     * @return reportedHTTPCode
+     */
+    public int getReportedHTTPCode()
+    {
+        return reportedHTTPCode;
+    }
+
+    /**
+     * The class that created this exception.
+     *
+     * @return reportingClassName
+     */
+    public String getReportingClassName()
+    {
+        return reportingClassName;
+    }
+
+
+    /**
+     * The type of request that the class was performing when the condition occurred that resulted in this
+     * exception.
+     *
+     * @return reportingActionDescription
+     */
+    public String getReportingActionDescription()
+    {
+        return reportingActionDescription;
+    }
+
+
+    /**
+     * A formatted short description of the cause of the condition that resulted in this exception.
+     *
+     * @return reportedErrorMessage
+     */
+    public String getErrorMessage()
+    {
+        return reportedErrorMessage;
+    }
+
+
+    /**
+     * A description of the action that the system took as a result of the error condition.
+     *
+     * @return reportedSystemAction
+     */
+    public String getReportedSystemAction()
+    {
+        return reportedSystemAction;
+    }
+
+
+    /**
+     * A description of the action necessary to correct the error.
+     *
+     * @return reportedUserAction
+     */
+    public String getReportedUserAction()
+    {
+        return reportedUserAction;
+    }
+
+
+    /**
+     * An exception that was caught and wrapped by this exception.  If a null is returned, then this exception is
+     * newly created and not the result of a previous exception.
+     *
+     * @return reportedCaughtException
+     */
+    public Throwable getReportedCaughtException() { return reportedCaughtException; }
+
+
+    /**
+     * Provide a common implementation of hashCode for all OCF properties objects.  The UUID is unique and
+     * is randomly assigned and so its hashCode is as good as anything to describe the hash code of the properties
+     * object.
+     */
+    public int hashCode()
+    {
+        return hashCode;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/cbfdd7fc/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/PropertyServerException.java
----------------------------------------------------------------------
diff --git a/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/PropertyServerException.java b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/PropertyServerException.java
new file mode 100644
index 0000000..f78eba9
--- /dev/null
+++ b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/PropertyServerException.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.apache.atlas.ocf.ffdc;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * PropertyServerException provides a checked exception for reporting errors when connecting to a
+ * metadata repository to retrieve properties about the connected asset.
+ * It may be a configuration error or temporary outage.  The parameters captured by the constructors
+ * pinpoint the type an cause of the error.
+ */
+public class PropertyServerException extends OCFCheckedExceptionBase
+{
+    private static final Logger log = LoggerFactory.getLogger(PropertyServerException.class);
+
+    /**
+     * This is the typical constructor for creating a PropertyServerException.  It captures the essential details
+     * about the error, where it occurred and how to fix it.
+     *
+     * @param httpCode - code to use on a REST interface
+     * @param className - name of class reporting error
+     * @param actionDescription - description of function it was performing when error detected
+     * @param errorMessage - description of error
+     * @param systemAction - actions of the system as a result of the error
+     * @param userAction - instructions for correcting the error
+     */
+    public PropertyServerException(int httpCode, String className, String  actionDescription, String errorMessage, String systemAction, String userAction)
+    {
+        super(httpCode, className, actionDescription, errorMessage, systemAction, userAction);
+
+        if (log.isDebugEnabled())
+        {
+            log.debug(httpCode + ", " + className + ", " + actionDescription);
+        }
+    }
+
+
+    /**
+     * This constructor is used when an unexpected exception has been caught that needs to be wrapped in a
+     * PropertyServerException in order to add the essential details about the error, where it occurred and
+     * how to fix it.
+     *
+     * @param httpCode -- code to use on a REST interface
+     * @param className - name of class reporting error
+     * @param actionDescription - description of function it was performing when error detected
+     * @param errorMessage - description of error
+     * @param systemAction - actions of the system as a result of the error
+     * @param userAction - instructions for correcting the error
+     * @param caughtError - the exception/error that caused this exception to be raised
+     */
+    public PropertyServerException(int httpCode, String className, String  actionDescription, String errorMessage, String systemAction, String userAction, Throwable caughtError)
+    {
+        super(httpCode, className, actionDescription, errorMessage, systemAction, userAction, caughtError);
+
+        if (log.isDebugEnabled())
+        {
+            log.debug(httpCode + ", " + className + ", " + actionDescription + ", " + caughtError.toString());
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/cbfdd7fc/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/README.md
----------------------------------------------------------------------
diff --git a/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/README.md b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/README.md
new file mode 100644
index 0000000..40e4d12
--- /dev/null
+++ b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/ffdc/README.md
@@ -0,0 +1,46 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements.  See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership.  The ASF licenses this file
+  ~ to you 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.
+  -->
+
+# Open Connector Framework (OCF) FFDC
+
+Package org.apache.atlas.ocf.ffdc provides the first failure data capture
+(FFDC) support for the OCF module.  This includes an error code enum,
+a runtime exception, a base class for checked exceptions plus
+implementation of each specific checked exception.
+
+The error code enum (OCFErrorCode) has an entry for each unique situation
+where an exception is returned.  Each entry defines:
+
+* A unique id for the error
+* An HTTP error code for rest calls
+* A unique message Id
+* Message text with place holders for specific values
+* A description of the cause of the error and system action as a result.
+* A description of how to correct the error (if known)
+
+Each exception (whether a checked or runtime exception) has two constructors.
+
+* The first constructor is used when a new error has been detected.
+* The second constructor is used when another exception has been caught.
+This caught exception is passed on the constructor so it is effectively
+embedded in the OCF exception.
+
+Both constructors take the values from the OCFErrorCode
+enum to define the cause and resolution.  These values are passed
+as individual parameters so that subclasses implemented outside of
+the OCF packages can define their own FFDC values.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/cbfdd7fc/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AdditionalProperties.java
----------------------------------------------------------------------
diff --git a/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AdditionalProperties.java b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AdditionalProperties.java
new file mode 100644
index 0000000..55b6c1c
--- /dev/null
+++ b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AdditionalProperties.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.apache.atlas.ocf.properties;
+
+import java.util.*;
+
+
+/**
+ * The AdditionalProperties class provides support for arbitrary properties to be added to a properties object.
+ * It wraps a java.util.Map map object built around HashMap.
+ */
+public class AdditionalProperties extends AssetPropertyBase
+{
+    private Map<String,Object>  additionalProperties = new HashMap<>();
+
+
+    /**
+     * Constructor for a new set of additional properties that are not connected either directly or indirectly to an asset.
+     *
+     * @param additionalProperties - map of properties for the metadata element.
+     */
+    public AdditionalProperties(Map<String,Object>  additionalProperties)
+    {
+        this(null, additionalProperties);
+    }
+
+
+    /**
+     * Constructor for a new set of additional properties that are connected either directly or indirectly to an asset.
+     *
+     * @param parentAsset - description of the asset that these additional properties are attached to.
+     * @param additionalProperties - map of properties for the metadata element.
+     */
+    public AdditionalProperties(AssetDescriptor     parentAsset,
+                                Map<String,Object>  additionalProperties)
+    {
+        super(parentAsset);
+
+        if (additionalProperties != null)
+        {
+            this.additionalProperties = new HashMap<>(additionalProperties);
+        }
+    }
+
+
+    /**
+     * Copy/clone Constructor for additional properties that are not connected to an asset.
+     *
+     * @param templateProperties - template object to copy.
+     */
+    public AdditionalProperties(AdditionalProperties templateProperties)
+    {
+        this(null, templateProperties);
+    }
+
+
+    /**
+     * Copy/clone Constructor for additional properties that are connected to an asset.
+     *
+     * @param parentAsset - description of the asset that these additional properties are attached to.
+     * @param templateProperties - template object to copy.
+     */
+    public AdditionalProperties(AssetDescriptor   parentAsset, AdditionalProperties templateProperties)
+    {
+        super(parentAsset, templateProperties);
+
+        /*
+         * An empty properties object is created in the private variable declaration so nothing to do.
+         */
+        if (templateProperties != null)
+        {
+            /*
+             * Process templateProperties if they are not null
+             */
+            Iterator<String> propertyNames = templateProperties.getPropertyNames();
+
+            if (propertyNames != null)
+            {
+                while (propertyNames.hasNext())
+                {
+                    String newPropertyName = propertyNames.next();
+                    Object newPropertyValue = templateProperties.getProperty(newPropertyName);
+
+                    additionalProperties.put(newPropertyName, newPropertyValue);
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Returns a list of the additional stored properties for the element.
+     * If no stored properties are present then null is returned.
+     *
+     * @return list of additional properties
+     */
+    public Iterator<String> getPropertyNames()
+    {
+        return additionalProperties.keySet().iterator();
+    }
+
+
+    /**
+     * Returns the requested additional stored property for the element.
+     * If no stored property with that name is present then null is returned.
+     *
+     * @param name - String name of the property to return.
+     * @return requested property value.
+     */
+    public Object getProperty(String name)
+    {
+        return additionalProperties.get(name);
+    }
+
+
+    /**
+     * Test whether the supplied object is equal to this object.
+     *
+     * @param testObject - object to test
+     * @return boolean indicating if the supplied object represents the same content as this object.
+     */
+    @Override
+    public boolean equals(Object testObject)
+    {
+        if (this == testObject)
+        {
+            return true;
+        }
+        if (testObject == null || getClass() != testObject.getClass())
+        {
+            return false;
+        }
+
+        AdditionalProperties that = (AdditionalProperties) testObject;
+
+        return additionalProperties != null ? additionalProperties.equals(that.additionalProperties) : that.additionalProperties == null;
+    }
+
+
+    /**
+     * Standard toString method.
+     *
+     * @return print out of variables in a JSON-style
+     */
+    @Override
+    public String toString()
+    {
+        return "AdditionalProperties{" +
+                "additionalProperties=" + additionalProperties +
+                '}';
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/cbfdd7fc/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/Annotation.java
----------------------------------------------------------------------
diff --git a/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/Annotation.java b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/Annotation.java
new file mode 100644
index 0000000..c9394a4
--- /dev/null
+++ b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/Annotation.java
@@ -0,0 +1,377 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.apache.atlas.ocf.properties;
+
+import java.util.Date;
+
+/**
+ * An annotation describes the results of an analysis undertaken by an Open Discovery Framework (ODF) discovery service.
+ * It describes when the analysis happened, the type of analysis and the results.
+ */
+public class Annotation extends ElementHeader
+{
+    /*
+     * Details from the AnnotationReport entity
+     */
+    private String               reportName = null;
+    private String               reportDescription = null;
+    private Date                 creationDate = null;
+    private AdditionalProperties analysisParameters = null;
+
+    /*
+     * Details from the Annotation entity itself
+     */
+    private String               annotationType = null;
+    private String               summary = null;
+    private int                  confidenceLevel = 0;
+    private String               expression = null;
+    private String               explanation = null;
+    private String               analysisStep = null;
+    private String               jsonProperties = null;
+    private AnnotationStatus     annotationStatus = null;
+
+    /*
+     * Details from the latest AnnotationReview entity.
+     */
+    private Date                 reviewDate = null;
+    private String               steward = null;
+    private String               reviewComment = null;
+
+    /*
+     * Additional properties added directly to the Annotation entity and supported by
+     * the sub-types of Annotation.
+     */
+    private AdditionalProperties  additionalProperties = null;
+
+
+    /**
+     * Typical Constructor
+     *
+     * @param parentAsset - description of the asset that this annotation is attached to.
+     * @param type - details of the metadata type for this properties object
+     * @param guid - String - unique id
+     * @param url - String - URL
+     * @param classifications - List of classifications
+     * @param reportName - report name string
+     * @param reportDescription - String for the report description
+     * @param creationDate - Date that annotation was created.
+     * @param analysisParameters - Properties that hold the parameters used to drive the discovery service's analysis.
+     * @param annotationType - String for annotation type
+     * @param summary - String for summary
+     * @param confidenceLevel - int for confidence level
+     * @param expression - String for the expression that represent the relationship between the annotation and the asset.
+     * @param explanation - String for the explanation for the annotation
+     * @param analysisStep - String describing the analysis step that the discovery service was in when it created the annotation.
+     * @param jsonProperties String - JSON properties associated with the annotation
+     * @param annotationStatus - AnnotationStatus enum
+     * @param reviewDate - date that this annotation was reviewed.  If no review has taken place then this property is null.
+     * @param steward String name of steward that reviewed the annotation.
+     * @param reviewComment - string comment made by the steward as part of the review of the annotation. The comment covers the
+     * whole review which may have looked at multiple annotations so the comment may not necessarily refer only to this annotation.
+     * @param additionalProperties - additional properties object for annotation.  These are a combination of the additional
+     * properties from the Annotation entity and any properties introduced by the subtypes of annotation.
+     * The naming convention for subtype property names is entityName.attributeName.value.  If the property
+     * is a map then the map contents are named entityName.attributeName.propertyName.propertyValue.
+     */
+
+
+    public Annotation(AssetDescriptor       parentAsset,
+                      ElementType           type,
+                      String                guid,
+                      String                url,
+                      Classifications       classifications,
+                      String                reportName,
+                      String                reportDescription,
+                      Date                  creationDate,
+                      AdditionalProperties  analysisParameters,
+                      String                annotationType,
+                      String                summary,
+                      int                   confidenceLevel,
+                      String                expression,
+                      String                explanation,
+                      String                analysisStep,
+                      String                jsonProperties,
+                      AnnotationStatus      annotationStatus,
+                      Date                  reviewDate,
+                      String                steward,
+                      String                reviewComment,
+                      AdditionalProperties  additionalProperties)
+    {
+        super(parentAsset, type, guid, url, classifications);
+
+        this.reportName = reportName;
+        this.reportDescription = reportDescription;
+        this.creationDate = creationDate;
+        this.analysisParameters = analysisParameters;
+        this.annotationType = annotationType;
+        this.summary = summary;
+        this.confidenceLevel = confidenceLevel;
+        this.expression = expression;
+        this.explanation = explanation;
+        this.analysisStep = analysisStep;
+        this.jsonProperties = jsonProperties;
+        this.annotationStatus = annotationStatus;
+        this.reviewDate = reviewDate;
+        this.steward = steward;
+        this.reviewComment = reviewComment;
+        this.additionalProperties = additionalProperties;
+    }
+
+    /**
+     * Copy/clone Constructor
+     *
+     * @param parentAsset - description of the asset that this annotation is attached to.
+     * @param templateAnnotation - template object to copy.
+     */
+    public Annotation(AssetDescriptor    parentAsset, Annotation   templateAnnotation)
+    {
+        /*
+         * Remember the parent
+         */
+        super(parentAsset, templateAnnotation);
+
+        if (templateAnnotation != null)
+        {
+            /*
+             * Copy the properties from the template into this annotation.
+             */
+            this.reportName = templateAnnotation.getReportName();
+            this.reportDescription = templateAnnotation.getReportDescription();
+            this.creationDate = templateAnnotation.getCreationDate();
+            this.analysisParameters = templateAnnotation.getAnalysisParameters();
+            this.annotationType = templateAnnotation.getAnnotationType();
+            this.summary = templateAnnotation.getSummary();
+            this.confidenceLevel = templateAnnotation.getConfidenceLevel();
+            this.expression = templateAnnotation.getExpression();
+            this.explanation = templateAnnotation.getExplanation();
+            this.analysisStep = templateAnnotation.getAnalysisStep();
+            this.jsonProperties = templateAnnotation.getJsonProperties();
+            this.annotationStatus = templateAnnotation.getAnnotationStatus();
+            this.reviewDate = templateAnnotation.getReviewDate();
+            this.steward = templateAnnotation.getSteward();
+            this.reviewComment = templateAnnotation.getReviewComment();
+            this.additionalProperties = new AdditionalProperties(parentAsset, templateAnnotation.getAdditionalProperties());
+        }
+    }
+
+
+    /**
+     * Return the name of the discovery analysis report that created this annotation.
+     *
+     * @return String - report name
+     */
+    public String getReportName()
+    {
+        return reportName;
+    }
+
+
+    /**
+     * Return the discovery analysis report description that this annotation is a part of.
+     *
+     * @return String - report description
+     */
+    public String getReportDescription()
+    {
+        return reportDescription;
+    }
+
+
+    /**
+     * Return the creation date for the annotation.  If this date is not known then null is returned.
+     *
+     * @return Date that the annotation was created.
+     */
+    public Date getCreationDate() {
+        return creationDate;
+    }
+
+
+    /**
+     * Return the properties that hold the parameters used to drive the discovery service's analysis.
+     *
+     * @return AdditionalProperties - object storing the analysis parameters
+     */
+    public AdditionalProperties getAnalysisParameters()
+    {
+        return analysisParameters;
+    }
+
+
+    /**
+     * Return the informal name for the type of annotation.
+     *
+     * @return String - annotation type
+     */
+    public String getAnnotationType()
+    {
+        return annotationType;
+    }
+
+
+    /**
+     * Return the summary description for the annotation.
+     *
+     * @return String - summary of annotation
+     */
+    public String getSummary()
+    {
+        return summary;
+    }
+
+
+    /**
+     * Return the confidence level of the discovery service that the annotation is correct.
+     *
+     * @return int - confidence level
+     */
+    public int getConfidenceLevel()
+    {
+        return confidenceLevel;
+    }
+
+
+    /**
+     * Return the expression that represent the relationship between the annotation and the asset.
+     *
+     * @return String - expression
+     */
+    public String getExpression()
+    {
+        return expression;
+    }
+
+
+    /**
+     * Return the explanation for the annotation.
+     *
+     * @return String - explanation
+     */
+    public String getExplanation() {
+        return explanation;
+    }
+
+
+    /**
+     * Return a description of the analysis step that the discovery service was in when it created the annotation.
+     *
+     * @return String - analysis step
+     */
+    public String getAnalysisStep()
+    {
+        return analysisStep;
+    }
+
+
+    /**
+     * Return the JSON properties associated with the annotation.
+     *
+     * @return String - JSON properties of annotation
+     */
+    public String getJsonProperties()
+    {
+        return jsonProperties;
+    }
+
+
+    /**
+     * Return the current status of the annotation.
+     *
+     * @return AnnotationStatus - current status of annotation
+     */
+    public AnnotationStatus getAnnotationStatus()
+    {
+        return annotationStatus;
+    }
+
+
+    /**
+     * Return the date that this annotation was reviewed.  If no review has taken place then this property is null.
+     *
+     * @return Date - review date
+     */
+    public Date getReviewDate()
+    {
+        return reviewDate;
+    }
+
+
+    /**
+     * Return the name of the steward that reviewed the annotation.
+     *
+     * @return String - steward's name.
+     */
+    public String getSteward()
+    {
+        return steward;
+    }
+
+
+    /**
+     * Return any comments made by the steward during the review.
+     *
+     * @return String - review comment
+     */
+    public String getReviewComment()
+    {
+        return reviewComment;
+    }
+
+
+    /**
+     * Return the additional properties for the Annotation.
+     *
+     * @return AdditionalProperties - additional properties object
+     */
+    public AdditionalProperties getAdditionalProperties()
+    {
+        return additionalProperties;
+    }
+
+
+    /**
+     * Standard toString method.
+     *
+     * @return print out of variables in a JSON-style
+     */
+    @Override
+    public String toString()
+    {
+        return "Annotation{" +
+                "reportName='" + reportName + '\'' +
+                ", reportDescription='" + reportDescription + '\'' +
+                ", creationDate=" + creationDate +
+                ", analysisParameters=" + analysisParameters +
+                ", annotationType='" + annotationType + '\'' +
+                ", summary='" + summary + '\'' +
+                ", confidenceLevel=" + confidenceLevel +
+                ", expression='" + expression + '\'' +
+                ", explanation='" + explanation + '\'' +
+                ", analysisStep='" + analysisStep + '\'' +
+                ", jsonProperties='" + jsonProperties + '\'' +
+                ", annotationStatus=" + annotationStatus +
+                ", reviewDate=" + reviewDate +
+                ", steward='" + steward + '\'' +
+                ", reviewComment='" + reviewComment + '\'' +
+                ", additionalProperties=" + additionalProperties +
+                ", type=" + type +
+                ", guid='" + guid + '\'' +
+                ", url='" + url + '\'' +
+                '}';
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/cbfdd7fc/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AnnotationStatus.java
----------------------------------------------------------------------
diff --git a/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AnnotationStatus.java b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AnnotationStatus.java
new file mode 100644
index 0000000..a671594
--- /dev/null
+++ b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AnnotationStatus.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.apache.atlas.ocf.properties;
+
+import java.io.Serializable;
+
+/**
+ * An AnnotationStatus defines the current status for an annotation plus some default descriptive text.
+ */
+public enum AnnotationStatus implements Serializable
+{
+    NEW_ANNOTATION      (0,  "New",      "Annotation has been created but not reviewed"),
+    REVIEWED_ANNOTATION (1,  "Reviewed", "Annotation has been reviewed by no decision has been made"),
+    APPROVED_ANNOTATION (2,  "Approved", "Annotation has been approved"),
+    ACTIONED_ANNOTATION (3,  "Actioned", "Annotation has been approved and insight has been added to Asset's metadata"),
+    INVALID_ANNOTATION  (4,  "Invalid",  "Annotation has been reviewed and declared invalid"),
+    IGNORE_ANNOTATION   (5,  "Ignore",   "Annotation is invalid and should be ignored"),
+    OTHER_STATUS        (98, "Other",    "Annotation's status stored in additional properties"),
+    UNKNOWN_STATUS      (99, "Unknown",  "Annotation has not had a status assigned");
+
+    private static final long     serialVersionUID = 1L;
+
+    private int            statusCode;
+    private String         statusName;
+    private String         statusDescription;
+
+
+    /**
+     * Typical Constructor
+     */
+    AnnotationStatus(int     statusCode, String   statusName,  String   statusDescription)
+    {
+        /*
+         * Save the values supplied
+         */
+        this.statusCode = statusCode;
+        this.statusName = statusName;
+        this.statusDescription = statusDescription;
+    }
+
+
+    /**
+     * Return the status code for this enum instance
+     *
+     * @return int - status code
+     */
+    public int getStatusCode()
+    {
+        return statusCode;
+    }
+
+
+    /**
+     * Return the default name for the status for this enum instance.
+     *
+     * @return String - default status name
+     */
+    public String getStatusName()
+    {
+        return statusName;
+    }
+
+
+    /**
+     * REturn the default description for the status for this enum instance.
+     *
+     * @return String - default status description
+     */
+    public String getStatusDescription()
+    {
+        return statusDescription;
+    }
+
+
+    /**
+     * Standard toString method.
+     *
+     * @return print out of variables in a JSON-style
+     */
+    @Override
+    public String toString()
+    {
+        return "AnnotationStatus{" +
+                "statusCode=" + statusCode +
+                ", statusName='" + statusName + '\'' +
+                ", statusDescription='" + statusDescription + '\'' +
+                '}';
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/cbfdd7fc/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/Annotations.java
----------------------------------------------------------------------
diff --git a/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/Annotations.java b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/Annotations.java
new file mode 100644
index 0000000..2b7e99d
--- /dev/null
+++ b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/Annotations.java
@@ -0,0 +1,128 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.atlas.ocf.properties;
+
+import java.util.Iterator;
+
+/**
+ * Annotations supports an iterator over a list of annotations.  Callers can use it to step through the list
+ * just once.  If they want to parse the list again, they could use the copy/clone constructor to create
+ * a new iterator.
+ */
+public abstract class Annotations extends AssetPropertyIteratorBase implements Iterator<Annotation>
+{
+    /**
+     * Typical Constructor creates an iterator with the supplied list of elements.
+     *
+     * @param parentAsset - descriptor of parent asset
+     * @param totalElementCount - the total number of elements to process.  A negative value is converted to 0.
+     * @param maxCacheSize - maximum number of elements that should be retrieved from the property server and
+     *                     cached in the element list at any one time.  If a number less than one is supplied, 1 is used.
+     */
+    public Annotations(AssetDescriptor              parentAsset,
+                       int                          totalElementCount,
+                       int                          maxCacheSize)
+    {
+        super(parentAsset, totalElementCount, maxCacheSize);
+    }
+
+
+    /**
+     * Copy/clone constructor.  Used to reset iterator element pointer to 0;
+     *
+     * @param parentAsset - descriptor of parent asset
+     * @param template - type-specific iterator to copy; null to create an empty iterator
+     */
+    public Annotations(AssetDescriptor   parentAsset, Annotations    template)
+    {
+        super(parentAsset, template);
+    }
+
+
+    /**
+     * Provides a concrete implementation of cloneElement for the specific iterator type.
+     *
+     * @param parentAsset - descriptor of parent asset
+     * @param template - object to clone
+     * @return new cloned object.
+     */
+    protected  AssetPropertyBase  cloneElement(AssetDescriptor  parentAsset, AssetPropertyBase   template)
+    {
+        return new Annotation(parentAsset, (Annotation)template);
+    }
+
+
+    /**
+     * Clones this iterator.
+     *
+     * @param parentAsset - descriptor of parent asset
+     * @return new cloned object.
+     */
+    protected  abstract Annotations  cloneIterator(AssetDescriptor  parentAsset);
+
+
+    /**
+     * The iterator can only be used once to step through the elements.  This method returns
+     * a boolean to indicate if it has got to the end of the list yet.
+     *
+     * @return boolean indicating whether there are more elements.
+     */
+    @Override
+    public boolean hasNext()
+    {
+        return super.pagingIterator.hasNext();
+    }
+
+
+    /**
+     * Return the next element in the iteration.
+     *
+     * @return Annotation - next element object that has been cloned.
+     */
+    @Override
+    public Annotation next()
+    {
+        return (Annotation)super.pagingIterator.next();
+    }
+
+
+    /**
+     * Remove the current element in the iterator. (Null implementation since this iterator works off of cached
+     * elements from the property (metadata) server.)
+     */
+    @Override
+    public void remove()
+    {
+        super.pagingIterator.remove();
+    }
+
+
+    /**
+     * Standard toString method.
+     *
+     * @return print out of variables in a JSON-style
+     */
+    @Override
+    public String toString()
+    {
+        return "Annotations{" +
+                "pagingIterator=" + pagingIterator +
+                '}';
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/cbfdd7fc/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetDescriptor.java
----------------------------------------------------------------------
diff --git a/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetDescriptor.java b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetDescriptor.java
new file mode 100644
index 0000000..63d8fd4
--- /dev/null
+++ b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetDescriptor.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.apache.atlas.ocf.properties;
+
+/**
+ * This is the base class for a connected asset.  It is passed to all of the embedded property objects so the name
+ * and type can be used for error messages and other diagnostics.  It also carries the URL of the asset in the
+ * metadata repository where this is known to enable properties to be retrieved on request.
+ */
+public abstract class AssetDescriptor extends PropertyBase
+{
+    /*
+     * Derived name and type for use by nested property object for messages/debug.  If these default values
+     * are seen it is a sign that the asset properties are not being populated from the metadata repository.
+     */
+    private String assetName = "<Unknown>";
+    private String assetTypeName = "<Unknown>";
+
+    /*
+     * URL where the metadata about the asset is located.  It remains null if no repository is known.
+     */
+    private String url = null;
+
+    /*
+     * Unique id for the asset.
+     */
+    private String guid = null;
+
+
+    /**
+     * Typical constructor - the asset descriptor is effectively empty - and the protected
+     * set methods need to be called to add useful content to it.
+     */
+    public AssetDescriptor()
+    {
+        /*
+         * Nothing to do except call superclass
+         */
+        super();
+    }
+
+
+    /**
+     * Explicit constructor - the asset descriptor is explicitly given the url for the asset.
+     *
+     * @param guid - unique id for the asset
+     * @param url - URL for the asset in the metadata repository
+     */
+    public AssetDescriptor(String guid, String  url)
+    {
+        super();
+
+        this.guid = guid;
+        this.url = url;
+    }
+
+
+    /**
+     * Copy/clone Constructor - used to copy the asset descriptor for a new consumer.
+     *
+     * @param templateAssetDescriptor - template asset descriptor to copy.
+     */
+    public AssetDescriptor(AssetDescriptor   templateAssetDescriptor)
+    {
+        super();
+
+        this.guid = templateAssetDescriptor.getGUID();
+        this.assetName = templateAssetDescriptor.getAssetName();
+        this.assetTypeName = templateAssetDescriptor.getAssetTypeName();
+        this.url = templateAssetDescriptor.getURL();
+    }
+
+
+    /**
+     * Method to enable a subclass to set up the asset name.
+     *
+     * @param assetName - String - name of asset for messages etc
+     */
+    protected void setAssetName(String     assetName)
+    {
+        this.assetName = assetName;
+    }
+
+
+    /**
+     * Method to enable a subclass to set up the asset type name.
+     *
+     * @param assetTypeName - String - new type name
+     */
+    protected void setAssetTypeName(String    assetTypeName)
+    {
+        this.assetTypeName = assetTypeName;
+    }
+
+
+    /**
+     * Return the unique id for this element.
+     *
+     * @return guid - unique id
+     */
+    public String getGUID() {
+        return guid;
+    }
+
+
+    /**
+     * Return the name of the asset - for use in messages and other diagnostics.
+     *
+     * @return String - asset name
+     */
+    public String getAssetName()
+    {
+        return assetName;
+    }
+
+
+    /**
+     * Return the name of the asset's type - for use in messages and other diagnostics.
+     *
+     * @return String - asset type name
+     */
+    public String getAssetTypeName()
+    {
+        return assetTypeName;
+    }
+
+
+    /**
+     * Return the URL of the asset in the metadata repository if supported.
+     *
+     * @return String - URL
+     */
+    public String getURL() { return url; }
+
+
+    /**
+     * Standard toString method.
+     *
+     * @return print out of variables in a JSON-style
+     */
+    @Override
+    public String toString()
+    {
+        return "AssetDescriptor{" +
+                "assetName='" + assetName + '\'' +
+                ", assetTypeName='" + assetTypeName + '\'' +
+                ", url='" + url + '\'' +
+                ", guid='" + guid + '\'' +
+                '}';
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/cbfdd7fc/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetDetail.java
----------------------------------------------------------------------
diff --git a/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetDetail.java b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetDetail.java
new file mode 100644
index 0000000..c0bd56d
--- /dev/null
+++ b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetDetail.java
@@ -0,0 +1,332 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.atlas.ocf.properties;
+
+/**
+ * AssetDetail extends AssetSummary to provide all of the properties related to this asset.  It includes:
+ * <ul>
+ *     <li>AssetProperties - properties unique to the particular type of asset including any vendor-specific facets.</li>
+ *     <li>ExternalIdentifiers - list of identifiers for this asset that are used in other systems.</li>
+ *     <li>RelatedMediaReferences - list of links to external media (images, audio, video) about this asset.</li>
+ *     <li>NoteLogs - list of NoteLogs for this asset, often providing more detail on how to use the asset and
+ *                   its current status.</li>
+ *     <li>ExternalReferences - list of links to additional information about this asset.</li>
+ *     <li>Connections - list of connections defined to access this asset.</li>
+ *     <li>Licenses - list of licenses associated with the asset.</li>
+ *     <li>Certifications - list of certifications that have been awarded to this asset.</li>
+ * </ul>
+ */
+public class AssetDetail extends AssetSummary
+{
+    private AdditionalProperties   assetProperties = null;
+    private ExternalIdentifiers    externalIdentifiers = null;
+    private RelatedMediaReferences relatedMediaReferences = null;
+    private NoteLogs               noteLogs = null;
+    private ExternalReferences     externalReferences = null;
+    private Connections            connections = null;
+    private Licenses               licenses = null;
+    private Certifications         certifications = null;
+
+
+    /**
+     * Typical constructor - initialize superclasses
+     *
+     * @param type - details of the metadata type for this asset
+     * @param guid - guid property
+     * @param url - element URL used to access its properties in the metadata repository.
+     * @param qualifiedName - unique name
+     * @param displayName - consumable name
+     * @param description - description of the asset
+     * @param shortDescription - short description from relationship with Connection
+     * @param owner - owner name
+     * @param classifications - enumeration of classifications
+     * @param assetProperties - AdditionalProperties object
+     * @param externalIdentifiers - ExternalIdentifiers enumeration
+     * @param relatedMediaReferences - RelatedMediaReferences enumeration
+     * @param noteLogs - NoteLogs iterator
+     * @param externalReferences - ExternalReferences iterator
+     * @param connections - List of connections attached to the asset
+     * @param licenses - List of licenses
+     * @param certifications - Certifications - list of certifications
+     */
+    public AssetDetail(ElementType            type,
+                       String                 guid,
+                       String                 url,
+                       String                 qualifiedName,
+                       String                 displayName,
+                       String                 shortDescription,
+                       String                 description,
+                       String                 owner,
+                       Classifications        classifications,
+                       AdditionalProperties   assetProperties,
+                       ExternalIdentifiers    externalIdentifiers,
+                       RelatedMediaReferences relatedMediaReferences,
+                       NoteLogs               noteLogs,
+                       ExternalReferences     externalReferences,
+                       Connections            connections,
+                       Licenses               licenses,
+                       Certifications         certifications)
+    {
+        super(type,
+              guid,
+              url,
+              qualifiedName,
+              displayName,
+              shortDescription,
+              description,
+              owner,
+              classifications);
+
+        this.assetProperties = assetProperties;
+        this.externalIdentifiers = externalIdentifiers;
+        this.relatedMediaReferences = relatedMediaReferences;
+        this.noteLogs = noteLogs;
+        this.externalReferences = externalReferences;
+        this.connections = connections;
+        this.licenses = licenses;
+        this.certifications = certifications;
+    }
+
+    /**
+     * Copy/clone constructor.  Note, this is a deep copy
+     *
+     * @param templateAssetDetail - template to copy
+     */
+    public AssetDetail(AssetDetail  templateAssetDetail)
+    {
+        /*
+         * Initialize superclass
+         */
+        super(templateAssetDetail);
+
+        /*
+         * Copy details from template, ensuring the parentAsset is this object, not the template's.
+         */
+        if (templateAssetDetail != null)
+        {
+            AdditionalProperties   templateAssetProperties = templateAssetDetail.getAssetProperties();
+            ExternalIdentifiers    templateExternalIdentifiers = templateAssetDetail.getExternalIdentifiers();
+            RelatedMediaReferences templateRelatedMediaReferences = templateAssetDetail.getRelatedMediaReferences();
+            NoteLogs               templateNoteLogs = templateAssetDetail.getNoteLogs();
+            ExternalReferences     templateExternalReferences = templateAssetDetail.getExternalReferences();
+            Connections            templateConnections = templateAssetDetail.getConnections();
+            Licenses               templateLicenses = templateAssetDetail.getLicenses();
+            Certifications         templateCertifications = templateAssetDetail.getCertifications();
+
+            if (templateAssetProperties != null)
+            {
+                assetProperties = new AdditionalProperties(this, templateAssetProperties);
+            }
+            if (templateExternalIdentifiers != null)
+            {
+                externalIdentifiers = templateExternalIdentifiers.cloneIterator(this);
+            }
+            if (templateRelatedMediaReferences != null)
+            {
+                relatedMediaReferences = templateRelatedMediaReferences.cloneIterator(this);
+            }
+            if (templateNoteLogs != null)
+            {
+                noteLogs = templateNoteLogs.cloneIterator(this);
+            }
+            if (templateExternalReferences != null)
+            {
+                externalReferences = templateExternalReferences.cloneIterator(this);
+            }
+            if (templateConnections != null)
+            {
+                connections = templateConnections.cloneIterator(this);
+            }
+            if (templateLicenses != null)
+            {
+                licenses = templateLicenses.cloneIterator(this);
+            }
+            if (templateCertifications != null)
+            {
+                certifications = templateCertifications.cloneIterator(this);
+            }
+        }
+    }
+
+
+    /**
+     * Return the set of properties that are specific to the particular type of asset.  The caller is given their
+     * own copy of the property object.  The properties are named entityName.attributeName. The values are all strings.
+     *
+     * @return AdditionalProperties - asset properties using the name of attributes from the model.
+     */
+    public AdditionalProperties getAssetProperties()
+    {
+        if (assetProperties == null)
+        {
+            return assetProperties;
+        }
+        else
+        {
+            return new AdditionalProperties(this, assetProperties);
+        }
+    }
+
+
+    /**
+     * Return an enumeration of the external identifiers for this asset (or null if none).
+     *
+     * @return ExternalIdentifiers enumeration
+     */
+    public ExternalIdentifiers getExternalIdentifiers()
+    {
+        if (externalIdentifiers == null)
+        {
+            return externalIdentifiers;
+        }
+        else
+        {
+            return externalIdentifiers.cloneIterator(this);
+        }
+    }
+
+
+    /**
+     * Return an enumeration of references to the related media associated with this asset.
+     *
+     * @return RelatedMediaReferences enumeration
+     */
+    public RelatedMediaReferences getRelatedMediaReferences()
+    {
+        if (relatedMediaReferences == null)
+        {
+            return relatedMediaReferences;
+        }
+        else
+        {
+            return relatedMediaReferences.cloneIterator(this);
+        }
+    }
+
+
+    /**
+     * Return an enumeration of NoteLogs linked to this asset.
+     *
+     * @return Notelogs iterator
+     */
+    public NoteLogs getNoteLogs()
+    {
+        if (noteLogs == null)
+        {
+            return noteLogs;
+        }
+        else
+        {
+            return noteLogs.cloneIterator(this);
+        }
+    }
+
+
+    /**
+     * Return the enumeration of external references associated with this asset.
+     *
+     * @return ExternalReferences iterator
+     */
+    public ExternalReferences getExternalReferences()
+    {
+        if (externalReferences == null)
+        {
+            return externalReferences;
+        }
+        else
+        {
+            return externalReferences.cloneIterator(this);
+        }
+    }
+
+
+    /**
+     * Return an enumeration of the connections defined for this asset.
+     *
+     * @return Connections enumeration
+     */
+    public Connections getConnections()
+    {
+        if (connections == null)
+        {
+            return connections;
+        }
+        else
+        {
+            return connections.cloneIterator(this);
+        }
+    }
+
+
+    /**
+     * Return the list of licenses associated with the asset.
+     *
+     * @return Licenses
+     */
+    public Licenses getLicenses()
+    {
+        if (licenses == null)
+        {
+            return licenses;
+        }
+        else
+        {
+            return licenses.cloneIterator(this);
+        }
+    }
+
+
+    /**
+     * Return the list of certifications awarded to the asset.
+     *
+     * @return Certifications - list of certifications
+     */
+    public Certifications getCertifications()
+    {
+        if (certifications == null)
+        {
+            return certifications;
+        }
+        else
+        {
+            return certifications.cloneIterator(this);
+        }
+    }
+
+
+    /**
+     * Standard toString method.
+     *
+     * @return print out of variables in a JSON-style
+     */
+    @Override
+    public String toString()
+    {
+        return "AssetDetail{" +
+                "assetProperties=" + assetProperties +
+                ", externalIdentifiers=" + externalIdentifiers +
+                ", relatedMediaReferences=" + relatedMediaReferences +
+                ", noteLogs=" + noteLogs +
+                ", externalReferences=" + externalReferences +
+                ", connections=" + connections +
+                ", licenses=" + licenses +
+                ", certifications=" + certifications +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/atlas/blob/cbfdd7fc/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetPropertyBase.java
----------------------------------------------------------------------
diff --git a/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetPropertyBase.java b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetPropertyBase.java
new file mode 100644
index 0000000..09ccd90
--- /dev/null
+++ b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetPropertyBase.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.apache.atlas.ocf.properties;
+
+/**
+ * The AssetPropertyBase class is a base class for all properties that link off of the connected asset.
+ * It manages the information about the parent asset.
+ */
+public abstract class AssetPropertyBase extends PropertyBase
+{
+    private AssetDescriptor     parentAsset = null;
+
+    /**
+     * Typical constructor that sets the link to the connected asset to null
+     *
+     * @param parentAsset - descriptor of asset that his property relates to.
+     */
+
+    protected AssetPropertyBase(AssetDescriptor     parentAsset)
+    {
+        /*
+         * Initialize superclass and save the parent asset.
+         */
+        super();
+        this.parentAsset = parentAsset;
+    }
+
+
+    /**
+     * Copy/clone constructor - sets up details of the parent asset from the template
+     *
+     * @param parentAsset - descriptor of asset that his property relates to.
+     * @param  template - AssetPropertyBase to copy
+     */
+    protected AssetPropertyBase(AssetDescriptor     parentAsset, AssetPropertyBase  template)
+    {
+        /*
+         * Initialize superclass and save the parentAsset
+         */
+        super(template);
+        this.parentAsset = parentAsset;
+    }
+
+
+    /**
+     * Return the asset descriptor of the parent asset.
+     *
+     * @return AssetDescriptor
+     */
+    protected  AssetDescriptor  getParentAsset() { return parentAsset; }
+
+
+    /**
+     * Return the name of the connected asset that this property is connected to.
+     *
+     * @return String name of the connected asset
+     */
+    protected String getParentAssetName()
+    {
+        String  parentAssetName = "<Unknown>";
+
+        if (parentAsset != null)
+        {
+            parentAssetName = parentAsset.getAssetName();
+        }
+
+        return parentAssetName;
+    }
+
+
+    /**
+     * Return the type of the connected asset that this property relates to.
+     *
+     * @return String name of the connected asset's type.
+     */
+    protected String getParentAssetTypeName()
+    {
+        String  parentAssetTypeName = "<Unknown>";
+
+        if (parentAsset != null)
+        {
+            parentAssetTypeName = parentAsset.getAssetTypeName();
+        }
+
+        return parentAssetTypeName;
+    }
+
+
+    /**
+     * An equals() method for subclasses to check they are connected to the same parent asset.
+     *
+     * @param testObject - object to test
+     * @return boolean indicating whether this object is connected to equivalent parent assets.
+     */
+    @Override
+    public boolean equals(Object testObject)
+    {
+        if (this == testObject)
+        {
+            return true;
+        }
+        if (testObject == null || getClass() != testObject.getClass())
+        {
+            return false;
+        }
+
+        AssetPropertyBase that = (AssetPropertyBase) testObject;
+
+        return parentAsset != null ? parentAsset.equals(that.parentAsset) : that.parentAsset == null;
+    }
+
+
+    /**
+     * Standard toString method.
+     *
+     * @return print out of variables in a JSON-style
+     */
+    @Override
+    public String toString()
+    {
+        return "AssetPropertyBase{" +
+                "parentAsset=" + parentAsset +
+                '}';
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/atlas/blob/cbfdd7fc/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetPropertyIteratorBase.java
----------------------------------------------------------------------
diff --git a/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetPropertyIteratorBase.java b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetPropertyIteratorBase.java
new file mode 100644
index 0000000..5bb30eb
--- /dev/null
+++ b/om-fwk-ocf/src/main/java/org/apache/atlas/ocf/properties/AssetPropertyIteratorBase.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.apache.atlas.ocf.properties;
+
+import org.apache.atlas.ocf.ffdc.PropertyServerException;
+
+import java.util.ArrayList;
+
+public abstract class AssetPropertyIteratorBase extends AssetPropertyBase
+{
+    protected PagingIterator pagingIterator = null;
+
+    /**
+     * Typical Constructor creates an iterator with the supplied list of comments.
+     *
+     * @param parentAsset - descriptor of parent asset
+     * @param totalElementCount - the total number of elements to process.  A negative value is converted to 0.
+     * @param maxCacheSize - maximum number of elements that should be retrieved from the property server and
+     *                     cached in the element list at any one time.  If a number less than one is supplied, 1 is used.
+     */
+    protected AssetPropertyIteratorBase(AssetDescriptor              parentAsset,
+                                        int                          totalElementCount,
+                                        int                          maxCacheSize)
+    {
+        /*
+         * Initialize superclass.
+         */
+        super(parentAsset);
+
+        pagingIterator = new PagingIterator(parentAsset, this, totalElementCount, maxCacheSize);
+    }
+
+
+    /**
+     * Copy/clone constructor - sets up details of the parent asset from the template
+     *
+     * @param parentAsset - descriptor of asset that his property relates to.
+     * @param  template - AssetPropertyBaseImpl to copy
+     */
+    protected AssetPropertyIteratorBase(AssetDescriptor     parentAsset, AssetPropertyIteratorBase  template)
+    {
+        /*
+         * Initialize superclass.
+         */
+        super(parentAsset, template);
+
+        if (template != null)
+        {
+            pagingIterator = new PagingIterator(parentAsset, this, template.pagingIterator);
+        }
+    }
+
+
+    /**
+     * Return the number of elements in the list.
+     *
+     * @return elementCount
+     */
+    public int getElementCount()
+    {
+        if (pagingIterator == null)
+        {
+            return 0;
+        }
+        else
+        {
+            return pagingIterator.getElementCount();
+        }
+    }
+
+
+    /**
+     * Method implemented by a subclass that ensures the cloning process is a deep clone.
+     *
+     * @param parentAsset - descriptor of parent asset
+     * @param template - object to clone
+     * @return new cloned object.
+     */
+    protected abstract AssetPropertyBase  cloneElement(AssetDescriptor  parentAsset, AssetPropertyBase   template);
+
+
+    /**
+     * Method implemented by subclass to retrieve the next cached list of elements.
+     *
+     * @param cacheStartPointer - where to start the cache.
+     * @param maximumSize - maximum number of elements in the cache.
+     * @return list of elements corresponding to the supplied cache pointers.
+     * @throws PropertyServerException - there is a problem retrieving elements from the property (metadata) server.
+     */
+    protected abstract ArrayList<AssetPropertyBase> getCachedList(int  cacheStartPointer,
+                                                                  int  maximumSize) throws PropertyServerException;
+}