/**
* Copyright (c) 2009-2010 Misys Open Source Solutions (MOSS) and others
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Contributors:
* Misys Open Source Solutions - initial API and implementation
* -
*/
package org.openhealthtools.openxds.registry.adapter.omar31;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Logger;
/**
* This class implements builders for the various Axiom OMElement contents
* objects needed in submissions to XDS registry and repository connections.
*
* @author LiW
* @version 2.1 - Jan 12, 2008
*/
public class RimAxiom {
private static final Log myLog = LogFactory.getLog(RimAxiom.class);
private static final String XDS_RIM_V3_NAMESPACE = "urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0";
private static final String HAS_MEMBER = "urn:oasis:names:tc:ebxml-regrep:AssociationType:HasMember";
private static final String RPLC = "urn:oasis:names:tc:ebxml-regrep:AssociationType:RPLC";
//private static final int RIM_SHORT_NAME = 64;
private static final int RIM_LONG_NAME = 128;
private static OMNamespace nsRim = OMAbstractFactory.getOMFactory().createOMNamespace(XDS_RIM_V3_NAMESPACE, "rim");
private OMElement root = null;
private String id = null;
private Log log = null;
/**
* Create a new XML builder.
*
* @param id The ID to assign to the ExtrinsicObject being built
* @param connection The connection description for where this XML will be sent
*/
RimAxiom(String id, Log log) {
this.id = id;
this.log = log;
}
/**
* Get a new instance of an XML builder for ebRIM XDSDocumentEntry metadata.
*
* @param id The id for the ExtrinsicObject representing the metadata
* @param connection The connection to which this metadata will be sent
* @param log The log to use when reporting warnings and errors
* @return The ebRIM XML builder
*/
public static RimAxiom newXdsDocumentEntryBuilder(String id, Log log) {
RimAxiom xml = new RimAxiom(id, log);
OMFactory fac = OMAbstractFactory.getOMFactory();
xml.root = fac.createOMElement("ExtrinsicObject", nsRim);
xml.root.addAttribute("id", id, null);
return xml;
}
/**
* Get a new instance of an XML builder for ebRIM XDSSubmissionSet metadata.
*
* @param id The id for the RegistryPackage representing the metadata
* @param connection The connection to which this metadata will be sent
* @param log The log to use when reporting warnings and errors
* @return The ebRIM XML builder
*/
public static RimAxiom newXdsSubmissionSetBuilder(String id, Log log) {
RimAxiom xml = new RimAxiom(id, log);
OMFactory fac = OMAbstractFactory.getOMFactory();
xml.root = fac.createOMElement("RegistryPackage", nsRim);
xml.root.addAttribute("id", id, null);
return xml;
}
/**
* Get the OMElement built by this builder.
*
* @return The XML Axiom OMElemnt document
*/
public OMElement getRootElement() {
return root;
}
/**
* Add an attribute to the root of this ebRIM object.
*
* @param name The name of the attribute
* @param value The value of the attribute
* @param isRequired True if this attribute is required to be present
* @throws XdsRimException When a required attribute has the value null
*/
public void addAttribute(String name, String value, boolean isRequired) throws XdsRimException {
if (value != null) {
root.addAttribute(name, value, null);
} else if (isRequired) {
throw new XdsRimException("Required attribute \"" + name + "\" not supplied.");
}
}
/**
* Add a name to this ebRIM object.
*
* @param name The name to add
* @param isRequired True if this name is required to be present
* @throws XdsRimException When a required name has the value null
*/
public void addName(String name, boolean isRequired) throws XdsRimException {
if (name != null) {
addRimNameElement(root, name, nsRim);
} else if (isRequired) {
throw new XdsRimException("Required Name not supplied.");
}
}
/**
* Add a description to this ebRIM object.
*
* @param comment The description to add
* @param isRequired True if this description is required to be present
* @throws XdsRimException When a required description has the value null
*/
public void addDescription(String comment, boolean isRequired) throws XdsRimException {
if (comment != null) {
addRimDescriptionElement(root, comment, nsRim);
} else if (isRequired) {
throw new XdsRimException("Required Description not supplied.");
}
}
/**
* Add a single valued slot to this ebRIM object.
*
* @param name The slot name
* @param value The slot value
* @param isRequired True if this slot must have a value in this ebRIM object
* @throws XdsRimException If this slot is required but has a null value
*/
public void addSlot(String name, String value, boolean isRequired) throws XdsRimException {
if (value != null) {
addRimSlotElement(root, name, value, nsRim);
} else if (isRequired) {
throw new XdsRimException("Required slot \"" + name + "\" not supplied.");
}
}
/**
* Add a multi-valued slot to this ebRIM.
*
* @param name The slot name
* @param values The slots values
* @param isRequired True if this slot must have a value in this ebRIM object
* @throws XdsRimException If this slot is required but has no value
*/
public void addSlot(String name, List<String> values, boolean isRequired) throws XdsRimException {
if (values != null) {
addRimSlotElement(root, name, values, nsRim);
} else if (isRequired) {
throw new XdsRimException("Required slot \"" + name + "\" not supplied.");
}
}
/**
* Add a classification to this ebRIM object.
*
* @param codeType The name of the code type to use for this classification
* @param value The code value
* @param classificationScheme The classification scheme for this code type
* @param classId The classification id
* @param isRequired True if this classification must be in this ebRIM object
* @throws XdsRimException When the classification value does correspond to a known code
*/
public void addClassification(String displayName, String codingScheme, String value, String classificationScheme, String classId, boolean isRequired) throws XdsRimException {
if (value == null) {
if (isRequired)
throw new XdsRimException("Required classification \"" + codingScheme + "\" not supplied.");
} else {
addRimClassificationElement(root, classId, id, value, classificationScheme, displayName, codingScheme, nsRim);
}
}
/**
* Add a multi-valued classification to this ebRIM object.
*
* @param codeType The name of the code type to use for this classification
* @param values A collection of code values
* @param classificationScheme The classification scheme for this code type
* @param classId The classification id
* @param isRequired True if this classification must be in this ebRIM object
* @throws XdsRimException When the classification value does correspond to a known code
*/
public void addClassification(String displayname,String coadingscheme, Collection<String> values, String classificationScheme, String classId, boolean isRequired) throws XdsRimException {
if (values != null) {
for (String value: values) {
addClassification(displayname,coadingscheme, value, classificationScheme, classId, isRequired);
}
} else if (isRequired) {
throw new XdsRimException("Required classification \"" + coadingscheme + "\" not supplied.");
}
}
/**
* Add a multi-fielded classification to this ebRIM object.
*
* @param mainField The main field name
* @param mainValue The value of main field
* @param otherFields The name and values of other fields.
* @param classificationScheme The classification scheme for this code type
* @param classId The classification id
* @param isRequired True if this classification must be in this ebRIM object
* @throws XdsRimException When the classification value does correspond to a known code
*/
public void addClassification(String mainField, String mainValue, Map<String, List<String>> otherFields,
String classificationScheme, String classId, boolean isRequired) throws XdsRimException {
if( mainField != null && mainValue != null) {
addRimClassificationElement(root, classId, id, classificationScheme, mainField, mainValue, otherFields, nsRim);
} else if (isRequired) {
throw new XdsRimException("Required classification \"" + mainField + "\" not supplied.");
}
}
/**
* Add an external identifier to this ebRIM object.
*
* @param name The name of the identifier
* @param value The value
* @param identificationScheme The identification scheme this identifier belongs to
* @param registryObject The object id of registry, for example doc id.
* @param id The id of this ExternalIndentifier
* @param isRequired True if this identifier must be present in this ebRIM object
* @throws XdsRimException When this identifier is required but has the value null
*/
public void addExternalIdentifier(String name, String value, String identificationScheme, String registryObject, String id, boolean isRequired) throws XdsRimException {
if (value != null) {
addRimExternalIdentifierElement(root, value, identificationScheme, name, registryObject, id, nsRim);
} else if (isRequired) {
throw new XdsRimException("Required external identifier \"" + name + "\" not supplied.");
}
}
/* -------------------------------------------------------------------------------------- */
/**
* Add a new ebXML Axiom element of the given type and add it to the parent as
* a child element.
*
* @param parent The parent element this should be added to
* @param tagName The element tag name
* @param rimNameSpace the rim name space of the root element
* @return The created element
*/
public static OMElement addRimElement(OMElement parent, String tagName, OMNamespace rimNameSpace) {
OMFactory fac = OMAbstractFactory.getOMFactory();
OMElement child = fac.createOMElement(tagName, rimNameSpace);
parent.addChild(child);
return child;
}
/**
* Add a new ebXML Name element to the parent element.
*
* @param parent The parent element this should be added to
* @param name The name data to put in the element
* @param rimNameSpace the rim name space of the root element
* @return The new name element
*/
public static OMElement addRimNameElement(OMElement parent, String name, OMNamespace rimNameSpace) {
OMElement nameElement = addRimElement(parent, "Name", rimNameSpace);
OMElement localized = addRimElement(nameElement, "LocalizedString", rimNameSpace);
localized.addAttribute("value", trimRimString(name, RIM_LONG_NAME), null);
return nameElement;
}
/**
* Add a new ebXML Description element to the parent element.
*
* @param parent The parent element this should be added to
* @param comment The comment data to put in the element
* @param rimNameSpace the rim name space of the root element
* @return The new name element
*/
public static OMElement addRimDescriptionElement(OMElement parent, String comment, OMNamespace rimNameSpace){
OMElement descElement = addRimElement(parent, "Description", rimNameSpace);
OMElement localized = addRimElement(descElement, "LocalizedString", rimNameSpace);
localized.addAttribute("value", trimRimString(comment, RIM_LONG_NAME), null);
return descElement;
}
/**
* Add a new ebXML Slot element to the parent element.
*
* @param parent The parent element this should be added to
* @param name The name of the slot
* @param value The value of the slot
* @param rimNameSpace the rim name space of the root element
* @return The new slot element
*/
public static OMElement addRimSlotElement(OMElement parent, String name, String value, OMNamespace rimNameSpace) {
OMElement slotElement = addRimElement(parent, "Slot", rimNameSpace);
slotElement.addAttribute("name", name, null);
OMElement valueList = addRimElement(slotElement, "ValueList", rimNameSpace);
OMElement valueNode = addRimElement(valueList, "Value", rimNameSpace);
OMFactory fac = OMAbstractFactory.getOMFactory();
valueNode.addChild(fac.createOMText(trimRimString(value, RIM_LONG_NAME)));
return slotElement;
}
/**
* Add a new ebXML Slot element to the parent element.
*
* @param parent The parent element this should be added to
* @param name The name of the slot
* @param values The collection of values to put into the slot value list
* @param rimNameSpace the rim name space of the root element
* @return The new slot element
*/
public static OMElement addRimSlotElement(OMElement parent, String name, List<String> values, OMNamespace rimNameSpace) {
OMElement slotElement = addRimElement(parent, "Slot", rimNameSpace);
slotElement.addAttribute("name", name, null);
OMElement valueList = addRimElement(slotElement, "ValueList", rimNameSpace);
OMFactory fac = OMAbstractFactory.getOMFactory();
for (String value: values) {
if (value == null) continue;
OMElement valueNode = addRimElement(valueList, "Value", rimNameSpace);
valueNode.addChild(fac.createOMText(trimRimString(value, RIM_LONG_NAME)));
}
return slotElement;
}
/**
* Add a new ebXML Classification element to the parent element.
*
* @param parent The parent element this should be added to
* @param classId The classification id
* @param id The id of the registry object being classified
* @param value The classification code asigned ot the registry object
* @param scheme The classification scheme/axis that the code applies to
* @param display A human-friendly display name for the code value
* @param codingScheme The coding scheme from which the code value is drawn
* @param rimNameSpace the rim name space of the root element
* @return The new classification element
*/
public static OMElement addRimClassificationElement(OMElement parent, String classId, String id, String value,
String scheme, String display, String codingScheme, OMNamespace rimNameSpace) {
OMElement classElement = addRimElement(parent, "Classification", rimNameSpace);
classElement.addAttribute("id", classId, null);
classElement.addAttribute("classificationScheme", scheme, null);
classElement.addAttribute("classifiedObject", id, null);
classElement.addAttribute("nodeRepresentation", value, null);
addRimSlotElement(classElement, "codingScheme", codingScheme, rimNameSpace);
addRimNameElement(classElement, display, rimNameSpace);
return classElement;
}
/**
* Add a new ebXML Classification element with multiple slots to the parent element.
*
* @param parent The parent element this should be added to
* @param classId The classification id
* @param id The id of the registry object being classified
* @param value The classification code asigned ot the registry object
* @param scheme The classification scheme/axis that the code applies to
* @param mainField The single valued main slot field
* @param mainValue The single display value of the main field.
* @param otherFields The multiple valued other slot fields.
* @param codingScheme The coding scheme from which the code value is drawn
* @param rimNameSpace the rim name space of the root element
* @return The new classification element
*/
public static OMElement addRimClassificationElement(OMElement parent, String classId, String id, String scheme,
String mainField, String mainValue, Map<String, List<String>> otherFields, OMNamespace rimNameSpace) {
OMElement classElement = addRimElement(parent, "Classification", rimNameSpace);
classElement.addAttribute("id", classId, null);
classElement.addAttribute("classificationScheme", scheme, null);
classElement.addAttribute("classifiedObject", id, null);
classElement.addAttribute("nodeRepresentation", "", null);
addRimSlotElement(classElement, mainField, mainValue, rimNameSpace);
Set<Map.Entry<String, List<String>>> entries = otherFields.entrySet();
for (Map.Entry<String, List<String>> entry : entries) {
String key = entry.getKey();
List<String> values = entry.getValue();
if (values != null && values.size() > 0) {
addRimSlotElement(classElement, key, values, rimNameSpace);
}
}
return classElement;
}
/**
* Add a new ebXML Classification element to the parent element.
*
* @param parent The parent element to get the classification
* @param classId The classification id
* @param id The id of the ebRIM object being classified
* @param ref The registry reference of the internal classification scheme
* @param rimNameSpace the rim name space of the root element
* @return The new classification element
*/
public static OMElement addRimClassificationElement(OMElement parent, String classId, String id, String ref, OMNamespace rimNameSpace) {
OMElement classElement = addRimElement(parent, "Classification", rimNameSpace);
classElement.addAttribute("id", classId, null);
classElement.addAttribute("classifiedObject", id, null);
classElement.addAttribute("classificationNode", ref, null);
return classElement;
}
/**
* Add a new ebXML ExternalIdentifier element to the parent element.
*
* @param parent The parent element this should be added to
* @param value The value to give to this identifier
* @param scheme The identification scheme that this identifier is drawn from
* @param display A human-friendly display name for the type of this identifier
* @param registryObject The object id of registry, for example doc id.
* @param id The id of this ExternalIndentifier
* @param rimNameSpace the rim name space of the root element
* @return The new external identifier element
*/
public static OMElement addRimExternalIdentifierElement(OMElement parent, String value, String scheme,
String display, String registryObject, String id, OMNamespace rimNameSpace) {
OMElement identifierElement = addRimElement(parent, "ExternalIdentifier", rimNameSpace);
identifierElement.addAttribute("id", id, null);
identifierElement.addAttribute("registryObject", registryObject, null);
identifierElement.addAttribute("identificationScheme", scheme, null);
identifierElement.addAttribute("value", value, null);
addRimNameElement(identifierElement, display, rimNameSpace);
return identifierElement;
}
/**
* Add a new ebXML Association element that connects a document entry to a submission set.
*
* @param parent The parent element this should be added to
* @param setId The id of the submission set
* @param docId The id of the document entry
* @param rimNameSpace the rim name space of the root element
* @return The new association element
*/
public static OMElement addRimSubmissionDocumentAssociationElement(OMElement parent,
String setId, String docId, OMNamespace rimNameSpace) {
OMElement assocElement = addRimElement(parent, "Association", rimNameSpace);
assocElement.addAttribute("id", "as-hasmember", null);
assocElement.addAttribute("associationType", HAS_MEMBER, null);
assocElement.addAttribute("sourceObject", setId, null);
assocElement.addAttribute("targetObject", docId, null);
addRimSlotElement(assocElement, "SubmissionSetStatus", "Original", rimNameSpace);
return assocElement;
}
/**
* Add a new ebXML Association element that connects a document entry to the document it is replacing.
*
* @param parent The parent element this should be added to
* @param newId The id of the new document
* @param oldId The id of the document being replaced
* @param rimNameSpace the rim name space of the root element
* @return The new association element
*/
public static OMElement addRimDocumentReplacementAssociationElement(OMElement parent,
String newId, String oldId, OMNamespace rimNameSpace) {
OMElement assocElement = addRimElement(parent, "Association", rimNameSpace);
assocElement.addAttribute("id", "as-replace", null);
assocElement.addAttribute("associationType", RPLC, null);
assocElement.addAttribute("sourceObject", newId, null);
assocElement.addAttribute("targetObject", oldId, null);
return assocElement;
}
/**
* Trim a string to the length specified in the RIM V.2 spec.
*
* @param input The input string
* @param size The maximum allowed length
* @return The input, trimmed to the specified length, if necssary
*/
private static String trimRimString(String input, int size) {
if (input == null) return null;
if (input.length() <= size) {
return input;
} else {
myLog.warn("Trimming ebXML RIM string to " + size + "characters: '" + input + "'");
return input.substring(0, size);
}
}
}