$search
00001 /* 00002 * Copyright (c) 2010, Lorenz Moesenlechner 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * * Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Neither the name of Willow Garage, Inc. nor the names of its 00014 * contributors may be used to endorse or promote products derived from 00015 * this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 00030 package edu.tum.cs.ias.knowrob.json_prolog; 00031 00032 import net.sf.json.*; 00033 import net.sf.json.util.JSONUtils; 00034 import jpl.JPLException; 00035 import jpl.Query; 00036 import jpl.Term; 00037 import java.util.*; 00038 import java.util.regex.Matcher; 00039 import java.util.regex.Pattern; 00040 00041 public class JSONQuery { 00042 00043 static public class InvalidJSONQuery extends Exception { 00044 public InvalidJSONQuery() { 00045 } 00046 00047 public InvalidJSONQuery(String msg) { 00048 super(msg); 00049 } 00050 00051 private static final long serialVersionUID = 1L; 00052 } 00053 00054 static public Query makeQuery(String json) throws InvalidJSONQuery { 00055 try { 00056 JSONArray json_query = JSONArray.fromObject(json); 00057 00058 return new Query(makeCompoundTerm(json_query)); 00059 } catch (Exception e) { 00060 throw new InvalidJSONQuery("Unable to parse JSON query: " + json + ", Exception: " + e.toString()); 00061 } 00062 } 00063 00064 00065 static public JSONObject encodeResult(Hashtable<String, Term> bindings) { 00066 JSONObject result = new JSONObject(); 00067 00068 Iterator<Map.Entry<String, Term>> it = bindings.entrySet().iterator(); 00069 while (it.hasNext()) { 00070 Map.Entry<String, Term> e = it.next(); 00071 00072 if (e.getValue().isFloat()) 00073 result.put(e.getKey(), e.getValue().floatValue()); 00074 else if (e.getValue().isInteger()) 00075 result.put(e.getKey(), e.getValue().intValue()); 00076 else if (e.getValue().isCompound() && !e.getValue().isAtom()) { 00077 if (isList(e.getValue())) 00078 result.put(e.getKey(), encodeList(e.getValue())); 00079 else 00080 result.put(e.getKey(), encodeCompoundTerm(e.getValue())); 00081 } 00082 else 00083 result.put(e.getKey(), e.getValue().name()); 00084 } 00085 return result; 00086 } 00087 00088 static Term makeCompoundTerm(JSONArray val) throws InvalidJSONQuery { 00089 if (val.isEmpty()) 00090 throw new InvalidJSONQuery("makeCompoundTerm: empty sequence."); 00091 00092 String predicate = val.getString(0); 00093 if (predicate == null) 00094 throw new InvalidJSONQuery("makeCompoundTerm: no predicate given."); 00095 00096 String[] split_predicate = predicate.split(":"); 00097 if(split_predicate.length == 1) { 00098 if(val.size() > 1) 00099 return new jpl.Compound(predicate, decodeJSONArray(val, 1)); 00100 else 00101 return new jpl.Atom(predicate); 00102 } 00103 else if(split_predicate.length == 2) { 00104 if(val.size() > 1) 00105 return new jpl.Compound(":", new Term[] { 00106 new jpl.Atom(split_predicate[0]), 00107 new jpl.Compound(split_predicate[1], decodeJSONArray(val, 1)) }); 00108 else 00109 return new jpl.Compound(":", new Term[] { 00110 new jpl.Atom(split_predicate[0]), 00111 new jpl.Atom(split_predicate[1]) }); 00112 } 00113 else 00114 throw new InvalidJSONQuery("Predicate encoding wrong. Found more than one ':' in " + predicate); 00115 } 00116 00117 static Term[] decodeJSONArray(JSONArray val) throws InvalidJSONQuery { 00118 return decodeJSONArray(val, 0); 00119 } 00120 00121 static private Term[] decodeJSONArray(JSONArray val, int startIndex) 00122 throws InvalidJSONQuery { 00123 if(startIndex >= val.size()) 00124 return new Term[0]; 00125 00126 Term[] terms = new Term[val.size() - startIndex]; 00127 00128 for (int i = startIndex; i < val.size(); i++) { 00129 if (JSONUtils.isString(val.get(i))) 00130 terms[i - startIndex] = decodeJSONValue(val.getString(i)); 00131 else if (JSONUtils.isBoolean(val.get(i))) 00132 terms[i - startIndex] = decodeJSONValue(val.getBoolean(i)); 00133 // else if (JSONUtils.isDouble(val.get(i))) 00134 // terms[i - startIndex] = decodeJSONValue(val.getDouble(i)); 00135 else if (JSONUtils.isNumber(val.get(i))) 00136 terms[i - startIndex] = decodeJSONValue(val.getInt(i)); 00137 else if (JSONUtils.isObject(val.get(i))) 00138 terms[i - startIndex] = decodeJSONValue(val.getJSONObject(i)); 00139 else if (JSONUtils.isArray(val.get(i))) 00140 terms[i - startIndex] = jpl.Util.termArrayToList(decodeJSONArray(val.getJSONArray(i))); 00141 else 00142 throw new InvalidJSONQuery("decodeJSONArray: unable to parse " 00143 + val.toString()); 00144 } 00145 return terms; 00146 } 00147 00148 static Term decodeJSONValue(String val) { 00149 00150 // wrap string in single quotes if it contains special characters 00151 val = val.replace("\\", ""); 00152 Matcher matcher = Pattern.compile("^[\\w_]*$").matcher(val); 00153 if(!matcher.find()) { 00154 val="'"+val+"'"; 00155 } 00156 return jpl.Util.textToTerm(val); 00157 } 00158 00159 static Term decodeJSONValue(boolean val) { 00160 // Hack. No idea if we need to serialize bools and how. 00161 return new jpl.Integer(val ? 1 : 0); 00162 } 00163 00164 static Term decodeJSONValue(double val) { 00165 return new jpl.Float(val); 00166 } 00167 00168 static Term decodeJSONValue(int val) { 00169 return new jpl.Integer(val); 00170 } 00171 00172 static Term decodeJSONValue(JSONObject val) throws InvalidJSONQuery { 00173 if (val.has("variable")) 00174 return new jpl.Variable(val.getString("variable")); 00175 else if (val.has("term")) 00176 return makeCompoundTerm(val.getJSONArray("term")); 00177 else if (val.has("list")) { 00178 JSONArray json_elements = val.getJSONArray("list"); 00179 return jpl.Util.termArrayToList(decodeJSONArray(json_elements)); 00180 } else 00181 throw new InvalidJSONQuery("decodeJSONValue: unable to parse " 00182 + val.toString()); 00183 } 00184 00185 static private JSONObject encodeCompoundTerm(Term term) { 00186 JSONObject result = new JSONObject(); 00187 JSONArray term_list = new JSONArray(); 00188 00189 term_list.element(term.name()); 00190 JSONArray args_list = encodeList(term.args()); 00191 00192 for (int i = 0; i < args_list.size(); i++) 00193 term_list.element(args_list.get(i)); 00194 00195 result.put("term", term_list); 00196 return result; 00197 } 00198 00199 static private JSONArray encodeList(Term term) throws JPLException { 00200 Term[] term_list = term.toTermArray(); 00201 return encodeList(term_list); 00202 } 00203 00204 static private JSONArray encodeList(Term[] term_list) throws JPLException { 00205 JSONArray result = new JSONArray(); 00206 for (int i = 0; i < term_list.length; i++) { 00207 if (term_list[i].isFloat()) 00208 result.element(term_list[i].floatValue()); 00209 else if (term_list[i].isInteger()) 00210 result.element(term_list[i].intValue()); 00211 else if (term_list[i].isAtom()) 00212 result.element(term_list[i].name()); 00213 else if (term_list[i].isCompound()) { 00214 if (isList(term_list[i])) 00215 result.element(encodeList(term_list[i])); 00216 else 00217 result.element(encodeCompoundTerm(term_list[i])); 00218 } else 00219 result.element(term_list[i].name()); 00220 } 00221 00222 return result; 00223 } 00224 00225 static private boolean isList(Term term) { 00226 try { 00227 term.listLength(); 00228 return true; 00229 } catch (JPLException e) { 00230 return false; 00231 } 00232 } 00233 00234 } //