/* * Copyright (c) 2012 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * 1Spatial PLC <http://www.1spatial.com> * HUMBOLDT EU Integrated Project #030962 * Data Harmonisation Panel <http://www.dhpanel.eu> */ package com.onespatial.jrc.tns.oml_to_rif.translate; import static com.onespatial.jrc.tns.oml_to_rif.model.rif.LogicalType.AND; import static com.onespatial.jrc.tns.oml_to_rif.model.rif.LogicalType.NOT; import static com.onespatial.jrc.tns.oml_to_rif.model.rif.LogicalType.OR; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.logging.Logger; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3._2007.rif.And; import org.w3._2007.rif.ArgsUNITERMType; import org.w3._2007.rif.Assert; import org.w3._2007.rif.Atom; import org.w3._2007.rif.Const; import org.w3._2007.rif.ContentFORMULAType; import org.w3._2007.rif.Declare; import org.w3._2007.rif.Do; import org.w3._2007.rif.Document; import org.w3._2007.rif.Equal; import org.w3._2007.rif.Exists; import org.w3._2007.rif.ExternalFORMULAType; import org.w3._2007.rif.Formula; import org.w3._2007.rif.Frame; import org.w3._2007.rif.GroupContents; import org.w3._2007.rif.INeg; import org.w3._2007.rif.If; import org.w3._2007.rif.Implies; import org.w3._2007.rif.Instance; import org.w3._2007.rif.Left; import org.w3._2007.rif.Member; import org.w3._2007.rif.ObjectFactory; import org.w3._2007.rif.Op; import org.w3._2007.rif.Or; import org.w3._2007.rif.Payload; import org.w3._2007.rif.Right; import org.w3._2007.rif.Sentence; import org.w3._2007.rif.SlotFrameType; import org.w3._2007.rif.ThenPart; import org.w3._2007.rif.Var; import org.w3._2007.rif.Assert.Target; import org.w3._2007.rif.Do.ActionVar; import org.w3._2007.rif.Do.Actions; import org.w3c.dom.Element; import com.onespatial.jrc.tns.oml_to_rif.RifExportException; import com.onespatial.jrc.tns.oml_to_rif.api.AbstractFollowableTranslator; import com.onespatial.jrc.tns.oml_to_rif.api.TranslationException; import com.onespatial.jrc.tns.oml_to_rif.model.rif.ComparisonType; import com.onespatial.jrc.tns.oml_to_rif.model.rif.ModelRifDocument; import com.onespatial.jrc.tns.oml_to_rif.model.rif.ModelRifMappingCondition; import com.onespatial.jrc.tns.oml_to_rif.model.rif.ModelSentence; import com.onespatial.jrc.tns.oml_to_rif.model.rif.PropertyMapping; import com.onespatial.jrc.tns.oml_to_rif.model.rif.StaticAssignment; import com.onespatial.jrc.tns.oml_to_rif.translate.context.RifVariable; import com.onespatial.jrc.tns.oml_to_rif.translate.context.RifVariable.Type; import eu.esdihumboldt.commons.goml.align.Cell; /** * Translates a collection of {@link ModelSentence} instances into a collection * of {@link Sentence} instances. NB {@link Cell}s and {@link Sentence}s do not * necessarily (nor usually) align one-to-one. * * @author Simon Payne (Simon.Payne@1spatial.com) / 1Spatial Group Ltd. * @author Richard Sunderland (Richard.Sunderland@1spatial.com) / 1Spatial Group Ltd. */ public class ModelRifToRifTranslator extends AbstractFollowableTranslator<ModelRifDocument, Document> { private ObjectFactory factory; private DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); private static final transient Logger log = Logger.getAnonymousLogger(); /** * Default constructor. */ public ModelRifToRifTranslator() { factory = new ObjectFactory(); } /** * @see com.onespatial.jrc.tns.oml_to_rif.api.Translator#translate(Object) * which this method implements. * @param source * {@link ModelRifDocument} * @return {@link Document} * @throws TranslationException * if any exceptions are thrown during translation. */ @Override public Document translate(ModelRifDocument source) throws TranslationException { final Document document = factory.createDocument(); Payload payload = factory.createPayload(); document.setPayload(payload); GroupContents group = factory.createGroupContents(); payload.setGroup(group); for (ModelSentence s : source.getSentences()) { group.getSentence().add(buildSentence(s)); } return document; } private Sentence buildSentence(ModelSentence s) { // sort variables within sentence final Sentence sentence = factory.createSentence(); final Implies implies = factory.createImplies(); sentence.setImplies(implies); final If if1 = factory.createIf(); implies.setIf(if1); final Exists exists = factory.createExists(); if1.setExists(exists); ThenPart then = factory.createThenPart(); implies.setThen(then); Do do1 = factory.createDo(); then.setDo(do1); processChildren(s, exists, do1); return sentence; } private void processChildren(ModelSentence s, final Exists exists, Do do1) { Formula existsFormula = factory.createFormula(); And and = factory.createAnd(); existsFormula.setAnd(and); exists.setFormula(existsFormula); Actions actions = factory.createDoActions(); do1.setActions(actions); for (RifVariable instanceVariable : s.getVariables(Type.INSTANCE)) { // source instance variables if (!instanceVariable.isActionVar()) { recurseChildren(exists, do1, instanceVariable, s, true); } else // target instance variables { recurseChildren(exists, do1, instanceVariable, s, false); } } Map<RifVariable, Frame> map = new LinkedHashMap<RifVariable, Frame>(); for (PropertyMapping mapping : s.getPropertyMappings()) { RifVariable contextVariable = mapping.getTarget().getContextVariable(); Frame match = map.get(contextVariable); if (match == null) { map.put(contextVariable, initialiseFrame(contextVariable)); } } for (StaticAssignment staticAssignment : s.getStaticAssignments()) { RifVariable contextVariable = staticAssignment.getTarget().getContextVariable(); Frame match = map.get(contextVariable); if (match == null) { map.put(contextVariable, initialiseFrame(contextVariable)); } } for (PropertyMapping mapping : s.getPropertyMappings()) { Frame frame = map.get(mapping.getTarget().getContextVariable()); createAssignmentSlot(mapping, frame); } for (StaticAssignment staticAssignment : s.getStaticAssignments()) { Frame frame = map.get(staticAssignment.getTarget().getContextVariable()); createStaticAssignmentSlot(staticAssignment, frame); } for (ModelRifMappingCondition mappingCondition : s.getMappingConditions()) { createFilter(exists.getFormula().getAnd().getFormula(), mappingCondition); } for (Frame frame : map.values()) { Assert assert1 = factory.createAssert(); Target target = factory.createAssertTarget(); target.setFrame(frame); assert1.setTarget(target); actions.getACTION().add(assert1); } } private void createFilter(List<Formula> list, ModelRifMappingCondition mappingCondition) { // if it's a logical filter if (mappingCondition.isLogical()) { createLogicalFilter(list, mappingCondition); } else if (mappingCondition.isComparative()) { createComparativeFilter(list, mappingCondition); } else if (mappingCondition.isGeometric()) { // TODO complete this bit } } private void createLogicalFilter(List<Formula> list, ModelRifMappingCondition mappingCondition) { log.fine("Creating logical filter"); //$NON-NLS-1$ Formula logicFilterFormula = factory.createFormula(); if (mappingCondition.getLogicalType().equals(NOT)) { INeg negation = factory.createINeg(); logicFilterFormula.setINeg(negation); // Formula subNegationFormula = factory.createFormula(); List<Formula> notList = new ArrayList<Formula>(); // notList.add(subNegationFormula); createChildFilters(mappingCondition, notList); negation.setFormula(notList.get(0)); log.fine("Filter is a NOT filter"); //$NON-NLS-1$ } else { if (mappingCondition.getLogicalType().equals(AND)) { And and1 = factory.createAnd(); logicFilterFormula.setAnd(and1); createChildFilters(mappingCondition, and1.getFormula()); log.fine("Filter is an AND filter"); //$NON-NLS-1$ } else if (mappingCondition.getLogicalType().equals(OR)) { Or or = factory.createOr(); logicFilterFormula.setOr(or); createChildFilters(mappingCondition, or.getFormula()); log.fine("Filter is an OR filter"); //$NON-NLS-1$ } } list.add(logicFilterFormula); } private void createComparativeFilter(List<Formula> list, ModelRifMappingCondition mappingCondition) { log.fine("Creating comparative filter"); //$NON-NLS-1$ Formula filterFormula = factory.createFormula(); list.add(filterFormula); if (mappingCondition.getOperator().equals(ComparisonType.NUMBER_EQUALS) || mappingCondition.getOperator().equals(ComparisonType.STRING_EQUALS)) { createEqualsFilter(mappingCondition, filterFormula); } else if (mappingCondition.getOperator().equals(ComparisonType.NUMBER_GREATER_THAN) || mappingCondition.getOperator().equals(ComparisonType.NUMBER_LESS_THAN) || mappingCondition.getOperator().equals(ComparisonType.STRING_CONTAINS)) { createExternalPredicateFilter(mappingCondition, filterFormula); } else { throw new UnsupportedOperationException("Comparison type is not supported: " //$NON-NLS-1$ + mappingCondition.getOperator().toString()); } } private void createExternalPredicateFilter(ModelRifMappingCondition mappingCondition, Formula filterFormula) { // create an <External>/<content>/<Atom> element hierarchy ExternalFORMULAType external = factory.createExternalFORMULAType(); filterFormula.setExternal(external); ContentFORMULAType content = factory.createContentFORMULAType(); external.setContent(content); Atom atom = factory.createAtom(); content.setAtom(atom); Op op = factory.createOp(); ArgsUNITERMType args = factory.createArgsUNITERMType(); atom.setOp(op); Const opConst = factory.createConst(); opConst.setType("rif:iri"); //$NON-NLS-1$ opConst.getContent().add(mappingCondition.getOperator().getRifPredicate()); op.setConst(opConst); atom.setArgs(args); args.setOrdered("yes"); //$NON-NLS-1$ Var var = factory.createVar(); var.getContent().add(mappingCondition.getLeft().getName()); args.getTERM().add(var); Const argsConst = factory.createConst(); argsConst.setType(getLiteralTypeFor(mappingCondition.getLiteralClass())); String literalValue = mappingCondition.getLiteralValue().toString(); // remove any wildcards if (mappingCondition.getOperator().equals(ComparisonType.STRING_CONTAINS)) { literalValue = literalValue.replaceAll("%", ""); //$NON-NLS-1$ //$NON-NLS-2$ } argsConst.getContent().add(literalValue); args.getTERM().add(argsConst); log.fine("Filter is a " + mappingCondition.getOperator().toString() + " filter"); //$NON-NLS-1$ //$NON-NLS-2$ } private void createEqualsFilter(ModelRifMappingCondition mappingCondition, Formula filterFormula) { // create an <Equals> element Equal equal = factory.createEqual(); filterFormula.setEqual(equal); Left left = factory.createLeft(); Right right = factory.createRight(); equal.setLeft(left); Var var = factory.createVar(); var.getContent().add(mappingCondition.getLeft().getName()); left.setVar(var); equal.setRight(right); Const const1 = factory.createConst(); const1.setType(getLiteralTypeFor(mappingCondition.getLiteralClass())); right.setConst(const1); const1.getContent().add(mappingCondition.getLiteralValue()); log.fine("Filter is a " + mappingCondition.getOperator().toString() + " filter"); //$NON-NLS-1$ //$NON-NLS-2$ } private String getLiteralTypeFor(Class<?> literalClass) { if (Long.class.isAssignableFrom(literalClass)) { return "http://www.w3.org/2001/XMLSchema#integer"; //$NON-NLS-1$ } if (Double.class.isAssignableFrom(literalClass)) { return "http://www.w3.org/2001/XMLSchema#double"; //$NON-NLS-1$ } return "http://www.w3.org/2001/XMLSchema#string"; //$NON-NLS-1$ } private void createChildFilters(ModelRifMappingCondition mappingCondition, List<Formula> list) { for (ModelRifMappingCondition child : mappingCondition.getChildren()) { createFilter(list, child); } } private void createStaticAssignmentSlot(StaticAssignment staticAssignment, Frame frame) { SlotFrameType slot = factory.createSlotFrameType(); slot.setOrdered("yes"); //$NON-NLS-1$ Const const1 = factory.createConst(); const1.getContent().add(staticAssignment.getTarget().getPropertyName()); const1.setType("rif:iri"); //$NON-NLS-1$ slot.getContent().add(const1); Const const2 = factory.createConst(); const2.setType("http://www.w3.org/2001/XMLSchema#string"); //$NON-NLS-1$ const2.getContent().add(staticAssignment.getContent()); slot.getContent().add(const2); frame.getSlot().add(slot); } private void createAssignmentSlot(PropertyMapping mapping, Frame frame) { SlotFrameType slot = factory.createSlotFrameType(); slot.setOrdered("yes"); //$NON-NLS-1$ Const const1 = factory.createConst(); const1.getContent().add(mapping.getTarget().getPropertyName()); const1.setType("rif:iri"); //$NON-NLS-1$ slot.getContent().add(const1); Var var1 = factory.createVar(); var1.getContent().add(mapping.getSource().getName()); slot.getContent().add(var1); frame.getSlot().add(slot); } private void recurseChildren(final Exists exists, Do do1, RifVariable variable, ModelSentence sentence, boolean isSource) { List<RifVariable> children = sentence.findChildren(variable); if (isSource) { exists.getDeclare().add(createSourceDeclare(variable)); if (variable.getType().equals(Type.INSTANCE)) { exists.getFormula().getAnd().getFormula().add( createSourceInstanceMembershipFormula(sentence, variable)); } } else { // if (!children.isEmpty()) // problem? do1.getActionVar().add(createTargetVariableDeclare(variable)); if (variable.getType() == Type.INSTANCE) { do1.getActions().getACTION() .add( createTargetInstanceMembershipFormula(do1.getActions(), sentence, variable)); } } if (!children.isEmpty()) { if (isSource) { Frame frame = initialiseFrame(variable); for (RifVariable child : children) { recurseChildren(exists, do1, child, sentence, isSource); createBindingSlot(child, frame); } Formula frameFormula = factory.createFormula(); frameFormula.setFrame(frame); exists.getFormula().getAnd().getFormula().add(frameFormula); } else { for (RifVariable child : children) { recurseChildren(exists, do1, child, sentence, isSource); } } } } private Frame initialiseFrame(RifVariable contextVariable) { Frame frame = factory.createFrame(); frame = factory.createFrame(); org.w3._2007.rif.Object frameObject = factory.createObject(); frame.setObject(frameObject); Var var = factory.createVar(); var.getContent().add(contextVariable.getName()); frameObject.setVar(var); return frame; } private Formula createSourceInstanceMembershipFormula(ModelSentence sentence, RifVariable instanceVariable) { Formula result = factory.createFormula(); Member member = factory.createMember(); Instance instance = factory.createInstance(); Var var = factory.createVar(); String name = sentence.getSourceClass().getName(); var.getContent().add(name); Const const1 = factory.createConst(); const1.setType("rif:iri"); //$NON-NLS-1$ const1.getContent().add(instanceVariable.getClassName()); org.w3._2007.rif.Class clazz = factory.createClass(); instance.setVar(var); clazz.setConst(const1); member.setInstance(instance); member.setClazz(clazz); result.setMember(member); return result; } private Assert createTargetInstanceMembershipFormula(Actions actions, ModelSentence sentence, RifVariable instanceVariable) { Assert assert1 = factory.createAssert(); Target target = factory.createAssertTarget(); Member member = factory.createMember(); Instance instance = factory.createInstance(); Var var = factory.createVar(); var.getContent().add(instanceVariable.getName()); instance.setVar(var); member.setInstance(instance); org.w3._2007.rif.Class clazz = factory.createClass(); Const const1 = factory.createConst(); const1.setType("rif:iri"); //$NON-NLS-1$ const1.getContent().add(instanceVariable.getClassName()); clazz.setConst(const1); member.setClazz(clazz); target.setMember(member); assert1.setTarget(target); return assert1; } private void createBindingSlot(RifVariable child, Frame frame) { SlotFrameType slot = factory.createSlotFrameType(); slot.setOrdered("yes"); //$NON-NLS-1$ Const const1 = factory.createConst(); const1.getContent().add(child.getPropertyName()); const1.setType("rif:iri"); //$NON-NLS-1$ slot.getContent().add(const1); Var var1 = factory.createVar(); var1.getContent().add(child.getName()); slot.getContent().add(var1); frame.getSlot().add(slot); } private ActionVar createTargetVariableDeclare(RifVariable variable) { ActionVar targetInstanceActionVar = factory.createDoActionVar(); Var var = factory.createVar(); var.getContent().add(variable.getName()); targetInstanceActionVar.setVar(var); if (variable.getType() == Type.INSTANCE) { targetInstanceActionVar.setNew(createElement("New")); //$NON-NLS-1$ } else { Frame frame = initialiseFrame(variable.getContextVariable()); createBindingSlot(variable, frame); targetInstanceActionVar.setFrame(frame); } return targetInstanceActionVar; } private Declare createSourceDeclare(RifVariable variable) { Declare propertyDeclare = factory.createDeclare(); Var var = factory.createVar(); var.getContent().add(variable.getName()); propertyDeclare.setVar(var); return propertyDeclare; } private Element createElement(String tagName) { DocumentBuilder docBuilder; try { docBuilder = docBuilderFactory.newDocumentBuilder(); org.w3c.dom.Document doc = docBuilder.newDocument(); return doc.createElement(tagName); } catch (ParserConfigurationException e) { throw new RifExportException(e); } } }