http://git-wip-us.apache.org/repos/asf/atlas/blob/8a57e657/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefPatch.java ---------------------------------------------------------------------- diff --git a/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefPatch.java b/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefPatch.java new file mode 100644 index 0000000..b6dcf23 --- /dev/null +++ b/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefPatch.java @@ -0,0 +1,399 @@ +/* + * 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.omrs.metadatacollection.properties.typedefs; + +import org.apache.atlas.omrs.metadatacollection.properties.instances.InstanceStatus; + +import java.util.ArrayList; +import java.util.Map; + + +/** + * TypeDefPatch describes a change (patch) to a typeDef's properties, options, external standards mappings or + * list of valid instance statuses. + * A patch can be applied to an EntityDef, RelationshipDef or ClassificationDef. + * Changes to a TypeDef's category or superclasses requires a new type definition. + * In addition it is not possible to delete an attribute through a patch. + */ +public class TypeDefPatch extends TypeDefElementHeader +{ + private TypeDefPatchAction action = null; + private String typeDefGUID = null; + private String typeName = null; + private long applyToVersion = 0L; + private long updateToVersion = 0L; + private String newVersionName = null; + private String description = null; + private String descriptionGUID = null; + private ArrayList<TypeDefAttribute> typeDefAttributes = null; + private Map<String, String> typeDefOptions = null; + private ArrayList<ExternalStandardMapping> externalStandardMappings = null; + private ArrayList<InstanceStatus> validInstanceStatusList = null; + + private static final long serialVersionUID = 1L; + + + /** + * Default constructor relies on the initialization of variables in their declaration. + */ + public TypeDefPatch() + { + } + + + /** + * Return the type of action that this patch requires. + * + * @return TypeDefPatchAction enum + */ + public TypeDefPatchAction getAction() { + return action; + } + + + /** + * Set up the type of action that this patch requires. + * + * @param action - TypeDefPatchAction enum + */ + public void setAction(TypeDefPatchAction action) { + this.action = action; + } + + + /** + * Return the unique identifier for the affected TypeDef. + * + * @return String guid + */ + public String getTypeDefGUID() + { + return typeDefGUID; + } + + + /** + * Set up the unique identifier for the affected TypeDef. + * + * @param typeDefGUID - String guid + */ + public void setTypeDefGUID(String typeDefGUID) + { + this.typeDefGUID = typeDefGUID; + } + + + /** + * Return the unique name for the affected TypeDef. + * + * @return String name + */ + public String getTypeName() { + return typeName; + } + + + /** + * Set up the unique name for the affected TypeDef. + * + * @param typeName - String name + */ + public void setTypeName(String typeName) { + this.typeName = typeName; + } + + + /** + * Return the version number of the TypeDef that this patch applies to. + * + * @return long version number + */ + public long getApplyToVersion() { + return applyToVersion; + } + + + /** + * Set up the version number of the TypeDef that this patch applies to. + * + * @param applyToVersion - long version number + */ + public void setApplyToVersion(long applyToVersion) { + this.applyToVersion = applyToVersion; + } + + + /** + * Return the new version number of the TypeDef. + * + * @return long version number + */ + public long getUpdateToVersion() { + return updateToVersion; + } + + + /** + * Set up the new versionName of the TypeDef. + * + * @param updateToVersion long version number + */ + public void setUpdateToVersion(long updateToVersion) { + this.updateToVersion = updateToVersion; + } + + + /** + * Return the new version name ot use once the patch is applied. + * + * @return String version name + */ + public String getNewVersionName() + { + return newVersionName; + } + + + /** + * Set up the new version name ot use once the patch is applied. + * + * @param newVersionName - String version name + */ + public void setNewVersionName(String newVersionName) + { + this.newVersionName = newVersionName; + } + + + /** + * Return the new description for the TypeDef. + * + * @return String description + */ + public String getDescription() + { + return description; + } + + + /** + * Set up the new description for the TypeDef + * + * @param description - String description + */ + public void setDescription(String description) + { + this.description = description; + } + + + /** + * Return the unique identifier for the new glossary term that describes the TypeDef. + * + * @return String unique identifier + */ + public String getDescriptionGUID() + { + return descriptionGUID; + } + + + /** + * Set up the unique identifier for the new glossary term that describes the TypeDef. + * + * @param descriptionGUID - String unique identifier + */ + public void setDescriptionGUID(String descriptionGUID) + { + this.descriptionGUID = descriptionGUID; + } + + + /** + * Return the list of typeDefAttributes that are either new or changing. + * + * @return list of AttributeDefs + */ + public ArrayList<TypeDefAttribute> getTypeDefAttributes() { + return typeDefAttributes; + } + + + /** + * Set up the list of typeDefAttributes that are either new or changing. + * + * @param typeDefAttributes - list of AttributeDefs + */ + public void setTypeDefAttributes(ArrayList<TypeDefAttribute> typeDefAttributes) + { + this.typeDefAttributes = typeDefAttributes; + } + + + /** + * Return the TypeDef options for the patch. + * + * @return map of TypeDef Options that are new or changing. + */ + public Map<String, String> getTypeDefOptions() { + return typeDefOptions; + } + + + /** + * Set up the TypeDef options for the patch. + * + * @param typeDefOptions - map of TypeDef Options that are new or changing. + */ + public void setTypeDefOptions(Map<String, String> typeDefOptions) { + this.typeDefOptions = typeDefOptions; + } + + + /** + * Return the list of External Standards Mappings that are either new or changing. + * + * @return list of external standards mappings + */ + public ArrayList<ExternalStandardMapping> getExternalStandardMappings() + { + return externalStandardMappings; + } + + + /** + * Set up the list of External Standards Mappings that are either new or changing. + * + * @param externalStandardMappings list of external standards mappings + */ + public void setExternalStandardMappings(ArrayList<ExternalStandardMapping> externalStandardMappings) + { + this.externalStandardMappings = externalStandardMappings; + } + + + /** + * Return the list of valid statuses for an instance of this TypeDef. + * + * @return list of valid statuses + */ + public ArrayList<InstanceStatus> getValidInstanceStatusList() + { + return validInstanceStatusList; + } + + + /** + * Set up the list of valid statuses for an instance of this TypeDef. + * + * @param validInstanceStatusList - list of valid statuses + */ + public void setValidInstanceStatusList(ArrayList<InstanceStatus> validInstanceStatusList) + { + this.validInstanceStatusList = validInstanceStatusList; + } + + + /** + * Standard toString method. + * + * @return JSON style description of variables. + */ + @Override + public String toString() + { + return "TypeDefPatch{" + + "action=" + action + + ", typeDefGUID='" + typeDefGUID + '\'' + + ", typeName='" + typeName + '\'' + + ", applyToVersion=" + applyToVersion + + ", updateToVersion=" + updateToVersion + + ", newVersionName='" + newVersionName + '\'' + + ", typeDefAttributes=" + typeDefAttributes + + ", typeDefOptions=" + typeDefOptions + + ", externalStandardMappings=" + externalStandardMappings + + ", validInstanceStatusList=" + validInstanceStatusList + + '}'; + } + + /** + * Validated that the GUID, name and versionName of a TypeDef are equal. + * + * @param object to test + * @return boolean flag to say object is the same TypeDefPatch + */ + @Override + public boolean equals(Object object) + { + if (this == object) + { + return true; + } + if (object == null || getClass() != object.getClass()) + { + return false; + } + + TypeDefPatch that = (TypeDefPatch) object; + + if (applyToVersion != that.applyToVersion) + { + return false; + } + if (updateToVersion != that.updateToVersion) + { + return false; + } + if (action != that.action) + { + return false; + } + if (typeDefGUID != null ? !typeDefGUID.equals(that.typeDefGUID) : that.typeDefGUID != null) + { + return false; + } + if (typeName != null ? !typeName.equals(that.typeName) : that.typeName != null) + { + return false; + } + if (typeDefAttributes != null ? !typeDefAttributes.equals(that.typeDefAttributes) : that.typeDefAttributes != null) + { + return false; + } + if (typeDefOptions != null ? !typeDefOptions.equals(that.typeDefOptions) : that.typeDefOptions != null) + { + return false; + } + if (externalStandardMappings != null ? !externalStandardMappings.equals(that.externalStandardMappings) : that.externalStandardMappings != null) + { + return false; + } + return validInstanceStatusList != null ? validInstanceStatusList.equals(that.validInstanceStatusList) : that.validInstanceStatusList == null; + } + + /** + * Using the GUID as a hashcode - it should be unique if all connected metadata repositories are behaving properly. + * + * @return int hash code + */ + @Override + public int hashCode() + { + return typeDefGUID != null ? typeDefGUID.hashCode() : 0; + } +}
http://git-wip-us.apache.org/repos/asf/atlas/blob/8a57e657/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefPatchAction.java ---------------------------------------------------------------------- diff --git a/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefPatchAction.java b/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefPatchAction.java new file mode 100644 index 0000000..c89c42a --- /dev/null +++ b/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefPatchAction.java @@ -0,0 +1,103 @@ +/* + * 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.omrs.metadatacollection.properties.typedefs; + + +/** + * TypeDefPatchAction defines the types of actions that can be taken to update a TypeDef. These changes are safe + * to make while there are active instances using them. If more extensive changes need to be made to a TypeDef + * then a new TypeDef should be defined. + */ +public enum TypeDefPatchAction +{ + ADD_ATTRIBUTES (1, "AddAttributes", + "Add one or more new attributes to a TypeDef"), + ADD_OPTIONS (2, "AddOptions", + "Extend the current list of options for a TypeDef. These options are used to " + + "help process metadata instances. " + + "They may be different in each TypeDef."), + UPDATE_OPTIONS (3, "UpdateOptions", + "Replace the options from a TypeDef. These options are used to help " + + "process metadata instances. " + + "They may be different in each TypeDef."), + DELETE_OPTIONS (4, "DeleteOptions", + "Delete the options from a TypeDef. These options are used to help " + + "process metadata instances. " + + "They may be different in each TypeDef."), + ADD_EXTERNAL_STANDARDS (5, "AddExternalStandardMapping", + "Add a mapping to an external standard either for the TypeDef or the supplied attributes."), + UPDATE_EXTERNAL_STANDARDS (6, "UpdateExternalStandardMapping", + "Update a mapping to an external standard either for the TypeDef or the supplied attributes."), + DELETE_EXTERNAL_STANDARDS (7, "DeleteExternalStandardMapping", + "Remove a mapping to an external standard either for the TypeDef or the supplied attributes."), + UPDATE_DESCRIPTIONS (8, "UpdateDescriptions", + "Update the descriptions and descriptionGUIDs of the TypeDef and its attributes."); + + + private int patchActionCode; + private String patchActionName; + private String patchActionDescription; + + + /** + * Constructor to set up a single instances of the enum. + * + * @param patchActionCode - numeric code for the patch action + * @param patchActionName - descriptive name for the patch action + * @param patchActionDescription - description of the patch action + */ + TypeDefPatchAction(int patchActionCode, String patchActionName, String patchActionDescription) + { + this.patchActionCode = patchActionCode; + this.patchActionName = patchActionName; + this.patchActionDescription = patchActionDescription; + } + + + /** + * Return the code value for the patch action. + * + * @return int code + */ + public int getPatchActionCode() + { + return patchActionCode; + } + + + /** + * Return the descriptive name for the patch action. + * + * @return String name + */ + public String getPatchActionName() + { + return patchActionName; + } + + + /** + * Return the description of the patch action. + * + * @return String description + */ + public String getPatchActionDescription() + { + return patchActionDescription; + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/8a57e657/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefProperties.java ---------------------------------------------------------------------- diff --git a/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefProperties.java b/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefProperties.java new file mode 100644 index 0000000..cfb549e --- /dev/null +++ b/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefProperties.java @@ -0,0 +1,154 @@ +/* + * 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.omrs.metadatacollection.properties.typedefs; + +import org.apache.atlas.omrs.ffdc.OMRSErrorCode; +import org.apache.atlas.omrs.ffdc.exception.OMRSRuntimeException; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + + +/** + * The TypeDefProperties class provides support for arbitrary properties that belong to a TypeDef object. + * It is used for searching the TypeDefs. + * It wraps a java.util.Map map object built around HashMap. + */ +public class TypeDefProperties extends TypeDefElementHeader +{ + private Map<String,Object> typeDefProperties = new HashMap<>(); + + + /** + * Typical constructor + */ + public TypeDefProperties() + { + /* + * Nothing to do + */ + } + + + /** + * Copy/clone Constructor. + * + * @param templateProperties - template object to copy. + */ + public TypeDefProperties(TypeDefProperties 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); + + typeDefProperties.put(newPropertyName, newPropertyValue); + } + } + } + } + + + /** + * Returns a list of the instance properties for the element. + * If no stored properties are present then null is returned. + * + * @return list of properties + */ + public Iterator<String> getPropertyNames() + { + return typeDefProperties.keySet().iterator(); + } + + + /** + * Returns the requested instance 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 typeDefProperties.get(name); + } + + + /** + * Adds or updates an instance property. + * If a null is supplied for the property name, an OMRS runtime exception is thrown. + * If a null is supplied for the property value, the property is removed. + * + * @param newPropertyName - name + * @param newPropertyValue - value + */ + public void setProperty(String newPropertyName, Object newPropertyValue) + { + if (newPropertyName == null) + { + /* + * Build and throw exception. + */ + OMRSErrorCode errorCode = OMRSErrorCode.NULL_PROPERTY_NAME; + String errorMessage = errorCode.getErrorMessageId() + + errorCode.getFormattedErrorMessage(); + + throw new OMRSRuntimeException(errorCode.getHTTPErrorCode(), + this.getClass().getName(), + "setProperty", + errorMessage, + errorCode.getSystemAction(), + errorCode.getUserAction()); + } + else if (newPropertyValue == null) + { + typeDefProperties.remove(newPropertyName); + } + else + { + typeDefProperties.put(newPropertyName, newPropertyValue); + } + } + + + /** + * Standard toString method. + * + * @return JSON style description of variables. + */ + @Override + public String toString() + { + return "TypeDefProperties{" + + "typeDefProperties=" + typeDefProperties + + '}'; + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/8a57e657/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefSummary.java ---------------------------------------------------------------------- diff --git a/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefSummary.java b/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefSummary.java new file mode 100644 index 0000000..864c82d --- /dev/null +++ b/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/properties/typedefs/TypeDefSummary.java @@ -0,0 +1,168 @@ +/* + * 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.omrs.metadatacollection.properties.typedefs; + + +/** + * The TypeDefSummary holds basic identifying information for a specific TypeDef. It is used in + * the registration process between repositories. + */ +public class TypeDefSummary extends TypeDefLink +{ + protected long version = 0L; + protected String versionName = null; + protected TypeDefCategory category = TypeDefCategory.UNKNOWN_DEF; + + + /** + * Default constructor + */ + public TypeDefSummary() + { + super(); + } + + + /** + * Typical constructor is passed the properties of the typedef being constructed. + * + * @param category - category of this TypeDef + * @param guid - unique id for the TypeDef + * @param name - unique name for the TypeDef + * @param version - active version number for the TypeDef + * @param versionName - unique name for the TypeDef + */ + public TypeDefSummary(TypeDefCategory category, + String guid, + String name, + long version, + String versionName) + { + super(guid, name); + + this.category = category; + this.version = version; + this.versionName = versionName; + } + + + /** + * Copy/clone constructor copies the values from the supplied template. + * + * @param template TypeDefSummary + */ + public TypeDefSummary(TypeDefSummary template) + { + super(template); + + if (template != null) + { + this.category = template.getCategory(); + this.guid = template.getGUID(); + this.versionName = template.getVersionName(); + this.version = template.getVersion(); + } + } + + + /** + * Return the category of the TypeDef. + * + * @return TypeDefCategory enum + */ + public TypeDefCategory getCategory() + { + return category; + } + + + /** + * Set up the category of the TypeDef. + * + * @param category - TypeDefCategory enum + */ + public void setCategory(TypeDefCategory category) + { + this.category = category; + } + + /** + * Return the version of the TypeDef. Versions are created when a TypeDef's properties are changed. If + * a description is updated, then this does not create a new version. + * + * @return String version number + */ + public long getVersion() + { + return version; + } + + + /** + * Set up the version of the TypeDef. Versions are created when a TypeDef's properties are changed. If + * a description is updated, then this does not create a new version. + * + * @param version - long version number + */ + public void setVersion(long version) + { + this.version = version; + } + + + /** + * Return the version name is more of a human readable form of the version number. It can be used to show whether the + * change is a minor or major update. + * + * @return String version name + */ + public String getVersionName() + { + return versionName; + } + + + /** + * Set up the version name is more of a human readable form of the version number. It can be used to show whether the + * change is a minor or major update. + * + * @param versionName - String version name + */ + public void setVersionName(String versionName) + { + this.versionName = versionName; + } + + + /** + * Standard toString method. + * + * @return JSON style description of variables. + */ + @Override + public String toString() + { + return "TypeDefSummary{" + + "version=" + version + + ", versionName='" + versionName + '\'' + + ", category=" + category + + ", guid='" + guid + '\'' + + ", name='" + name + '\'' + + '}'; + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/8a57e657/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/repositoryconnector/OMRSMetadataCollectionManager.java ---------------------------------------------------------------------- diff --git a/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/repositoryconnector/OMRSMetadataCollectionManager.java b/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/repositoryconnector/OMRSMetadataCollectionManager.java new file mode 100644 index 0000000..a001208 --- /dev/null +++ b/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/repositoryconnector/OMRSMetadataCollectionManager.java @@ -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 + * <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.omrs.metadatacollection.repositoryconnector; + +import org.apache.atlas.omrs.metadatacollection.OMRSMetadataCollection; + +/** + * OMRSRepositoryConnectors are used by OMRS to retrieve metadata from metadata repositories. Each implementation + * of the OMRSRepositoryConnector is for a different type of repository. This interface defines the extension that + * an OMRSRepositoryConnector must implement over the base connector definition. It describes the concept of a + * metadata collection. This is a collection of metadata that includes the type definitions (TypeDefs) and + * metadata instances (Entities and Relationships) stored in the repository. + */ +public interface OMRSMetadataCollectionManager +{ + /** + * Set up the unique Id for this metadata collection. + * + * @param metadataCollectionId - String unique Id + */ + void setMetadataCollectionId(String metadataCollectionId); + + + /** + * Returns the metadata collection object that provides an OMRS abstraction of the metadata within + * a metadata repository. + * + * @return OMRSMetadataCollection - metadata TypeDefs and instances retrieved from the metadata repository. + */ + OMRSMetadataCollection getMetadataCollection(); +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/8a57e657/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/repositoryconnector/OMRSRepositoryConnector.java ---------------------------------------------------------------------- diff --git a/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/repositoryconnector/OMRSRepositoryConnector.java b/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/repositoryconnector/OMRSRepositoryConnector.java new file mode 100644 index 0000000..46bd19a --- /dev/null +++ b/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/repositoryconnector/OMRSRepositoryConnector.java @@ -0,0 +1,29 @@ +/* + * 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.omrs.metadatacollection.repositoryconnector; + +import org.apache.atlas.ocf.ConnectorBase; + + +/** + * The OMRSRepositoryConnector provides access to the secure properties for OMRS Connector implementations. + * Subclasses need to implement the OMRSMetadataCollectionManager interface. + */ +public abstract class OMRSRepositoryConnector extends ConnectorBase implements OMRSMetadataCollectionManager +{ +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/8a57e657/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/repositoryconnector/OMRSRepositoryConnectorProviderBase.java ---------------------------------------------------------------------- diff --git a/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/repositoryconnector/OMRSRepositoryConnectorProviderBase.java b/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/repositoryconnector/OMRSRepositoryConnectorProviderBase.java new file mode 100644 index 0000000..c05747c --- /dev/null +++ b/omrs/src/main/java/org/apache/atlas/omrs/metadatacollection/repositoryconnector/OMRSRepositoryConnectorProviderBase.java @@ -0,0 +1,43 @@ +/* + * 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.omrs.metadatacollection.repositoryconnector; + +import org.apache.atlas.ocf.ConnectorProviderBase; + +/** + * The OMRSRepositoryConnectorProviderBase provides a base class for the connector provider supporting OMRS Connectors. + * It adds no function but provides a placeholder for additional function if needed for the creation of + * any OMRS Repository connectors. + * + * It extends ConnectorProviderBase which does the creation of connector instances. The subclasses of + * OMRSRepositoryConnectorProviderBase must initialize ConnectorProviderBase with the Java class + * name of the OMRS Connector implementation (by calling super.setConnectorClassName(className)). + * Then the connector provider will work. + */ +public abstract class OMRSRepositoryConnectorProviderBase extends ConnectorProviderBase +{ + /** + * Default Constructor + */ + public OMRSRepositoryConnectorProviderBase() + { + /* + * Nothing to do + */ + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/8a57e657/omrs/src/main/java/org/apache/atlas/omrs/metadatahighway/CohortConnectionStatus.java ---------------------------------------------------------------------- diff --git a/omrs/src/main/java/org/apache/atlas/omrs/metadatahighway/CohortConnectionStatus.java b/omrs/src/main/java/org/apache/atlas/omrs/metadatahighway/CohortConnectionStatus.java new file mode 100644 index 0000000..65eb068 --- /dev/null +++ b/omrs/src/main/java/org/apache/atlas/omrs/metadatahighway/CohortConnectionStatus.java @@ -0,0 +1,122 @@ +/* + * 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.omrs.metadatahighway; + + +/** + * CohortConnectionStatus defines the status of the local server's connection to the metadata highway for + * a specific cohort. + * <ul> + * <li> + * NOT_INITIALIZED - the local components for communicating with other members of the cohort are not initialized. + * This should never been seen on the admin console since it is the value for the cohort manager used on the + * variable declaration. + * </li> + * <li> + * INITIALIZING - the local components for communicating with the other members of the cohort are initializing. + * It the server is working properly this status is only set for a split-second. + * If it is seen on the admin console it probably means one of the underlying connectors is hanging during its + * initialization. + * </li> + * <li> + * NEW - the local components for the cohort are initialized but they have not yet exchanged messages with the other + * members of the cohort. At this point, the local metadata collection id may be changed. + * </li> + * <li> + * CONFIGURATION_ERROR - means there is an error in the configuration and connection is not possible. + * The administrator needs to either fix the config or fix the system's infrastructure around the server. + * </li> + * <li> + * CONNECTED - means the server is connected to the metadata highway for this cohort and is exchanging messages. + * </li> + * <li> + * DISCONNECTING - means the server is disconnecting from the metadata highway and is in the process of shutting + * down the local components that manage communication with the other members of this cohort. + * </li> + * <li> + * DISCONNECTED - means the server is disconnected from the metadata highway for this cohort. This may be because the + * local server is shutting down or the configuration is being adjusted. + * </li> + * </ul> + */ +public enum CohortConnectionStatus +{ + NOT_INITIALIZED (0, "NotInitialized", "The local components for communicating with the cohort are not initialized."), + INITIALIZING (1, "Initializing", "The local components for communicating with the cohort are initializing."), + NEW (2, "New", "The local components for communicating with the cohort are initialized " + + "but they have not exchanged messages with the other members of cohort."), + CONFIGURATION_ERROR (3, "ConfigurationError", "There is an error in the configuration and connection is not possible."), + CONNECTED (4, "Connected", "The server is connected to the metadata highway for this cohort and messages " + + "are being exchanged with other members of the cohort."), + DISCONNECTING (5, "Initializing", "The local components for communicating with the cohort are disconnecting."), + DISCONNECTED (6, "Disconnected", "The server is disconnected from the metadata highway for this cohort. This may be because the " + + "local server is shutting down or the configuration is being adjusted."); + + + private int statusCode; + private String statusName; + private String statusDescription; + + + /** + * Create an instance of the enum. + * + * @param statusCode - numeric code + * @param statusName - name + * @param statusDescription - description + */ + CohortConnectionStatus(int statusCode, String statusName, String statusDescription) + { + this.statusCode = statusCode; + this.statusName = statusName; + this.statusDescription = statusDescription; + } + + + /** + * Return the numeric code for the enum. + * + * @return int code + */ + public int getStatusCode() + { + return statusCode; + } + + + /** + * Return the name for the enum. + * + * @return String name + */ + public String getStatusName() + { + return statusName; + } + + + /** + * Return the description of the enum. + * + * @return String description + */ + public String getStatusDescription() + { + return statusDescription; + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/8a57e657/omrs/src/main/java/org/apache/atlas/omrs/metadatahighway/OMRSCohortManager.java ---------------------------------------------------------------------- diff --git a/omrs/src/main/java/org/apache/atlas/omrs/metadatahighway/OMRSCohortManager.java b/omrs/src/main/java/org/apache/atlas/omrs/metadatahighway/OMRSCohortManager.java new file mode 100644 index 0000000..755dae8 --- /dev/null +++ b/omrs/src/main/java/org/apache/atlas/omrs/metadatahighway/OMRSCohortManager.java @@ -0,0 +1,382 @@ +/* + * 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.omrs.metadatahighway; + +import org.apache.atlas.ocf.ffdc.ConnectorCheckedException; +import org.apache.atlas.omrs.admin.properties.OpenMetadataEventProtocolVersion; +import org.apache.atlas.omrs.auditlog.OMRSAuditCode; +import org.apache.atlas.omrs.auditlog.OMRSAuditLog; +import org.apache.atlas.omrs.auditlog.OMRSAuditingComponent; +import org.apache.atlas.omrs.ffdc.OMRSErrorCode; +import org.apache.atlas.omrs.ffdc.exception.OMRSConnectorErrorException; +import org.apache.atlas.omrs.metadatahighway.cohortregistry.OMRSCohortRegistry; +import org.apache.atlas.omrs.metadatahighway.cohortregistry.store.OMRSCohortRegistryStore; +import org.apache.atlas.omrs.eventmanagement.*; +import org.apache.atlas.omrs.enterprise.connectormanager.OMRSConnectionConsumer; +import org.apache.atlas.omrs.localrepository.OMRSLocalRepository; +import org.apache.atlas.omrs.eventmanagement.OMRSRepositoryEventExchangeRule; +import org.apache.atlas.omrs.topicconnectors.OMRSTopicConnector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * The OMRSCohortManager manages the components that connect to a single open metadata repository cohort. + */ +public class OMRSCohortManager +{ + private String cohortName = null; + private OMRSTopicConnector cohortTopicConnector = null; + private OMRSRepositoryEventManager cohortRepositoryEventManager = null; + private OMRSCohortRegistry cohortRegistry = null; + private OMRSEventListener cohortEventListener = null; + private CohortConnectionStatus cohortConnectionStatus = CohortConnectionStatus.NOT_INITIALIZED; + + private OMRSRepositoryEventManager localRepositoryEventManager = null; + + private static final OMRSAuditLog auditLog = new OMRSAuditLog(OMRSAuditingComponent.COHORT_MANAGER); + + private static final Logger log = LoggerFactory.getLogger(OMRSCohortManager.class); + + + /** + * Default Constructor that relies on the initialization of variables in their declaration. + */ + public OMRSCohortManager() + { + } + + + /** + * The constructor defines the minimum information necessary to connect to a cohort. If these values + * are not correctly configured, the constructor will throw an exception. + * + * @param cohortName - name of the cohort. This is a local name used for messages. + * @param localMetadataCollectionId - configured value for the local metadata collection id + * @param localServerName - the name of the local server. It is a descriptive name for informational purposes. + * @param localServerType - the type of the local server. It is a descriptive name for informational purposes. + * @param localOrganizationName - the name of the organization that owns the local server/repository. + * It is a descriptive name for informational purposes. + * @param localRepository - link to the local repository - may be null. + * @param connectionConsumer - The connection consumer is a component interested in maintaining details of the + * connections to each of the members of the open metadata repository cohort. If it is + * null, the cohort registry does not publish connections for members of the open + * metadata repository cohort. + * @param cohortRegistryStore - the cohort registry store where details of members of the cohort are kept + * @param cohortTopicConnector - Connector to the cohort's OMRS Topic. + * @param enterpriseTopicConnector - Connector to the federated OMRS Topic. + * @param eventProtocolVersion - Protocol to use for events to the cohort. + * @param inboundEventExchangeRule - rule for processing inbound events. + */ + public void initialize(String cohortName, + String localMetadataCollectionId, + String localServerName, + String localServerType, + String localOrganizationName, + OMRSLocalRepository localRepository, + OMRSConnectionConsumer connectionConsumer, + OMRSTopicConnector enterpriseTopicConnector, + OMRSCohortRegistryStore cohortRegistryStore, + OMRSTopicConnector cohortTopicConnector, + OpenMetadataEventProtocolVersion eventProtocolVersion, + OMRSRepositoryEventExchangeRule inboundEventExchangeRule) + { + final String actionDescription = "Initialize Cohort Manager"; + + if (log.isDebugEnabled()) + { + log.debug(actionDescription); + } + + try + { + this.cohortName = cohortName; + + OMRSAuditCode auditCode = OMRSAuditCode.COHORT_INITIALIZING; + auditLog.logRecord(actionDescription, + auditCode.getLogMessageId(), + auditCode.getSeverity(), + auditCode.getFormattedLogMessage(cohortName), + null, + auditCode.getSystemAction(), + auditCode.getUserAction()); + + /* + * Set up the config status. It is updated multiple times during this method to help detect whether + * underlying component are hanging in their initialization. Most of these intermediary states are + * unlikely to be seen. + */ + this.cohortConnectionStatus = CohortConnectionStatus.INITIALIZING; + + /* + * Create the event manager for processing incoming events from the cohort's OMRS Topic. + */ + this.cohortRepositoryEventManager = new OMRSRepositoryEventManager(inboundEventExchangeRule); + + /* + * Create an event publisher for the cohort registry to use to send registration requests. + */ + OMRSEventPublisher outboundRegistryEventProcessor = new OMRSEventPublisher(cohortName, + eventProtocolVersion, + cohortTopicConnector); + + /* + * The presence/absence of the local repository affects the behaviour of the cohort registry. + */ + if (localRepository != null) + { + /* + * The local repository is present so set up the CohortRegistry to play a full role in the protocol. + */ + this.cohortRegistry.initialize(cohortName, + localMetadataCollectionId, + localRepository.getLocalRepositoryRemoteConnection(), + localServerName, + localServerType, + localOrganizationName, + outboundRegistryEventProcessor, + cohortRegistryStore, + localRepository.getTypeDefValidator(), + connectionConsumer); + + localRepositoryEventManager = localRepository.getOutboundRepositoryEventManager(); + + if (localRepositoryEventManager != null) + { + /* + * Register an event publisher with the local repository for this cohort. This will mean + * other members of the cohort can receive events from the local server's repository. + */ + OMRSEventPublisher repositoryEventPublisher = new OMRSEventPublisher(cohortName, + eventProtocolVersion, + cohortTopicConnector); + + + localRepositoryEventManager.registerTypeDefProcessor(repositoryEventPublisher); + localRepositoryEventManager.registerInstanceProcessor(repositoryEventPublisher); + } + + /* + * Register the local repository's processors with the cohort's event manager. This will + * route incoming repository events to the local repository. + */ + if (localRepository.getIncomingTypeDefEventProcessor() != null) + { + this.cohortRepositoryEventManager.registerTypeDefProcessor( + localRepository.getIncomingTypeDefEventProcessor()); + } + if (localRepository.getIncomingInstanceEventProcessor() != null) + { + this.cohortRepositoryEventManager.registerInstanceProcessor( + localRepository.getIncomingInstanceEventProcessor()); + } + } + else /* no local repository */ + { + /* + * If there is no local repository, then the cohort registry is focusing on managing registrations + * from remote members of the cohort to configure the enterprise access capability. + */ + this.cohortRegistry.initialize(cohortName, + null, + null, + localServerName, + localServerType, + localOrganizationName, + outboundRegistryEventProcessor, + null, + null, + connectionConsumer); + } + + /* + * If the enterprise omrs topic is active, then register an event publisher for it. + * This topic is active if the Open Metadata Access Services (OMASs) are active. + */ + if (enterpriseTopicConnector != null) + { + OMRSEventPublisher enterpriseEventPublisher = new OMRSEventPublisher("OMAS Enterprise Access", + eventProtocolVersion, + cohortTopicConnector); + + this.cohortRepositoryEventManager.registerInstanceProcessor(enterpriseEventPublisher); + } + + this.cohortConnectionStatus = CohortConnectionStatus.NEW; + + /* + * The cohort topic connector is used by the local cohort components to communicate with the other + * members of the cohort. + */ + if (cohortTopicConnector != null) + { + /* + * Finally create the event listener and register it with the cohort OMRS Topic. + */ + OMRSEventListener cohortEventListener = new OMRSEventListener(cohortName, + localMetadataCollectionId, + this.cohortRegistry, + this.cohortRepositoryEventManager, + this.cohortRepositoryEventManager); + cohortTopicConnector.registerListener(cohortEventListener); + this.cohortTopicConnector = cohortTopicConnector; + this.cohortEventListener = cohortEventListener; + + /* + * Once the event infrastructure is set up it is ok to send out registration requests to the + * rest of the cohort. + */ + this.cohortRegistry.connectToCohort(); + + this.cohortConnectionStatus = CohortConnectionStatus.CONNECTED; + } + } + catch (Throwable error) + { + this.cohortConnectionStatus = CohortConnectionStatus.CONFIGURATION_ERROR; + throw error; + } + + if (log.isDebugEnabled()) + { + log.debug(actionDescription + " COMPLETE"); + } + } + + + /** + * Return the name of the cohort. + * + * @return String name + */ + public String getCohortName() + { + return cohortName; + } + + + /** + * Return the status of the connection with the metadata highway. + * + * @return CohortConnectionStatus + */ + public CohortConnectionStatus getCohortConnectionStatus() + { + return cohortConnectionStatus; + } + + + /** + * Disconnect from the cohort. + * + * @param permanent - flag indicating if the local repository should unregister from the cohort because it is + * not going ot connect again. + */ + public synchronized void disconnect(boolean permanent) + { + final String actionDescription = "Disconnect Cohort Manager"; + + if (log.isDebugEnabled()) + { + log.debug(actionDescription); + } + + try + { + cohortConnectionStatus = CohortConnectionStatus.DISCONNECTING; + + OMRSAuditCode auditCode = OMRSAuditCode.COHORT_DISCONNECTING; + auditLog.logRecord(actionDescription, + auditCode.getLogMessageId(), + auditCode.getSeverity(), + auditCode.getFormattedLogMessage(cohortName), + null, + auditCode.getSystemAction(), + auditCode.getUserAction()); + + if (cohortRegistry != null) + { + cohortRegistry.disconnectFromCohort(permanent); + } + + if (cohortTopicConnector != null) + { + cohortTopicConnector.disconnect(); + } + + cohortConnectionStatus = CohortConnectionStatus.DISCONNECTED; + } + catch (ConnectorCheckedException error) + { + if (log.isDebugEnabled()) + { + log.debug(actionDescription + " FAILED with connector checked exception"); + } + + /* + * Throw runtime exception to indicate that the cohort registry is not available. + */ + OMRSErrorCode errorCode = OMRSErrorCode.COHORT_DISCONNECT_FAILED; + String errorMessage = errorCode.getErrorMessageId() + + errorCode.getFormattedErrorMessage(cohortName); + + throw new OMRSConnectorErrorException(errorCode.getHTTPErrorCode(), + this.getClass().getName(), + actionDescription, + errorMessage, + errorCode.getSystemAction(), + errorCode.getUserAction(), + error); + + } + catch (Throwable error) + { + if (log.isDebugEnabled()) + { + log.debug(actionDescription + " FAILED with exception"); + } + + throw error; + } + + if (log.isDebugEnabled()) + { + log.debug(actionDescription + " COMPLETE"); + } + } + + + /** + * Standard toString method. + * + * @return JSON style description of variables. + */ + @Override + public String toString() + { + return "OMRSCohortManager{" + + "cohortName='" + cohortName + '\'' + + ", cohortTopicConnector=" + cohortTopicConnector + + ", cohortRepositoryEventManager=" + cohortRepositoryEventManager + + ", cohortRegistry=" + cohortRegistry + + ", cohortEventListener=" + cohortEventListener + + ", cohortConnectionStatus=" + cohortConnectionStatus + + ", localRepositoryEventManager=" + localRepositoryEventManager + + '}'; + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/8a57e657/omrs/src/main/java/org/apache/atlas/omrs/metadatahighway/OMRSMetadataHighwayManager.java ---------------------------------------------------------------------- diff --git a/omrs/src/main/java/org/apache/atlas/omrs/metadatahighway/OMRSMetadataHighwayManager.java b/omrs/src/main/java/org/apache/atlas/omrs/metadatahighway/OMRSMetadataHighwayManager.java new file mode 100644 index 0000000..07ef814 --- /dev/null +++ b/omrs/src/main/java/org/apache/atlas/omrs/metadatahighway/OMRSMetadataHighwayManager.java @@ -0,0 +1,453 @@ +/* + * 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.omrs.metadatahighway; + +import org.apache.atlas.ocf.Connector; +import org.apache.atlas.ocf.ConnectorBroker; +import org.apache.atlas.ocf.properties.Connection; +import org.apache.atlas.omrs.admin.properties.CohortConfig; +import org.apache.atlas.omrs.auditlog.OMRSAuditCode; +import org.apache.atlas.omrs.auditlog.OMRSAuditLog; +import org.apache.atlas.omrs.auditlog.OMRSAuditingComponent; +import org.apache.atlas.omrs.ffdc.exception.OMRSLogicErrorException; +import org.apache.atlas.omrs.metadatahighway.cohortregistry.store.OMRSCohortRegistryStore; +import org.apache.atlas.omrs.eventmanagement.*; +import org.apache.atlas.omrs.enterprise.connectormanager.OMRSConnectionConsumer; +import org.apache.atlas.omrs.ffdc.exception.OMRSConfigErrorException; +import org.apache.atlas.omrs.ffdc.OMRSErrorCode; +import org.apache.atlas.omrs.localrepository.OMRSLocalRepository; +import org.apache.atlas.omrs.localrepository.repositorycontentmanager.OMRSTypeDefValidator; +import org.apache.atlas.omrs.topicconnectors.OMRSTopicConnector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; + +/** + * OMRSMetadataHighwayManager is responsible for managing the connectivity to to each cohort that the local + * server is a member of. + */ +public class OMRSMetadataHighwayManager +{ + private ArrayList<OMRSCohortManager> cohortManagers = new ArrayList<>(); + + private String localServerName = null; + private String localServerType = null; + private String localOrganizationName = null; + private OMRSLocalRepository localRepository = null; + private OMRSTypeDefValidator localTypeDefValidator = null; + private OMRSConnectionConsumer enterpriseAccessConnectionConsumer = null; + private OMRSTopicConnector enterpriseAccessTopicConnector = null; + + + private static final OMRSAuditLog auditLog = new OMRSAuditLog(OMRSAuditingComponent.METADATA_HIGHWAY_MANAGER); + + private static final Logger log = LoggerFactory.getLogger(OMRSEventPublisher.class); + + /** + * Constructor taking the values that are used in every cohort. Any of these values may be null. + * + * @param localServerName - name of the local server. + * @param localServerType - descriptive type of the local server. + * @param localOrganizationName - name of the organization that owns the local server. + * @param localRepository - link to local repository - may be null. + * @param localTypeDefValidator - the TypeDefValidator is ues in evaluating the type definitions (TypeDefs) + * passed around the cohort. + * @param enterpriseAccessConnectionConsumer - connection consumer for managing the connections of enterprise access. + * @param enterpriseAccessTopicConnector - connector for the OMRS Topic for enterprise access. + */ + public OMRSMetadataHighwayManager(String localServerName, + String localServerType, + String localOrganizationName, + OMRSLocalRepository localRepository, + OMRSTypeDefValidator localTypeDefValidator, + OMRSConnectionConsumer enterpriseAccessConnectionConsumer, + OMRSTopicConnector enterpriseAccessTopicConnector) + { + this.localServerName = localServerName; + this.localServerType = localServerType; + this.localOrganizationName = localOrganizationName; + this.localRepository = localRepository; + this.localTypeDefValidator = localTypeDefValidator; + this.enterpriseAccessConnectionConsumer = enterpriseAccessConnectionConsumer; + this.enterpriseAccessTopicConnector = enterpriseAccessTopicConnector; + } + + + /** + * Initialize each cohort manager in turn. Configuration errors will result in an exception and the initialization + * process will halt. + * + * @param cohortConfigList - list of cohorts to initialize + */ + public void initialize(ArrayList<CohortConfig> cohortConfigList) + { + if (cohortConfigList != null) + { + /* + * Loop through the configured cohorts + */ + for (CohortConfig cohortConfig : cohortConfigList) + { + this.connectToCohort(cohortConfig); + } + } + } + + + /** + * Initialize the components to connect the local repository to a cohort. + * + * @param cohortConfig - description of cohort. + * @return the status of the cohort + */ + public CohortConnectionStatus connectToCohort(CohortConfig cohortConfig) + { + OMRSCohortManager cohortManager = new OMRSCohortManager(); + String localMetadataCollectionId = null; + String actionDescription = "Connect to Cohort"; + + /* + * Validate the cohort name exists + */ + if (cohortConfig.getCohortName() == null) + { + OMRSErrorCode errorCode = OMRSErrorCode.NULL_COHORT_NAME; + String errorMessage = errorCode.getErrorMessageId() + + errorCode.getFormattedErrorMessage(); + + throw new OMRSLogicErrorException(errorCode.getHTTPErrorCode(), + this.getClass().getName(), + actionDescription, + errorMessage, + errorCode.getSystemAction(), + errorCode.getUserAction()); + } + + /* + * Loop through the existing cohort managers to make sure the new cohort name is unique + */ + for (OMRSCohortManager existingCohortManager : cohortManagers) + { + if (existingCohortManager != null) + { + if (cohortConfig.getCohortName().equals(existingCohortManager.getCohortName())) + { + OMRSErrorCode errorCode = OMRSErrorCode.DUPLICATE_COHORT_NAME; + String errorMessage = errorCode.getErrorMessageId() + + errorCode.getFormattedErrorMessage(cohortConfig.getCohortName()); + + throw new OMRSLogicErrorException(errorCode.getHTTPErrorCode(), + this.getClass().getName(), + actionDescription, + errorMessage, + errorCode.getSystemAction(), + errorCode.getUserAction()); + } + } + } + + /* + * Extract the local metadata collection id if there is a local repository + */ + if (localRepository != null) + { + localMetadataCollectionId = localRepository.getMetadataCollectionId(); + } + + /* + * Create the resources needed by the cohort and initialize them in a cohort manager. + */ + try + { + OMRSCohortRegistryStore cohortRegistryStore + = getCohortRegistryStore(cohortConfig.getCohortName(), + cohortConfig.getCohortRegistryConnection()); + + OMRSTopicConnector cohortTopicConnector + = getTopicConnector(cohortConfig.getCohortName(), + cohortConfig.getCohortOMRSTopicConnection()); + + OMRSRepositoryEventExchangeRule inboundEventExchangeRule + = new OMRSRepositoryEventExchangeRule(cohortConfig.getCohortName() + " Events To Process", + localTypeDefValidator, + cohortConfig.getEventsToProcessRule(), + cohortConfig.getSelectedTypesToProcess()); + + cohortManager.initialize(cohortConfig.getCohortName(), + localMetadataCollectionId, + localServerName, + localServerType, + localOrganizationName, + localRepository, + enterpriseAccessConnectionConsumer, + enterpriseAccessTopicConnector, + cohortRegistryStore, + cohortTopicConnector, + cohortConfig.getCohortOMRSTopicProtocolVersion(), + inboundEventExchangeRule); + + /* + * The cohort manager is only added to the list if it initializes successfully. + */ + cohortManagers.add(cohortManager); + } + catch (OMRSConfigErrorException error) + { + OMRSAuditCode auditCode = OMRSAuditCode.COHORT_CONFIG_ERROR; + auditLog.logRecord(actionDescription, + auditCode.getLogMessageId(), + auditCode.getSeverity(), + auditCode.getFormattedLogMessage(cohortConfig.getCohortName()), + null, + auditCode.getSystemAction(), + auditCode.getUserAction()); + + throw error; + } + catch (Throwable error) + { + throw error; + } + + return cohortManager.getCohortConnectionStatus(); + } + + + /** + * Return the status of the named cohort. + * + * @param cohortName name of cohort + * @return connection status - if the cohort manager is not running then "NOT_INITIALIZED" is returned + */ + public CohortConnectionStatus getCohortConnectionStatus(String cohortName) + { + String actionDescription = "Get cohort status"; + + if (cohortName == null) + { + OMRSErrorCode errorCode = OMRSErrorCode.NULL_COHORT_NAME; + String errorMessage = errorCode.getErrorMessageId() + + errorCode.getFormattedErrorMessage(); + + throw new OMRSLogicErrorException(errorCode.getHTTPErrorCode(), + this.getClass().getName(), + actionDescription, + errorMessage, + errorCode.getSystemAction(), + errorCode.getUserAction()); + } + + for (OMRSCohortManager existingCohortManager : cohortManagers) + { + if (existingCohortManager != null) + { + if (cohortName.equals(existingCohortManager.getCohortName())) + { + return existingCohortManager.getCohortConnectionStatus(); + } + } + } + + /* + * No cohort manager was found so return not initialized. + */ + return CohortConnectionStatus.NOT_INITIALIZED; + } + + + /** + * Disconnect communications from a specific cohort. + * + * @param cohortName - name of cohort + * @param permanent - is the local server permanently disconnecting from the cohort - causes an unregistration + * event to be sent to the other members. + * @return boolean flag to indicate success. + */ + public boolean disconnectFromCohort(String cohortName, boolean permanent) + { + String actionDescription = "Disconnect cohort"; + + if (cohortName == null) + { + OMRSErrorCode errorCode = OMRSErrorCode.NULL_COHORT_NAME; + String errorMessage = errorCode.getErrorMessageId() + + errorCode.getFormattedErrorMessage(); + + throw new OMRSLogicErrorException(errorCode.getHTTPErrorCode(), + this.getClass().getName(), + actionDescription, + errorMessage, + errorCode.getSystemAction(), + errorCode.getUserAction()); + } + + for (OMRSCohortManager existingCohortManager : cohortManagers) + { + if (existingCohortManager != null) + { + if (cohortName.equals(existingCohortManager.getCohortName())) + { + existingCohortManager.disconnect(permanent); + return true; + } + } + } + + return false; + } + + + /** + * Disconnect from all cohorts. + * + * @param permanent - indicates whether the cohort registry should unregister from the cohort + * and clear its registry store or just disconnect from the event topic. + */ + public void disconnect(boolean permanent) + { + final String actionDescription = "Disconnecting from metadata highway"; + + if (log.isDebugEnabled()) + { + log.debug(actionDescription); + } + + for (OMRSCohortManager cohortManager : cohortManagers) + { + if (cohortManager != null) + { + cohortManager.disconnect(permanent); + } + } + + if (log.isDebugEnabled()) + { + log.debug(actionDescription + " COMPLETE"); + } + } + + + /** + * Create a connector to the cohort registry store. If there is a problem with the connection information + * that means a connector can not be created, an exception is thrown. + * + * @param cohortName - name of the cohort that this registry store is for + * @param cohortRegistryConnection - connection to the cluster registry store. + * @return OMRSCohortRegistryStore connector + */ + private OMRSCohortRegistryStore getCohortRegistryStore(String cohortName, + Connection cohortRegistryConnection) + { + final String methodName = "getCohortRegistryStore()"; + + try + { + ConnectorBroker connectorBroker = new ConnectorBroker(); + Connector connector = connectorBroker.getConnector(cohortRegistryConnection); + + return (OMRSCohortRegistryStore)connector; + } + catch (Throwable error) + { + if (log.isDebugEnabled()) + { + log.debug("Unable to create cohort registry store connector: " + error.toString()); + } + + /* + * Throw runtime exception to indicate that the cohort registry is not available. + */ + OMRSErrorCode errorCode = OMRSErrorCode.NULL_REGISTRY_STORE; + String errorMessage = errorCode.getErrorMessageId() + + errorCode.getFormattedErrorMessage(cohortName); + + throw new OMRSConfigErrorException(errorCode.getHTTPErrorCode(), + this.getClass().getName(), + methodName, + errorMessage, + errorCode.getSystemAction(), + errorCode.getUserAction(), + error); + } + } + + /** + * Creates a topic connector using information from the supplied topic connection. This connector supported + * the Open Connector Framework (OCF) so it is possible to configure different connector implementations for + * different event/messaging infrastructure. If there is a problem with the connection information + * that means a connector can not be created, an exception is thrown. + * + * @param cohortName - name of the cohort that this registry store is for + * @param topicConnection - connection parameters + * @return OMRSTopicConnector for managing communications with the event/messaging infrastructure. + */ + private OMRSTopicConnector getTopicConnector(String cohortName, + Connection topicConnection) + { + try + { + ConnectorBroker connectorBroker = new ConnectorBroker(); + Connector connector = connectorBroker.getConnector(topicConnection); + + return (OMRSTopicConnector)connector; + } + catch (Throwable error) + { + String methodName = "getTopicConnector()"; + + if (log.isDebugEnabled()) + { + log.debug("Unable to create topic connector: " + error.toString()); + } + + OMRSErrorCode errorCode = OMRSErrorCode.NULL_TOPIC_CONNECTOR; + String errorMessage = errorCode.getErrorMessageId() + + errorCode.getFormattedErrorMessage(cohortName); + + throw new OMRSConfigErrorException(errorCode.getHTTPErrorCode(), + this.getClass().getName(), + methodName, + errorMessage, + errorCode.getSystemAction(), + errorCode.getUserAction(), + error); + } + } + + + /** + * Standard toString method. + * + * @return JSON style description of variables. + */ + @Override + public String toString() + { + return "OMRSMetadataHighwayManager{" + + "cohortManagers=" + cohortManagers + + ", localServerName='" + localServerName + '\'' + + ", localServerType='" + localServerType + '\'' + + ", localOrganizationName='" + localOrganizationName + '\'' + + ", localRepository=" + localRepository + + ", localTypeDefValidator=" + localTypeDefValidator + + ", enterpriseAccessConnectionConsumer=" + enterpriseAccessConnectionConsumer + + ", enterpriseAccessTopicConnector=" + enterpriseAccessTopicConnector + + '}'; + } +}
