You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stanbol.apache.org by fc...@apache.org on 2011/07/12 17:20:23 UTC

svn commit: r1145631 - /incubator/stanbol/trunk/commons/jsonld/src/main/java/org/apache/stanbol/commons/jsonld/JsonLdParser.java

Author: fchrist
Date: Tue Jul 12 15:20:23 2011
New Revision: 1145631

URL: http://svn.apache.org/viewvc?rev=1145631&view=rev
Log:
STANBOL-220 Fixed bug parsing lists/arrays

Modified:
    incubator/stanbol/trunk/commons/jsonld/src/main/java/org/apache/stanbol/commons/jsonld/JsonLdParser.java

Modified: incubator/stanbol/trunk/commons/jsonld/src/main/java/org/apache/stanbol/commons/jsonld/JsonLdParser.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/commons/jsonld/src/main/java/org/apache/stanbol/commons/jsonld/JsonLdParser.java?rev=1145631&r1=1145630&r2=1145631&view=diff
==============================================================================
--- incubator/stanbol/trunk/commons/jsonld/src/main/java/org/apache/stanbol/commons/jsonld/JsonLdParser.java (original)
+++ incubator/stanbol/trunk/commons/jsonld/src/main/java/org/apache/stanbol/commons/jsonld/JsonLdParser.java Tue Jul 12 15:20:23 2011
@@ -1,6 +1,8 @@
 package org.apache.stanbol.commons.jsonld;
 
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.codehaus.jettison.json.JSONArray;
@@ -12,192 +14,240 @@ import org.slf4j.LoggerFactory;
 /**
  * The JsonLdParser can be used to parse a given JSON-LD String representation
  * into a JSON-LD data structure.
- *
+ * 
  * @author Fabian Christ
  */
 public class JsonLdParser extends JsonLdParserCommon {
 
-    private static Logger logger = LoggerFactory.getLogger(JsonLdParser.class);
+	private static Logger logger = LoggerFactory.getLogger(JsonLdParser.class);
 
-    /**
-     * Parse the given String into a JSON-LD data structure.
-     * 
-     * @param jsonLdString A JSON-LD String.
-     * @return JSON-LD data structure.
-     */
-    public static JsonLd parse(String jsonLdString) throws Exception {
-        JsonLd jld = null;
-
-        JSONObject jo = parseJson(jsonLdString);
-        if (jo != null) {
-            jld = new JsonLd();
-            parseSubject(jo, jld, 1, null);
-        }
-
-        return jld;
-    }
-    
-    /**
-     * Parses a single subject.
-     * 
-     * @param jo
-     *            JSON object that holds the subject's data.
-     * @param jld
-     *            JsonLd object to add the created subject resource.
-     */
-    private static void parseSubject(JSONObject jo, JsonLd jld, int bnodeCount, String profile) {
-
-        // The root subject is used for cases where no explicit subject is specified. We need
-        // at least one dummy subject (bnode) to support type coercion because types are assigned to
-        // subjects.
-        JsonLdResource subject = new JsonLdResource();
-
-        try {
-            if (jo.has(JsonLdCommon.CONTEXT)) {
-                JSONObject context = jo.getJSONObject(JsonLdCommon.CONTEXT);
-                for (int i = 0; i < context.names().length(); i++) {
-                    String name = context.names().getString(i).toLowerCase();
-                    if (name.equals(JsonLdCommon.TYPES)) {
-                        JSONObject typeObject = context.getJSONObject(name);
-                        for (int j = 0; j < typeObject.names().length(); j++) {
-                            String property = typeObject.names().getString(j);
-                            String type = typeObject.getString(property);
-                            subject.putCoercionType(property, type);
-                        }
-                    } else {
-                        jld.addNamespacePrefix(context.getString(name), name);
-                    }
-                }
-
-                jo.remove(JsonLdCommon.CONTEXT);
-            }
-
-            // If there is a local profile specified for this subject, we
-            // use that one. Otherwise we assign the profile given by the parameter.
-            if (jo.has(JsonLdCommon.PROFILE)) {
-                String localProfile = unCURIE(jo.getString(JsonLdCommon.PROFILE), jld.getNamespacePrefixMap());
-                profile = localProfile;
-                jo.remove(JsonLdCommon.PROFILE);
-            }
-            subject.setProfile(profile);
-
-            if (jo.has(JsonLdCommon.SUBJECT)) {
-                // Check for N subjects
-                Object subjectObject = jo.get(JsonLdCommon.SUBJECT);
-                if (subjectObject instanceof JSONArray) {
-                    // There is an array of subjects. We create all subjects
-                    // in sequence.
-                    JSONArray subjects = (JSONArray) subjectObject;
-                    for (int i = 0; i < subjects.length(); i++) {
-                        parseSubject(subjects.getJSONObject(i), jld, bnodeCount++, profile);
-                    }
-                } else {
-                    String subjectName = unCURIE(jo.getString(JsonLdCommon.SUBJECT), jld.getNamespacePrefixMap());
-                    subject.setSubject(subjectName);
-                }
-                jo.remove(JsonLdCommon.SUBJECT);
-            } else {
-                // No subject specified. We create a dummy bnode
-                // and add this subject.
-                subject.setSubject("_:bnode" + bnodeCount);
-                jld.put(subject.getSubject(), subject);
-            }
-
-            // Iterate through the rest of properties and unCURIE property values
-            // depending on their type
-            if (jo.names() != null && jo.names().length() > 0) {
-                for (int i = 0; i < jo.names().length(); i++) {
-                    String property = jo.names().getString(i);
-                    Object valueObject = jo.get(property);
-                    if (valueObject instanceof JSONObject) {
-                        JSONObject jsonValue = (JSONObject) valueObject;
-                        subject.putProperty(property, convertToMapAndList(jsonValue, jld
-                                .getNamespacePrefixMap()));
-                    } else if (valueObject instanceof String) {
-                        String stringValue = (String) valueObject;
-                        subject.putProperty(property, unCURIE(stringValue, jld.getNamespacePrefixMap()));
-                    } else {
-                        subject.putProperty(property, valueObject);
-                    }
-                }
-            }
-
-        } catch (JSONException e) {
-            logger.error("There were JSON problems when parsing the JSON-LD String", e);
-            e.printStackTrace();
-        }
-    }
-
-    /**
-     * Converts a JSON object into a Map or List data structure.
-     * 
-     * <p>
-     * The JSON-LD implementation is based on Map and List data types. If the input is a JSONObject, it will
-     * be converted into a Map&lt;String, Object>. If the input is a JSONArray, it will be converted into a
-     * List&lt;Object>. Otherwise the input will be returned untouched.
-     * 
-     * @param input
-     *            Object that will be converted.
-     * @return
-     */
-    private static Object convertToMapAndList(Object input, Map<String,String> namespacePrefixMap) {
-        if (input instanceof JSONObject) {
-            JSONObject jo = (JSONObject) input;
-
-            // Handle IRIs
-            if (jo.has(JsonLdCommon.IRI)) {
-                try {
-                    return new JsonLdIRI(unCURIE(jo.getString(JsonLdCommon.IRI), namespacePrefixMap));
-                } catch (JSONException e) {
-                    return null;
-                }
-            }
-            else {
-                // Handle arbitrary JSON
-                return convertToMap(jo, namespacePrefixMap);
-            }
-        } else if (input instanceof String) {
-            return unCURIE((String) input, namespacePrefixMap);
-        } else {
-            return input;
-        }
-    }
-
-    /**
-     * Converts a JSONOBject into a Map&lt;String, Object>.
-     * 
-     * @param jo
-     *            JSONOBject to be converted.
-     * @return A Map that represents the same information as the JSONOBject.
-     */
-    private static Map<String,Object> convertToMap(JSONObject jo, Map<String,String> namespacePrefixMap) {
-        Map<String,Object> jsonMap = null;
-        try {
-            if (jo.names() != null && jo.names().length() > 0) {
-                jsonMap = new HashMap<String,Object>();
-                for (int i = 0; i < jo.names().length(); i++) {
-                    String name = jo.names().getString(i);
-                    jsonMap.put(name, convertToMapAndList(jo.get(name), namespacePrefixMap));
-                }
-            }
-        } catch (JSONException e) { /* ignored */}
-        return jsonMap;
-    }
-
-    /**
-     * Replaces the CURIE prefixes with the namespace to create full qualified IRIs.
-     * 
-     * @param curie
-     *            The CURIE to create an IRI from.
-     * @param namespacePrefixMap
-     *            A Map with known namespaces.
-     * @return
-     */
-    private static String unCURIE(String curie, Map<String,String> namespacePrefixMap) {
-        for (String namespace : namespacePrefixMap.keySet()) {
-            String prefix = namespacePrefixMap.get(namespace) + ":";
-            curie = curie.replaceAll(prefix, namespace);
-        }
-        return curie;
-    }
+	/**
+	 * Parse the given String into a JSON-LD data structure.
+	 * 
+	 * @param jsonLdString
+	 *            A JSON-LD String.
+	 * @return JSON-LD data structure.
+	 */
+	public static JsonLd parse(String jsonLdString) throws Exception {
+		JsonLd jld = null;
+
+		JSONObject jo = parseJson(jsonLdString);
+		if (jo != null) {
+			jld = new JsonLd();
+			parseSubject(jo, jld, 1, null);
+		}
+
+		return jld;
+	}
+
+	/**
+	 * Parses a single subject.
+	 * 
+	 * @param jo
+	 *            JSON object that holds the subject's data.
+	 * @param jld
+	 *            JsonLd object to add the created subject resource.
+	 */
+	private static void parseSubject(JSONObject jo, JsonLd jld, int bnodeCount,
+			String profile) {
+
+		// The root subject is used for cases where no explicit subject is
+		// specified. We need
+		// at least one dummy subject (bnode) to support type coercion because
+		// types are assigned to
+		// subjects.
+		JsonLdResource subject = new JsonLdResource();
+
+		try {
+			if (jo.has(JsonLdCommon.CONTEXT)) {
+				JSONObject context = jo.getJSONObject(JsonLdCommon.CONTEXT);
+				for (int i = 0; i < context.names().length(); i++) {
+					String name = context.names().getString(i).toLowerCase();
+					if (name.equals(JsonLdCommon.TYPES)) {
+						JSONObject typeObject = context.getJSONObject(name);
+						for (int j = 0; j < typeObject.names().length(); j++) {
+							String property = typeObject.names().getString(j);
+							String type = typeObject.getString(property);
+							subject.putCoercionType(property, type);
+						}
+					} else {
+						jld.addNamespacePrefix(context.getString(name), name);
+					}
+				}
+
+				jo.remove(JsonLdCommon.CONTEXT);
+			}
+
+			// If there is a local profile specified for this subject, we
+			// use that one. Otherwise we assign the profile given by the
+			// parameter.
+			if (jo.has(JsonLdCommon.PROFILE)) {
+				String localProfile = unCURIE(jo
+						.getString(JsonLdCommon.PROFILE), jld
+						.getNamespacePrefixMap());
+				profile = localProfile;
+				jo.remove(JsonLdCommon.PROFILE);
+			}
+			subject.setProfile(profile);
+
+			if (jo.has(JsonLdCommon.SUBJECT)) {
+				// Check for N subjects
+				Object subjectObject = jo.get(JsonLdCommon.SUBJECT);
+				if (subjectObject instanceof JSONArray) {
+					// There is an array of subjects. We create all subjects
+					// in sequence.
+					JSONArray subjects = (JSONArray) subjectObject;
+					for (int i = 0; i < subjects.length(); i++) {
+						parseSubject(subjects.getJSONObject(i), jld,
+								bnodeCount++, profile);
+					}
+				} else {
+					String subjectName = unCURIE(jo
+							.getString(JsonLdCommon.SUBJECT), jld
+							.getNamespacePrefixMap());
+					subject.setSubject(subjectName);
+				}
+				jo.remove(JsonLdCommon.SUBJECT);
+			} else {
+				// No subject specified. We create a dummy bnode
+				// and add this subject.
+				subject.setSubject("_:bnode" + bnodeCount);
+				jld.put(subject.getSubject(), subject);
+			}
+
+			// Iterate through the rest of properties and unCURIE property
+			// values
+			// depending on their type
+			if (jo.names() != null && jo.names().length() > 0) {
+				for (int i = 0; i < jo.names().length(); i++) {
+					String property = jo.names().getString(i);
+					Object valueObject = jo.get(property);
+					handleProperty(jld, subject, property, valueObject);
+				}
+			}
+
+		} catch (JSONException e) {
+			logger.error(
+					"There were JSON problems when parsing the JSON-LD String",
+					e);
+			e.printStackTrace();
+		}
+	}
+
+	private static void handleProperty(JsonLd jld, JsonLdResource subject,
+			String property, Object valueObject) {
+		if (valueObject instanceof JSONObject) {
+			JSONObject jsonValue = (JSONObject) valueObject;
+			subject.putProperty(property, convertToMapAndList(jsonValue, jld
+					.getNamespacePrefixMap()));
+		} else if (valueObject instanceof JSONArray) {
+			JSONArray arrayValue = (JSONArray) valueObject;
+			subject.putProperty(property, convertToMapAndList(arrayValue, jld
+					.getNamespacePrefixMap()));
+		} else if (valueObject instanceof String) {
+			String stringValue = (String) valueObject;
+			subject.putProperty(property, unCURIE(stringValue, jld
+					.getNamespacePrefixMap()));
+		} else {
+			subject.putProperty(property, valueObject);
+		}
+	}
+
+	/**
+	 * Converts a JSON object into a Map or List data structure.
+	 * 
+	 * <p>
+	 * The JSON-LD implementation is based on Map and List data types. If the
+	 * input is a JSONObject, it will be converted into a Map&lt;String,
+	 * Object>. If the input is a JSONArray, it will be converted into a
+	 * List&lt;Object>. Otherwise the input will be returned untouched.
+	 * 
+	 * @param input
+	 *            Object that will be converted.
+	 * @return
+	 */
+	private static Object convertToMapAndList(Object input,
+			Map<String, String> namespacePrefixMap) {
+		if (input instanceof JSONObject) {
+			JSONObject jo = (JSONObject) input;
+
+			// Handle IRIs
+			if (jo.has(JsonLdCommon.IRI)) {
+				try {
+					return new JsonLdIRI(unCURIE(
+							jo.getString(JsonLdCommon.IRI), namespacePrefixMap));
+				} catch (JSONException e) {
+					return null;
+				}
+			} else {
+				// Handle arbitrary JSON
+				return convertToMap(jo, namespacePrefixMap);
+			}
+		} else if (input instanceof JSONArray) {
+			JSONArray ao = (JSONArray) input;
+			return convertToList(ao, namespacePrefixMap);
+		} else if (input instanceof String) {
+			return unCURIE((String) input, namespacePrefixMap);
+		} else {
+			return input;
+		}
+	}
+
+	/**
+	 * Converts a JSONOBject into a Map&lt;String, Object>.
+	 * 
+	 * @param jo
+	 *            JSONOBject to be converted.
+	 * @return A Map that represents the same information as the JSONOBject.
+	 */
+	private static Map<String, Object> convertToMap(JSONObject jo,
+			Map<String, String> namespacePrefixMap) {
+		Map<String, Object> jsonMap = null;
+		try {
+			if (jo.names() != null && jo.names().length() > 0) {
+				jsonMap = new HashMap<String, Object>();
+				for (int i = 0; i < jo.names().length(); i++) {
+					String name = jo.names().getString(i);
+					jsonMap.put(name, convertToMapAndList(jo.get(name),
+							namespacePrefixMap));
+				}
+			}
+		} catch (JSONException e) { /* ignored */
+		}
+		return jsonMap;
+	}
+
+	private static List<Object> convertToList(JSONArray arrayValue,
+			Map<String, String> namespacePrefixMap) {
+
+		List<Object> values = new ArrayList<Object>();
+		for (int i=0; i<arrayValue.length(); i++) {
+			try {
+				values.add(convertToMapAndList(arrayValue.get(i), namespacePrefixMap));
+			} catch (JSONException e) {
+				logger.error("Error converting JSONArray to list", e);
+			}
+		}
+		
+		return values;
+	}
+	
+	/**
+	 * Replaces the CURIE prefixes with the namespace to create full qualified
+	 * IRIs.
+	 * 
+	 * @param curie
+	 *            The CURIE to create an IRI from.
+	 * @param namespacePrefixMap
+	 *            A Map with known namespaces.
+	 * @return
+	 */
+	private static String unCURIE(String curie,
+			Map<String, String> namespacePrefixMap) {
+		for (String namespace : namespacePrefixMap.keySet()) {
+			String prefix = namespacePrefixMap.get(namespace) + ":";
+			curie = curie.replaceAll(prefix, namespace);
+		}
+		return curie;
+	}
 }