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

com.bigdata.rdf.sail.webapp.client.EncodeDecodeValue Maven / Gradle / Ivy

/**

Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016.  All rights reserved.

Contact:
     SYSTAP, LLC DBA Blazegraph
     2501 Calvert ST NW #106
     Washington, DC 20008
     [email protected]

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 Oct 13, 2011
 */

package com.bigdata.rdf.sail.webapp.client;

import org.openrdf.model.BNode;
import org.openrdf.model.Literal;
import org.openrdf.model.Resource;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.impl.LiteralImpl;
import org.openrdf.model.impl.URIImpl;

/**
 * Utility class to encode/decode RDF {@link Value}s for interchange with the
 * REST API.
 * 
 * @author Bryan Thompson
 * @version $Id$
 */
public class EncodeDecodeValue {

//    /*
//     * Note: The decode logic was derived from the JavaCharStream file generated
//     * by JavaCC.
//     */
//    
//    private static final int hexval(char c) {
//        switch (c) {
//        case '0':
//            return 0;
//        case '1':
//            return 1;
//        case '2':
//            return 2;
//        case '3':
//            return 3;
//        case '4':
//            return 4;
//        case '5':
//            return 5;
//        case '6':
//            return 6;
//        case '7':
//            return 7;
//        case '8':
//            return 8;
//        case '9':
//            return 9;
//
//        case 'a':
//        case 'A':
//            return 10;
//        case 'b':
//        case 'B':
//            return 11;
//        case 'c':
//        case 'C':
//            return 12;
//        case 'd':
//        case 'D':
//            return 13;
//        case 'e':
//        case 'E':
//            return 14;
//        case 'f':
//        case 'F':
//            return 15;
//        }
//
//        throw new AssertionError();
//    }
//
//    private static class DecodeString {
//        private final StringBuilder sb = new StringBuilder();
//        private final String src;
//        private int srcpos = 0;
//        DecodeString(final String s) {
//            this.src = s;
//        }
//        
//        private char ReadByte() {
//            return src.charAt(srcpos++);
//        }
//        
//        private void backup(final int n) {
//
//            sb.setLength(sb.length() - n);
//            
//        }
//        
//        /**
//         * Read a character.
//         * 
//         * TODO Does not handle the 8 character escape code sequences (but
//         * neither does the SPARQL parser!)
//         */
//        private char readChar() throws java.io.IOException {
//            char c;
//
//            sb.append(c = ReadByte());
//            
//            if (c == '\\') {
//
//                int backSlashCnt = 1;
//
//                for (;;) // Read all the backslashes
//                {
//
//                    try {
//                        sb.append(c=ReadByte());
//                        if (c != '\\') {
//                            // found a non-backslash char.
//                            if ((c == 'u') && ((backSlashCnt & 1) == 1)) {
//                                if (--bufpos < 0)
//                                    bufpos = bufsize - 1;
//
//                                break;
//                            }
//
//                            backup(backSlashCnt);
//                            return '\\';
//                        }
//                    } catch (java.io.IOException e) {
//                        // We are returning one backslash so we should only
//                        // backup (count-1)
//                        if (backSlashCnt > 1)
//                            backup(backSlashCnt - 1);
//
//                        return '\\';
//                    }
//
//                    backSlashCnt++;
//                }
//
//                // Here, we have seen an odd number of backslash's followed by a
//                // 'u'
//                try {
//                    while ((c = ReadByte()) == 'u') {}
//
//                    // Decode the code sequence.
//                    c = (char) (hexval(c) << 12 | hexval(ReadByte()) << 8
//                            | hexval(ReadByte()) << 4 | hexval(ReadByte()));
//                    
//                    sb.append(c);
//
//                } catch (java.io.IOException e) {
//
//                    throw new Error("Invalid escape character");
//                    
//                }
//
//                if (backSlashCnt == 1)
//                    return c;
//                else {
//                    backup(backSlashCnt - 1);
//                    return '\\';
//                }
//            } else {
//                return c;
//            }
//        }
//
//    }
//
//    /**
//     * Apply code point escape sequences for anything that we need to escape.
//     * For our purposes, this is just " and >.
//     * @param s
//     * @return
//     * 
//     * @see http://www.w3.org/TR/sparql11-query/#codepointEscape
//     */
//    static String encodeEscapeSequences(final String s) {
//
//        return s;
//        
//    }
//    
//    /**
//     * Decode all code point escape sequences. Note that we need to decode more
//     * than we encode since we are not responsible for the encoding when it
//     * comes to the REST API, just the decoding.
//     * 
//     * @param s
//     *            The string, which may have escape sequences encoded.
//     * 
//     * @return The string with escape sequences decoded.
//     * 
//     * @throws IllegalArgumentException
//     *             if the argument is null.
//     * @throws IllegalArgumentException
//     *             if the argument is contains an ill-formed escape code
//     *             sequence.
//     * 
//     * @see http://www.w3.org/TR/sparql11-query/#codepointEscape
//     * 
//     */
//    static String decodeEscapeSequences(final String s) {
//
////        // Remove any escape sequences.
////        final StringBuilder sb = new StringBuilder();
////        for (int i = 0; i < slen; i++) {
////            char ch = s.charAt(i);
////            if (ch == '\\') {
////                if (i + 1 == slen)
////                    throw new IllegalArgumentException(s);
////                ch = s.charAt(i);
////            }
////            sb.append(ch);
////        }
////        final String t = sb.toString();
//
//        return s;
//        
//    }
    
    /**
     * Decode a URI or Literal.
     * 
     * @param s
     *            The value to be decoded.
     * 
     * @return The URI or literal -or- null if the argument was
     *         null.
     * 
     * @throws IllegalArgumentException
     *             if the request parameter could not be decoded as an RDF
     *             {@link Value}.
     */
    public static Value decodeValue(final String s) {

        if(s == null)
            return null;
        
//        final String s = decodeEscapeSequences(ss);
        
        final int slen = s.length();
        
        if (slen == 0)
            throw new IllegalArgumentException("");

        final char ch = s.charAt(0);
        
        if(ch == '\"' || ch == '\'') {
            
            /*
             * Literal.
             */
            
            final int closeQuotePos = s.lastIndexOf(ch);
            
            if (closeQuotePos == 0)
                throw new IllegalArgumentException(s);
            
            final String label = s.substring(1, closeQuotePos);

            if (slen == closeQuotePos + 1) {
                
                /*
                 * Plain literal.
                 */

                return new LiteralImpl(label);
                
            }

            final char ch2 = s.charAt(closeQuotePos + 1);

            if (ch2 == '@') {
             
                /*
                 * Language code literal.
                 */
                
                final String languageCode = s.substring(closeQuotePos + 2);
                
                return new LiteralImpl(label, languageCode);
                
            } else if (ch2 == '^') {
                
                /*
                 * Datatype literal.
                 */
                
                if (slen <= closeQuotePos + 2)
                    throw new IllegalArgumentException(s);

                if (s.charAt(closeQuotePos + 2) != '^')
                    throw new IllegalArgumentException(s);

                final String datatypeStr = s.substring(closeQuotePos + 3);

                final URI datatypeURI = decodeURI(datatypeStr);
                
                return new LiteralImpl(label,datatypeURI);
                
            } else {
                
                throw new IllegalArgumentException(s);
                
            }
            
        } else if (ch == '<') {

            /*
             * URI
             */
            
            if (s.charAt(slen - 1) != '>')
                throw new IllegalArgumentException(s);

            final String uriStr = s.substring(1, slen - 1);

            return new URIImpl(uriStr);

        } else {

            throw new IllegalArgumentException(s);

        }
        
    }

   /**
    * Type safe variant for a {@link Resource}.
    * 
    * @param param
    *           The encoded value.
    * 
    * @return The Resource -or- null if the argument was
    *         null.
    */
    public static Resource decodeResource(final String param) {

        final Value v = decodeValue(param);

        if (v == null || v instanceof Resource)
            return (Resource) v;

        throw new IllegalArgumentException("Not a Resource: '" + param + "'");

    }

   /**
    * Type safe variant for a {@link URI}.
    * 
    * @param param
    *           The encoded value.
    * 
    * @return The URI -or- null if the argument was
    *         null.
    */
   public static URI decodeURI(final String param) {

        final Value v = decodeValue(param);

        if (v == null || v instanceof URI)
            return (URI) v;

        throw new IllegalArgumentException("Not an URI: '" + param + "'");

    }
    
    /**
     * Encode an RDF {@link Value} as it should appear if used in a SPARQL
     * query. E.g., a literal will look like "abc",
     * "abc"@en or
     * "3"^^xsd:int.  A URI will look like <http://www.bigdata.com/>
     * .
     * 
     * @param v
     *            The value (optional).
     *            
     * @return The encoded value -or- null if the argument is
     *         null.
     * 
     * @throws IllegalArgumentException
     *             if the argument is a {@link BNode}.
     */
    public static String encodeValue(final Value v) {
        if(v == null)
            return null;
        if (v instanceof BNode)
            throw new IllegalArgumentException();
        if (v instanceof URI) {
            return "<" + v.stringValue() + ">";
        }
        if (v instanceof Literal) {
            final Literal lit = (Literal) v;
            final StringBuilder sb = new StringBuilder();
            sb.append("\"");
            sb.append(lit.getLabel());
            sb.append("\"");
            if (lit.getLanguage() != null) {
                sb.append("@");
                sb.append(lit.getLanguage());
            }
            if (lit.getDatatype() != null) {
                sb.append("^^");
                sb.append(encodeValue(lit.getDatatype()));
            }
            return sb.toString();
        }
        throw new AssertionError();
    }

   /**
    * Decode an array of named graph contexts.
    * 
    * @param strings
    *           An array of encoded named graph contexts (required).
    * 
    * @return An array of decoded resources that is 1:1 with the original array.
    * 
    * @throws IllegalArgumentException
    *            if the argument is null.
    * 
    * @see com.bigdata.rdf.store.BD;#NULL_GRAPH
    * 
    * @see  Resource... contexts
    *      not encoded/decoded according to openrdf semantics (REST API) 
    */
    public static Resource[] decodeContexts(final String[] strings) {

       if (strings == null) {
          // Not allowed per the openrdf pattern.
          throw new IllegalArgumentException();
      }

      if (strings.length == 0) {

         // Allowed. Corresponds to all named graphs.
         return EMPTY_RESOURCE_ARRAY;

      }

      final Resource[] tmp = new Resource[strings.length];

      for (int i = 0; i < strings.length; i++) {

         final String s = strings[i];

         if (s == null || s.length() == 0) {

            /*
             * Allowed. This is a reference to the openrdf "null" graph.
             * 
             * Note: "c=" reports a zero length string so we need to decode that
             * to a null reference.
             */
            tmp[i] = null;

         } else {

            tmp[i] = decodeResource(s);

         }

      }

      return tmp;
      
    }

    /**
    * Encode each Resource.
    * 

* Note: When generating URL parameters, we will have zero or more * &c=... instances. These are turned into a Resource[]. If * there are no such arguments, then the array needs to be turned into * Resource[0] on receipt by the webapp in order to be correctly decoded by * {@link #decodeContexts(String[])}. * * @param values * An array of RDF {@link Value}s. * * @return An array of encoded RDF values that is 1:1 with the original * array. * * @throws IllegalArgumentException * if the argument is null. * * @see com.bigdata.rdf.store.BD;#NULL_GRAPH * * @see Resource... contexts * not encoded/decoded according to openrdf semantics (REST API) */ public static String[] encodeContexts(final Resource[] values) { if (values == null) { // Not allowed per the openrdf patterns. throw new IllegalArgumentException(); } if (values.length == 0) { // Allowed. Corresponds to all named graphs. return EMPTY_STRING_ARRAY; } final String[] strings = new String[values.length]; for (int i = 0; i < values.length; i++) { final Value val = values[i]; if (val == null) { strings[i] = null; // i.e., an openrdf null graph reference. } else { strings[i] = encodeValue(val); } } return strings; } /** An empty String[] for encode. */ static private final String[] EMPTY_STRING_ARRAY = new String[0]; /** An empty Resource[] for decode. */ static private final Resource[] EMPTY_RESOURCE_ARRAY = new Resource[0]; }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy