package tr.com.srdc.mdr.core.impl.ai; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import tr.com.srdc.mdr.core.MDRConstants; import tr.com.srdc.mdr.core.api.ai.ClassificationScheme; import tr.com.srdc.mdr.core.api.ai.Context; import tr.com.srdc.mdr.core.api.ai.DataElement; import tr.com.srdc.mdr.core.api.ai.DataElementConcept; import tr.com.srdc.mdr.core.api.ai.ValueDomain; import tr.com.srdc.mdr.core.api.composite.ClassificationSchemeItem; import tr.com.srdc.mdr.core.impl.composite.AdministrationRecordImpl; import tr.com.srdc.mdr.core.impl.composite.DataElementDerivationImpl; import tr.com.srdc.mdr.core.model.MDRException; import tr.com.srdc.mdr.core.model.MDRResourceFactory; import tr.com.srdc.mdr.core.model.iso11179.AdministeredItemResource; import tr.com.srdc.mdr.core.model.iso11179.DataElementConceptResource; import tr.com.srdc.mdr.core.model.iso11179.DataElementResource; import tr.com.srdc.mdr.core.model.iso11179.RepresentationClassResource; import tr.com.srdc.mdr.core.model.iso11179.ValueDomainResource; import tr.com.srdc.mdr.core.model.iso11179.composite.AdministeredItemContextResource; import tr.com.srdc.mdr.core.model.iso11179.composite.AdministrationRecordResource; import tr.com.srdc.mdr.core.model.iso11179.composite.ClassificationSchemeItemResource; import tr.com.srdc.mdr.core.model.iso11179.composite.DataElementDerivationResource; import tr.com.srdc.mdr.core.model.iso11179.composite.DataElementExampleResource; import tr.com.srdc.mdr.core.model.iso11179.composite.OrganizationResource; import tr.com.srdc.mdr.core.model.iso11179.composite.RegistrationAuthorityResource; import tr.com.srdc.mdr.core.model.iso11179.composite.StewardshipRelationshipResource; import tr.com.srdc.mdr.core.model.iso11179.composite.SubmissionRelationshipResource; import tr.com.srdc.mdr.core.store.MDRDatabase; import tr.com.srdc.mdr.core.util.MappingRelation; import com.hp.hpl.jena.enhanced.EnhGraph; import com.hp.hpl.jena.graph.Node; import com.hp.hpl.jena.ontology.OntClass; import com.hp.hpl.jena.ontology.OntResource; import com.hp.hpl.jena.rdf.model.NodeIterator; import com.hp.hpl.jena.rdf.model.Property; import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.Resource; import com.hp.hpl.jena.rdf.model.ResourceFactory; /** * A Data Element is considered to be a basic unit of data of interest to an * organization. It is a unit of data for which the definition, identification, * representation, and permissible values are specified by means of a set of * attributes. * * @author pacaci * @author mert * @author serike * @author alp * @author anil * */ public class DataElementImpl extends AdministeredItemImpl implements DataElementResource { private static final Logger logger = LoggerFactory .getLogger(DataElementImpl.class); /** * Instead of calling the constructor of this class, use * {@link MDRResourceFactory#createDataElement(AdministrationRecordResource, String, Integer)} * to avoid entering illegal states. * * @param n * Mostly created by <code>Node.createURI()</code>. * @param g * The graph which holds all triples. * @param dataElementAdministrationRecord * The Administration Record for a {@link DataElementResource}. * @param representationClassQualifier * Optional. A qualifier to the Representation Class used in * naming {@link DataElementResource}s and * {@link ValueDomainResource}s. * @param dataElementPrecision * Optional. The degree of specificity for a * {@link DataElementResource}. * @param administeredBy * An Administered Item is administered by an * {@link OrganizationResource} represented by the * {@link StewardshipRelationshipResource}. * @param submittedBy * An Administered Item is submitted by an * {@link OrganizationResource} represented by the * {@link SubmissionRelationshipResource}. * @param registeredBy * An {@link AdministeredItemResource} is registered by a * {@link RegistrationAuthorityResource}. * @param having * An {@link AdministeredItemResource} has to have at least one * {@link AdministeredItemContextResource}. * @param expressingDataElementConceptExpression * An {@link DataElementResource} has to have at least one * {@link DataElementConceptResource} * @param representedByDataElementRepresentation * An {@link DataElementResource} has to have at least one * {@link ValueDomainResource} * @param mdrDatabase * */ public DataElementImpl(Node n, EnhGraph g, AdministrationRecordResource dataElementAdministrationRecord, String representationClassQualifier, Integer dataElementPrecision, StewardshipRelationshipResource administeredBy, SubmissionRelationshipResource submittedBy, RegistrationAuthorityResource registeredBy, AdministeredItemContextResource having, DataElementConceptResource expressingDataElementConceptExpression, ValueDomainResource representedByDataElementRepresentation, MDRDatabase mdrDatabase) { super(n, g, administeredBy, submittedBy, registeredBy, having, mdrDatabase); setSuperClass(mdrDatabase.getVocabulary().DataElement); setAdministrationRecord(dataElementAdministrationRecord); setRepresentationClassQualifier(representationClassQualifier); setDataElementPrecision(dataElementPrecision); setExpressingDataElementConceptExpression(expressingDataElementConceptExpression); setRepresentedByDataElementRepresentation(representedByDataElementRepresentation); } public DataElementImpl(Resource resource, MDRDatabase mdrDatabase) { super(resource, mdrDatabase); } @Override public void setAdministrationRecord( AdministrationRecordResource dataElementAdministrationRecord) { if (dataElementAdministrationRecord == null) { throw new IllegalArgumentException( "Administration Record must be specified for Data Element."); } setPropertyValue( mdrDatabase.getVocabulary().dataElementAdministrationRecord, dataElementAdministrationRecord); } @Override public AdministrationRecordResource getAdministrationRecord() { return new AdministrationRecordImpl( getPropertyResourceValue(mdrDatabase.getVocabulary().dataElementAdministrationRecord), mdrDatabase); } @Override public void setRepresentationClassQualifier( String representationClassQualifier) { setPropertyValue( mdrDatabase.getVocabulary().representationClassQualifier, mdrDatabase.getUtil().createTypedLiteral( representationClassQualifier)); } @Override public String getRepresentationClassQualifier() { RDFNode representationClassQualifier = getPropertyValue(mdrDatabase .getVocabulary().representationClassQualifier); if (representationClassQualifier == null) { logger.debug("DataElement does not have representationClassQualifier"); return null; } return representationClassQualifier.asLiteral().getString(); } @Override public void setDataElementPrecision(Integer dataElementPrecision) { setPropertyValue(mdrDatabase.getVocabulary().dataElementPrecision, mdrDatabase.getUtil().createTypedLiteral(dataElementPrecision)); } @Override public Integer getDataElementPrecision() { RDFNode dataElementPrecision = getPropertyValue(mdrDatabase .getVocabulary().dataElementPrecision); if (dataElementPrecision == null) { logger.debug("DataElement does not have dataElementPrecision"); return null; } return dataElementPrecision.asLiteral().getInt(); } @Override public void setExpressingDataElementConceptExpression( DataElementConceptResource expressingDataElementConceptExpression) { if (expressingDataElementConceptExpression == null) { throw new IllegalArgumentException( "Data Element Concept must be specified for Data Element."); } setPropertyValue( mdrDatabase.getVocabulary().expressingDataElementConceptExpression, expressingDataElementConceptExpression); } @Override public DataElementConceptResource getExpressingDataElementConceptExpression() { return new DataElementConceptImpl( getPropertyResourceValue(mdrDatabase.getVocabulary().expressingDataElementConceptExpression), mdrDatabase); } @Override public void setRepresentedByDataElementRepresentation( ValueDomainResource representedByDataElementRepresentation) { if (representedByDataElementRepresentation == null) { throw new IllegalArgumentException( "Value Domain must be specified for Data Element."); } setPropertyValue( mdrDatabase.getVocabulary().representedByDataElementRepresentation, representedByDataElementRepresentation); } @Override public ValueDomainResource getRepresentedByDataElementRepresentation() { RDFNode representedByDataElementRepresentation = getPropertyValue(mdrDatabase .getVocabulary().representedByDataElementRepresentation); OntClass ontClass = representedByDataElementRepresentation.as( OntResource.class).asClass(); ValueDomainResource valueDomainIND = null; if (ontClass .hasSuperClass(mdrDatabase.getVocabulary().EnumeratedValueDomain)) { valueDomainIND = new EnumeratedValueDomainImpl( representedByDataElementRepresentation.asResource(), mdrDatabase); logger.info("Representer ValueDomain is an EnumeratedValueDomain"); } if (ontClass .hasSuperClass(mdrDatabase.getVocabulary().NonEnumeratedValueDomain)) { valueDomainIND = new NonEnumeratedValueDomainImpl( representedByDataElementRepresentation.asResource(), mdrDatabase); } if (valueDomainIND == null) { throw new IllegalStateException( "Property value should have a valid OntClass."); } return valueDomainIND; } @Override public void addInputToDerivationInput( DataElementDerivationResource inputToDerivationInput) { if (inputToDerivationInput == null) { throw new IllegalArgumentException( "Null is not allowed as a value of the property to be added."); } addProperty(mdrDatabase.getVocabulary().inputToDerivationInput, inputToDerivationInput); } @Override public void removeInputToDerivationInput( DataElementDerivationResource inputToDerivationInput) { if (inputToDerivationInput == null) { throw new IllegalArgumentException( "Null is not allowed as a value of the property to be removed."); } removeProperty(mdrDatabase.getVocabulary().inputToDerivationInput, inputToDerivationInput); } @Override public List<DataElementDerivationResource> getInputToDerivationInputs() throws MDRException { NodeIterator it = listPropertyValues(mdrDatabase.getVocabulary().inputToDerivationInput); return mdrDatabase.getUtil().createList(it, DataElementDerivationResource.class); } @Override public void setDerivedFromDerivationOutput( DataElementDerivationResource derivedFromDerivationOutput) { setPropertyValue( mdrDatabase.getVocabulary().derivedFromDerivationOutput, derivedFromDerivationOutput); } @Override public DataElementDerivationResource getDerivedFromDerivationOutput() { Resource derivedFromDerivationOutput = getPropertyResourceValue(mdrDatabase .getVocabulary().derivedFromDerivationOutput); if (derivedFromDerivationOutput == null) { logger.debug("DataElement is not derived from DataElementDerivation"); return null; } return new DataElementDerivationImpl(derivedFromDerivationOutput, mdrDatabase); } @Override public void addExemplifiedByExemplification( DataElementExampleResource exemplifiedByExemplification) { if (exemplifiedByExemplification == null) { throw new IllegalArgumentException( "Null is not allowed as a value of the property to be added."); } addProperty(mdrDatabase.getVocabulary().exemplifiedByExemplification, exemplifiedByExemplification); } @Override public void removeExemplifiedByExemplification( DataElementExampleResource exemplifiedByExemplification) { if (exemplifiedByExemplification == null) { throw new IllegalArgumentException( "Null is not allowed as a value of the property to be removed."); } removeProperty( mdrDatabase.getVocabulary().exemplifiedByExemplification, exemplifiedByExemplification); } @Override public List<DataElementExampleResource> getExemplifiedByExemplifications() throws MDRException { NodeIterator it = listPropertyValues(mdrDatabase.getVocabulary().exemplifiedByExemplification); return mdrDatabase.getUtil().createList(it, DataElementExampleResource.class); } @Override public void setTypedByDataElementRepresentationClass( RepresentationClassResource typedByDataElementRepresentationClass) { setPropertyValue( mdrDatabase.getVocabulary().typedByDataElementRepresentationClass, typedByDataElementRepresentationClass); } @Override public RepresentationClassResource getTypedByDataElementRepresentationClass() { Resource typedByDataElementRepresentationClass = getPropertyResourceValue(mdrDatabase .getVocabulary().typedByDataElementRepresentationClass); if (typedByDataElementRepresentationClass == null) { logger.debug("DataElement is not typed by RepresentationClass"); return null; } return new RepresentationClassImpl( typedByDataElementRepresentationClass, mdrDatabase); } // ////////////////////////////////////////////// // ////////////////////////////////////////////// // ////////////////////////////////////////////// // ///// High-Level Interface Methods//////////// // ////////////////////////////////////////////// // ////////////////////////////////////////////// // ////////////////////////////////////////////// @Override public void delete() { super.delete(); this.remove(); } @Override public DataElementResource asMDRResource() { return this; } @Override public DataElementConcept getDataElementConcept() { return this.getExpressingDataElementConceptExpression(); } @Override public ValueDomain getValueDomain() { return this.getRepresentedByDataElementRepresentation(); } @Override public void addExtractionSpecification(String oid, String esType, String esScript) { Context context = getContext(); // get the classification ClassificationScheme cs = context.getClassificationScheme(oid); // there are no ClassificationSchemes for this content model type if (cs == null) { cs = context.createClassificationScheme(oid, MDRConstants.CS_EXTRACTION_SPEC); } ClassificationSchemeItem csi = cs.createClassificationSchemeItem( esType, esScript); this.addClassifiedBy(csi.asMDRResource()); } @Override public List<ClassificationSchemeItem> getExtractionSpecifications() { List<ClassificationSchemeItem> specifications = new ArrayList<ClassificationSchemeItem>(); try { for (ClassificationSchemeItemResource resource : this .getClassifiedBy()) { if (resource.getClassificationScheme().getDefinition() .equals(MDRConstants.CS_EXTRACTION_SPEC)) { specifications.add(resource); } } } catch (MDRException e) { e.printStackTrace(); return null; } return specifications; } @Override public void addMapping(MappingRelation relation, DataElement matchedElement) { String skosNS = "http://www.w3.org/2004/02/skos/core#"; String relationType = relation.getRelationType(); // here existance of mapping will be checked List<ClassificationSchemeItem> existingMappings = this.getMappings(); for (ClassificationSchemeItem mapping : existingMappings) { if (mapping.getItemValue().equals(matchedElement.getUniqueID()) && mapping.getTypeName().equals(relation.getRelationType()) && mapping.getClassificationScheme().getDefinition() .equals(MDRConstants.CS_MAPPING)) { // mapping already exists, just return so no mapping will be added logger.debug("Already existing mapping " + this.getName() + " " + relationType + " " + matchedElement.getName()); return; } } Context context = getContext(); // get the classification ClassificationScheme cs = context.getClassificationScheme(relation .getObjectOID()); // there are no ClassificationSchemes for this content model if (cs == null) { cs = context.createClassificationScheme(relation.getObjectOID(), MDRConstants.CS_MAPPING); } ClassificationSchemeItem csi = cs.createClassificationSchemeItem( relationType, matchedElement.getUniqueID()); String[] relParts = relationType.split(":"); if (relParts[0].equals("skos")) { Property p = ResourceFactory.createProperty(skosNS + relParts[1]); this.asMDRResource().addProperty(p, matchedElement.asMDRResource()); this.addClassifiedBy(csi.asMDRResource()); } else { logger.error("Mapping Relation Namespace is not supported:" + relParts[0]); } // If the relation is symmetric, add classification scheme item for the // other data element if (relation.isSymmetric()) { // get the classification cs = context.getClassificationScheme(relation.getSubjectOID()); // there are no ClassificationSchemes for this content model if (cs == null) { cs = context.createClassificationScheme( relation.getSubjectOID(), MDRConstants.CS_MAPPING); } csi = cs.createClassificationSchemeItem(relationType, this.getUniqueID()); if (relParts[0].equals("skos")) { Property p = ResourceFactory.createProperty(skosNS + relParts[1]); matchedElement.asMDRResource().addProperty(p, this.asMDRResource()); matchedElement.asMDRResource().addClassifiedBy( csi.asMDRResource()); } else { logger.error("Mapping Relation Namespace is not supported:" + relParts[0]); } } } @Override public List<ClassificationSchemeItem> getMappings() { List<ClassificationSchemeItem> specifications = new ArrayList<ClassificationSchemeItem>(); try { for (ClassificationSchemeItemResource resource : this .getClassifiedBy()) { if (resource.getClassificationScheme().getDefinition() .equals(MDRConstants.CS_MAPPING)) { specifications.add(resource); } } } catch (MDRException e) { e.printStackTrace(); return null; } return specifications; } }