All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.konig.core.path.PathParser Maven / Gradle / Ivy

There is a newer version: 2.11.0
Show newest version
package io.konig.core.path;

/*
 * #%L
 * Konig Core
 * %%
 * Copyright (C) 2015 - 2017 Gregory McFall
 * %%
 * 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.
 * #L%
 */


import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

import org.openrdf.model.BNode;
import org.openrdf.model.Resource;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.impl.URIImpl;
import org.openrdf.rio.RDFHandlerException;
import org.openrdf.rio.RDFParseException;
import org.openrdf.rio.helpers.RDFHandlerBase;

import io.konig.core.Context;
import io.konig.core.NameMap;
import io.konig.core.NamespaceManager;
import io.konig.core.Path;
import io.konig.core.vocab.VAR;
import io.konig.rio.turtle.NamespaceMap;
import io.konig.rio.turtle.SeaTurtleParser;

public class PathParser extends SeaTurtleParser {
	
	private NamespaceManager nsManager;

	public PathParser(NamespaceManager nsManager) {
		this(nsManager==null ? null : new NamespaceMapAdapter(nsManager), null);
		this.nsManager = nsManager;
	}
	
	public PathParser(NamespaceMap map, PushbackReader reader) {
		super(map);
		setRDFHandler(new Handler());
		this.reader = reader;
	}

	public PathParser(NameMap nameMap) {
		this.nameMap = nameMap;
	}

	public Path path(Reader input) throws PathParseException {
		
		super.initParse(input, "");
		
		return path();
	}
	
	/**
	 * Here's the official Turtle 1.1 Syntax
	 * 
	 * PrefixedName	::=	PNAME_LN | PNAME_NS
	 *              ::= (PNAME_NS PN_LOCAL) | PNAME_NS
	 *              ::= PNAME_NS PN_LOCAL?
	 *              ::= PN_PREFIX? ':' PN_LOCAL?      
	 * 
* * We customize the Turtle syntax by redefining PrefixedName as follows. *
	 * PrefixedName	::=	(PN_PREFIX? ':' PN_LOCAL?) | bareLocalName 
	 * bareLocalName ::= PN_PREFIX
	 * 
* Notice that this customization requires that a bareLocalName is allowed only if it matches * the syntax of a namespace prefix. * * We also modify the production rules for PN_LOCAL and PN_PREFIX to exclude '.' characters. */ // protected URI prefixedName(int c) throws IOException, RDFParseException { // unread(c); // // String prefix = pn_prefix(); // // c = read(); // // if (c != ':') { // unread(c); // // Treat the prefix as a bare local name. // if (localNameService != null) { // Set set = localNameService.lookupLocalName(prefix); // if (set.isEmpty()) { // StringBuilder err = err(); // err.append("No URI found with local name '"); // err.append(prefix); // err.append("'"); // fail(err); // } // // if (set.size()>1) { // StringBuilder err = err(); // err.append("Local name '"); // err.append(prefix); // err.append("' is ambgious. Matching values include "); // // int count = 0; // for (URI uri : set) { // if (count > 0) { // err.append(", "); // } // err.append('<'); // err.append(uri.stringValue()); // err.append('>'); // count++; // if (count >= 3) { // break; // } // } // if (set.size()>3) { // err.append(" ..."); // } // fail(err); // } // return set.iterator().next(); // } else { // // StringBuilder err = err(); // err.append("Bare local names not supported. "); // err.append("Use a fully-qualified IRI or a prefixed name, "); // err.append("or assign a LocalNameService to this PathParser."); // fail(err); // } // // } // // String localName = pn_local(); // // String namespace = namespaceMap.get(prefix); // if (namespace == null) { // fail("Namespace not defined for prefix '" + prefix + "'"); // } // // return valueFactory.createURI(namespace + localName); // } /** *
	 * path ::= step+
	 * step ::= namedIndividual | in | out | filter
	 * 
* * @param path */ private Path path() throws PathParseException { Path path = new PathImpl(); try { prologue(); path.setContext(getContext()); int c; while (!done(c=next())) { unread(c); Step step=null; switch (c) { case '.' : case '/' : step = out(); break; case '^' : step = in(); break; case '[' : step = filter(); break; case '?' : step = variable(); break; default : step = namedIndividual(); } path.asList().add(step); } } catch (IOException | RDFParseException | RDFHandlerException e) { throw new PathParseException(e); } if (nameMap != null ) { Context context = path.getContext(); if (context.asList().isEmpty() && nsManager != null) { PathContextBuilder.buildContext(path, nsManager); } } return path; } private Step variable() throws RDFParseException, RDFHandlerException, IOException { read(); String name = pn_local(); URI predicate = new URIImpl(VAR.NAMESPACE + "?" + name); return new OutStep(predicate); } protected boolean done(int c) throws IOException { return c==-1; } /** * Don't allow dots ('.') in the middle of a local name */ public String pn_local() throws IOException, RDFParseException { StringBuilder builder = buffer(); int c = read(); if ( !pn_chars_u(c) && (c != ':') && !inRange(c, '0', '9') && !plx(c) ) { unread(c); } else { builder.appendCodePoint(c); int last = -1; for (;;) { c = read(); if ( !pn_chars(c) && (c != ':') && !plx(c) ) { break; } builder.appendCodePoint(c); last = c; } unread(c); } return builder.toString(); } /** *
	 * namedIndividual ::= iri
	 * 
* @throws RDFHandlerException */ private Step namedIndividual() throws RDFParseException, IOException, RDFHandlerException { URI iri = iri(); return new VertexStep(iri); } private Handler handler() { return (Handler) getRDFHandler(); } /** *
	 * filter ::= blankNodePropertyList
	 * 
* * The blankNodePropertyList rule is defined in the * Turtle 1.1 specification. */ private Step filter() throws RDFParseException, RDFHandlerException, IOException { BNode bnode = blankNodePropertyList(); if (bnode == null) { StringBuilder err = err(); err.append("BNode property list cannot be empty"); fail(err); } BlankNodeStep top = handler().peek(); return top.step; } /** *
	 * in ::= '^' iri
	 * 
* @throws RDFHandlerException */ private Step in() throws RDFParseException, IOException, RDFHandlerException { read('^'); URI predicate = iri(); return new InStep(predicate); } /** *
	 * out ::= '/' iri
	 * 
* @throws RDFHandlerException */ private Step out() throws RDFParseException, IOException, RDFHandlerException { int delim = read(); if (delim!='/' && delim!='.') { throw new RDFParseException("Expected '.' or '/'"); } URI predicate = iri(); return new OutStep(predicate); } /** * PN_PREFIX ::= PN_CHARS_BASE PN_CHARS* */ protected void pn_prefix(int c) throws IOException, RDFParseException { if (pn_chars_base(c)) { buffer.appendCodePoint(c); for (;;) { c = read(); if (pn_chars(c)) { buffer.appendCodePoint(c); } else { break; } } } unread(c); } private static class Handler extends RDFHandlerBase { List stack = new ArrayList<>(); @Override public void handleStatement(Statement st) throws RDFHandlerException { BlankNodeStep top = peek(); Resource subject = st.getSubject(); URI predicate = st.getPredicate(); Value object = st.getObject(); if (!(subject instanceof BNode)) { throw new RDFHandlerException( "Expected subject to be a BNode, but found: " + subject.toString()); } BNode bnode = (BNode) subject; if (top == null) { top = new BlankNodeStep(bnode, new HasStep()); stack.add(top); } if (bnode != top.bnode) { throw new RDFHandlerException("Nested BNodes not supported yet."); // TODO: support nested BNodes. } top.step.add(predicate, object); } private BlankNodeStep peek() { return stack.isEmpty() ? null : stack.get(stack.size()-1); } } private static class BlankNodeStep { private BNode bnode; private HasStep step; public BlankNodeStep(BNode bnode, HasStep step) { this.bnode = bnode; this.step = step; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy