/* * 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. * * Contributions from 2013-2017 where performed either by US government * employees, or under US Veterans Health Administration contracts. * * US Veterans Health Administration contributions by government employees * are work of the U.S. Government and are not subject to copyright * protection in the United States. Portions contributed by government * employees are USGovWork (17USC ยง105). Not subject to copyright. * * Contribution by contractors to the US Veterans Health Administration * during this period are contractually contributed under the * Apache License, Version 2.0. * * See: https://www.usa.gov/government-works * * Contributions prior to 2013: * * Copyright (C) International Health Terminology Standards Development Organisation. * Licensed under the Apache License, Version 2.0. * */ package sh.isaac.provider.logic; //~--- JDK imports ------------------------------------------------------------ import java.util.Optional; //~--- non-JDK imports -------------------------------------------------------- import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionBaseVisitor; import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionLexer; import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser; import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.AttributeContext; import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.AttributeGroupContext; import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.AttributeSetContext; import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.ConceptReferenceContext; import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.ExpressionContext; import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.FocusConceptContext; import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.NonGroupedAttributeSetContext; import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.RefinementContext; import se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.SubExpressionContext; import sh.isaac.api.Get; import sh.isaac.api.component.concept.ConceptChronology; import sh.isaac.api.logic.LogicalExpressionBuilder; import sh.isaac.api.logic.assertions.Assertion; import sh.isaac.api.logic.assertions.SomeRole; import sh.isaac.api.logic.assertions.connectors.And; import sh.isaac.utility.Frills; import static sh.isaac.api.logic.LogicalExpressionBuilder.And; import static sh.isaac.api.logic.LogicalExpressionBuilder.ConceptAssertion; import static sh.isaac.api.logic.LogicalExpressionBuilder.NecessarySet; import static sh.isaac.api.logic.LogicalExpressionBuilder.SomeRole; import static sh.isaac.api.logic.LogicalExpressionBuilder.SufficientSet; //~--- classes ---------------------------------------------------------------- /** * {@link ISAACVisitor}. * * @author Tony Weida */ public class ISAACVisitor extends SNOMEDCTExpressionBaseVisitor<Object> { /** The logger. */ static Logger logger = LogManager.getLogger(ISAACVisitor.class); //~--- fields -------------------------------------------------------------- /** The default to primitive. */ private final boolean defaultToPrimitive; /** The def builder. */ private final LogicalExpressionBuilder defBuilder; //~--- constructors -------------------------------------------------------- /** * Instantiates a new ISAAC visitor. * * @param defBuilder the def builder */ public ISAACVisitor(LogicalExpressionBuilder defBuilder) { this(defBuilder, null); } /** * Instantiates a new ISAAC visitor. * * @param defBuilder the def builder * @param c the c */ public ISAACVisitor(LogicalExpressionBuilder defBuilder, ConceptChronology<?> c) { this(defBuilder, c, false); } /** * Instantiates a new ISAAC visitor. * * @param defBuilder the def builder * @param c the c * @param defaultToPrimitive the default to primitive */ public ISAACVisitor(LogicalExpressionBuilder defBuilder, ConceptChronology<?> c, boolean defaultToPrimitive) { super(); this.defaultToPrimitive = defaultToPrimitive; this.defBuilder = defBuilder; } //~--- methods ------------------------------------------------------------- /** * Visit attribute. * * @param ctx the ctx * @return the object */ @Override public Object visitAttribute(se.liu.imt.mi.snomedct.expression.SNOMEDCTExpressionParser.AttributeContext ctx) { logger.debug("visitAttribute: " + ctx.getText()); SomeRole role = null; if (ctx.attributeValue() .getChild(0) .getClass() == SNOMEDCTExpressionParser.ConceptReferenceContext.class) { final ConceptChronology<?> property = (ConceptChronology<?>) visitConceptReference(ctx.conceptReference()); final ConceptChronology<?> value = (ConceptChronology<?>) visitConceptReference(ctx.attributeValue() .conceptReference()); role = SomeRole(property, ConceptAssertion(value, this.defBuilder)); } else if (ctx.attributeValue() .getChild(0) .getClass() == SNOMEDCTExpressionParser.NestedExpressionContext.class) { final ConceptChronology<?> property = (ConceptChronology<?>) visitConceptReference(ctx.conceptReference()); final Assertion result = (Assertion) visit(ctx.attributeValue() .nestedExpression() .subExpression()); role = SomeRole(property, result); } else { logger.warn("Shouldn't ever get here"); } return role; } /** * Visit attribute group. * * @param ctx the ctx * @return the object */ @Override public Object visitAttributeGroup(AttributeGroupContext ctx) { logger.debug("visitAttributeGroup: " + ctx.getText()); throw new RuntimeException("LOINC EXPRESSION SERVICE> Cannot (yet) handle attribute group"); } /** * Visit attribute set. * * @param ctx the ctx * @return the object */ @Override public Object visitAttributeSet(AttributeSetContext ctx) { logger.debug("visitAttributeSet: " + ctx.getText()); throw new RuntimeException("LOINC EXPRESSION SERVICE> Cannot (yet) handle attribute set"); } /** * Visit concept reference. * * @param ctx the ctx * @return the object */ @Override public Object visitConceptReference(ConceptReferenceContext ctx) { logger.debug("visitConceptReference: " + ctx.getText()); final Optional<Integer> nid = Frills.getNidForSCTID(Long.parseLong(ctx.getText())); if (!nid.isPresent()) { throw new RuntimeException(("LOINC EXPRESSION SERVICE> Missing nid for sctid: " + ctx.getText())); } return Get.conceptService() .getConcept(nid.get()); } /** * Visit expression. * * @param ctx the ctx * @return the object */ @Override public Object visitExpression(ExpressionContext ctx) { logger.debug("visitExpression: " + ctx.getText()); final Object subExpression = visit(ctx.subExpression()); if (((ctx.definitionStatus() == null) && (this.defaultToPrimitive == true)) || (((ctx.definitionStatus() != null) && (ctx.definitionStatus().start.getType() == SNOMEDCTExpressionLexer.SC_OF)))) { return NecessarySet((And) subExpression); } else { return SufficientSet((And) subExpression); } } /** * Visit focus concept. * * @param ctx the ctx * @return the object */ @Override public Object visitFocusConcept(FocusConceptContext ctx) { logger.debug("visitFocusConcept: " + ctx.getText()); if (ctx.getChildCount() > 1) { throw new RuntimeException("LOINC EXPRESSION SERVICE> Cannot (yet) handle conjoined focus concept"); } return visit(ctx.conceptReference(0)); } /** * Visit non grouped attribute set. * * @param ctx the ctx * @return the object */ // TODO: see more complex processing in OWLVisitor @Override public Object visitNonGroupedAttributeSet(NonGroupedAttributeSetContext ctx) { logger.debug("visitNonGroupedAttributeSet: " + ctx.getText()); final int childCount = ctx.getChildCount(); final Assertion[] assertions = new Assertion[(childCount + 1) / 2]; for (int i = 0; i < childCount; i = i + 2) { // Use an iterator assertions[(i + 1) / 2] = (SomeRole) visitAttribute((AttributeContext) ctx.getChild(i)); } return assertions; } /** * Visit refinement. * * @param ctx the ctx * @return the object */ @Override public Object visitRefinement(RefinementContext ctx) { logger.debug("visitRefinement: " + ctx.getText()); return visit(ctx.nonGroupedAttributeSet()); } /** * Visit sub expression. * * @param ctx the ctx * @return the object */ @Override public Object visitSubExpression(SubExpressionContext ctx) { logger.debug("visitSubExpression: " + ctx.getText()); Object result; if (ctx.getChildCount() > 1) { final Assertion[] refinementAssertions = (Assertion[]) visit(ctx.refinement()); final Assertion[] assertions = new Assertion[refinementAssertions.length + 1]; assertions[0] = ConceptAssertion((ConceptChronology<?>) visit(ctx.focusConcept()), this.defBuilder); System.arraycopy(refinementAssertions, 0, assertions, 1, refinementAssertions.length); result = And(assertions); } else { result = ConceptAssertion((ConceptChronology<?>) visit(ctx.focusConcept()), this.defBuilder); } return result; } }