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

org.openrdf.rio.helpers.RDFParserHelper Maven / Gradle / Ivy

/* 
 * Licensed to Aduna under one or more contributor license agreements.  
 * See the NOTICE.txt file distributed with this work for additional 
 * information regarding copyright ownership. 
 *
 * Aduna licenses this file to you under the terms of the Aduna BSD 
 * License (the "License"); you may not use this file except in compliance 
 * with the License. See the LICENSE.txt file distributed with this work 
 * for the full License.
 *
 * 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.
 */
package org.openrdf.rio.helpers;

import java.util.Optional;

import org.openrdf.model.Literal;
import org.openrdf.model.IRI;
import org.openrdf.model.ValueFactory;
import org.openrdf.model.util.LiteralUtilException;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.model.vocabulary.XMLSchema;
import org.openrdf.rio.DatatypeHandler;
import org.openrdf.rio.LanguageHandler;
import org.openrdf.rio.ParseErrorListener;
import org.openrdf.rio.ParserConfig;
import org.openrdf.rio.RDFParseException;
import org.openrdf.rio.RDFParser;
import org.openrdf.rio.RioSetting;

/**
 * Helper methods that may be used by {@link RDFParser} implementations.
 * 

* This class contains reference implementations of the workflows for * {@link ParseErrorListener}, {@link RDFParseException}, {@link ParserConfig}, * {@link DatatypeHandler} and {@link LanguageHandler} related methods * * @author Peter Ansell * @since 2.7.1 */ public class RDFParserHelper { /** * Create a literal using the given parameters, including iterative * verification and normalization by any {@link DatatypeHandler} or * {@link LanguageHandler} implementations that are found in the * {@link ParserConfig}. * * @param label * The value for {@link Literal#getLabel()}, which may be iteratively * normalized. * @param lang * If this is not null, and the datatype is either not null, or is * equal to {@link RDF#LANGSTRING}, then a language literal will be * created. * @param datatype * If datatype is not null, and the datatype is not equal to * {@link RDF#LANGSTRING} with a non-null lang, then a datatype * literal will be created. * @param parserConfig * The source of parser settings, including the desired list of * {@link DatatypeHandler} and {@link LanguageHandler}s to use for * verification and normalization of datatype and language literals * respectively. * @param errListener * The {@link ParseErrorListener} to use for signalling errors. This * will be called if a setting is enabled by setting it to true in the * {@link ParserConfig}, after which the error may trigger an * {@link RDFParseException} if the setting is not present in * {@link ParserConfig#getNonFatalErrors()}. * @param valueFactory * The {@link ValueFactory} to use for creating new {@link Literal}s * using this method. * @return A {@link Literal} created based on the given parameters. * @throws RDFParseException * If there was an error during the process that could not be * recovered from, based on settings in the given parser config. * @since 2.7.1 */ public static final Literal createLiteral(String label, String lang, IRI datatype, ParserConfig parserConfig, ParseErrorListener errListener, ValueFactory valueFactory) throws RDFParseException { return createLiteral(label, lang, datatype, parserConfig, errListener, valueFactory, -1, -1); } /** * Create a literal using the given parameters, including iterative * verification and normalization by any {@link DatatypeHandler} or * {@link LanguageHandler} implementations that are found in the * {@link ParserConfig}. * * @param label * The value for {@link Literal#getLabel()}, which may be iteratively * normalized. * @param lang * If this is not null, and the datatype is either not null, or is * equal to {@link RDF#LANGSTRING}, then a language literal will be * created. * @param datatype * If datatype is not null, and the datatype is not equal to * {@link RDF#LANGSTRING} with a non-null lang, then a datatype * literal will be created. * @param parserConfig * The source of parser settings, including the desired list of * {@link DatatypeHandler} and {@link LanguageHandler}s to use for * verification and normalization of datatype and language literals * respectively. * @param errListener * The {@link ParseErrorListener} to use for signalling errors. This * will be called if a setting is enabled by setting it to true in the * {@link ParserConfig}, after which the error may trigger an * {@link RDFParseException} if the setting is not present in * {@link ParserConfig#getNonFatalErrors()}. * @param valueFactory * The {@link ValueFactory} to use for creating new {@link Literal}s * using this method. * @param lineNo * Optional line number, should default to setting this as -1 if not * known. Used for * {@link ParseErrorListener#error(String, long, long)} and for * {@link RDFParseException#RDFParseException(String, long, long)}. * @param columnNo * Optional column number, should default to setting this as -1 if not * known. Used for * {@link ParseErrorListener#error(String, long, long)} and for * {@link RDFParseException#RDFParseException(String, long, long)}. * @return A {@link Literal} created based on the given parameters. * @throws RDFParseException * If there was an error during the process that could not be * recovered from, based on settings in the given parser config. * @since 2.7.4 */ public static final Literal createLiteral(String label, String lang, IRI datatype, ParserConfig parserConfig, ParseErrorListener errListener, ValueFactory valueFactory, long lineNo, long columnNo) throws RDFParseException { if (label == null) { throw new NullPointerException("Cannot create a literal using a null label"); } Literal result = null; String workingLabel = label; Optional workingLang = Optional.ofNullable(lang); IRI workingDatatype = datatype; // In RDF-1.1 we must do lang check first as language literals will all // have datatype RDF.LANGSTRING, but only language literals would have a // non-null lang if (workingLang.isPresent() && (workingDatatype == null || RDF.LANGSTRING.equals(workingDatatype))) { boolean recognisedLanguage = false; for (LanguageHandler nextHandler : parserConfig.get(BasicParserSettings.LANGUAGE_HANDLERS)) { if (nextHandler.isRecognizedLanguage(workingLang.get())) { recognisedLanguage = true; if (parserConfig.get(BasicParserSettings.VERIFY_LANGUAGE_TAGS)) { try { if (!nextHandler.verifyLanguage(workingLabel, workingLang.get())) { reportError("'" + lang + "' is not a valid language tag ", lineNo, columnNo, BasicParserSettings.VERIFY_LANGUAGE_TAGS, parserConfig, errListener); } } catch (LiteralUtilException e) { reportError( "'" + label + " could not be verified by a language handler that recognised it. language was " + lang, lineNo, columnNo, BasicParserSettings.VERIFY_LANGUAGE_TAGS, parserConfig, errListener); } } if (parserConfig.get(BasicParserSettings.NORMALIZE_LANGUAGE_TAGS)) { try { result = nextHandler.normalizeLanguage(workingLabel, workingLang.get(), valueFactory); workingLabel = result.getLabel(); workingLang = result.getLanguage(); workingDatatype = result.getDatatype(); } catch (LiteralUtilException e) { reportError( "'" + label + "' did not have a valid value for language " + lang + ": " + e.getMessage() + " and could not be normalised", lineNo, columnNo, BasicParserSettings.NORMALIZE_LANGUAGE_TAGS, parserConfig, errListener); } } } } if (!recognisedLanguage) { reportError( "'" + label + "' was not recognised as a language literal, and could not be verified, with language " + lang, lineNo, columnNo, BasicParserSettings.FAIL_ON_UNKNOWN_LANGUAGES, parserConfig, errListener); } } else if (workingDatatype != null) { boolean recognisedDatatype = false; for (DatatypeHandler nextHandler : parserConfig.get(BasicParserSettings.DATATYPE_HANDLERS)) { if (nextHandler.isRecognizedDatatype(workingDatatype)) { recognisedDatatype = true; if (parserConfig.get(BasicParserSettings.VERIFY_DATATYPE_VALUES)) { try { if (!nextHandler.verifyDatatype(workingLabel, workingDatatype)) { reportError("'" + label + "' is not a valid value for datatype " + datatype, lineNo, columnNo, BasicParserSettings.VERIFY_DATATYPE_VALUES, parserConfig, errListener); } } catch (LiteralUtilException e) { reportError( "'" + label + " could not be verified by a datatype handler that recognised it. datatype was " + datatype, lineNo, columnNo, BasicParserSettings.VERIFY_DATATYPE_VALUES, parserConfig, errListener); } } if (parserConfig.get(BasicParserSettings.NORMALIZE_DATATYPE_VALUES)) { try { result = nextHandler.normalizeDatatype(workingLabel, workingDatatype, valueFactory); workingLabel = result.getLabel(); workingLang = result.getLanguage(); workingDatatype = result.getDatatype(); } catch (LiteralUtilException e) { reportError( "'" + label + "' is not a valid value for datatype " + datatype + ": " + e.getMessage() + " and could not be normalised", lineNo, columnNo, BasicParserSettings.NORMALIZE_DATATYPE_VALUES, parserConfig, errListener); } } } } if (!recognisedDatatype) { reportError( "'" + label + "' was not recognised, and could not be verified, with datatype " + datatype, lineNo, columnNo, BasicParserSettings.FAIL_ON_UNKNOWN_DATATYPES, parserConfig, errListener); } } if (result == null) { try { // Backup for unnormalised language literal creation if (workingLang.isPresent() && (workingDatatype == null || RDF.LANGSTRING.equals(workingDatatype))) { result = valueFactory.createLiteral(workingLabel, workingLang.get().intern()); } // Backup for unnormalised datatype literal creation else if (workingDatatype != null) { result = valueFactory.createLiteral(workingLabel, workingDatatype); } else { result = valueFactory.createLiteral(workingLabel, XMLSchema.STRING); } } catch (Exception e) { reportFatalError(e, lineNo, columnNo, errListener); } } return result; } /** * Reports an error with associated line- and column number to the registered * ParseErrorListener, if the given setting has been set to true. *

* This method also throws an {@link RDFParseException} when the given * setting has been set to true and it is not a nonFatalError. * * @param msg * The message to use for * {@link ParseErrorListener#error(String, long, long)} and for * {@link RDFParseException#RDFParseException(String, long, long)}. * @param relevantSetting * The boolean setting that will be checked to determine if this is an * issue that we need to look at at all. If this setting is true, then * the error listener will receive the error, and if * {@link ParserConfig#isNonFatalError(RioSetting)} returns true an * exception will be thrown. * @param parserConfig * The {@link ParserConfig} to use for determining if the error is * first sent to the ParseErrorListener, and whether it is then also * non-fatal to avoid throwing an {@link RDFParseException}. * @param errListener * The {@link ParseErrorListener} that will be sent messages about * errors that are enabled. * @throws RDFParseException * If {@link ParserConfig#get(RioSetting)} returns true, and * {@link ParserConfig#isNonFatalError(RioSetting)} returns true for * the given setting. * @since 2.7.1 */ public static void reportError(String msg, RioSetting relevantSetting, ParserConfig parserConfig, ParseErrorListener errListener) throws RDFParseException { reportError(msg, -1, -1, relevantSetting, parserConfig, errListener); } /** * Reports an error with associated line- and column number to the registered * ParseErrorListener, if the given setting has been set to true. *

* This method also throws an {@link RDFParseException} when the given * setting has been set to true and it is not a nonFatalError. * * @param msg * The message to use for * {@link ParseErrorListener#error(String, long, long)} and for * {@link RDFParseException#RDFParseException(String, long, long)}. * @param lineNo * Optional line number, should default to setting this as -1 if not * known. Used for * {@link ParseErrorListener#error(String, long, long)} and for * {@link RDFParseException#RDFParseException(String, long, long)}. * @param columnNo * Optional column number, should default to setting this as -1 if not * known. Used for * {@link ParseErrorListener#error(String, long, long)} and for * {@link RDFParseException#RDFParseException(String, long, long)}. * @param relevantSetting * The boolean setting that will be checked to determine if this is an * issue that we need to look at at all. If this setting is true, then * the error listener will receive the error, and if * {@link ParserConfig#isNonFatalError(RioSetting)} returns true an * exception will be thrown. * @param parserConfig * The {@link ParserConfig} to use for determining if the error is * first sent to the ParseErrorListener, and whether it is then also * non-fatal to avoid throwing an {@link RDFParseException}. * @param errListener * The {@link ParseErrorListener} that will be sent messages about * errors that are enabled. * @throws RDFParseException * If {@link ParserConfig#get(RioSetting)} returns true, and * {@link ParserConfig#isNonFatalError(RioSetting)} returns true for * the given setting. * @since 2.7.1 */ public static void reportError(String msg, long lineNo, long columnNo, RioSetting relevantSetting, ParserConfig parserConfig, ParseErrorListener errListener) throws RDFParseException { if (parserConfig.get(relevantSetting)) { if (errListener != null) { errListener.error(msg, lineNo, columnNo); } if (!parserConfig.isNonFatalError(relevantSetting)) { throw new RDFParseException(msg, lineNo, columnNo); } } } /** * Reports an error with associated line- and column number to the registered * ParseErrorListener, if the given setting has been set to true. *

* This method also throws an {@link RDFParseException} when the given * setting has been set to true and it is not a nonFatalError. * * @param e * The exception whose message to use for * {@link ParseErrorListener#error(String, long, long)} and for * {@link RDFParseException#RDFParseException(String, long, long)}. * @param lineNo * Optional line number, should default to setting this as -1 if not * known. Used for * {@link ParseErrorListener#error(String, long, long)} and for * {@link RDFParseException#RDFParseException(String, long, long)}. * @param columnNo * Optional column number, should default to setting this as -1 if not * known. Used for * {@link ParseErrorListener#error(String, long, long)} and for * {@link RDFParseException#RDFParseException(String, long, long)}. * @param relevantSetting * The boolean setting that will be checked to determine if this is an * issue that we need to look at at all. If this setting is true, then * the error listener will receive the error, and if * {@link ParserConfig#isNonFatalError(RioSetting)} returns true an * exception will be thrown. * @param parserConfig * The {@link ParserConfig} to use for determining if the error is * first sent to the ParseErrorListener, and whether it is then also * non-fatal to avoid throwing an {@link RDFParseException}. * @param errListener * The {@link ParseErrorListener} that will be sent messages about * errors that are enabled. * @throws RDFParseException * If {@link ParserConfig#get(RioSetting)} returns true, and * {@link ParserConfig#isNonFatalError(RioSetting)} returns true for * the given setting. * @since 2.7.1 */ public static void reportError(Exception e, long lineNo, long columnNo, RioSetting relevantSetting, ParserConfig parserConfig, ParseErrorListener errListener) throws RDFParseException { if (parserConfig.get(relevantSetting)) { if (errListener != null) { errListener.error(e.getMessage(), lineNo, columnNo); } if (!parserConfig.isNonFatalError(relevantSetting)) { if (e instanceof RDFParseException) { throw (RDFParseException)e; } else { throw new RDFParseException(e, lineNo, columnNo); } } } } /** * Reports a fatal error to the registered ParseErrorListener, if any, and * throws a ParseException afterwards. This method simply calls * {@link #reportFatalError(String, long, long, ParseErrorListener)} * supplying -1 for the line- and column number. * * @since 2.7.1 */ public static void reportFatalError(String msg, ParseErrorListener errListener) throws RDFParseException { reportFatalError(msg, -1, -1, errListener); } /** * Reports a fatal error with associated line- and column number to the * registered ParseErrorListener, if any, and throws a * ParseException afterwards. * * @since 2.7.1 */ public static void reportFatalError(String msg, long lineNo, long columnNo, ParseErrorListener errListener) throws RDFParseException { if (errListener != null) { errListener.fatalError(msg, lineNo, columnNo); } throw new RDFParseException(msg, lineNo, columnNo); } /** * Reports a fatal error to the registered ParseErrorListener, if any, and * throws a ParseException afterwards. An exception is made for the * case where the supplied exception is a {@link RDFParseException}; in that * case the supplied exception is not wrapped in another ParseException and * the error message is not reported to the ParseErrorListener, assuming that * it has already been reported when the original ParseException was thrown. *

* This method simply calls * {@link #reportFatalError(Exception, long, long, ParseErrorListener)} * supplying -1 for the line- and column number. * * @since 2.7.1 */ public static void reportFatalError(Exception e, ParseErrorListener errListener) throws RDFParseException { reportFatalError(e, -1, -1, errListener); } /** * Reports a fatal error with associated line- and column number to the * registered ParseErrorListener, if any, and throws a * ParseException wrapped the supplied exception afterwards. An * exception is made for the case where the supplied exception is a * {@link RDFParseException}; in that case the supplied exception is not * wrapped in another ParseException and the error message is not reported to * the ParseErrorListener, assuming that it has already been reported when * the original ParseException was thrown. * * @since 2.7.1 */ public static void reportFatalError(Exception e, long lineNo, long columnNo, ParseErrorListener errListener) throws RDFParseException { if (e instanceof RDFParseException) { throw (RDFParseException)e; } else { if (errListener != null) { errListener.fatalError(e.getMessage(), lineNo, columnNo); } throw new RDFParseException(e, lineNo, columnNo); } } /** * Protected constructor to prevent direct instantiation. */ protected RDFParserHelper() { } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy