de.interactive_instruments.ShapeChange.SBVR.Sbvr2FolParser.java Source code

Java tutorial

Introduction

Here is the source code for de.interactive_instruments.ShapeChange.SBVR.Sbvr2FolParser.java

Source

/**
 * ShapeChange - processing application schemas for geographic information
 *
 * This file is part of ShapeChange. ShapeChange takes a ISO 19109 
 * Application Schema from a UML model and translates it into a 
 * GML Application Schema or other implementation representations.
 *
 * Additional information about the software can be found at
 * http://shapechange.net/
 *
 * (c) 2002-2015 interactive instruments GmbH, Bonn, Germany
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contact:
 * interactive instruments GmbH
 * Trierer Strasse 70-72
 * 53115 Bonn
 * Germany
 */

package de.interactive_instruments.ShapeChange.SBVR;

import java.util.List;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;

import de.interactive_instruments.ShapeChange.MessageSource;
import de.interactive_instruments.ShapeChange.Options;
import de.interactive_instruments.ShapeChange.ShapeChangeResult;
import de.interactive_instruments.ShapeChange.FOL.FolExpression;
import de.interactive_instruments.ShapeChange.FOL.Variable;
import de.interactive_instruments.ShapeChange.Model.ClassInfo;
import de.interactive_instruments.ShapeChange.Model.FolConstraint;
import de.interactive_instruments.ShapeChange.Model.Model;
import de.interactive_instruments.ShapeChange.Model.TextConstraint;
import de.interactive_instruments.antlr.ShapeChangeAntlr.SbvrParserHelper;
import de.interactive_instruments.antlr.sbvr.SBVRLexer;
import de.interactive_instruments.antlr.sbvr.SBVRParser;

/**
 * Parses First Order Logic expressions from SBVR constraints.
 * 
 * @author Johannes Echterhoff
 *
 */
public class Sbvr2FolParser implements MessageSource {

    private ShapeChangeResult result;

    private Set<String> nouns = new TreeSet<String>();
    private Set<String> verbs = new TreeSet<String>();

    private Options options;

    private Model model;

    private SbvrParserHelper helper;

    public Sbvr2FolParser(Model m) {

        this.result = m.result();
        this.options = m.options();
        this.model = m;

        helper = SbvrUtil.createParserHelper(m);

        nouns = helper.nouns;
        verbs = helper.verbs;

        // System.out.println("----- Nouns:");
        // for (String noun : nouns) {
        // System.out.println("nouns.add(\"" + noun + "\");");
        // }
        // System.out.println();
        // System.out.println("----- Verbs:");
        // for (String verb : verbs) {
        // System.out.println("verbs.add(\"" + verb + "\");");
        // }

    }

    /**
     * Parsed a first order logic expression from the given constraint. If
     * errors occur while parsing they are logged and <code>null</code> is
     * returned.
     * 
     * @param con
     * @return the first order logic expression represented by the constraint,
     *         or <code>null</code> if errors were detected while parsing
     */
    public FolExpression parse(FolConstraint con) {

        Variable.reset();

        SbvrParsingResult parsingResult = new SbvrParsingResult();
        parsingResult.setConstraint(con);

        ANTLRInputStream input = new ANTLRInputStream(con.text());

        // create a lexer that feeds off of input CharStream
        SBVRLexer lexer = new SBVRLexer(input);

        // create a buffer of tokens pulled from the lexer
        CommonTokenStream tokens = new CommonTokenStream(lexer);

        // create a parser that feeds off the tokens buffer
        SBVRParser parser = new SBVRParser(tokens);
        parser.helper = helper;

        /*
         * remove ConsoleErrorListener and add our own
         */
        parser.removeErrorListeners();
        SbvrErrorListener parsingErrorListener = new SbvrErrorListener();
        parser.addErrorListener(parsingErrorListener);

        // execute parsing, starting with rule 'sentence'
        ParseTree tree = parser.sentence();

        // get rule invocation stack for debugging
        parsingResult.setRuleInvocationStack(tree.toStringTree(parser));

        // if there were parsing errors, log them
        if (parsingErrorListener.hasErrors()) {

            parsingResult.addErrors(parsingErrorListener.getErrors());

        } else {

            // walk parse tree to apply further validation
            SbvrValidationErrorListener validationErrorListener = new SbvrValidationErrorListener(nouns, verbs);

            ParseTreeWalker walker = new ParseTreeWalker();
            walker.walk(validationErrorListener, tree);

            // if there were validation errors, log them
            if (validationErrorListener.hasErrors()) {

                parsingResult.addErrors(validationErrorListener.getErrors());

            } else {

                // no parsing or validation errors encountered

                // create FOL expression

                Sbvr2FolVisitor folVisitor = new Sbvr2FolVisitor(model, con);

                FolExpression folExpr = folVisitor.visit(tree);

                if (folExpr == null) {

                    if (folVisitor.hasErrors()) {
                        parsingResult.addErrors(folVisitor.getErrors());
                    } else {
                        result.addError(this, 1);
                    }

                } else {
                    parsingResult.setFirstOrderLogicExpression(folExpr);
                }
            }
        }

        logParsingResult(parsingResult);

        if (parsingResult.hasFirstOrderLogicExpression()) {
            return parsingResult.getFirstOrderLogicExpression();
        } else {
            return null;
        }
    }

    private void logParsingResult(SbvrParsingResult parsingResult) {

        if (parsingResult != null) {

            TextConstraint con = parsingResult.getConstraint();

            result.addInfo("SBVR constraint " + con.name() + ": " + con.text()
                    + (con.contextModelElmt() instanceof ClassInfo
                            ? " (on class '" + con.contextModelElmt().name() + "' in package '"
                                    + ((ClassInfo) con.contextModelElmt()).pkg().name() + ")"
                            : ""));

            if (parsingResult.getFirstOrderLogicExpression() != null) {
                result.addInfo(SbvrConstants.INDENTATION_FOR_MESSAGE_DETAILS
                        + parsingResult.getFirstOrderLogicExpression().toString());
            } else {
                TreeMap<String, List<SbvrErrorInfo>> errors = parsingResult.getErrors();

                if (!errors.isEmpty()) {

                    for (List<SbvrErrorInfo> ei : errors.values()) {
                        SbvrUtil.printErrors(ei, con.text(), result);
                        // printErrors(ei, con.text());
                    }
                }
            }

            // rule stack is relevant for debugging
            if (parsingResult.hasRuleInvocationStack()) {
                result.addDebug(SbvrConstants.INDENTATION_FOR_MESSAGE_DETAILS + "rule stack: "
                        + parsingResult.getRuleInvocationStack());
            }
        }
    }

    // private void printErrors(List<SbvrErrorInfo> errors, String sbvrRuleText)
    // {
    //
    // for (SbvrErrorInfo err : errors) {
    //
    // result.addError(SbvrConstants.INDENTATION_FOR_MESSAGE_DETAILS
    // + err.getErrorCategory() + ": " + err.getErrorMessage());
    //
    // if (err.hasOffendingTextInfo()) {
    //
    // result.addError(SbvrConstants.INDENTATION_FOR_MESSAGE_DETAILS
    // + SbvrConstants.RULE_MESSAGE_PREFIX + sbvrRuleText);
    //
    // StringBuilder sb = new StringBuilder();
    //
    // int start = err.getOffendingTextStartIndex();
    // int stop = err.getOffendingTextStopIndex();
    //
    // for (int i = 0; i < start
    // + SbvrConstants.INDENTATION_FOR_MESSAGE_DETAILS.length()
    // + SbvrConstants.RULE_MESSAGE_PREFIX.length(); i++)
    // sb.append(" ");
    //
    // if (start >= 0 && stop >= 0) {
    // for (int i = start; i <= stop; i++)
    // sb.append("^");
    // }
    // result.addError(sb.toString());
    // }
    // }
    // }

    @Override
    public String message(int mnr) {

        switch (mnr) {

        case 1:
            return "Translation to First Order Logic expression was not successfull but no errors were reported.";

        default:
            return "(Unknown message)";
        }
    }
}