/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com 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; version 2 of the License. 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Created on Feb 11, 2011 */ package com.bigdata.rdf.error; import java.util.Formatter; import com.bigdata.util.NV; /** * Exception Base class for errors defined by the W3C for XQuery, XPath, and * SPARQL. * * @see http://www.w3.org/TR/xquery/#errors * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ */ public class W3CQueryLanguageException extends RuntimeException { /** * Namespace for the error URIs. */ protected static final transient String err = "http://www.w3.org/2005/xqt-errors"; /** * */ private static final long serialVersionUID = 1L; /** Language family for errors. */ public static enum LanguageFamily { /** * XQuery */ XQ, /** * XPath */ XP, /** * SPARQL */ SP } /** Error category. */ public static enum ErrorCategory { /** Static analysis error. */ ST, /** Dynamic (runtime) error. */ DY, /** Type error. */ TY }; /** * The {@link LanguageFamily}. */ public final LanguageFamily languageFamily; /** * The {@link ErrorCategory}. */ public final ErrorCategory errorCategory; /** * The four digit error code. */ public final int errorCode; /** * * @param languageFamily * The {@link LanguageFamily}. * @param errorCategory * The {@link ErrorCategory}. * @param errorCode * The four digit error code. */ protected W3CQueryLanguageException(final LanguageFamily languageFamily, final ErrorCategory errorCategory, final int errorCode) { super(toURI(languageFamily, errorCategory, errorCode, null/* params */)); this.languageFamily = languageFamily; this.errorCategory = errorCategory; this.errorCode = errorCode; } /** * * @param languageFamily * The {@link LanguageFamily}. * @param errorCategory * The {@link ErrorCategory}. * @param errorCode * The four digit error code. * @param msg * The <em>URI</em> corresponding to the error. Frequently used * errors should use * {@link #toURI(LanguageFamily, ErrorCategory, int)} to define * the URI statically to avoid heap churn. */ protected W3CQueryLanguageException(final LanguageFamily languageFamily, final ErrorCategory errorCategory, final int errorCode, final String msg) { super(msg == null ? toURI(languageFamily, errorCategory, errorCode, null/* params */) : msg); this.languageFamily = languageFamily; this.errorCategory = errorCategory; this.errorCode = errorCode; } /** * @param languageFamily * The {@link LanguageFamily}. * @param errorCategory * The {@link ErrorCategory}. * @param errorCode * The four digit error code. * @param params * Additional parameters for the error message (optional and may * be <code>null</code>). When non-<code>null</code> and * non-empty, the parameters are appended to the constructed URI * as query parameters. */ protected W3CQueryLanguageException(final LanguageFamily languageFamily, final ErrorCategory errorCategory, final int errorCode, final NV[] params) { super(toURI(languageFamily, errorCategory, errorCode, params)); this.languageFamily = languageFamily; this.errorCategory = errorCategory; this.errorCode = errorCode; } /** * Return the URI for the given error. This is used to avoid the runtime * creation of strings for frequently thrown errors, such as type errors. * Various subclasses use this method to declare concrete URIs which are * then passed into their constructors for specific kinds of errors. * * @param languageFamily * The {@link LanguageFamily}. * @param errorCategory * The {@link ErrorCategory}. * @param errorCode * The four digit error code. * @param params * Additional parameters for the error message (optional and may * be <code>null</code>). When non-<code>null</code> and * non-empty, the parameters are appended to the constructed URI * as query parameters. * * @return The URI. */ static protected String toURI(final LanguageFamily languageFamily, final ErrorCategory errorCategory, final int errorCode, final NV[] params) { if (errorCode >= 10000 || errorCode < 0) throw new IllegalArgumentException(); final String uri; { final StringBuffer sb = new StringBuffer(4); final Formatter f = new Formatter(sb); f.format("%04d", errorCode); uri = err + languageFamily + errorCategory + sb.toString(); } if (params == null || params.length == 0) { return uri; } // Add query parameters. { final StringBuilder sb = new StringBuilder(); sb.append(uri); for (int i = 0; i < params.length; i++) { final NV nv = params[i]; sb.append(i == 0 ? '?' : '&'); sb.append(encode(nv.getName())); sb.append('='); sb.append(encode(nv.getValue())); } return sb.toString(); } } /** * Safe UTF-8 encoder (handles the highly unlikely exception that can be * thrown as well as a <code>null</code> value). * * @param s * The string. * * @return The encoded string. */ private static String encode(final String s) { if (s == null) return encode("null"); // try { // // return URLEncoder.encode(s, "UTF-8"); // // } catch (UnsupportedEncodingException ex) { // // return s; // // } /* * I prefer the plain text of the string as this is really a QName and * not a navigable URI. */ return s; } // public static void main(String[] x) { // // System.err.println(toURI(LanguageFamily.SP,ErrorCategory.TY,120)); // // } }