You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by Kevin Brown <et...@google.com> on 2008/07/19 21:50:25 UTC

Re: svn commit: r678158 - in /incubator/shindig/trunk: ./ java/social-api/ java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/ java/social-api/src/test/java/org/apache/shindig/social/ java/social-api/src/test/java/org/apache/shin

Hey Ian,

The casing is inconsistent here -- it should be Json and Api for all cases
rather than JSON or API.

Thanks!

On Sat, Jul 19, 2008 at 6:51 AM, <ie...@apache.org> wrote:

> Author: ieb
> Date: Sat Jul 19 06:51:03 2008
> New Revision: 678158
>
> URL: http://svn.apache.org/viewvc?rev=678158&view=rev
> Log:
> SHINDIG-451
> Applying patch from the JIRA.
>
> Adds a json-lib (net.sf) converter, not wired into social-api at present.
>
> Added:
>
>  incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConversionException.java
>
>  incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverter.java
>
>  incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONLibConverterUtils.java
>
>  incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>
>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/JsonLibTestsGuiceModule.java
>
>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidator.java
>
>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorExpcetion.java
>
>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorTest.java
>
>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>
>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/JsonConverterPerformancePerf.java
> Modified:
>    incubator/shindig/trunk/java/social-api/pom.xml
>    incubator/shindig/trunk/pom.xml
>
> Modified: incubator/shindig/trunk/java/social-api/pom.xml
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/pom.xml?rev=678158&r1=678157&r2=678158&view=diff
>
> ==============================================================================
> --- incubator/shindig/trunk/java/social-api/pom.xml (original)
> +++ incubator/shindig/trunk/java/social-api/pom.xml Sat Jul 19 06:51:03
> 2008
> @@ -60,12 +60,31 @@
>       <groupId>org.apache.shindig</groupId>
>       <artifactId>shindig-common</artifactId>
>     </dependency>
> +    <!-- is this Ok, only used in test to load the features -->
> +    <dependency>
> +      <groupId>org.apache.shindig</groupId>
> +      <artifactId>shindig-features</artifactId>
> +      <scope>test</scope>
> +    </dependency>
>
>     <!-- external depenencies -->
>     <dependency>
>       <groupId>org.json</groupId>
>       <artifactId>json</artifactId>
>     </dependency>
> +    <!-- the classifier prevents this working in dep management -->
> +    <dependency>
> +      <groupId>net.sf.json-lib</groupId>
> +      <artifactId>json-lib</artifactId>
> +      <version>2.2</version>
> +      <classifier>jdk15</classifier>
> +      <type>jar</type>
> +    </dependency>
> +    <dependency>
> +      <groupId>rhino</groupId>
> +      <artifactId>js</artifactId>
> +      <scope>test</scope>
> +    </dependency>
>     <dependency>
>       <groupId>com.google.code.guice</groupId>
>       <artifactId>guice</artifactId>
> @@ -112,5 +131,10 @@
>       <artifactId>core</artifactId>
>       <scope>compile</scope>
>     </dependency>
> +    <dependency>
> +      <groupId>log4j</groupId>
> +      <artifactId>log4j</artifactId>
> +      <scope>test</scope>
> +    </dependency>
>   </dependencies>
>  </project>
>
> Added:
> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConversionException.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConversionException.java?rev=678158&view=auto
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConversionException.java
> (added)
> +++
> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConversionException.java
> Sat Jul 19 06:51:03 2008
> @@ -0,0 +1,43 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License. You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * 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.apache.shindig.social.opensocial.util;
> +
> +/**
> + * Where a conversion exception happens in the Json Lib conversion, this
> + * exception is thrown.
> + */
> +public class BeanJsonLibConversionException extends RuntimeException {
> +
> +  private static final long serialVersionUID = -8609384443448202372L;
> +
> +  public BeanJsonLibConversionException() {
> +  }
> +
> +  public BeanJsonLibConversionException(String arg0) {
> +    super(arg0);
> +  }
> +
> +  public BeanJsonLibConversionException(Throwable arg0) {
> +    super(arg0);
> +  }
> +
> +  public BeanJsonLibConversionException(String arg0, Throwable arg1) {
> +    super(arg0, arg1);
> +  }
> +
> +}
>
> Added:
> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverter.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverter.java?rev=678158&view=auto
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverter.java
> (added)
> +++
> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverter.java
> Sat Jul 19 06:51:03 2008
> @@ -0,0 +1,286 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License. You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * 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.apache.shindig.social.opensocial.util;
> +
> +import java.lang.reflect.Array;
> +import java.lang.reflect.InvocationTargetException;
> +import java.util.Collection;
> +import java.util.HashMap;
> +import java.util.List;
> +import java.util.Map;
> +
> +import net.sf.ezmorph.MorpherRegistry;
> +import net.sf.json.JSONArray;
> +import net.sf.json.JSONException;
> +import net.sf.json.JSONObject;
> +import net.sf.json.JsonConfig;
> +import net.sf.json.processors.DefaultValueProcessor;
> +import net.sf.json.util.EnumMorpher;
> +import net.sf.json.util.JSONUtils;
> +import net.sf.json.util.NewBeanInstanceStrategy;
> +import net.sf.json.util.PropertyFilter;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.commons.logging.LogFactory;
> +import org.apache.shindig.social.opensocial.model.Address;
> +import org.apache.shindig.social.opensocial.model.Email;
> +import org.apache.shindig.social.opensocial.model.Enum;
> +import org.apache.shindig.social.opensocial.model.MediaItem;
> +import org.apache.shindig.social.opensocial.model.Organization;
> +import org.apache.shindig.social.opensocial.model.Phone;
> +import org.apache.shindig.social.opensocial.model.Url;
> +
> +
> +import com.google.inject.Inject;
> +import com.google.inject.Injector;
> +
> +/**
> + *
> + */
> +public class BeanJsonLibConverter implements BeanConverter {
> +
> +  protected static final Log log = LogFactory
> +      .getLog(BeanJsonLibConverter.class);
> +  private Injector injector;
> +  private JsonConfig jsonConfig;
> +  private boolean debugMode = false;
> +
> +  /*
> +   * Register the Enum Morphers so that JSON -> Bean works correctly for
> enums.
> +   */
> +  static {
> +    MorpherRegistry morpherRegistry = JSONUtils.getMorpherRegistry();
> +    morpherRegistry.registerMorpher(new EnumMorpher(Address.Field.class));
> +    morpherRegistry.registerMorpher(new EnumMorpher(Phone.Field.class));
> +    morpherRegistry.registerMorpher(new EnumMorpher(Email.Field.class));
> +    morpherRegistry.registerMorpher(new
> EnumMorpher(MediaItem.Field.class));
> +    morpherRegistry.registerMorpher(new
> EnumMorpher(MediaItem.Type.class));
> +    morpherRegistry.registerMorpher(new EnumMorpher(Enum.Drinker.class));
> +    morpherRegistry.registerMorpher(new EnumMorpher(Enum.Field.class));
> +    morpherRegistry.registerMorpher(new EnumMorpher(Enum.Gender.class));
> +    morpherRegistry
> +        .registerMorpher(new EnumMorpher(Enum.NetworkPresence.class));
> +    morpherRegistry.registerMorpher(new EnumMorpher(Enum.Smoker.class));
> +
> +    morpherRegistry.registerMorpher(new JSONObjectToMapMorpher());
> +  }
> +
> +  @Inject
> +  public BeanJsonLibConverter(Injector injector) {
> +    this.injector = injector;
> +    createJsonConfig();
> +  }
> +
> +  @SuppressWarnings("unchecked")
> +  public <T> T convertToObject(String string, final Class<T>
> rootBeanClass) {
> +
> +    if (string.startsWith("[")) {
> +      JSONArray jsonArray = JSONArray.fromObject(string, jsonConfig);
> +      if (debugMode) {
> +        JSONLibConverterUtils.dumpJsonArray(jsonArray, " ");
> +      }
> +
> +      if (rootBeanClass.isArray()) {
> +        Class<?> componentType = rootBeanClass.getComponentType();
> +        Object rootObject = injector.getInstance(componentType);
> +        List<?> o = JSONArray.toList(jsonArray, rootObject, jsonConfig);
> +        Object[] result = (Object[]) Array.newInstance(componentType,
> o.size());
> +        for (int i = 0; i < o.size(); i++) {
> +          result[i] = o.get(i);
> +        }
> +        return (T) result;
> +
> +      } else {
> +        T rootObject = injector.getInstance(rootBeanClass);
> +        Object o = JSONArray.toArray(jsonArray, rootObject, jsonConfig);
> +        return (T) o;
> +      }
> +    } else {
> +      JSONObject jsonObject = JSONObject.fromObject(string, jsonConfig);
> +
> +      if (debugMode) {
> +        JSONLibConverterUtils.dumpJsonObject(jsonObject, " ");
> +      }
> +
> +      T rootObject = injector.getInstance(rootBeanClass);
> +      Object o = JSONObject.toBean(jsonObject, rootObject, jsonConfig);
> +      return (T) o;
> +
> +    }
> +  }
> +
> +  /**
> +   * @return
> +   */
> +  private void createJsonConfig() {
> +
> +    jsonConfig = new JsonConfig();
> +
> +    /*
> +     * This hook deals with the creation of new beans in the JSON -> Java
> Bean
> +     * conversion
> +     */
> +    jsonConfig.setNewBeanInstanceStrategy(new NewBeanInstanceStrategy() {
> +
> +      @SuppressWarnings("unchecked")
> +      @Override
> +      public Object newInstance(Class beanClass, JSONObject jsonObject)
> +          throws InstantiationException, IllegalAccessException,
> +          SecurityException, NoSuchMethodException,
> InvocationTargetException {
> +        if (beanClass != null) {
> +          Object o =
> BeanJsonLibConverter.this.injector.getInstance(beanClass);
> +          if (debugMode) {
> +            log.info("Created Object " + o + " for " + beanClass + " with
> ["
> +                + jsonObject + "]");
> +          }
> +          return o;
> +        }
> +        return DEFAULT.newInstance(beanClass, jsonObject);
> +      }
> +
> +    });
> +
> +    /*
> +     * We are expecting null for nulls
> +     */
> +    jsonConfig.registerDefaultValueProcessor(String.class,
> +        new DefaultValueProcessor() {
> +          @SuppressWarnings("unchecked")
> +          public Object getDefaultValue(Class target) {
> +            return null;
> +          }
> +        });
> +
> +    jsonConfig.setJsonPropertyFilter(new PropertyFilter() {
> +
> +      public boolean apply(Object source, String name, Object value) {
> +        return filterProperty(source, name, value);
> +      }
> +
> +    });
> +
> +    jsonConfig.setJavaPropertyFilter(new PropertyFilter() {
> +
> +      public boolean apply(Object source, String name, Object value) {
> +        return filterProperty(source,name,value);
> +      }
> +
> +    });
> +
> +    // the classMap deals with the basic json string to bean conversion
> +
> +    Map<String, Class<?>> classMap = new HashMap<String, Class<?>>();
> +
> +    /*
> +     * mappings are required where there is a List of objects in the
> interface
> +     * with no indication of what type the list should contain. At the
> moment,
> +     * we are using 1 map for all json trees, as there is no conflict, but
> if
> +     * there is a map could be selected on the basis of the root object.
> It
> +     * would be better to do this with generics, but this is good enough
> and
> +     * compact enough for the moment.
> +     *
> +     */
> +    //
> +    // activity
> +    classMap.put("mediaItems", MediaItem.class);
> +    // this may not be necessary
> +    classMap.put("templateParams", Map.class);
> +    // BodyType needs no mappings
> +    // Message needs no mappings
> +    // Name needs no mappings
> +    // Organization needs no mappings
> +    // Url needs no mappings
> +    // Email needs no mappings
> +    // Phone Needs no mappings
> +    // Address Needs no mappings
> +    // MediaItem needs no mappings
> +
> +    // Person map
> +    classMap.put("addresses", Address.class);
> +    classMap.put("phoneNumbers", Phone.class);
> +    classMap.put("emails", Email.class);
> +    classMap.put("mediaItems", MediaItem.class);
> +    classMap.put("jobs", Organization.class);
> +    classMap.put("schools", Organization.class);
> +    classMap.put("urls", Url.class);
> +    jsonConfig.setClassMap(classMap);
> +
> +  }
> +
> +  /**
> +   * @param source
> +   * @param name
> +   * @param value
> +   * @return
> +   */
> +  protected boolean filterProperty(Object source, String name, Object
> value) {
> +    if ( value == null ) {
> +      return true;
> +    }
> +    if ( value instanceof JSONArray ) {
> +      JSONArray array = (JSONArray) value;
> +      if ( array.size() == 0 ) {
> +        return true;
> +      }
> +    }
> +    if ( value instanceof JSONObject ) {
> +      JSONObject object = (JSONObject) value;
> +      if ( object.isNullObject() || object.isEmpty()  ) {
> +        return true;
> +      }
> +    }
> +    if ( value instanceof Collection) {
> +      Collection<?> collection = (Collection<?>) value;
> +      if ( collection.size() == 0  ) {
> +        return true;
> +      }
> +    }
> +    if ( value instanceof Object[] ) {
> +      Object[] oarray = (Object[]) value;
> +      if ( oarray.length == 0 ) {
> +        return true;
> +      }
> +    }
> +    return false;
> +  }
> +
> +  public String convertToString(Object pojo) {
> +
> +    try {
> +      JSONObject jsonObject = JSONObject.fromObject(pojo, jsonConfig);
> +      return jsonObject.toString();
> +    } catch (JSONException jse) {
> +      Class<?> pojoClass = pojo.getClass();
> +      if (JSONUtils.isArray(pojoClass)) {
> +        JSONArray jsonArray = JSONArray.fromObject(pojo);
> +        String result = jsonArray.toString();
> +        return result;
> +      }
> +      throw jse;
> +    }
> +  }
> +
> +  /**
> +   * @param string
> +   * @param class1
> +   */
> +  public void addMapping(String key, Class<?> class1) {
> +    jsonConfig.getClassMap().put(key, class1);
> +  }
> +
> +}
>
> Added:
> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONLibConverterUtils.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONLibConverterUtils.java?rev=678158&view=auto
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONLibConverterUtils.java
> (added)
> +++
> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONLibConverterUtils.java
> Sat Jul 19 06:51:03 2008
> @@ -0,0 +1,72 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License. You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * 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.apache.shindig.social.opensocial.util;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.commons.logging.LogFactory;
> +
> +import net.sf.json.JSONArray;
> +import net.sf.json.JSONObject;
> +
> +/**
> + *
> + */
> +public class JSONLibConverterUtils {
> +  protected static final Log log = LogFactory
> +  .getLog(JSONLibConverterUtils.class);
> +
> +
> +  /**
> +   * @param jsonObject
> +   */
> +  public static final void dumpJsonObject(JSONObject jsonObject, String
> indent) {
> +    for (Object key : jsonObject.keySet()) {
> +      Object value = jsonObject.get(key);
> +      if (value instanceof JSONObject) {
> +        log.info(indent + key + ":JSONObject");
> +        dumpJsonObject((JSONObject) value, indent + "  ");
> +      } else if (value instanceof JSONArray) {
> +        log.info(indent + key + ":JSONArray " + ((JSONArray)
> value).size());
> +        dumpJsonArray((JSONArray) value, indent + "  ");
> +      } else {
> +        log.info(indent + key + ":" + value + ":"
> +            + (value == null ? "na" : value.getClass()));
> +      }
> +    }
> +  }
> +
> +
> +  /**
> +   * @param value
> +   * @param string
> +   */
> +  static void dumpJsonArray(JSONArray array, String indent) {
> +    for (Object value : array) {
> +      if (value instanceof JSONObject) {
> +        log.info(indent + ":JSONObject");
> +        dumpJsonObject((JSONObject) value, indent + "  ");
> +      } else if (value instanceof JSONArray) {
> +        log.info(indent + ":JSONArray " + ((JSONArray) value).size());
> +        dumpJsonArray((JSONArray) value, indent + "  ");
> +      } else {
> +        log.info(indent + ":" + value + ":"
> +            + (value == null ? "na" : value.getClass()));
> +      }
> +    }
> +  }
> +}
>
> Added:
> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONObjectToMapMorpher.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONObjectToMapMorpher.java?rev=678158&view=auto
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONObjectToMapMorpher.java
> (added)
> +++
> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONObjectToMapMorpher.java
> Sat Jul 19 06:51:03 2008
> @@ -0,0 +1,50 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License. You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * 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.apache.shindig.social.opensocial.util;
> +
> +import java.util.HashMap;
> +import java.util.Map;
> +
> +import net.sf.ezmorph.Morpher;
> +import net.sf.ezmorph.ObjectMorpher;
> +import net.sf.json.JSONObject;
> +
> +/**
> + *
> + */
> +public class JSONObjectToMapMorpher implements Morpher, ObjectMorpher {
> +
> +  public Class<?> morphsTo() {
> +    return Map.class;
> +  }
> +
> +  @SuppressWarnings("unchecked")
> +  public boolean supports(Class clazz) {
> +    return (JSONObject.class.equals(clazz));
> +  }
> +
> +  public Object morph(Object bean) {
> +    Map<Object, Object> result = new HashMap<Object, Object>();
> +    JSONObject jsonObject = (JSONObject) bean;
> +    for ( Object key : jsonObject.keySet()) {
> +      result.put(key,jsonObject.get(key));
> +    }
> +    return result;
> +  }
> +
> +}
>
> Added:
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/JsonLibTestsGuiceModule.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/JsonLibTestsGuiceModule.java?rev=678158&view=auto
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/JsonLibTestsGuiceModule.java
> (added)
> +++
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/JsonLibTestsGuiceModule.java
> Sat Jul 19 06:51:03 2008
> @@ -0,0 +1,40 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + *   http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * 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.apache.shindig.social;
> +
> +import java.util.ArrayList;
> +import java.util.HashMap;
> +import java.util.List;
> +import java.util.Map;
> +
> +import com.google.inject.AbstractModule;
> +
> +/**
> + * Provides social api component injection for all large tests
> + */
> +public class JsonLibTestsGuiceModule extends AbstractModule {
> +  @Override
> +  protected void configure() {
> +
> +    bind(Map.class).to(HashMap.class);
> +    bind(List.class).to(ArrayList.class);
> +    bind(Map[].class).to(HashMap[].class);
> +  }
> +
> +}
>
> Added:
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidator.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidator.java?rev=678158&view=auto
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidator.java
> (added)
> +++
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidator.java
> Sat Jul 19 06:51:03 2008
> @@ -0,0 +1,352 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License. You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * 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.apache.shindig.social.opensocial.util;
> +
> +import java.io.IOException;
> +import java.io.InputStream;
> +import java.io.InputStreamReader;
> +import java.util.ArrayList;
> +import java.util.HashMap;
> +import java.util.List;
> +import java.util.Map;
> +
> +import javax.xml.parsers.DocumentBuilder;
> +import javax.xml.parsers.DocumentBuilderFactory;
> +import javax.xml.parsers.ParserConfigurationException;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.commons.logging.LogFactory;
> +import org.mozilla.javascript.Context;
> +import org.mozilla.javascript.EvaluatorException;
> +import org.mozilla.javascript.Script;
> +import org.mozilla.javascript.ScriptableObject;
> +import org.w3c.dom.Document;
> +import org.w3c.dom.NamedNodeMap;
> +import org.w3c.dom.Node;
> +import org.w3c.dom.NodeList;
> +import org.xml.sax.SAXException;
> +
> +/**
> + * A class that loads a feature set from features into a Javascript Parser
> to
> + * make the model available to validate JSON messages against.
> + */
> +public class APIValidator {
> +
> +  private static final Log log = LogFactory.getLog(APIValidator.class);
> +  private Context ctx;
> +  private ScriptableObject scope;
> +
> +  /**
> +   * @param feature
> +   *                The name of the feature are eg "opensocial-reference",
> this
> +   *                is a classpath stub (not starting with /) where the
> location
> +   *                contains a feature.xml file.
> +   * @throws SAXException
> +   *                 if feature.xml is not parsable
> +   * @throws ParserConfigurationException
> +   *                 if the parsers are invalid
> +   * @throws IOException
> +   *                 if feature.xml or the javascript that represents the
> +   *                 feature is missing
> +   *
> +   */
> +  public APIValidator(String feature) throws IOException,
> +      ParserConfigurationException, SAXException {
> +    ctx = Context.enter();
> +    scope = ctx.initStandardObjects();
> +    load(feature);
> +  }
> +
> +  /**
> +   * @param json
> +   *                The json to validate expected in a form { xyz: yyy }
> form
> +   * @param object
> +   *                The json Fields object specifying the structure of the
> json
> +   *                object, each field in this object contains the name of
> the
> +   *                json field in the json structure.
> +   * @param optionalFields
> +   *                If any of the fields that appear in the json structure
> are
> +   *                optional, then they should be defined in this
> parameter.
> +   * @param nullfields
> +   * @throws APIValidatorExpcetion
> +   *                 if there is a problem validating the json
> +   * @return a map so string object pairs containing the fields at the top
> level
> +   *         of the json tree. Where these are native java objects, they
> will
> +   *         appear as native object. Complex json objects will appear as
> Rhino
> +   *         specific objects
> +   */
> +  public Map<String, Object> validate(String json, String object,
> +      String[] optionalFields, String[] nullfields)
> +      throws APIValidatorExpcetion {
> +
> +    /*
> +     * Object[] ids = ScriptableObject.getPropertyIds(scope); for (Object
> id :
> +     * ids) { Object o = ScriptableObject.getProperty(scope,
> +     * String.valueOf(id)); log.debug("ID is " + id + " class " +
> id.getClass() + "
> +     * is " + o); if (o instanceof ScriptableObject) {
> +     * listScriptable(String.valueOf(id), (ScriptableObject) o); } }
> +     */
> +
> +    log.debug("Loading " + json);
> +    json = json.trim();
> +    if (!json.endsWith("}")) {
> +      json = json + "}";
> +    }
> +    if (!json.startsWith("{")) {
> +      json = "{" + json;
> +    }
> +    json = "( testingObject = " + json + " )";
> +
> +    Object so = null;
> +    try {
> +      so = ctx.evaluateString(scope, json, "test json", 0, null);
> +    } catch (EvaluatorException ex) {
> +      log.error("Non parseable JSON " + json);
> +    }
> +    log.debug("Loaded " + so);
> +
> +    return validateOject(so, object, optionalFields, nullfields);
> +
> +  }
> +
> +  /**
> +   * Validate an JSON Object extracted
> +   *
> +   * @param object
> +   * @param string
> +   * @param optional
> +   * @return
> +   * @throws APIValidatorExpcetion
> +   */
> +  public Map<String, Object> validateOject(Object jsonObject, String
> object,
> +      String[] optionalFields, String[] nullFields)
> +      throws APIValidatorExpcetion {
> +    Map<String, String> optional = new HashMap<String, String>();
> +    for (String opt : optionalFields) {
> +      optional.put(opt, opt);
> +    }
> +    Map<String, String> nullf = new HashMap<String, String>();
> +    for (String nf : nullFields) {
> +      nullf.put(nf, nf);
> +    }
> +
> +    ScriptableObject specification = getScriptableObject(object);
> +    log.debug("Looking for  " + object + " found " + specification);
> +    listScriptable(object, specification);
> +
> +    Map<String, Object> resultFields = new HashMap<String, Object>();
> +
> +    if (jsonObject instanceof ScriptableObject) {
> +      ScriptableObject parsedJSONObject = (ScriptableObject) jsonObject;
> +      listScriptable("testingObject", parsedJSONObject);
> +      Object[] fields = specification.getIds();
> +      for (Object f : fields) {
> +        Object fieldName = specification.get(String.valueOf(f),
> specification);
> +        Object o = parsedJSONObject.get(String.valueOf(fieldName),
> +            parsedJSONObject);
> +        if (o == ScriptableObject.NOT_FOUND) {
> +          if (optional.containsKey(fieldName)) {
> +            log.warn("Missing Optional Field " + fieldName);
> +          } else if (!nullf.containsKey(fieldName)) {
> +            log.error("Missing Field " + fieldName);
> +            throw new APIValidatorExpcetion("Missing Field " + fieldName);
> +          }
> +        } else {
> +          if (nullf.containsKey(fieldName)) {
> +            log.error("Field should have been null and was not");
> +          }
> +          if (o == null) {
> +            if (nullf.containsKey(fieldName)) {
> +              log.error("Null Fields has been serialized " + fieldName);
> +            }
> +            log.debug("Got a Null object for Field " + f + ":" + fieldName
> +                + " on json [[" + jsonObject + "]]");
> +
> +          } else {
> +
> +            log.debug("Got JSON Field  Field," + f + ":" + fieldName + "
> as "
> +                + o + " " + o.getClass());
> +          }
> +          resultFields.put(String.valueOf(fieldName), o);
> +        }
> +      }
> +
> +    } else {
> +      throw new APIValidatorExpcetion(
> +          "Parsing JSON resulted in invalid Javascript object, which was "
> +              + jsonObject + " JSON was [[" + jsonObject + "]]");
> +    }
> +    return resultFields;
> +  }
> +
> +  /**
> +   * get an object from the json context and scope.
> +   *
> +   * @param object
> +   *                the name of the object specified as a path from the
> base
> +   *                object
> +   * @return the json object
> +   */
> +  private ScriptableObject getScriptableObject(String object) {
> +    String[] path = object.split("\\.");
> +    log.debug("Looking up " + object + " elements " + path.length);
> +
> +    ScriptableObject s = scope;
> +    for (String pe : path) {
> +      log.debug("Looking up " + pe + " in " + s);
> +      s = (ScriptableObject) s.get(pe, s);
> +      log.debug("Looking for " + pe + " in found " + s);
> +    }
> +    return s;
> +  }
> +
> +  /**
> +   * List a scriptable object at log debug level, constructors will not be
> +   * expanded as this loads to recursion.
> +   *
> +   * @param id
> +   *                The name of the object
> +   * @param scriptableObject
> +   *                the scriptable Object
> +   */
> +  private void listScriptable(String id, ScriptableObject
> scriptableObject) {
> +    log.debug("ID is Scriptable " + id);
> +    if (!id.endsWith("constructor")) {
> +      Object[] allIDs = scriptableObject.getAllIds();
> +      for (Object oid : allIDs) {
> +        log.debug(id + "." + oid);
> +        Object o = scriptableObject.get(String.valueOf(oid),
> scriptableObject);
> +        if (o instanceof ScriptableObject) {
> +          listScriptable(id + "." + String.valueOf(oid),
> (ScriptableObject) o);
> +        }
> +      }
> +    }
> +  }
> +
> +  /**
> +   * Load a feature based on the spec
> +   *
> +   * @param spec
> +   *                The name of the location of the spec in the classpath,
> must
> +   *                not start with a '/' and must should contain a
> feature.xml
> +   *                file in the location
> +   * @throws IOException
> +   *                 If any of the resources cant be found
> +   * @throws ParserConfigurationException
> +   *                 If the parser has a problem being constructed
> +   * @throws SAXException
> +   *                 on a parse error on the features.xml
> +   */
> +  private void load(String spec) throws IOException, SAXException,
> +      ParserConfigurationException {
> +
> +    List<String> scripts = getScripts(spec);
> +
> +    List<Script> compiled = new ArrayList<Script>();
> +    for (String script : scripts) {
> +      String scriptPath = spec + "/" + script;
> +      InputStream in =
> this.getClass().getClassLoader().getResourceAsStream(
> +          scriptPath);
> +      if (in == null) {
> +        in = this.getClass().getClassLoader().getResourceAsStream(
> +            "features/" + scriptPath);
> +        if (in == null) {
> +          throw new IOException("Cant load spec " + spec + " or
> features/"+spec+" from classpath");
> +        }
> +      }
> +      InputStreamReader reader = new InputStreamReader(in);
> +      Script compiledScript = ctx.compileReader(reader, spec, 0, null);
> +      compiled.add(compiledScript);
> +    }
> +
> +    for (Script compiledScript : compiled) {
> +      compiledScript.exec(ctx, scope);
> +    }
> +
> +  }
> +
> +  /**
> +   * Add some javascript to the context, and execute it. If extra custom
> +   * javascript is wanted in the context or scope then this method will
> load it.
> +   *
> +   * @param javascript
> +   */
> +  public void addScript(String javascript) {
> +    Script compileScript = ctx.compileString(javascript, "AdditionalJS",
> 0,
> +        null);
> +    compileScript.exec(ctx, scope);
> +  }
> +
> +  /**
> +   * Get an ordered list of javascript resources from a feature sets.
> +   *
> +   * @param spec
> +   *                The spec location
> +   * @return An ordered list of javascript resources, these are relative
> to
> +   *         specification file.
> +   * @throws IOException
> +   *                 If any of the resources can't be loaded.
> +   * @throws SAXException
> +   *                 Where the feature.xml file is not parsable
> +   * @throws ParserConfigurationException
> +   *                 where the parser can't be constructed.
> +   * @return An ordered list of script that need to be loaded and executed
> to
> +   *         make the feature available in the context.
> +   */
> +  private List<String> getScripts(String spec) throws SAXException,
> +      IOException, ParserConfigurationException {
> +    String features = spec + "/feature.xml";
> +    InputStream in = this.getClass().getClassLoader().getResourceAsStream(
> +        features);
> +    if (in == null) {
> +      in = this.getClass().getClassLoader().getResourceAsStream(
> +          "features/"+features);
> +      if (in == null) {
> +        throw new IOException("Cant find " + features + " or features/" +
> features+ " in classpath ");
> +      }
> +    }
> +    DocumentBuilderFactory builderFactory = DocumentBuilderFactory
> +        .newInstance();
> +    DocumentBuilder documentBuilder = builderFactory.newDocumentBuilder();
> +    Document doc = documentBuilder.parse(in);
> +    NodeList nl = doc.getElementsByTagName("script");
> +    List<String> scripts = new ArrayList<String>();
> +    for (int i = 0; i < nl.getLength(); i++) {
> +      Node scriptNode = nl.item(i);
> +      NamedNodeMap attributes = scriptNode.getAttributes();
> +      Node scriptAttr = attributes.getNamedItem("src");
> +      String script = scriptAttr.getNodeValue();
> +      scripts.add(script);
> +    }
> +    return scripts;
> +  }
> +
> +  /**
> +   * @param nameJSON
> +   */
> +  public static void dump(Map<?, ?> nameJSON) {
> +    if (log.isDebugEnabled()) {
> +      for (Object k : nameJSON.keySet()) {
> +        Object o = nameJSON.get(k);
> +        log.info("Key [" + k + "] value:["
> +            + (o == null ? o : o + ":" + o.getClass()) + "]");
> +      }
> +    }
> +  }
> +
> +}
>
> Added:
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorExpcetion.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorExpcetion.java?rev=678158&view=auto
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorExpcetion.java
> (added)
> +++
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorExpcetion.java
> Sat Jul 19 06:51:03 2008
> @@ -0,0 +1,42 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License. You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * 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.apache.shindig.social.opensocial.util;
> +
> +/**
> + * Thrown when there is a validation exception on one of the apis
> + */
> +public class APIValidatorExpcetion extends Exception {
> +
> +  private static final long serialVersionUID = -8969858718669454612L;
> +
> +  public APIValidatorExpcetion() {
> +  }
> +
> +  public APIValidatorExpcetion(String message) {
> +    super(message);
> +  }
> +
> +  public APIValidatorExpcetion(Throwable cause) {
> +    super(cause);
> +  }
> +
> +  public APIValidatorExpcetion(String message, Throwable cause) {
> +    super(message, cause);
> +  }
> +
> +}
>
> Added:
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorTest.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorTest.java?rev=678158&view=auto
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorTest.java
> (added)
> +++
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorTest.java
> Sat Jul 19 06:51:03 2008
> @@ -0,0 +1,89 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License. You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * 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.apache.shindig.social.opensocial.util;
> +
> +
> +import java.io.IOException;
> +import java.util.Map;
> +
> +import javax.xml.parsers.ParserConfigurationException;
> +
> +import org.junit.Assert;
> +import org.junit.Test;
> +import org.xml.sax.SAXException;
> +
> +/**
> + * Test the api validator to make certain it behaves as is expected.
> + */
> +public class APIValidatorTest {
> +
> +  /**
> +   * A definition of the test json used in this unit test.
> +   */
> +  private static final String TEST_DEFINITION =
> +    "var TestDef = {}; TestDef.Field = { FIELD1 : \"json\", FIELD2 :
> \"xyz\", FIELD3 : \"shouldBeMissing\" };";
> +
> +  /**
> +   * test the validator for successful validation
> +   * @throws APIValidatorExpcetion
> +   * @throws IOException
> +   * @throws ParserConfigurationException
> +   * @throws SAXException
> +   */
> +  @Test
> +  public void testValidator() throws APIValidatorExpcetion, IOException,
> ParserConfigurationException, SAXException {
> +    APIValidator apiVal = new APIValidator("opensocial-reference");
> +    apiVal.addScript(TEST_DEFINITION);
> +    String[] optional = {"shouldBeMissing"};
> +    String[] nullfields = {};
> +     Map<String, Object> result = apiVal.validate("{ json: \"A Test
> JSON\", xyz : 123 }", "TestDef.Field", optional, nullfields );
> +     Assert.assertNotNull(result);
> +     Assert.assertNotNull(result.get("json"));
> +     Assert.assertNotNull(result.get("xyz"));
> +     Assert.assertEquals(String.class,result.get("json").getClass());
> +     Assert.assertEquals(Integer.class,result.get("xyz").getClass());
> +     Assert.assertEquals("A Test JSON",result.get("json"));
> +     Assert.assertEquals(123,((Integer)result.get("xyz")).intValue());
> +
> +
> +  }
> +
> +  /**
> +   * Test for a failing validation
> +   * @throws APIValidatorExpcetion
> +   * @throws IOException
> +   * @throws ParserConfigurationException
> +   * @throws SAXException
> +   */
> +  @Test
> +  public void testValidatorFail() throws APIValidatorExpcetion,
> IOException, ParserConfigurationException, SAXException {
> +    APIValidator apiVal = new APIValidator("opensocial-reference");
> +    apiVal.addScript(TEST_DEFINITION);
> +    String[] optional = {};
> +    String[] nullfields = {};
> +    try {
> +      apiVal.validate("{ jsonIsMissing: \"A Test JSON\", xyz : 123 }",
> "TestDef.Field", optional, nullfields );
> +      Assert.fail("Should have Generated an APIValidatorException ");
> +    } catch ( APIValidatorExpcetion ex ) {
> +
> +    }
> +
> +
> +  }
> +
> +}
>
> Added:
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverterTest.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverterTest.java?rev=678158&view=auto
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverterTest.java
> (added)
> +++
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverterTest.java
> Sat Jul 19 06:51:03 2008
> @@ -0,0 +1,359 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License. You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * 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.apache.shindig.social.opensocial.util;
> +
> +import java.util.ArrayList;
> +import java.util.List;
> +import java.util.Map;
> +
> +import junit.framework.TestCase;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.commons.logging.LogFactory;
> +import org.apache.shindig.social.JsonLibTestsGuiceModule;
> +import org.apache.shindig.social.opensocial.model.Activity;
> +import org.apache.shindig.social.opensocial.model.ActivityImpl;
> +import org.apache.shindig.social.opensocial.model.Address;
> +import org.apache.shindig.social.opensocial.model.AddressImpl;
> +import org.apache.shindig.social.opensocial.model.Email;
> +import org.apache.shindig.social.opensocial.model.EmailImpl;
> +import org.apache.shindig.social.opensocial.model.MediaItem;
> +import org.apache.shindig.social.opensocial.model.MediaItemImpl;
> +import org.apache.shindig.social.opensocial.model.Name;
> +import org.apache.shindig.social.opensocial.model.NameImpl;
> +import org.apache.shindig.social.opensocial.model.Person;
> +import org.apache.shindig.social.opensocial.model.PersonImpl;
> +import org.apache.shindig.social.opensocial.model.Phone;
> +import org.apache.shindig.social.opensocial.model.PhoneImpl;
> +
> +import com.google.common.collect.Lists;
> +import com.google.common.collect.Maps;
> +import com.google.inject.Guice;
> +
> +public class BeanJsonLibConverterTest extends TestCase {
> +
> +  private static final Log log = LogFactory
> +      .getLog(BeanJsonLibConverterTest.class);
> +  private Person johnDoe;
> +  private Activity activity;
> +
> +  private BeanJsonLibConverter beanJsonConverter;
> +  private APIValidator apiValidator;
> +  // set to true to get loging output at info level
> +  private boolean outputInfo = false;
> +
> +  @Override
> +  public void setUp() throws Exception {
> +    super.setUp();
> +    johnDoe = new PersonImpl("johnDoeId", new NameImpl("John Doe"));
> +    johnDoe.setPhoneNumbers(Lists.<Phone> newArrayList(new PhoneImpl(
> +        "+33H000000000", "home"), new PhoneImpl("+33M000000000",
> "mobile"),
> +        new PhoneImpl("+33W000000000", "work")));
> +
> +    johnDoe.setAddresses(Lists.<Address> newArrayList(new AddressImpl(
> +        "My home address")));
> +
> +    johnDoe.setEmails(Lists.<Email> newArrayList(new EmailImpl(
> +        "john.doe@work.bar", "work"),
> +        new EmailImpl("john.doe@home.bar", "home")));
> +
> +    activity = new ActivityImpl("activityId", johnDoe.getId());
> +
> +    activity.setMediaItems(Lists.<MediaItem> newArrayList(new
> MediaItemImpl(
> +        "image/jpg", MediaItem.Type.IMAGE, "http://foo.bar")));
> +
> +    beanJsonConverter = new BeanJsonLibConverter(Guice
> +        .createInjector(new JsonLibTestsGuiceModule()));
> +
> +    apiValidator = new APIValidator("opensocial-reference");
> +
> +  }
> +
> +  public static class SpecialPerson extends PersonImpl {
> +    public static final String[] OPTIONALFIELDS = {};
> +    public static final String[] NULLFIELDS  =
> {"jobInterests","nickname","romance","religion","timeZone",
> +
>  "relationshipStatus","tags","networkPresence","books","quotes","phoneNumbers","languagesSpoken",
> +
>  "activities","jobs","dateOfBirth","profileVideo","bodyType","urls","schools","music","addresses",
> +
>  "livingArrangement","thumbnailUrl","humor","sports","scaredOf","movies","age","pets","hasApp","turnOffs",
> +
>  "gender","fashion","drinker","aboutMe","children","sexualOrientation","heroes","profileSong","lookingFor",
> +
>  "cars","turnOns","tvShows","profileUrl","status","currentLocation","smoker","happiestWhen","ethnicity",
> +
>  "food","emails","politicalViews","interests","familyName","honorificSuffix","additionalName","honorificPrefix","givenName"};
> +
> +    private String newfield;
> +
> +    public SpecialPerson() {
> +      super();
> +    }
> +
> +    public SpecialPerson(String id, String name, String newfield) {
> +      super(id, new NameImpl(name));
> +      this.newfield = newfield;
> +    }
> +
> +    public String getNewfield() {
> +      return newfield;
> +    }
> +
> +    public void setNewfield(String newfield) {
> +      this.newfield = newfield;
> +    }
> +
> +  }
> +
> +  public void testToJsonOnInheritedClass() throws Exception {
> +    SpecialPerson cassie = new SpecialPerson("5", "robot", "nonsense");
> +
> +    String result = beanJsonConverter.convertToString(cassie);
> +
> +    validatePerson(result, "5", "robot", SpecialPerson.OPTIONALFIELDS,
> SpecialPerson.NULLFIELDS);
> +
> +    apiValidator.addScript(" specialPerson = { SPECIAL : \"newfield\" };
> ");
> +    String[] optional = {};
> +    String[] nullfields = {};
> +    Map<String, Object> special = apiValidator.validate(result,
> +        "specialPerson", optional,nullfields);
> +    assertNotNull(special.get("newfield"));
> +    assertEquals(String.class, special.get("newfield").getClass());
> +    assertEquals("nonsense", special.get("newfield"));
> +
> +    // convert back into an object Tree
> +
> +    SpecialPerson parseCassie = beanJsonConverter.convertToObject(result,
> +        SpecialPerson.class);
> +
> +    assertNotNull(parseCassie);
> +    assertEquals(cassie.getId(), parseCassie.getId());
> +    assertEquals(cassie.getNewfield(), parseCassie.getNewfield());
> +
> +    Name name = parseCassie.getName();
> +    Name cassieName = cassie.getName();
> +    assertNotNull(name);
> +    assertEquals(cassieName.getUnstructured(), name.getUnstructured());
> +    assertEquals(cassieName.getAdditionalName(),
> name.getAdditionalName());
> +    assertEquals(cassieName.getFamilyName(), name.getFamilyName());
> +    assertEquals(cassieName.getGivenName(), name.getGivenName());
> +    assertEquals(cassieName.getHonorificPrefix(),
> name.getHonorificPrefix());
> +    assertEquals(cassieName.getHonorificSuffix(),
> name.getHonorificSuffix());
> +
> +  }
> +
> +  /**
> +   * @param result
> +   * @throws APIValidatorExpcetion
> +   */
> +  private void validatePerson(String result, String id, String name,
> String[] optional, String[] nullfields)
> +      throws APIValidatorExpcetion {
> +
> +    Map<String, Object> standard = apiValidator.validate(result,
> +        "opensocial.Person.Field", optional,nullfields);
> +    assertNotNull(standard.get("id"));
> +    assertEquals(String.class, standard.get("id").getClass());
> +    assertEquals(id, standard.get("id"));
> +
> +    assertNotNull(standard.get("name"));
> +    Map<String, Object> nameJSON = apiValidator.validateOject(standard
> +        .get("name"), "opensocial.Name.Field", optional,nullfields);
> +    APIValidator.dump(nameJSON);
> +
> +    assertNotNull(nameJSON.get("unstructured"));
> +    assertEquals(String.class, nameJSON.get("unstructured").getClass());
> +    assertEquals(name, nameJSON.get("unstructured"));
> +
> +    // additional name
> +    assertNull(nameJSON.get("additionalName"));
> +
> +  }
> +
> +  public void testPersonToJson() throws Exception {
> +    String result = beanJsonConverter.convertToString(johnDoe);
> +    if (outputInfo) {
> +      log.info("JSON (" + result + ")");
> +    }
> +    Person parsedPerson = beanJsonConverter.convertToObject(result,
> +        Person.class);
> +
> +    assertEquals(johnDoe.getId(), parsedPerson.getId());
> +    assertEquals(johnDoe.getName().getUnstructured(),
> parsedPerson.getName()
> +        .getUnstructured());
> +
> +    List<Address> addresses = parsedPerson.getAddresses();
> +    if (outputInfo) {
> +      for (Object o : addresses) {
> +        log.info("Address " + o);
> +      }
> +    }
> +
> +    assertEquals(1, addresses.size());
> +    Address address = addresses.get(0);
> +    String unstructured = address.getUnstructuredAddress();
> +
> +    assertNotNull(unstructured);
> +    assertEquals(johnDoe.getAddresses().get(0).getUnstructuredAddress(),
> +        parsedPerson.getAddresses().get(0).getUnstructuredAddress());
> +
> +    assertEquals(3, parsedPerson.getPhoneNumbers().size());
> +
> +    for (int i = 0; i < johnDoe.getPhoneNumbers().size(); i++) {
> +      Phone expectedPhone = johnDoe.getPhoneNumbers().get(i);
> +      Phone actualPhone = parsedPerson.getPhoneNumbers().get(i);
> +      assertEquals(expectedPhone.getType(), actualPhone.getType());
> +      assertEquals(expectedPhone.getNumber(), actualPhone.getNumber());
> +    }
> +
> +    assertEquals(2, parsedPerson.getEmails().size());
> +
> +    for (int i = 0; i < johnDoe.getEmails().size(); i++) {
> +      Email expectedEmail = johnDoe.getEmails().get(i);
> +      Email actualEmail = parsedPerson.getEmails().get(i);
> +      assertEquals(expectedEmail.getType(), actualEmail.getType());
> +      assertEquals(expectedEmail.getAddress(), actualEmail.getAddress());
> +    }
> +  }
> +
> +  public void testActivityToJson() throws Exception {
> +
> +    String result = beanJsonConverter.convertToString(activity);
> +    if (outputInfo) {
> +      log.info("JSON (" + result + ")");
> +    }
> +    Activity parsedActivity = beanJsonConverter.convertToObject(result,
> +        Activity.class);
> +    assertEquals(activity.getUserId(), parsedActivity.getUserId());
> +    assertEquals(activity.getId(), parsedActivity.getId());
> +
> +    assertEquals(1, parsedActivity.getMediaItems().size());
> +
> +    MediaItem expectedItem = activity.getMediaItems().get(0);
> +    MediaItem actualItem = parsedActivity.getMediaItems().get(0);
> +
> +    assertEquals(expectedItem.getUrl(), actualItem.getUrl());
> +    assertEquals(expectedItem.getMimeType(), actualItem.getMimeType());
> +    assertEquals(expectedItem.getType().toString(), actualItem.getType()
> +        .toString());
> +  }
> +
> +  public void testMapsToJson() throws Exception {
> +    Map<String, Map<String, String>> map = Maps.newHashMap();
> +
> +    Map<String, String> item1Map = Maps.newHashMap();
> +    item1Map.put("value", "1");
> +
> +    // Null values shouldn't cause exceptions
> +    item1Map.put("value2", null);
> +    map.put("item1", item1Map);
> +
> +    Map<String, String> item2Map = Maps.newHashMap();
> +    item2Map.put("value", "2");
> +    map.put("item2", item2Map);
> +
> +    String result = beanJsonConverter.convertToString(map);
> +    if (outputInfo) {
> +      log.info("JSON (" + result + ")");
> +    }
> +    // there is introspection that can tell jsonobject -> bean converter
> what a
> +    // map should contain, so we have to tell it
> +    beanJsonConverter.addMapping("item1", Map.class);
> +    beanJsonConverter.addMapping("item2", Map.class);
> +    Map<?, ?> parsedMap = beanJsonConverter
> +        .convertToObject(result, Map.class);
> +
> +    if (outputInfo) {
> +      log.info("Dumping Map (" + parsedMap + ")");
> +    }
> +    APIValidator.dump(parsedMap);
> +
> +    assertEquals("1", ((Map<?,?>)parsedMap.get("item1")).get("value"));
> +    assertEquals("2", ((Map<?,?>)parsedMap.get("item2")).get("value"));
> +  }
> +
> +  public void testListsToJson() throws Exception {
> +    Map<String, String> item1Map = Maps.newHashMap();
> +    item1Map.put("value", "1");
> +
> +    Map<String, String> item2Map = Maps.newHashMap();
> +    item2Map.put("value", "2");
> +
> +    // put the list into a container before serializing, top level lists
> dont
> +    // appear
> +    // to be allowed in json
> +    // just check that the list is in the holder correctly
> +    List<Map<String, String>> list = new ArrayList<Map<String, String>>();
> +    list.add(item1Map);
> +    list.add(item2Map);
> +    String result = beanJsonConverter.convertToString(list);
> +    if (outputInfo) {
> +      log.info("JSON (" + result + ")");
> +    }
> +    Map<?, ?>[] parsedList = beanJsonConverter.convertToObject(
> +        result, Map[].class);
> +
> +    assertEquals("1", parsedList[0].get("value"));
> +    assertEquals("2", parsedList[1].get("value"));
> +  }
> +
> +  public void testArrayToJson() throws Exception {
> +    String[] colors = { "blue", "green", "aquamarine" };
> +    String result = beanJsonConverter.convertToString(colors);
> +    if (outputInfo) {
> +      log.info("JSON (" + result + ")");
> +    }
> +    String[] parsedColors = beanJsonConverter.convertToObject(result,
> +        String[].class);
> +    assertEquals(colors.length, parsedColors.length);
> +    assertEquals(colors[0], parsedColors[0]);
> +    assertEquals(colors[1], parsedColors[1]);
> +    assertEquals(colors[2], parsedColors[2]);
> +  }
> +
> +  public void testJsonToActivity() throws Exception {
> +    String jsonActivity = "{userId : 5, id : 6, mediaItems : ["
> +        + "{url : 'hello', mimeType : 'mimey', type : 'VIDEO'}" + "]}";
> +    Activity result = beanJsonConverter.convertToObject(jsonActivity,
> +        Activity.class);
> +
> +    assertEquals("5", result.getUserId());
> +    assertEquals("6", result.getId());
> +
> +    assertEquals(1, result.getMediaItems().size());
> +
> +    MediaItem actualItem = result.getMediaItems().get(0);
> +
> +    assertEquals("hello", actualItem.getUrl());
> +    assertEquals("mimey", actualItem.getMimeType());
> +    assertEquals("video", actualItem.getType().toString());
> +  }
> +
> +  public void testJsonToMap() throws Exception {
> +    String jsonActivity = "{count : 0, favoriteColor : 'yellow'}";
> +    Map<String, String> data = Maps.newHashMap();
> +    data = beanJsonConverter.convertToObject(jsonActivity,
> +        (Class<Map<String, String>>) data.getClass());
> +
> +    assertEquals(2, data.size());
> +
> +    for (String key : data.keySet()) {
> +      Object value = data.get(key);
> +      if (key.equals("count")) {
> +        assertEquals(0, value);
> +      } else if (key.equals("favoriteColor")) {
> +        assertEquals("yellow", value);
> +      }
> +    }
> +  }
> +
> +}
>
> Added:
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/JsonConverterPerformancePerf.java
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/JsonConverterPerformancePerf.java?rev=678158&view=auto
>
> ==============================================================================
> ---
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/JsonConverterPerformancePerf.java
> (added)
> +++
> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/JsonConverterPerformancePerf.java
> Sat Jul 19 06:51:03 2008
> @@ -0,0 +1,271 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License. You may obtain a copy of the License at
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * 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.apache.shindig.social.opensocial.util;
> +
> +import junit.framework.TestCase;
> +
> +import org.apache.commons.logging.Log;
> +import org.apache.commons.logging.LogFactory;
> +import org.apache.shindig.social.JsonLibTestsGuiceModule;
> +import org.apache.shindig.social.SocialApiTestsGuiceModule;
> +import org.apache.shindig.social.opensocial.model.Activity;
> +import org.apache.shindig.social.opensocial.model.ActivityImpl;
> +import org.apache.shindig.social.opensocial.model.Address;
> +import org.apache.shindig.social.opensocial.model.AddressImpl;
> +import org.apache.shindig.social.opensocial.model.Email;
> +import org.apache.shindig.social.opensocial.model.EmailImpl;
> +import org.apache.shindig.social.opensocial.model.MediaItem;
> +import org.apache.shindig.social.opensocial.model.MediaItemImpl;
> +import org.apache.shindig.social.opensocial.model.NameImpl;
> +import org.apache.shindig.social.opensocial.model.Person;
> +import org.apache.shindig.social.opensocial.model.PersonImpl;
> +import org.apache.shindig.social.opensocial.model.Phone;
> +import org.apache.shindig.social.opensocial.model.PhoneImpl;
> +import org.json.JSONObject;
> +
> +import com.google.common.collect.Lists;
> +import com.google.inject.Guice;
> +
> +public class JsonConverterPerformancePerf extends TestCase {
> +
> +  private static final Log log = LogFactory
> +      .getLog(JsonConverterPerformancePerf.class);
> +  private static final int TEST_SIZE = 10000;
> +  private Person johnDoe;
> +  private Activity activity;
> +
> +  private BeanJsonLibConverter beanJsonLibConverter;
> +  private APIValidator apiValidator;
> +  // set to true to get loging output at info level
> +  private boolean outputInfo = false;
> +  private BeanJsonConverter beanJsonConverter;
> +
> +  @Override
> +  public void setUp() throws Exception {
> +    super.setUp();
> +    johnDoe = new PersonImpl("johnDoeId", new NameImpl("John Doe"));
> +    johnDoe.setPhoneNumbers(Lists.<Phone> newArrayList(new PhoneImpl(
> +        "+33H000000000", "home"), new PhoneImpl("+33M000000000",
> "mobile"),
> +        new PhoneImpl("+33W000000000", "work")));
> +
> +    johnDoe.setAddresses(Lists.<Address> newArrayList(new AddressImpl(
> +        "My home address")));
> +
> +    johnDoe.setEmails(Lists.<Email> newArrayList(new EmailImpl(
> +        "john.doe@work.bar", "work"),
> +        new EmailImpl("john.doe@home.bar", "home")));
> +
> +    activity = new ActivityImpl("activityId", johnDoe.getId());
> +
> +    activity.setMediaItems(Lists.<MediaItem> newArrayList(new
> MediaItemImpl(
> +        "image/jpg", MediaItem.Type.IMAGE, "http://foo.bar")));
> +
> +    beanJsonLibConverter = new BeanJsonLibConverter(Guice
> +        .createInjector(new JsonLibTestsGuiceModule()));
> +
> +    beanJsonConverter = new BeanJsonConverter(Guice
> +        .createInjector(new SocialApiTestsGuiceModule()));
> +
> +    apiValidator = new APIValidator("opensocial-reference");
> +
> +  }
> +
> +  public static class SpecialPerson extends PersonImpl {
> +    private String newfield;
> +
> +    public SpecialPerson() {
> +      super();
> +    }
> +
> +    public SpecialPerson(String id, String name, String newfield) {
> +      super(id, new NameImpl(name));
> +      this.newfield = newfield;
> +    }
> +
> +    public String getNewfield() {
> +      return newfield;
> +    }
> +
> +    public void setNewfield(String newfield) {
> +      this.newfield = newfield;
> +    }
> +
> +  }
> +
> +  public void testToJsonLibOnInheritedClassOutput() throws Exception {
> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
> +    for (int i = 0; i < TEST_SIZE; i++) {
> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot", "nonsense");
> +    }
> +    Runtime r = Runtime.getRuntime();
> +    r.gc();
> +    long memstart = r.totalMemory()-r.freeMemory();
> +    long startOutput = System.currentTimeMillis();
> +    String[] output = new String[TEST_SIZE];
> +    for (int i = 0; i < TEST_SIZE; i++) {
> +      output[i] = beanJsonLibConverter.convertToString(spa[i]);
> +    }
> +    long endOutput = System.currentTimeMillis();
> +    long memend = r.totalMemory()-r.freeMemory();
> +
> +    String[] serializeOutput = new String[TEST_SIZE];
> +    char[] source = output[0].toCharArray();
> +    r.gc();
> +
> +    long stringsizeStart = r.totalMemory()-r.freeMemory();
> +    for (int i = 0; i < TEST_SIZE; i++) {
> +      serializeOutput[i] = new String(source);
> +    }
> +    long stringsizeEnd = r.totalMemory()-r.freeMemory();
> +
> +    /*
> +     * Output the time per conversion and the memory usage - the output
> per
> +     * conversion.
> +     *
> +     */
> +
> +    log.info("SF JSON Lib Output "
> +        + average(startOutput, endOutput, TEST_SIZE)
> +        + " ms/conversion, "
> +        + (average(memstart, memend, TEST_SIZE)-average(stringsizeStart,
> stringsizeEnd, TEST_SIZE))
> +        + " heap bytes/conversion, output packet consumed on average "
> +        + average(stringsizeStart, stringsizeEnd, TEST_SIZE)+" for a
> string length of "+output[0].length());
> +    log.info("Output Was ["+output[0]+"]");
> +  }
> +
> +  public void testToJsonLibOnInheritedClassInput() throws Exception {
> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
> +    SpecialPerson[] sparesult = new SpecialPerson[TEST_SIZE];
> +    Runtime r = Runtime.getRuntime();
> +    r.gc();
> +    long personStart = r.totalMemory()-r.freeMemory();
> +    for (int i = 0; i < TEST_SIZE; i++) {
> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot", "nonsense");
> +    }
> +    long personEnd = r.totalMemory()-r.freeMemory();
> +
> +    String[] serializeOutput = new String[TEST_SIZE];
> +    r.gc();
> +    for (int i = 0; i < TEST_SIZE; i++) {
> +
> +      serializeOutput[i] = beanJsonLibConverter.convertToString(spa[i]);
> +    }
> +
> +    r.gc();
> +    long memstart = r.totalMemory()-r.freeMemory();
> +    long startInput = System.currentTimeMillis();
> +    for (int i = 0; i < TEST_SIZE; i++) {
> +        sparesult[i] = beanJsonLibConverter.convertToObject(
> +          serializeOutput[i], SpecialPerson.class);
> +    }
> +    long endInput = System.currentTimeMillis();
> +    long memend = r.totalMemory()-r.freeMemory();
> +
> +    log.info("SF JSON Lib Input "
> +        + average(startInput, endInput, TEST_SIZE)
> +        + " ms/conversion, "
> +        + (average(memstart, memend, TEST_SIZE)-average(personStart,
> personEnd, TEST_SIZE))
> +        + " heap bytes/conversion, person object consumed on average "
> +        + average(personStart, personEnd, TEST_SIZE));
> +  }
> +
> +  public void testToJsonOnInheritedClassOutput() throws Exception {
> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
> +    for (int i = 0; i < TEST_SIZE; i++) {
> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot", "nonsense");
> +    }
> +    Runtime r = Runtime.getRuntime();
> +    String[] output = new String[TEST_SIZE];
> +    r.gc();
> +    long memstart = r.totalMemory()-r.freeMemory();
> +    long startOutput = System.currentTimeMillis();
> +    for (int i = 0; i < TEST_SIZE; i++) {
> +      output[i]  = ((JSONObject)
> beanJsonConverter.convertToJson(spa[i])).toString();
> +    }
> +    long endOutput = System.currentTimeMillis();
> +    long memend = r.totalMemory()-r.freeMemory();
> +    String[] serializeOutput = new String[TEST_SIZE];
> +    char[] source = output[0].toCharArray();
> +    r.gc();
> +
> +    long stringsizeStart = r.totalMemory()-r.freeMemory();
> +
> +    for (int i = 0; i < TEST_SIZE; i++) {
> +      serializeOutput[i] = new String(source);
> +    }
> +    long stringsizeEnd = r.totalMemory()-r.freeMemory();
> +
> +    log.info("ORG JSON Lib Output "
> +        + average(startOutput, endOutput, TEST_SIZE)
> +        + " ms/conversion, "
> +        + (average(memstart, memend, TEST_SIZE)-average(stringsizeStart,
> stringsizeEnd, TEST_SIZE))
> +        + " heap bytes/conversion, output packet consumed on average "
> +        + average(stringsizeStart, stringsizeEnd, TEST_SIZE)+" for a
> string length of "+output[0].length());
> +    log.info("Output Was ["+output[0]+"]");
> +  }
> +
> +  /**
> +   * @param endOutput
> +   * @param startOutput
> +   * @param testSize
> +   * @return
> +   */
> +  private float average(long start, long end, int testSize) {
> +    float r = end - start;
> +    r = r / testSize;
> +    return r;
> +  }
> +
> +  public void XtestToJsonOnInheritedClassInput() throws Exception {
> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
> +    SpecialPerson[] sparesult = new SpecialPerson[TEST_SIZE];
> +    Runtime r = Runtime.getRuntime();
> +    r.gc();
> +    long personStart = r.totalMemory()-r.freeMemory();
> +    for (int i = 0; i < TEST_SIZE; i++) {
> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot", "nonsense");
> +    }
> +    long personEnd = r.totalMemory()-r.freeMemory();
> +
> +    String[] serializeOutput = new String[TEST_SIZE];
> +    r.gc();
> +    for (int i = 0; i < TEST_SIZE; i++) {
> +
> +      serializeOutput[i] = beanJsonConverter.convertToString(spa[i]);
> +    }
> +
> +    r.gc();
> +    long memstart = r.totalMemory()-r.freeMemory();
> +    long startInput = System.currentTimeMillis();
> +
> +    for (int i = 0; i < TEST_SIZE; i++) {
> +      sparesult[i] = beanJsonConverter.convertToObject(
> +          serializeOutput[i], SpecialPerson.class);
> +    }
> +    long endInput = System.currentTimeMillis();
> +    long memend = r.totalMemory()-r.freeMemory();
> +
> +    log.info("SF JSON Lib Input "
> +        + average(startInput, endInput, TEST_SIZE)
> +        + " ms/conversion, "
> +        + (average(memstart, memend, TEST_SIZE)-average(personStart,
> personEnd, TEST_SIZE))
> +        + " heap bytes/conversion, person object consumed on average "
> +        + average(personStart, personEnd, TEST_SIZE));
> +  }
> +
> +}
>
> Modified: incubator/shindig/trunk/pom.xml
> URL:
> http://svn.apache.org/viewvc/incubator/shindig/trunk/pom.xml?rev=678158&r1=678157&r2=678158&view=diff
>
> ==============================================================================
> --- incubator/shindig/trunk/pom.xml (original)
> +++ incubator/shindig/trunk/pom.xml Sat Jul 19 06:51:03 2008
> @@ -853,6 +853,16 @@
>         <artifactId>htmlunit</artifactId>
>         <version>2.1</version>
>       </dependency>
> +      <dependency>
> +        <groupId>log4j</groupId>
> +        <artifactId>log4j</artifactId>
> +        <version>1.2.13</version>
> +      </dependency>
> +      <dependency>
> +        <groupId>rhino</groupId>
> +        <artifactId>js</artifactId>
> +        <version>1.6R7</version>
> +      </dependency>
>     </dependencies>
>   </dependencyManagement>
>  </project>
>
>
>

Re: svn commit: r678158 - in /incubator/shindig/trunk: ./ java/social-api/ java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/ java/social-api/src/test/java/org/apache/shindig/social/ java/social-api/src/test/java/org/apache/shin

Posted by Chris Chabot <ch...@xs4all.nl>.
100% a-ok here, thanks


On Jul 20, 2008, at 12:31 PM, Ian Boston wrote:

> I am using git, which said it did a rename on svn commit.
>
> Can you verify that these did come through as moves when you update.
>
> Thanks
> Ian
>
>
>
> x43543:~/Apache/shindig/trunk ieb$ git svn dcommit
> Committing to https://svn.apache.org/repos/asf/incubator/shindig/ 
> trunk ...
>        R       java/social-api/src/main/java/org/apache/shindig/ 
> social/opensocial/util/JSONLibConverterUtils.java => java/social-api/ 
> src/main/java/org/apache/shindig/social/opensocial/util/ 
> JsonLibConverterUtils.java
>        R       java/social-api/src/main/java/org/apache/shindig/ 
> social/opensocial/util/JSONObjectToMapMorpher.java => java/social- 
> api/src/main/java/org/apache/shindig/social/opensocial/util/ 
> JsonObjectToMapMorpher.java
>        R       java/social-api/src/test/java/org/apache/shindig/ 
> social/opensocial/util/APIValidator.java => java/social-api/src/test/ 
> java/org/apache/shindig/social/opensocial/util/ApiValidator.java
>        R       java/social-api/src/test/java/org/apache/shindig/ 
> social/opensocial/util/APIValidatorExpcetion.java => java/social-api/ 
> src/test/java/org/apache/shindig/social/opensocial/util/ 
> ApiValidatorExpcetion.java
>        R       java/social-api/src/test/java/org/apache/shindig/ 
> social/opensocial/util/APIValidatorTest.java => java/social-api/src/ 
> test/java/org/apache/shindig/social/opensocial/util/ 
> ApiValidatorTest.java
>        M       java/social-api/src/main/java/org/apache/shindig/ 
> social/opensocial/util/BeanJsonLibConverter.java
>        M       java/social-api/src/test/java/org/apache/shindig/ 
> social/opensocial/util/BeanJsonLibConverterTest.java
>        M       java/social-api/src/test/java/org/apache/shindig/ 
> social/opensocial/util/JsonConverterPerformancePerf.java
> Committed r678263
>
> On 20 Jul 2008, at 10:46, Chris Chabot wrote:
>
>> Please make sure to do proper svn move's. Last time we had 2  
>> identical file names, but with different casing, everyone on a case  
>> insensitive file system got into trouble :)
>>
>> 	-- Chris
>>
>> On Jul 20, 2008, at 11:02 AM, Ian Boston wrote:
>>
>>> Ok will fix.
>>> Ian
>>>
>>> On 19 Jul 2008, at 20:50, Kevin Brown wrote:
>>>
>>>> Hey Ian,
>>>>
>>>> The casing is inconsistent here -- it should be Json and Api for  
>>>> all cases
>>>> rather than JSON or API.
>>>>
>>>> Thanks!
>>>>
>>>> On Sat, Jul 19, 2008 at 6:51 AM, <ie...@apache.org> wrote:
>>>>
>>>>> Author: ieb
>>>>> Date: Sat Jul 19 06:51:03 2008
>>>>> New Revision: 678158
>>>>>
>>>>> URL: http://svn.apache.org/viewvc?rev=678158&view=rev
>>>>> Log:
>>>>> SHINDIG-451
>>>>> Applying patch from the JIRA.
>>>>>
>>>>> Adds a json-lib (net.sf) converter, not wired into social-api at  
>>>>> present.
>>>>>
>>>>> Added:
>>>>>
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>>>>
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>>>>>
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>>>>>
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>>>>
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/JsonLibTestsGuiceModule.java
>>>>>
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/APIValidator.java
>>>>>
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>>>>>
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/APIValidatorTest.java
>>>>>
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>>>>
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>>>> Modified:
>>>>>  incubator/shindig/trunk/java/social-api/pom.xml
>>>>>  incubator/shindig/trunk/pom.xml
>>>>>
>>>>> Modified: incubator/shindig/trunk/java/social-api/pom.xml
>>>>> URL:
>>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/pom.xml?rev=678158&r1=678157&r2=678158&view=diff
>>>>>
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> ==================================================================
>>>>> --- incubator/shindig/trunk/java/social-api/pom.xml (original)
>>>>> +++ incubator/shindig/trunk/java/social-api/pom.xml Sat Jul 19  
>>>>> 06:51:03
>>>>> 2008
>>>>> @@ -60,12 +60,31 @@
>>>>>     <groupId>org.apache.shindig</groupId>
>>>>>     <artifactId>shindig-common</artifactId>
>>>>>   </dependency>
>>>>> +    <!-- is this Ok, only used in test to load the features -->
>>>>> +    <dependency>
>>>>> +      <groupId>org.apache.shindig</groupId>
>>>>> +      <artifactId>shindig-features</artifactId>
>>>>> +      <scope>test</scope>
>>>>> +    </dependency>
>>>>>
>>>>>   <!-- external depenencies -->
>>>>>   <dependency>
>>>>>     <groupId>org.json</groupId>
>>>>>     <artifactId>json</artifactId>
>>>>>   </dependency>
>>>>> +    <!-- the classifier prevents this working in dep management  
>>>>> -->
>>>>> +    <dependency>
>>>>> +      <groupId>net.sf.json-lib</groupId>
>>>>> +      <artifactId>json-lib</artifactId>
>>>>> +      <version>2.2</version>
>>>>> +      <classifier>jdk15</classifier>
>>>>> +      <type>jar</type>
>>>>> +    </dependency>
>>>>> +    <dependency>
>>>>> +      <groupId>rhino</groupId>
>>>>> +      <artifactId>js</artifactId>
>>>>> +      <scope>test</scope>
>>>>> +    </dependency>
>>>>>   <dependency>
>>>>>     <groupId>com.google.code.guice</groupId>
>>>>>     <artifactId>guice</artifactId>
>>>>> @@ -112,5 +131,10 @@
>>>>>     <artifactId>core</artifactId>
>>>>>     <scope>compile</scope>
>>>>>   </dependency>
>>>>> +    <dependency>
>>>>> +      <groupId>log4j</groupId>
>>>>> +      <artifactId>log4j</artifactId>
>>>>> +      <scope>test</scope>
>>>>> +    </dependency>
>>>>> </dependencies>
>>>>> </project>
>>>>>
>>>>> Added:
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>>>> URL:
>>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConversionException.java?rev=678158&view=auto
>>>>>
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> ==================================================================
>>>>> ---
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>>>> (added)
>>>>> +++
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>>>> Sat Jul 19 06:51:03 2008
>>>>> @@ -0,0 +1,43 @@
>>>>> +/*
>>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>>> + * or more contributor license agreements. See the NOTICE file
>>>>> + * distributed with this work for additional information
>>>>> + * regarding copyright ownership. The ASF licenses this file
>>>>> + * to you under the Apache License, Version 2.0 (the
>>>>> + * "License"); you may not use this file except in compliance
>>>>> + * with the License. You may obtain a copy of the License at
>>>>> + *
>>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>>> + *
>>>>> + * 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.apache.shindig.social.opensocial.util;
>>>>> +
>>>>> +/**
>>>>> + * Where a conversion exception happens in the Json Lib  
>>>>> conversion, this
>>>>> + * exception is thrown.
>>>>> + */
>>>>> +public class BeanJsonLibConversionException extends  
>>>>> RuntimeException {
>>>>> +
>>>>> +  private static final long serialVersionUID =  
>>>>> -8609384443448202372L;
>>>>> +
>>>>> +  public BeanJsonLibConversionException() {
>>>>> +  }
>>>>> +
>>>>> +  public BeanJsonLibConversionException(String arg0) {
>>>>> +    super(arg0);
>>>>> +  }
>>>>> +
>>>>> +  public BeanJsonLibConversionException(Throwable arg0) {
>>>>> +    super(arg0);
>>>>> +  }
>>>>> +
>>>>> +  public BeanJsonLibConversionException(String arg0, Throwable  
>>>>> arg1) {
>>>>> +    super(arg0, arg1);
>>>>> +  }
>>>>> +
>>>>> +}
>>>>>
>>>>> Added:
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>>>>> URL:
>>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverter.java?rev=678158&view=auto
>>>>>
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> ==================================================================
>>>>> ---
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>>>>> (added)
>>>>> +++
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>>>>> Sat Jul 19 06:51:03 2008
>>>>> @@ -0,0 +1,286 @@
>>>>> +/*
>>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>>> + * or more contributor license agreements. See the NOTICE file
>>>>> + * distributed with this work for additional information
>>>>> + * regarding copyright ownership. The ASF licenses this file
>>>>> + * to you under the Apache License, Version 2.0 (the
>>>>> + * "License"); you may not use this file except in compliance
>>>>> + * with the License. You may obtain a copy of the License at
>>>>> + *
>>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>>> + *
>>>>> + * 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.apache.shindig.social.opensocial.util;
>>>>> +
>>>>> +import java.lang.reflect.Array;
>>>>> +import java.lang.reflect.InvocationTargetException;
>>>>> +import java.util.Collection;
>>>>> +import java.util.HashMap;
>>>>> +import java.util.List;
>>>>> +import java.util.Map;
>>>>> +
>>>>> +import net.sf.ezmorph.MorpherRegistry;
>>>>> +import net.sf.json.JSONArray;
>>>>> +import net.sf.json.JSONException;
>>>>> +import net.sf.json.JSONObject;
>>>>> +import net.sf.json.JsonConfig;
>>>>> +import net.sf.json.processors.DefaultValueProcessor;
>>>>> +import net.sf.json.util.EnumMorpher;
>>>>> +import net.sf.json.util.JSONUtils;
>>>>> +import net.sf.json.util.NewBeanInstanceStrategy;
>>>>> +import net.sf.json.util.PropertyFilter;
>>>>> +
>>>>> +import org.apache.commons.logging.Log;
>>>>> +import org.apache.commons.logging.LogFactory;
>>>>> +import org.apache.shindig.social.opensocial.model.Address;
>>>>> +import org.apache.shindig.social.opensocial.model.Email;
>>>>> +import org.apache.shindig.social.opensocial.model.Enum;
>>>>> +import org.apache.shindig.social.opensocial.model.MediaItem;
>>>>> +import org.apache.shindig.social.opensocial.model.Organization;
>>>>> +import org.apache.shindig.social.opensocial.model.Phone;
>>>>> +import org.apache.shindig.social.opensocial.model.Url;
>>>>> +
>>>>> +
>>>>> +import com.google.inject.Inject;
>>>>> +import com.google.inject.Injector;
>>>>> +
>>>>> +/**
>>>>> + *
>>>>> + */
>>>>> +public class BeanJsonLibConverter implements BeanConverter {
>>>>> +
>>>>> +  protected static final Log log = LogFactory
>>>>> +      .getLog(BeanJsonLibConverter.class);
>>>>> +  private Injector injector;
>>>>> +  private JsonConfig jsonConfig;
>>>>> +  private boolean debugMode = false;
>>>>> +
>>>>> +  /*
>>>>> +   * Register the Enum Morphers so that JSON -> Bean works  
>>>>> correctly for
>>>>> enums.
>>>>> +   */
>>>>> +  static {
>>>>> +    MorpherRegistry morpherRegistry =  
>>>>> JSONUtils.getMorpherRegistry();
>>>>> +    morpherRegistry.registerMorpher(new  
>>>>> EnumMorpher(Address.Field.class));
>>>>> +    morpherRegistry.registerMorpher(new  
>>>>> EnumMorpher(Phone.Field.class));
>>>>> +    morpherRegistry.registerMorpher(new  
>>>>> EnumMorpher(Email.Field.class));
>>>>> +    morpherRegistry.registerMorpher(new
>>>>> EnumMorpher(MediaItem.Field.class));
>>>>> +    morpherRegistry.registerMorpher(new
>>>>> EnumMorpher(MediaItem.Type.class));
>>>>> +    morpherRegistry.registerMorpher(new  
>>>>> EnumMorpher(Enum.Drinker.class));
>>>>> +    morpherRegistry.registerMorpher(new  
>>>>> EnumMorpher(Enum.Field.class));
>>>>> +    morpherRegistry.registerMorpher(new  
>>>>> EnumMorpher(Enum.Gender.class));
>>>>> +    morpherRegistry
>>>>> +        .registerMorpher(new  
>>>>> EnumMorpher(Enum.NetworkPresence.class));
>>>>> +    morpherRegistry.registerMorpher(new  
>>>>> EnumMorpher(Enum.Smoker.class));
>>>>> +
>>>>> +    morpherRegistry.registerMorpher(new  
>>>>> JSONObjectToMapMorpher());
>>>>> +  }
>>>>> +
>>>>> +  @Inject
>>>>> +  public BeanJsonLibConverter(Injector injector) {
>>>>> +    this.injector = injector;
>>>>> +    createJsonConfig();
>>>>> +  }
>>>>> +
>>>>> +  @SuppressWarnings("unchecked")
>>>>> +  public <T> T convertToObject(String string, final Class<T>
>>>>> rootBeanClass) {
>>>>> +
>>>>> +    if (string.startsWith("[")) {
>>>>> +      JSONArray jsonArray = JSONArray.fromObject(string,  
>>>>> jsonConfig);
>>>>> +      if (debugMode) {
>>>>> +        JSONLibConverterUtils.dumpJsonArray(jsonArray, " ");
>>>>> +      }
>>>>> +
>>>>> +      if (rootBeanClass.isArray()) {
>>>>> +        Class<?> componentType =  
>>>>> rootBeanClass.getComponentType();
>>>>> +        Object rootObject = injector.getInstance(componentType);
>>>>> +        List<?> o = JSONArray.toList(jsonArray, rootObject,  
>>>>> jsonConfig);
>>>>> +        Object[] result = (Object[])  
>>>>> Array.newInstance(componentType,
>>>>> o.size());
>>>>> +        for (int i = 0; i < o.size(); i++) {
>>>>> +          result[i] = o.get(i);
>>>>> +        }
>>>>> +        return (T) result;
>>>>> +
>>>>> +      } else {
>>>>> +        T rootObject = injector.getInstance(rootBeanClass);
>>>>> +        Object o = JSONArray.toArray(jsonArray, rootObject,  
>>>>> jsonConfig);
>>>>> +        return (T) o;
>>>>> +      }
>>>>> +    } else {
>>>>> +      JSONObject jsonObject = JSONObject.fromObject(string,  
>>>>> jsonConfig);
>>>>> +
>>>>> +      if (debugMode) {
>>>>> +        JSONLibConverterUtils.dumpJsonObject(jsonObject, " ");
>>>>> +      }
>>>>> +
>>>>> +      T rootObject = injector.getInstance(rootBeanClass);
>>>>> +      Object o = JSONObject.toBean(jsonObject, rootObject,  
>>>>> jsonConfig);
>>>>> +      return (T) o;
>>>>> +
>>>>> +    }
>>>>> +  }
>>>>> +
>>>>> +  /**
>>>>> +   * @return
>>>>> +   */
>>>>> +  private void createJsonConfig() {
>>>>> +
>>>>> +    jsonConfig = new JsonConfig();
>>>>> +
>>>>> +    /*
>>>>> +     * This hook deals with the creation of new beans in the  
>>>>> JSON -> Java
>>>>> Bean
>>>>> +     * conversion
>>>>> +     */
>>>>> +    jsonConfig.setNewBeanInstanceStrategy(new  
>>>>> NewBeanInstanceStrategy() {
>>>>> +
>>>>> +      @SuppressWarnings("unchecked")
>>>>> +      @Override
>>>>> +      public Object newInstance(Class beanClass, JSONObject  
>>>>> jsonObject)
>>>>> +          throws InstantiationException, IllegalAccessException,
>>>>> +          SecurityException, NoSuchMethodException,
>>>>> InvocationTargetException {
>>>>> +        if (beanClass != null) {
>>>>> +          Object o =
>>>>> BeanJsonLibConverter.this.injector.getInstance(beanClass);
>>>>> +          if (debugMode) {
>>>>> +            log.info("Created Object " + o + " for " +  
>>>>> beanClass + " with
>>>>> ["
>>>>> +                + jsonObject + "]");
>>>>> +          }
>>>>> +          return o;
>>>>> +        }
>>>>> +        return DEFAULT.newInstance(beanClass, jsonObject);
>>>>> +      }
>>>>> +
>>>>> +    });
>>>>> +
>>>>> +    /*
>>>>> +     * We are expecting null for nulls
>>>>> +     */
>>>>> +    jsonConfig.registerDefaultValueProcessor(String.class,
>>>>> +        new DefaultValueProcessor() {
>>>>> +          @SuppressWarnings("unchecked")
>>>>> +          public Object getDefaultValue(Class target) {
>>>>> +            return null;
>>>>> +          }
>>>>> +        });
>>>>> +
>>>>> +    jsonConfig.setJsonPropertyFilter(new PropertyFilter() {
>>>>> +
>>>>> +      public boolean apply(Object source, String name, Object  
>>>>> value) {
>>>>> +        return filterProperty(source, name, value);
>>>>> +      }
>>>>> +
>>>>> +    });
>>>>> +
>>>>> +    jsonConfig.setJavaPropertyFilter(new PropertyFilter() {
>>>>> +
>>>>> +      public boolean apply(Object source, String name, Object  
>>>>> value) {
>>>>> +        return filterProperty(source,name,value);
>>>>> +      }
>>>>> +
>>>>> +    });
>>>>> +
>>>>> +    // the classMap deals with the basic json string to bean  
>>>>> conversion
>>>>> +
>>>>> +    Map<String, Class<?>> classMap = new HashMap<String, Class<? 
>>>>> >>();
>>>>> +
>>>>> +    /*
>>>>> +     * mappings are required where there is a List of objects  
>>>>> in the
>>>>> interface
>>>>> +     * with no indication of what type the list should contain.  
>>>>> At the
>>>>> moment,
>>>>> +     * we are using 1 map for all json trees, as there is no  
>>>>> conflict, but
>>>>> if
>>>>> +     * there is a map could be selected on the basis of the  
>>>>> root object.
>>>>> It
>>>>> +     * would be better to do this with generics, but this is  
>>>>> good enough
>>>>> and
>>>>> +     * compact enough for the moment.
>>>>> +     *
>>>>> +     */
>>>>> +    //
>>>>> +    // activity
>>>>> +    classMap.put("mediaItems", MediaItem.class);
>>>>> +    // this may not be necessary
>>>>> +    classMap.put("templateParams", Map.class);
>>>>> +    // BodyType needs no mappings
>>>>> +    // Message needs no mappings
>>>>> +    // Name needs no mappings
>>>>> +    // Organization needs no mappings
>>>>> +    // Url needs no mappings
>>>>> +    // Email needs no mappings
>>>>> +    // Phone Needs no mappings
>>>>> +    // Address Needs no mappings
>>>>> +    // MediaItem needs no mappings
>>>>> +
>>>>> +    // Person map
>>>>> +    classMap.put("addresses", Address.class);
>>>>> +    classMap.put("phoneNumbers", Phone.class);
>>>>> +    classMap.put("emails", Email.class);
>>>>> +    classMap.put("mediaItems", MediaItem.class);
>>>>> +    classMap.put("jobs", Organization.class);
>>>>> +    classMap.put("schools", Organization.class);
>>>>> +    classMap.put("urls", Url.class);
>>>>> +    jsonConfig.setClassMap(classMap);
>>>>> +
>>>>> +  }
>>>>> +
>>>>> +  /**
>>>>> +   * @param source
>>>>> +   * @param name
>>>>> +   * @param value
>>>>> +   * @return
>>>>> +   */
>>>>> +  protected boolean filterProperty(Object source, String name,  
>>>>> Object
>>>>> value) {
>>>>> +    if ( value == null ) {
>>>>> +      return true;
>>>>> +    }
>>>>> +    if ( value instanceof JSONArray ) {
>>>>> +      JSONArray array = (JSONArray) value;
>>>>> +      if ( array.size() == 0 ) {
>>>>> +        return true;
>>>>> +      }
>>>>> +    }
>>>>> +    if ( value instanceof JSONObject ) {
>>>>> +      JSONObject object = (JSONObject) value;
>>>>> +      if ( object.isNullObject() || object.isEmpty()  ) {
>>>>> +        return true;
>>>>> +      }
>>>>> +    }
>>>>> +    if ( value instanceof Collection) {
>>>>> +      Collection<?> collection = (Collection<?>) value;
>>>>> +      if ( collection.size() == 0  ) {
>>>>> +        return true;
>>>>> +      }
>>>>> +    }
>>>>> +    if ( value instanceof Object[] ) {
>>>>> +      Object[] oarray = (Object[]) value;
>>>>> +      if ( oarray.length == 0 ) {
>>>>> +        return true;
>>>>> +      }
>>>>> +    }
>>>>> +    return false;
>>>>> +  }
>>>>> +
>>>>> +  public String convertToString(Object pojo) {
>>>>> +
>>>>> +    try {
>>>>> +      JSONObject jsonObject = JSONObject.fromObject(pojo,  
>>>>> jsonConfig);
>>>>> +      return jsonObject.toString();
>>>>> +    } catch (JSONException jse) {
>>>>> +      Class<?> pojoClass = pojo.getClass();
>>>>> +      if (JSONUtils.isArray(pojoClass)) {
>>>>> +        JSONArray jsonArray = JSONArray.fromObject(pojo);
>>>>> +        String result = jsonArray.toString();
>>>>> +        return result;
>>>>> +      }
>>>>> +      throw jse;
>>>>> +    }
>>>>> +  }
>>>>> +
>>>>> +  /**
>>>>> +   * @param string
>>>>> +   * @param class1
>>>>> +   */
>>>>> +  public void addMapping(String key, Class<?> class1) {
>>>>> +    jsonConfig.getClassMap().put(key, class1);
>>>>> +  }
>>>>> +
>>>>> +}
>>>>>
>>>>> Added:
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>>>>> URL:
>>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONLibConverterUtils.java?rev=678158&view=auto
>>>>>
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> ==================================================================
>>>>> ---
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>>>>> (added)
>>>>> +++
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>>>>> Sat Jul 19 06:51:03 2008
>>>>> @@ -0,0 +1,72 @@
>>>>> +/*
>>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>>> + * or more contributor license agreements. See the NOTICE file
>>>>> + * distributed with this work for additional information
>>>>> + * regarding copyright ownership. The ASF licenses this file
>>>>> + * to you under the Apache License, Version 2.0 (the
>>>>> + * "License"); you may not use this file except in compliance
>>>>> + * with the License. You may obtain a copy of the License at
>>>>> + *
>>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>>> + *
>>>>> + * 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.apache.shindig.social.opensocial.util;
>>>>> +
>>>>> +import org.apache.commons.logging.Log;
>>>>> +import org.apache.commons.logging.LogFactory;
>>>>> +
>>>>> +import net.sf.json.JSONArray;
>>>>> +import net.sf.json.JSONObject;
>>>>> +
>>>>> +/**
>>>>> + *
>>>>> + */
>>>>> +public class JSONLibConverterUtils {
>>>>> +  protected static final Log log = LogFactory
>>>>> +  .getLog(JSONLibConverterUtils.class);
>>>>> +
>>>>> +
>>>>> +  /**
>>>>> +   * @param jsonObject
>>>>> +   */
>>>>> +  public static final void dumpJsonObject(JSONObject  
>>>>> jsonObject, String
>>>>> indent) {
>>>>> +    for (Object key : jsonObject.keySet()) {
>>>>> +      Object value = jsonObject.get(key);
>>>>> +      if (value instanceof JSONObject) {
>>>>> +        log.info(indent + key + ":JSONObject");
>>>>> +        dumpJsonObject((JSONObject) value, indent + "  ");
>>>>> +      } else if (value instanceof JSONArray) {
>>>>> +        log.info(indent + key + ":JSONArray " + ((JSONArray)
>>>>> value).size());
>>>>> +        dumpJsonArray((JSONArray) value, indent + "  ");
>>>>> +      } else {
>>>>> +        log.info(indent + key + ":" + value + ":"
>>>>> +            + (value == null ? "na" : value.getClass()));
>>>>> +      }
>>>>> +    }
>>>>> +  }
>>>>> +
>>>>> +
>>>>> +  /**
>>>>> +   * @param value
>>>>> +   * @param string
>>>>> +   */
>>>>> +  static void dumpJsonArray(JSONArray array, String indent) {
>>>>> +    for (Object value : array) {
>>>>> +      if (value instanceof JSONObject) {
>>>>> +        log.info(indent + ":JSONObject");
>>>>> +        dumpJsonObject((JSONObject) value, indent + "  ");
>>>>> +      } else if (value instanceof JSONArray) {
>>>>> +        log.info(indent + ":JSONArray " + ((JSONArray)  
>>>>> value).size());
>>>>> +        dumpJsonArray((JSONArray) value, indent + "  ");
>>>>> +      } else {
>>>>> +        log.info(indent + ":" + value + ":"
>>>>> +            + (value == null ? "na" : value.getClass()));
>>>>> +      }
>>>>> +    }
>>>>> +  }
>>>>> +}
>>>>>
>>>>> Added:
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>>>> URL:
>>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONObjectToMapMorpher.java?rev=678158&view=auto
>>>>>
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> ==================================================================
>>>>> ---
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>>>> (added)
>>>>> +++
>>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>>>> Sat Jul 19 06:51:03 2008
>>>>> @@ -0,0 +1,50 @@
>>>>> +/*
>>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>>> + * or more contributor license agreements. See the NOTICE file
>>>>> + * distributed with this work for additional information
>>>>> + * regarding copyright ownership. The ASF licenses this file
>>>>> + * to you under the Apache License, Version 2.0 (the
>>>>> + * "License"); you may not use this file except in compliance
>>>>> + * with the License. You may obtain a copy of the License at
>>>>> + *
>>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>>> + *
>>>>> + * 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.apache.shindig.social.opensocial.util;
>>>>> +
>>>>> +import java.util.HashMap;
>>>>> +import java.util.Map;
>>>>> +
>>>>> +import net.sf.ezmorph.Morpher;
>>>>> +import net.sf.ezmorph.ObjectMorpher;
>>>>> +import net.sf.json.JSONObject;
>>>>> +
>>>>> +/**
>>>>> + *
>>>>> + */
>>>>> +public class JSONObjectToMapMorpher implements Morpher,  
>>>>> ObjectMorpher {
>>>>> +
>>>>> +  public Class<?> morphsTo() {
>>>>> +    return Map.class;
>>>>> +  }
>>>>> +
>>>>> +  @SuppressWarnings("unchecked")
>>>>> +  public boolean supports(Class clazz) {
>>>>> +    return (JSONObject.class.equals(clazz));
>>>>> +  }
>>>>> +
>>>>> +  public Object morph(Object bean) {
>>>>> +    Map<Object, Object> result = new HashMap<Object, Object>();
>>>>> +    JSONObject jsonObject = (JSONObject) bean;
>>>>> +    for ( Object key : jsonObject.keySet()) {
>>>>> +      result.put(key,jsonObject.get(key));
>>>>> +    }
>>>>> +    return result;
>>>>> +  }
>>>>> +
>>>>> +}
>>>>>
>>>>> Added:
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/JsonLibTestsGuiceModule.java
>>>>> URL:
>>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/JsonLibTestsGuiceModule.java?rev=678158&view=auto
>>>>>
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> ==================================================================
>>>>> ---
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/JsonLibTestsGuiceModule.java
>>>>> (added)
>>>>> +++
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/JsonLibTestsGuiceModule.java
>>>>> Sat Jul 19 06:51:03 2008
>>>>> @@ -0,0 +1,40 @@
>>>>> +/*
>>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>>> + * or more contributor license agreements.  See the NOTICE file
>>>>> + * distributed with this work for additional information
>>>>> + * regarding copyright ownership.  The ASF licenses this file
>>>>> + * to you under the Apache License, Version 2.0 (the
>>>>> + * "License"); you may not use this file except in compliance
>>>>> + * with the License.  You may obtain a copy of the License at
>>>>> + *
>>>>> + *   http://www.apache.org/licenses/LICENSE-2.0
>>>>> + *
>>>>> + * 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.apache.shindig.social;
>>>>> +
>>>>> +import java.util.ArrayList;
>>>>> +import java.util.HashMap;
>>>>> +import java.util.List;
>>>>> +import java.util.Map;
>>>>> +
>>>>> +import com.google.inject.AbstractModule;
>>>>> +
>>>>> +/**
>>>>> + * Provides social api component injection for all large tests
>>>>> + */
>>>>> +public class JsonLibTestsGuiceModule extends AbstractModule {
>>>>> +  @Override
>>>>> +  protected void configure() {
>>>>> +
>>>>> +    bind(Map.class).to(HashMap.class);
>>>>> +    bind(List.class).to(ArrayList.class);
>>>>> +    bind(Map[].class).to(HashMap[].class);
>>>>> +  }
>>>>> +
>>>>> +}
>>>>>
>>>>> Added:
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/APIValidator.java
>>>>> URL:
>>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidator.java?rev=678158&view=auto
>>>>>
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> ==================================================================
>>>>> ---
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/APIValidator.java
>>>>> (added)
>>>>> +++
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/APIValidator.java
>>>>> Sat Jul 19 06:51:03 2008
>>>>> @@ -0,0 +1,352 @@
>>>>> +/*
>>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>>> + * or more contributor license agreements. See the NOTICE file
>>>>> + * distributed with this work for additional information
>>>>> + * regarding copyright ownership. The ASF licenses this file
>>>>> + * to you under the Apache License, Version 2.0 (the
>>>>> + * "License"); you may not use this file except in compliance
>>>>> + * with the License. You may obtain a copy of the License at
>>>>> + *
>>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>>> + *
>>>>> + * 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.apache.shindig.social.opensocial.util;
>>>>> +
>>>>> +import java.io.IOException;
>>>>> +import java.io.InputStream;
>>>>> +import java.io.InputStreamReader;
>>>>> +import java.util.ArrayList;
>>>>> +import java.util.HashMap;
>>>>> +import java.util.List;
>>>>> +import java.util.Map;
>>>>> +
>>>>> +import javax.xml.parsers.DocumentBuilder;
>>>>> +import javax.xml.parsers.DocumentBuilderFactory;
>>>>> +import javax.xml.parsers.ParserConfigurationException;
>>>>> +
>>>>> +import org.apache.commons.logging.Log;
>>>>> +import org.apache.commons.logging.LogFactory;
>>>>> +import org.mozilla.javascript.Context;
>>>>> +import org.mozilla.javascript.EvaluatorException;
>>>>> +import org.mozilla.javascript.Script;
>>>>> +import org.mozilla.javascript.ScriptableObject;
>>>>> +import org.w3c.dom.Document;
>>>>> +import org.w3c.dom.NamedNodeMap;
>>>>> +import org.w3c.dom.Node;
>>>>> +import org.w3c.dom.NodeList;
>>>>> +import org.xml.sax.SAXException;
>>>>> +
>>>>> +/**
>>>>> + * A class that loads a feature set from features into a  
>>>>> Javascript Parser
>>>>> to
>>>>> + * make the model available to validate JSON messages against.
>>>>> + */
>>>>> +public class APIValidator {
>>>>> +
>>>>> +  private static final Log log =  
>>>>> LogFactory.getLog(APIValidator.class);
>>>>> +  private Context ctx;
>>>>> +  private ScriptableObject scope;
>>>>> +
>>>>> +  /**
>>>>> +   * @param feature
>>>>> +   *                The name of the feature are eg "opensocial- 
>>>>> reference",
>>>>> this
>>>>> +   *                is a classpath stub (not starting with /)  
>>>>> where the
>>>>> location
>>>>> +   *                contains a feature.xml file.
>>>>> +   * @throws SAXException
>>>>> +   *                 if feature.xml is not parsable
>>>>> +   * @throws ParserConfigurationException
>>>>> +   *                 if the parsers are invalid
>>>>> +   * @throws IOException
>>>>> +   *                 if feature.xml or the javascript that  
>>>>> represents the
>>>>> +   *                 feature is missing
>>>>> +   *
>>>>> +   */
>>>>> +  public APIValidator(String feature) throws IOException,
>>>>> +      ParserConfigurationException, SAXException {
>>>>> +    ctx = Context.enter();
>>>>> +    scope = ctx.initStandardObjects();
>>>>> +    load(feature);
>>>>> +  }
>>>>> +
>>>>> +  /**
>>>>> +   * @param json
>>>>> +   *                The json to validate expected in a form  
>>>>> { xyz: yyy }
>>>>> form
>>>>> +   * @param object
>>>>> +   *                The json Fields object specifying the  
>>>>> structure of the
>>>>> json
>>>>> +   *                object, each field in this object contains  
>>>>> the name of
>>>>> the
>>>>> +   *                json field in the json structure.
>>>>> +   * @param optionalFields
>>>>> +   *                If any of the fields that appear in the  
>>>>> json structure
>>>>> are
>>>>> +   *                optional, then they should be defined in this
>>>>> parameter.
>>>>> +   * @param nullfields
>>>>> +   * @throws APIValidatorExpcetion
>>>>> +   *                 if there is a problem validating the json
>>>>> +   * @return a map so string object pairs containing the fields  
>>>>> at the top
>>>>> level
>>>>> +   *         of the json tree. Where these are native java  
>>>>> objects, they
>>>>> will
>>>>> +   *         appear as native object. Complex json objects will  
>>>>> appear as
>>>>> Rhino
>>>>> +   *         specific objects
>>>>> +   */
>>>>> +  public Map<String, Object> validate(String json, String object,
>>>>> +      String[] optionalFields, String[] nullfields)
>>>>> +      throws APIValidatorExpcetion {
>>>>> +
>>>>> +    /*
>>>>> +     * Object[] ids = ScriptableObject.getPropertyIds(scope);  
>>>>> for (Object
>>>>> id :
>>>>> +     * ids) { Object o = ScriptableObject.getProperty(scope,
>>>>> +     * String.valueOf(id)); log.debug("ID is " + id + " class " +
>>>>> id.getClass() + "
>>>>> +     * is " + o); if (o instanceof ScriptableObject) {
>>>>> +     * listScriptable(String.valueOf(id), (ScriptableObject)  
>>>>> o); } }
>>>>> +     */
>>>>> +
>>>>> +    log.debug("Loading " + json);
>>>>> +    json = json.trim();
>>>>> +    if (!json.endsWith("}")) {
>>>>> +      json = json + "}";
>>>>> +    }
>>>>> +    if (!json.startsWith("{")) {
>>>>> +      json = "{" + json;
>>>>> +    }
>>>>> +    json = "( testingObject = " + json + " )";
>>>>> +
>>>>> +    Object so = null;
>>>>> +    try {
>>>>> +      so = ctx.evaluateString(scope, json, "test json", 0, null);
>>>>> +    } catch (EvaluatorException ex) {
>>>>> +      log.error("Non parseable JSON " + json);
>>>>> +    }
>>>>> +    log.debug("Loaded " + so);
>>>>> +
>>>>> +    return validateOject(so, object, optionalFields, nullfields);
>>>>> +
>>>>> +  }
>>>>> +
>>>>> +  /**
>>>>> +   * Validate an JSON Object extracted
>>>>> +   *
>>>>> +   * @param object
>>>>> +   * @param string
>>>>> +   * @param optional
>>>>> +   * @return
>>>>> +   * @throws APIValidatorExpcetion
>>>>> +   */
>>>>> +  public Map<String, Object> validateOject(Object jsonObject,  
>>>>> String
>>>>> object,
>>>>> +      String[] optionalFields, String[] nullFields)
>>>>> +      throws APIValidatorExpcetion {
>>>>> +    Map<String, String> optional = new HashMap<String, String>();
>>>>> +    for (String opt : optionalFields) {
>>>>> +      optional.put(opt, opt);
>>>>> +    }
>>>>> +    Map<String, String> nullf = new HashMap<String, String>();
>>>>> +    for (String nf : nullFields) {
>>>>> +      nullf.put(nf, nf);
>>>>> +    }
>>>>> +
>>>>> +    ScriptableObject specification = getScriptableObject(object);
>>>>> +    log.debug("Looking for  " + object + " found " +  
>>>>> specification);
>>>>> +    listScriptable(object, specification);
>>>>> +
>>>>> +    Map<String, Object> resultFields = new HashMap<String,  
>>>>> Object>();
>>>>> +
>>>>> +    if (jsonObject instanceof ScriptableObject) {
>>>>> +      ScriptableObject parsedJSONObject = (ScriptableObject)  
>>>>> jsonObject;
>>>>> +      listScriptable("testingObject", parsedJSONObject);
>>>>> +      Object[] fields = specification.getIds();
>>>>> +      for (Object f : fields) {
>>>>> +        Object fieldName = specification.get(String.valueOf(f),
>>>>> specification);
>>>>> +        Object o =  
>>>>> parsedJSONObject.get(String.valueOf(fieldName),
>>>>> +            parsedJSONObject);
>>>>> +        if (o == ScriptableObject.NOT_FOUND) {
>>>>> +          if (optional.containsKey(fieldName)) {
>>>>> +            log.warn("Missing Optional Field " + fieldName);
>>>>> +          } else if (!nullf.containsKey(fieldName)) {
>>>>> +            log.error("Missing Field " + fieldName);
>>>>> +            throw new APIValidatorExpcetion("Missing Field " +  
>>>>> fieldName);
>>>>> +          }
>>>>> +        } else {
>>>>> +          if (nullf.containsKey(fieldName)) {
>>>>> +            log.error("Field should have been null and was not");
>>>>> +          }
>>>>> +          if (o == null) {
>>>>> +            if (nullf.containsKey(fieldName)) {
>>>>> +              log.error("Null Fields has been serialized " +  
>>>>> fieldName);
>>>>> +            }
>>>>> +            log.debug("Got a Null object for Field " + f + ":"  
>>>>> + fieldName
>>>>> +                + " on json [[" + jsonObject + "]]");
>>>>> +
>>>>> +          } else {
>>>>> +
>>>>> +            log.debug("Got JSON Field  Field," + f + ":" +  
>>>>> fieldName + "
>>>>> as "
>>>>> +                + o + " " + o.getClass());
>>>>> +          }
>>>>> +          resultFields.put(String.valueOf(fieldName), o);
>>>>> +        }
>>>>> +      }
>>>>> +
>>>>> +    } else {
>>>>> +      throw new APIValidatorExpcetion(
>>>>> +          "Parsing JSON resulted in invalid Javascript object,  
>>>>> which was "
>>>>> +              + jsonObject + " JSON was [[" + jsonObject + "]]");
>>>>> +    }
>>>>> +    return resultFields;
>>>>> +  }
>>>>> +
>>>>> +  /**
>>>>> +   * get an object from the json context and scope.
>>>>> +   *
>>>>> +   * @param object
>>>>> +   *                the name of the object specified as a path  
>>>>> from the
>>>>> base
>>>>> +   *                object
>>>>> +   * @return the json object
>>>>> +   */
>>>>> +  private ScriptableObject getScriptableObject(String object) {
>>>>> +    String[] path = object.split("\\.");
>>>>> +    log.debug("Looking up " + object + " elements " +  
>>>>> path.length);
>>>>> +
>>>>> +    ScriptableObject s = scope;
>>>>> +    for (String pe : path) {
>>>>> +      log.debug("Looking up " + pe + " in " + s);
>>>>> +      s = (ScriptableObject) s.get(pe, s);
>>>>> +      log.debug("Looking for " + pe + " in found " + s);
>>>>> +    }
>>>>> +    return s;
>>>>> +  }
>>>>> +
>>>>> +  /**
>>>>> +   * List a scriptable object at log debug level, constructors  
>>>>> will not be
>>>>> +   * expanded as this loads to recursion.
>>>>> +   *
>>>>> +   * @param id
>>>>> +   *                The name of the object
>>>>> +   * @param scriptableObject
>>>>> +   *                the scriptable Object
>>>>> +   */
>>>>> +  private void listScriptable(String id, ScriptableObject
>>>>> scriptableObject) {
>>>>> +    log.debug("ID is Scriptable " + id);
>>>>> +    if (!id.endsWith("constructor")) {
>>>>> +      Object[] allIDs = scriptableObject.getAllIds();
>>>>> +      for (Object oid : allIDs) {
>>>>> +        log.debug(id + "." + oid);
>>>>> +        Object o = scriptableObject.get(String.valueOf(oid),
>>>>> scriptableObject);
>>>>> +        if (o instanceof ScriptableObject) {
>>>>> +          listScriptable(id + "." + String.valueOf(oid),
>>>>> (ScriptableObject) o);
>>>>> +        }
>>>>> +      }
>>>>> +    }
>>>>> +  }
>>>>> +
>>>>> +  /**
>>>>> +   * Load a feature based on the spec
>>>>> +   *
>>>>> +   * @param spec
>>>>> +   *                The name of the location of the spec in the  
>>>>> classpath,
>>>>> must
>>>>> +   *                not start with a '/' and must should  
>>>>> contain a
>>>>> feature.xml
>>>>> +   *                file in the location
>>>>> +   * @throws IOException
>>>>> +   *                 If any of the resources cant be found
>>>>> +   * @throws ParserConfigurationException
>>>>> +   *                 If the parser has a problem being  
>>>>> constructed
>>>>> +   * @throws SAXException
>>>>> +   *                 on a parse error on the features.xml
>>>>> +   */
>>>>> +  private void load(String spec) throws IOException,  
>>>>> SAXException,
>>>>> +      ParserConfigurationException {
>>>>> +
>>>>> +    List<String> scripts = getScripts(spec);
>>>>> +
>>>>> +    List<Script> compiled = new ArrayList<Script>();
>>>>> +    for (String script : scripts) {
>>>>> +      String scriptPath = spec + "/" + script;
>>>>> +      InputStream in =
>>>>> this.getClass().getClassLoader().getResourceAsStream(
>>>>> +          scriptPath);
>>>>> +      if (in == null) {
>>>>> +        in =  
>>>>> this.getClass().getClassLoader().getResourceAsStream(
>>>>> +            "features/" + scriptPath);
>>>>> +        if (in == null) {
>>>>> +          throw new IOException("Cant load spec " + spec + " or
>>>>> features/"+spec+" from classpath");
>>>>> +        }
>>>>> +      }
>>>>> +      InputStreamReader reader = new InputStreamReader(in);
>>>>> +      Script compiledScript = ctx.compileReader(reader, spec,  
>>>>> 0, null);
>>>>> +      compiled.add(compiledScript);
>>>>> +    }
>>>>> +
>>>>> +    for (Script compiledScript : compiled) {
>>>>> +      compiledScript.exec(ctx, scope);
>>>>> +    }
>>>>> +
>>>>> +  }
>>>>> +
>>>>> +  /**
>>>>> +   * Add some javascript to the context, and execute it. If  
>>>>> extra custom
>>>>> +   * javascript is wanted in the context or scope then this  
>>>>> method will
>>>>> load it.
>>>>> +   *
>>>>> +   * @param javascript
>>>>> +   */
>>>>> +  public void addScript(String javascript) {
>>>>> +    Script compileScript = ctx.compileString(javascript,  
>>>>> "AdditionalJS",
>>>>> 0,
>>>>> +        null);
>>>>> +    compileScript.exec(ctx, scope);
>>>>> +  }
>>>>> +
>>>>> +  /**
>>>>> +   * Get an ordered list of javascript resources from a feature  
>>>>> sets.
>>>>> +   *
>>>>> +   * @param spec
>>>>> +   *                The spec location
>>>>> +   * @return An ordered list of javascript resources, these are  
>>>>> relative
>>>>> to
>>>>> +   *         specification file.
>>>>> +   * @throws IOException
>>>>> +   *                 If any of the resources can't be loaded.
>>>>> +   * @throws SAXException
>>>>> +   *                 Where the feature.xml file is not parsable
>>>>> +   * @throws ParserConfigurationException
>>>>> +   *                 where the parser can't be constructed.
>>>>> +   * @return An ordered list of script that need to be loaded  
>>>>> and executed
>>>>> to
>>>>> +   *         make the feature available in the context.
>>>>> +   */
>>>>> +  private List<String> getScripts(String spec) throws  
>>>>> SAXException,
>>>>> +      IOException, ParserConfigurationException {
>>>>> +    String features = spec + "/feature.xml";
>>>>> +    InputStream in =  
>>>>> this.getClass().getClassLoader().getResourceAsStream(
>>>>> +        features);
>>>>> +    if (in == null) {
>>>>> +      in = this.getClass().getClassLoader().getResourceAsStream(
>>>>> +          "features/"+features);
>>>>> +      if (in == null) {
>>>>> +        throw new IOException("Cant find " + features + " or  
>>>>> features/" +
>>>>> features+ " in classpath ");
>>>>> +      }
>>>>> +    }
>>>>> +    DocumentBuilderFactory builderFactory =  
>>>>> DocumentBuilderFactory
>>>>> +        .newInstance();
>>>>> +    DocumentBuilder documentBuilder =  
>>>>> builderFactory.newDocumentBuilder();
>>>>> +    Document doc = documentBuilder.parse(in);
>>>>> +    NodeList nl = doc.getElementsByTagName("script");
>>>>> +    List<String> scripts = new ArrayList<String>();
>>>>> +    for (int i = 0; i < nl.getLength(); i++) {
>>>>> +      Node scriptNode = nl.item(i);
>>>>> +      NamedNodeMap attributes = scriptNode.getAttributes();
>>>>> +      Node scriptAttr = attributes.getNamedItem("src");
>>>>> +      String script = scriptAttr.getNodeValue();
>>>>> +      scripts.add(script);
>>>>> +    }
>>>>> +    return scripts;
>>>>> +  }
>>>>> +
>>>>> +  /**
>>>>> +   * @param nameJSON
>>>>> +   */
>>>>> +  public static void dump(Map<?, ?> nameJSON) {
>>>>> +    if (log.isDebugEnabled()) {
>>>>> +      for (Object k : nameJSON.keySet()) {
>>>>> +        Object o = nameJSON.get(k);
>>>>> +        log.info("Key [" + k + "] value:["
>>>>> +            + (o == null ? o : o + ":" + o.getClass()) + "]");
>>>>> +      }
>>>>> +    }
>>>>> +  }
>>>>> +
>>>>> +}
>>>>>
>>>>> Added:
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>>>>> URL:
>>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorExpcetion.java?rev=678158&view=auto
>>>>>
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> ==================================================================
>>>>> ---
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>>>>> (added)
>>>>> +++
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>>>>> Sat Jul 19 06:51:03 2008
>>>>> @@ -0,0 +1,42 @@
>>>>> +/*
>>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>>> + * or more contributor license agreements. See the NOTICE file
>>>>> + * distributed with this work for additional information
>>>>> + * regarding copyright ownership. The ASF licenses this file
>>>>> + * to you under the Apache License, Version 2.0 (the
>>>>> + * "License"); you may not use this file except in compliance
>>>>> + * with the License. You may obtain a copy of the License at
>>>>> + *
>>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>>> + *
>>>>> + * 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.apache.shindig.social.opensocial.util;
>>>>> +
>>>>> +/**
>>>>> + * Thrown when there is a validation exception on one of the apis
>>>>> + */
>>>>> +public class APIValidatorExpcetion extends Exception {
>>>>> +
>>>>> +  private static final long serialVersionUID =  
>>>>> -8969858718669454612L;
>>>>> +
>>>>> +  public APIValidatorExpcetion() {
>>>>> +  }
>>>>> +
>>>>> +  public APIValidatorExpcetion(String message) {
>>>>> +    super(message);
>>>>> +  }
>>>>> +
>>>>> +  public APIValidatorExpcetion(Throwable cause) {
>>>>> +    super(cause);
>>>>> +  }
>>>>> +
>>>>> +  public APIValidatorExpcetion(String message, Throwable cause) {
>>>>> +    super(message, cause);
>>>>> +  }
>>>>> +
>>>>> +}
>>>>>
>>>>> Added:
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/APIValidatorTest.java
>>>>> URL:
>>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorTest.java?rev=678158&view=auto
>>>>>
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> ==================================================================
>>>>> ---
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/APIValidatorTest.java
>>>>> (added)
>>>>> +++
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/APIValidatorTest.java
>>>>> Sat Jul 19 06:51:03 2008
>>>>> @@ -0,0 +1,89 @@
>>>>> +/*
>>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>>> + * or more contributor license agreements. See the NOTICE file
>>>>> + * distributed with this work for additional information
>>>>> + * regarding copyright ownership. The ASF licenses this file
>>>>> + * to you under the Apache License, Version 2.0 (the
>>>>> + * "License"); you may not use this file except in compliance
>>>>> + * with the License. You may obtain a copy of the License at
>>>>> + *
>>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>>> + *
>>>>> + * 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.apache.shindig.social.opensocial.util;
>>>>> +
>>>>> +
>>>>> +import java.io.IOException;
>>>>> +import java.util.Map;
>>>>> +
>>>>> +import javax.xml.parsers.ParserConfigurationException;
>>>>> +
>>>>> +import org.junit.Assert;
>>>>> +import org.junit.Test;
>>>>> +import org.xml.sax.SAXException;
>>>>> +
>>>>> +/**
>>>>> + * Test the api validator to make certain it behaves as is  
>>>>> expected.
>>>>> + */
>>>>> +public class APIValidatorTest {
>>>>> +
>>>>> +  /**
>>>>> +   * A definition of the test json used in this unit test.
>>>>> +   */
>>>>> +  private static final String TEST_DEFINITION =
>>>>> +    "var TestDef = {}; TestDef.Field = { FIELD1 : \"json\",  
>>>>> FIELD2 :
>>>>> \"xyz\", FIELD3 : \"shouldBeMissing\" };";
>>>>> +
>>>>> +  /**
>>>>> +   * test the validator for successful validation
>>>>> +   * @throws APIValidatorExpcetion
>>>>> +   * @throws IOException
>>>>> +   * @throws ParserConfigurationException
>>>>> +   * @throws SAXException
>>>>> +   */
>>>>> +  @Test
>>>>> +  public void testValidator() throws APIValidatorExpcetion,  
>>>>> IOException,
>>>>> ParserConfigurationException, SAXException {
>>>>> +    APIValidator apiVal = new APIValidator("opensocial- 
>>>>> reference");
>>>>> +    apiVal.addScript(TEST_DEFINITION);
>>>>> +    String[] optional = {"shouldBeMissing"};
>>>>> +    String[] nullfields = {};
>>>>> +     Map<String, Object> result = apiVal.validate("{ json: \"A  
>>>>> Test
>>>>> JSON\", xyz : 123 }", "TestDef.Field", optional, nullfields );
>>>>> +     Assert.assertNotNull(result);
>>>>> +     Assert.assertNotNull(result.get("json"));
>>>>> +     Assert.assertNotNull(result.get("xyz"));
>>>>> +      
>>>>> Assert.assertEquals(String.class,result.get("json").getClass());
>>>>> +      
>>>>> Assert.assertEquals(Integer.class,result.get("xyz").getClass());
>>>>> +     Assert.assertEquals("A Test JSON",result.get("json"));
>>>>> +     Assert.assertEquals(123, 
>>>>> ((Integer)result.get("xyz")).intValue());
>>>>> +
>>>>> +
>>>>> +  }
>>>>> +
>>>>> +  /**
>>>>> +   * Test for a failing validation
>>>>> +   * @throws APIValidatorExpcetion
>>>>> +   * @throws IOException
>>>>> +   * @throws ParserConfigurationException
>>>>> +   * @throws SAXException
>>>>> +   */
>>>>> +  @Test
>>>>> +  public void testValidatorFail() throws APIValidatorExpcetion,
>>>>> IOException, ParserConfigurationException, SAXException {
>>>>> +    APIValidator apiVal = new APIValidator("opensocial- 
>>>>> reference");
>>>>> +    apiVal.addScript(TEST_DEFINITION);
>>>>> +    String[] optional = {};
>>>>> +    String[] nullfields = {};
>>>>> +    try {
>>>>> +      apiVal.validate("{ jsonIsMissing: \"A Test JSON\", xyz :  
>>>>> 123 }",
>>>>> "TestDef.Field", optional, nullfields );
>>>>> +      Assert.fail("Should have Generated an  
>>>>> APIValidatorException ");
>>>>> +    } catch ( APIValidatorExpcetion ex ) {
>>>>> +
>>>>> +    }
>>>>> +
>>>>> +
>>>>> +  }
>>>>> +
>>>>> +}
>>>>>
>>>>> Added:
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>>>> URL:
>>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverterTest.java?rev=678158&view=auto
>>>>>
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> ==================================================================
>>>>> ---
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>>>> (added)
>>>>> +++
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>>>> Sat Jul 19 06:51:03 2008
>>>>> @@ -0,0 +1,359 @@
>>>>> +/*
>>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>>> + * or more contributor license agreements. See the NOTICE file
>>>>> + * distributed with this work for additional information
>>>>> + * regarding copyright ownership. The ASF licenses this file
>>>>> + * to you under the Apache License, Version 2.0 (the
>>>>> + * "License"); you may not use this file except in compliance
>>>>> + * with the License. You may obtain a copy of the License at
>>>>> + *
>>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>>> + *
>>>>> + * 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.apache.shindig.social.opensocial.util;
>>>>> +
>>>>> +import java.util.ArrayList;
>>>>> +import java.util.List;
>>>>> +import java.util.Map;
>>>>> +
>>>>> +import junit.framework.TestCase;
>>>>> +
>>>>> +import org.apache.commons.logging.Log;
>>>>> +import org.apache.commons.logging.LogFactory;
>>>>> +import org.apache.shindig.social.JsonLibTestsGuiceModule;
>>>>> +import org.apache.shindig.social.opensocial.model.Activity;
>>>>> +import org.apache.shindig.social.opensocial.model.ActivityImpl;
>>>>> +import org.apache.shindig.social.opensocial.model.Address;
>>>>> +import org.apache.shindig.social.opensocial.model.AddressImpl;
>>>>> +import org.apache.shindig.social.opensocial.model.Email;
>>>>> +import org.apache.shindig.social.opensocial.model.EmailImpl;
>>>>> +import org.apache.shindig.social.opensocial.model.MediaItem;
>>>>> +import org.apache.shindig.social.opensocial.model.MediaItemImpl;
>>>>> +import org.apache.shindig.social.opensocial.model.Name;
>>>>> +import org.apache.shindig.social.opensocial.model.NameImpl;
>>>>> +import org.apache.shindig.social.opensocial.model.Person;
>>>>> +import org.apache.shindig.social.opensocial.model.PersonImpl;
>>>>> +import org.apache.shindig.social.opensocial.model.Phone;
>>>>> +import org.apache.shindig.social.opensocial.model.PhoneImpl;
>>>>> +
>>>>> +import com.google.common.collect.Lists;
>>>>> +import com.google.common.collect.Maps;
>>>>> +import com.google.inject.Guice;
>>>>> +
>>>>> +public class BeanJsonLibConverterTest extends TestCase {
>>>>> +
>>>>> +  private static final Log log = LogFactory
>>>>> +      .getLog(BeanJsonLibConverterTest.class);
>>>>> +  private Person johnDoe;
>>>>> +  private Activity activity;
>>>>> +
>>>>> +  private BeanJsonLibConverter beanJsonConverter;
>>>>> +  private APIValidator apiValidator;
>>>>> +  // set to true to get loging output at info level
>>>>> +  private boolean outputInfo = false;
>>>>> +
>>>>> +  @Override
>>>>> +  public void setUp() throws Exception {
>>>>> +    super.setUp();
>>>>> +    johnDoe = new PersonImpl("johnDoeId", new NameImpl("John  
>>>>> Doe"));
>>>>> +    johnDoe.setPhoneNumbers(Lists.<Phone> newArrayList(new  
>>>>> PhoneImpl(
>>>>> +        "+33H000000000", "home"), new PhoneImpl("+33M000000000",
>>>>> "mobile"),
>>>>> +        new PhoneImpl("+33W000000000", "work")));
>>>>> +
>>>>> +    johnDoe.setAddresses(Lists.<Address> newArrayList(new  
>>>>> AddressImpl(
>>>>> +        "My home address")));
>>>>> +
>>>>> +    johnDoe.setEmails(Lists.<Email> newArrayList(new EmailImpl(
>>>>> +        "john.doe@work.bar", "work"),
>>>>> +        new EmailImpl("john.doe@home.bar", "home")));
>>>>> +
>>>>> +    activity = new ActivityImpl("activityId", johnDoe.getId());
>>>>> +
>>>>> +    activity.setMediaItems(Lists.<MediaItem> newArrayList(new
>>>>> MediaItemImpl(
>>>>> +        "image/jpg", MediaItem.Type.IMAGE, "http://foo.bar")));
>>>>> +
>>>>> +    beanJsonConverter = new BeanJsonLibConverter(Guice
>>>>> +        .createInjector(new JsonLibTestsGuiceModule()));
>>>>> +
>>>>> +    apiValidator = new APIValidator("opensocial-reference");
>>>>> +
>>>>> +  }
>>>>> +
>>>>> +  public static class SpecialPerson extends PersonImpl {
>>>>> +    public static final String[] OPTIONALFIELDS = {};
>>>>> +    public static final String[] NULLFIELDS  =
>>>>> {"jobInterests","nickname","romance","religion","timeZone",
>>>>> +
>>>>> "relationshipStatus 
>>>>> ","tags 
>>>>> ","networkPresence 
>>>>> ","books","quotes","phoneNumbers","languagesSpoken",
>>>>> +
>>>>> "activities 
>>>>> ","jobs 
>>>>> ","dateOfBirth 
>>>>> ","profileVideo","bodyType","urls","schools","music","addresses",
>>>>> +
>>>>> "livingArrangement 
>>>>> ","thumbnailUrl 
>>>>> ","humor 
>>>>> ","sports","scaredOf","movies","age","pets","hasApp","turnOffs",
>>>>> +
>>>>> "gender 
>>>>> ","fashion 
>>>>> ","drinker 
>>>>> ","aboutMe 
>>>>> ","children 
>>>>> ","sexualOrientation","heroes","profileSong","lookingFor",
>>>>> +
>>>>> "cars 
>>>>> ","turnOns 
>>>>> ","tvShows 
>>>>> ","profileUrl 
>>>>> ","status","currentLocation","smoker","happiestWhen","ethnicity",
>>>>> +
>>>>> "food 
>>>>> ","emails 
>>>>> ","politicalViews 
>>>>> ","interests 
>>>>> ","familyName 
>>>>> ","honorificSuffix 
>>>>> ","additionalName","honorificPrefix","givenName"};
>>>>> +
>>>>> +    private String newfield;
>>>>> +
>>>>> +    public SpecialPerson() {
>>>>> +      super();
>>>>> +    }
>>>>> +
>>>>> +    public SpecialPerson(String id, String name, String  
>>>>> newfield) {
>>>>> +      super(id, new NameImpl(name));
>>>>> +      this.newfield = newfield;
>>>>> +    }
>>>>> +
>>>>> +    public String getNewfield() {
>>>>> +      return newfield;
>>>>> +    }
>>>>> +
>>>>> +    public void setNewfield(String newfield) {
>>>>> +      this.newfield = newfield;
>>>>> +    }
>>>>> +
>>>>> +  }
>>>>> +
>>>>> +  public void testToJsonOnInheritedClass() throws Exception {
>>>>> +    SpecialPerson cassie = new SpecialPerson("5", "robot",  
>>>>> "nonsense");
>>>>> +
>>>>> +    String result = beanJsonConverter.convertToString(cassie);
>>>>> +
>>>>> +    validatePerson(result, "5", "robot",  
>>>>> SpecialPerson.OPTIONALFIELDS,
>>>>> SpecialPerson.NULLFIELDS);
>>>>> +
>>>>> +    apiValidator.addScript(" specialPerson = { SPECIAL :  
>>>>> \"newfield\" };
>>>>> ");
>>>>> +    String[] optional = {};
>>>>> +    String[] nullfields = {};
>>>>> +    Map<String, Object> special = apiValidator.validate(result,
>>>>> +        "specialPerson", optional,nullfields);
>>>>> +    assertNotNull(special.get("newfield"));
>>>>> +    assertEquals(String.class,  
>>>>> special.get("newfield").getClass());
>>>>> +    assertEquals("nonsense", special.get("newfield"));
>>>>> +
>>>>> +    // convert back into an object Tree
>>>>> +
>>>>> +    SpecialPerson parseCassie =  
>>>>> beanJsonConverter.convertToObject(result,
>>>>> +        SpecialPerson.class);
>>>>> +
>>>>> +    assertNotNull(parseCassie);
>>>>> +    assertEquals(cassie.getId(), parseCassie.getId());
>>>>> +    assertEquals(cassie.getNewfield(),  
>>>>> parseCassie.getNewfield());
>>>>> +
>>>>> +    Name name = parseCassie.getName();
>>>>> +    Name cassieName = cassie.getName();
>>>>> +    assertNotNull(name);
>>>>> +    assertEquals(cassieName.getUnstructured(),  
>>>>> name.getUnstructured());
>>>>> +    assertEquals(cassieName.getAdditionalName(),
>>>>> name.getAdditionalName());
>>>>> +    assertEquals(cassieName.getFamilyName(),  
>>>>> name.getFamilyName());
>>>>> +    assertEquals(cassieName.getGivenName(), name.getGivenName());
>>>>> +    assertEquals(cassieName.getHonorificPrefix(),
>>>>> name.getHonorificPrefix());
>>>>> +    assertEquals(cassieName.getHonorificSuffix(),
>>>>> name.getHonorificSuffix());
>>>>> +
>>>>> +  }
>>>>> +
>>>>> +  /**
>>>>> +   * @param result
>>>>> +   * @throws APIValidatorExpcetion
>>>>> +   */
>>>>> +  private void validatePerson(String result, String id, String  
>>>>> name,
>>>>> String[] optional, String[] nullfields)
>>>>> +      throws APIValidatorExpcetion {
>>>>> +
>>>>> +    Map<String, Object> standard = apiValidator.validate(result,
>>>>> +        "opensocial.Person.Field", optional,nullfields);
>>>>> +    assertNotNull(standard.get("id"));
>>>>> +    assertEquals(String.class, standard.get("id").getClass());
>>>>> +    assertEquals(id, standard.get("id"));
>>>>> +
>>>>> +    assertNotNull(standard.get("name"));
>>>>> +    Map<String, Object> nameJSON =  
>>>>> apiValidator.validateOject(standard
>>>>> +        .get("name"), "opensocial.Name.Field",  
>>>>> optional,nullfields);
>>>>> +    APIValidator.dump(nameJSON);
>>>>> +
>>>>> +    assertNotNull(nameJSON.get("unstructured"));
>>>>> +    assertEquals(String.class,  
>>>>> nameJSON.get("unstructured").getClass());
>>>>> +    assertEquals(name, nameJSON.get("unstructured"));
>>>>> +
>>>>> +    // additional name
>>>>> +    assertNull(nameJSON.get("additionalName"));
>>>>> +
>>>>> +  }
>>>>> +
>>>>> +  public void testPersonToJson() throws Exception {
>>>>> +    String result = beanJsonConverter.convertToString(johnDoe);
>>>>> +    if (outputInfo) {
>>>>> +      log.info("JSON (" + result + ")");
>>>>> +    }
>>>>> +    Person parsedPerson =  
>>>>> beanJsonConverter.convertToObject(result,
>>>>> +        Person.class);
>>>>> +
>>>>> +    assertEquals(johnDoe.getId(), parsedPerson.getId());
>>>>> +    assertEquals(johnDoe.getName().getUnstructured(),
>>>>> parsedPerson.getName()
>>>>> +        .getUnstructured());
>>>>> +
>>>>> +    List<Address> addresses = parsedPerson.getAddresses();
>>>>> +    if (outputInfo) {
>>>>> +      for (Object o : addresses) {
>>>>> +        log.info("Address " + o);
>>>>> +      }
>>>>> +    }
>>>>> +
>>>>> +    assertEquals(1, addresses.size());
>>>>> +    Address address = addresses.get(0);
>>>>> +    String unstructured = address.getUnstructuredAddress();
>>>>> +
>>>>> +    assertNotNull(unstructured);
>>>>> +     
>>>>> assertEquals 
>>>>> (johnDoe.getAddresses().get(0).getUnstructuredAddress(),
>>>>> +         
>>>>> parsedPerson.getAddresses().get(0).getUnstructuredAddress());
>>>>> +
>>>>> +    assertEquals(3, parsedPerson.getPhoneNumbers().size());
>>>>> +
>>>>> +    for (int i = 0; i < johnDoe.getPhoneNumbers().size(); i++) {
>>>>> +      Phone expectedPhone = johnDoe.getPhoneNumbers().get(i);
>>>>> +      Phone actualPhone = parsedPerson.getPhoneNumbers().get(i);
>>>>> +      assertEquals(expectedPhone.getType(),  
>>>>> actualPhone.getType());
>>>>> +      assertEquals(expectedPhone.getNumber(),  
>>>>> actualPhone.getNumber());
>>>>> +    }
>>>>> +
>>>>> +    assertEquals(2, parsedPerson.getEmails().size());
>>>>> +
>>>>> +    for (int i = 0; i < johnDoe.getEmails().size(); i++) {
>>>>> +      Email expectedEmail = johnDoe.getEmails().get(i);
>>>>> +      Email actualEmail = parsedPerson.getEmails().get(i);
>>>>> +      assertEquals(expectedEmail.getType(),  
>>>>> actualEmail.getType());
>>>>> +      assertEquals(expectedEmail.getAddress(),  
>>>>> actualEmail.getAddress());
>>>>> +    }
>>>>> +  }
>>>>> +
>>>>> +  public void testActivityToJson() throws Exception {
>>>>> +
>>>>> +    String result = beanJsonConverter.convertToString(activity);
>>>>> +    if (outputInfo) {
>>>>> +      log.info("JSON (" + result + ")");
>>>>> +    }
>>>>> +    Activity parsedActivity =  
>>>>> beanJsonConverter.convertToObject(result,
>>>>> +        Activity.class);
>>>>> +    assertEquals(activity.getUserId(),  
>>>>> parsedActivity.getUserId());
>>>>> +    assertEquals(activity.getId(), parsedActivity.getId());
>>>>> +
>>>>> +    assertEquals(1, parsedActivity.getMediaItems().size());
>>>>> +
>>>>> +    MediaItem expectedItem = activity.getMediaItems().get(0);
>>>>> +    MediaItem actualItem = parsedActivity.getMediaItems().get(0);
>>>>> +
>>>>> +    assertEquals(expectedItem.getUrl(), actualItem.getUrl());
>>>>> +    assertEquals(expectedItem.getMimeType(),  
>>>>> actualItem.getMimeType());
>>>>> +    assertEquals(expectedItem.getType().toString(),  
>>>>> actualItem.getType()
>>>>> +        .toString());
>>>>> +  }
>>>>> +
>>>>> +  public void testMapsToJson() throws Exception {
>>>>> +    Map<String, Map<String, String>> map = Maps.newHashMap();
>>>>> +
>>>>> +    Map<String, String> item1Map = Maps.newHashMap();
>>>>> +    item1Map.put("value", "1");
>>>>> +
>>>>> +    // Null values shouldn't cause exceptions
>>>>> +    item1Map.put("value2", null);
>>>>> +    map.put("item1", item1Map);
>>>>> +
>>>>> +    Map<String, String> item2Map = Maps.newHashMap();
>>>>> +    item2Map.put("value", "2");
>>>>> +    map.put("item2", item2Map);
>>>>> +
>>>>> +    String result = beanJsonConverter.convertToString(map);
>>>>> +    if (outputInfo) {
>>>>> +      log.info("JSON (" + result + ")");
>>>>> +    }
>>>>> +    // there is introspection that can tell jsonobject -> bean  
>>>>> converter
>>>>> what a
>>>>> +    // map should contain, so we have to tell it
>>>>> +    beanJsonConverter.addMapping("item1", Map.class);
>>>>> +    beanJsonConverter.addMapping("item2", Map.class);
>>>>> +    Map<?, ?> parsedMap = beanJsonConverter
>>>>> +        .convertToObject(result, Map.class);
>>>>> +
>>>>> +    if (outputInfo) {
>>>>> +      log.info("Dumping Map (" + parsedMap + ")");
>>>>> +    }
>>>>> +    APIValidator.dump(parsedMap);
>>>>> +
>>>>> +    assertEquals("1", ((Map<?,? 
>>>>> >)parsedMap.get("item1")).get("value"));
>>>>> +    assertEquals("2", ((Map<?,? 
>>>>> >)parsedMap.get("item2")).get("value"));
>>>>> +  }
>>>>> +
>>>>> +  public void testListsToJson() throws Exception {
>>>>> +    Map<String, String> item1Map = Maps.newHashMap();
>>>>> +    item1Map.put("value", "1");
>>>>> +
>>>>> +    Map<String, String> item2Map = Maps.newHashMap();
>>>>> +    item2Map.put("value", "2");
>>>>> +
>>>>> +    // put the list into a container before serializing, top  
>>>>> level lists
>>>>> dont
>>>>> +    // appear
>>>>> +    // to be allowed in json
>>>>> +    // just check that the list is in the holder correctly
>>>>> +    List<Map<String, String>> list = new ArrayList<Map<String,  
>>>>> String>>();
>>>>> +    list.add(item1Map);
>>>>> +    list.add(item2Map);
>>>>> +    String result = beanJsonConverter.convertToString(list);
>>>>> +    if (outputInfo) {
>>>>> +      log.info("JSON (" + result + ")");
>>>>> +    }
>>>>> +    Map<?, ?>[] parsedList = beanJsonConverter.convertToObject(
>>>>> +        result, Map[].class);
>>>>> +
>>>>> +    assertEquals("1", parsedList[0].get("value"));
>>>>> +    assertEquals("2", parsedList[1].get("value"));
>>>>> +  }
>>>>> +
>>>>> +  public void testArrayToJson() throws Exception {
>>>>> +    String[] colors = { "blue", "green", "aquamarine" };
>>>>> +    String result = beanJsonConverter.convertToString(colors);
>>>>> +    if (outputInfo) {
>>>>> +      log.info("JSON (" + result + ")");
>>>>> +    }
>>>>> +    String[] parsedColors =  
>>>>> beanJsonConverter.convertToObject(result,
>>>>> +        String[].class);
>>>>> +    assertEquals(colors.length, parsedColors.length);
>>>>> +    assertEquals(colors[0], parsedColors[0]);
>>>>> +    assertEquals(colors[1], parsedColors[1]);
>>>>> +    assertEquals(colors[2], parsedColors[2]);
>>>>> +  }
>>>>> +
>>>>> +  public void testJsonToActivity() throws Exception {
>>>>> +    String jsonActivity = "{userId : 5, id : 6, mediaItems : ["
>>>>> +        + "{url : 'hello', mimeType : 'mimey', type : 'VIDEO'}"  
>>>>> + "]}";
>>>>> +    Activity result =  
>>>>> beanJsonConverter.convertToObject(jsonActivity,
>>>>> +        Activity.class);
>>>>> +
>>>>> +    assertEquals("5", result.getUserId());
>>>>> +    assertEquals("6", result.getId());
>>>>> +
>>>>> +    assertEquals(1, result.getMediaItems().size());
>>>>> +
>>>>> +    MediaItem actualItem = result.getMediaItems().get(0);
>>>>> +
>>>>> +    assertEquals("hello", actualItem.getUrl());
>>>>> +    assertEquals("mimey", actualItem.getMimeType());
>>>>> +    assertEquals("video", actualItem.getType().toString());
>>>>> +  }
>>>>> +
>>>>> +  public void testJsonToMap() throws Exception {
>>>>> +    String jsonActivity = "{count : 0, favoriteColor :  
>>>>> 'yellow'}";
>>>>> +    Map<String, String> data = Maps.newHashMap();
>>>>> +    data = beanJsonConverter.convertToObject(jsonActivity,
>>>>> +        (Class<Map<String, String>>) data.getClass());
>>>>> +
>>>>> +    assertEquals(2, data.size());
>>>>> +
>>>>> +    for (String key : data.keySet()) {
>>>>> +      Object value = data.get(key);
>>>>> +      if (key.equals("count")) {
>>>>> +        assertEquals(0, value);
>>>>> +      } else if (key.equals("favoriteColor")) {
>>>>> +        assertEquals("yellow", value);
>>>>> +      }
>>>>> +    }
>>>>> +  }
>>>>> +
>>>>> +}
>>>>>
>>>>> Added:
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>>>> URL:
>>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/JsonConverterPerformancePerf.java?rev=678158&view=auto
>>>>>
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> ==================================================================
>>>>> ---
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>>>> (added)
>>>>> +++
>>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>>>> Sat Jul 19 06:51:03 2008
>>>>> @@ -0,0 +1,271 @@
>>>>> +/*
>>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>>> + * or more contributor license agreements. See the NOTICE file
>>>>> + * distributed with this work for additional information
>>>>> + * regarding copyright ownership. The ASF licenses this file
>>>>> + * to you under the Apache License, Version 2.0 (the
>>>>> + * "License"); you may not use this file except in compliance
>>>>> + * with the License. You may obtain a copy of the License at
>>>>> + *
>>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>>> + *
>>>>> + * 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.apache.shindig.social.opensocial.util;
>>>>> +
>>>>> +import junit.framework.TestCase;
>>>>> +
>>>>> +import org.apache.commons.logging.Log;
>>>>> +import org.apache.commons.logging.LogFactory;
>>>>> +import org.apache.shindig.social.JsonLibTestsGuiceModule;
>>>>> +import org.apache.shindig.social.SocialApiTestsGuiceModule;
>>>>> +import org.apache.shindig.social.opensocial.model.Activity;
>>>>> +import org.apache.shindig.social.opensocial.model.ActivityImpl;
>>>>> +import org.apache.shindig.social.opensocial.model.Address;
>>>>> +import org.apache.shindig.social.opensocial.model.AddressImpl;
>>>>> +import org.apache.shindig.social.opensocial.model.Email;
>>>>> +import org.apache.shindig.social.opensocial.model.EmailImpl;
>>>>> +import org.apache.shindig.social.opensocial.model.MediaItem;
>>>>> +import org.apache.shindig.social.opensocial.model.MediaItemImpl;
>>>>> +import org.apache.shindig.social.opensocial.model.NameImpl;
>>>>> +import org.apache.shindig.social.opensocial.model.Person;
>>>>> +import org.apache.shindig.social.opensocial.model.PersonImpl;
>>>>> +import org.apache.shindig.social.opensocial.model.Phone;
>>>>> +import org.apache.shindig.social.opensocial.model.PhoneImpl;
>>>>> +import org.json.JSONObject;
>>>>> +
>>>>> +import com.google.common.collect.Lists;
>>>>> +import com.google.inject.Guice;
>>>>> +
>>>>> +public class JsonConverterPerformancePerf extends TestCase {
>>>>> +
>>>>> +  private static final Log log = LogFactory
>>>>> +      .getLog(JsonConverterPerformancePerf.class);
>>>>> +  private static final int TEST_SIZE = 10000;
>>>>> +  private Person johnDoe;
>>>>> +  private Activity activity;
>>>>> +
>>>>> +  private BeanJsonLibConverter beanJsonLibConverter;
>>>>> +  private APIValidator apiValidator;
>>>>> +  // set to true to get loging output at info level
>>>>> +  private boolean outputInfo = false;
>>>>> +  private BeanJsonConverter beanJsonConverter;
>>>>> +
>>>>> +  @Override
>>>>> +  public void setUp() throws Exception {
>>>>> +    super.setUp();
>>>>> +    johnDoe = new PersonImpl("johnDoeId", new NameImpl("John  
>>>>> Doe"));
>>>>> +    johnDoe.setPhoneNumbers(Lists.<Phone> newArrayList(new  
>>>>> PhoneImpl(
>>>>> +        "+33H000000000", "home"), new PhoneImpl("+33M000000000",
>>>>> "mobile"),
>>>>> +        new PhoneImpl("+33W000000000", "work")));
>>>>> +
>>>>> +    johnDoe.setAddresses(Lists.<Address> newArrayList(new  
>>>>> AddressImpl(
>>>>> +        "My home address")));
>>>>> +
>>>>> +    johnDoe.setEmails(Lists.<Email> newArrayList(new EmailImpl(
>>>>> +        "john.doe@work.bar", "work"),
>>>>> +        new EmailImpl("john.doe@home.bar", "home")));
>>>>> +
>>>>> +    activity = new ActivityImpl("activityId", johnDoe.getId());
>>>>> +
>>>>> +    activity.setMediaItems(Lists.<MediaItem> newArrayList(new
>>>>> MediaItemImpl(
>>>>> +        "image/jpg", MediaItem.Type.IMAGE, "http://foo.bar")));
>>>>> +
>>>>> +    beanJsonLibConverter = new BeanJsonLibConverter(Guice
>>>>> +        .createInjector(new JsonLibTestsGuiceModule()));
>>>>> +
>>>>> +    beanJsonConverter = new BeanJsonConverter(Guice
>>>>> +        .createInjector(new SocialApiTestsGuiceModule()));
>>>>> +
>>>>> +    apiValidator = new APIValidator("opensocial-reference");
>>>>> +
>>>>> +  }
>>>>> +
>>>>> +  public static class SpecialPerson extends PersonImpl {
>>>>> +    private String newfield;
>>>>> +
>>>>> +    public SpecialPerson() {
>>>>> +      super();
>>>>> +    }
>>>>> +
>>>>> +    public SpecialPerson(String id, String name, String  
>>>>> newfield) {
>>>>> +      super(id, new NameImpl(name));
>>>>> +      this.newfield = newfield;
>>>>> +    }
>>>>> +
>>>>> +    public String getNewfield() {
>>>>> +      return newfield;
>>>>> +    }
>>>>> +
>>>>> +    public void setNewfield(String newfield) {
>>>>> +      this.newfield = newfield;
>>>>> +    }
>>>>> +
>>>>> +  }
>>>>> +
>>>>> +  public void testToJsonLibOnInheritedClassOutput() throws  
>>>>> Exception {
>>>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>>>>> "nonsense");
>>>>> +    }
>>>>> +    Runtime r = Runtime.getRuntime();
>>>>> +    r.gc();
>>>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>>>> +    long startOutput = System.currentTimeMillis();
>>>>> +    String[] output = new String[TEST_SIZE];
>>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>>> +      output[i] = beanJsonLibConverter.convertToString(spa[i]);
>>>>> +    }
>>>>> +    long endOutput = System.currentTimeMillis();
>>>>> +    long memend = r.totalMemory()-r.freeMemory();
>>>>> +
>>>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>>>> +    char[] source = output[0].toCharArray();
>>>>> +    r.gc();
>>>>> +
>>>>> +    long stringsizeStart = r.totalMemory()-r.freeMemory();
>>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>>> +      serializeOutput[i] = new String(source);
>>>>> +    }
>>>>> +    long stringsizeEnd = r.totalMemory()-r.freeMemory();
>>>>> +
>>>>> +    /*
>>>>> +     * Output the time per conversion and the memory usage -  
>>>>> the output
>>>>> per
>>>>> +     * conversion.
>>>>> +     *
>>>>> +     */
>>>>> +
>>>>> +    log.info("SF JSON Lib Output "
>>>>> +        + average(startOutput, endOutput, TEST_SIZE)
>>>>> +        + " ms/conversion, "
>>>>> +        + (average(memstart, memend, TEST_SIZE)- 
>>>>> average(stringsizeStart,
>>>>> stringsizeEnd, TEST_SIZE))
>>>>> +        + " heap bytes/conversion, output packet consumed on  
>>>>> average "
>>>>> +        + average(stringsizeStart, stringsizeEnd, TEST_SIZE)+"  
>>>>> for a
>>>>> string length of "+output[0].length());
>>>>> +    log.info("Output Was ["+output[0]+"]");
>>>>> +  }
>>>>> +
>>>>> +  public void testToJsonLibOnInheritedClassInput() throws  
>>>>> Exception {
>>>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>>>> +    SpecialPerson[] sparesult = new SpecialPerson[TEST_SIZE];
>>>>> +    Runtime r = Runtime.getRuntime();
>>>>> +    r.gc();
>>>>> +    long personStart = r.totalMemory()-r.freeMemory();
>>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>>>>> "nonsense");
>>>>> +    }
>>>>> +    long personEnd = r.totalMemory()-r.freeMemory();
>>>>> +
>>>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>>>> +    r.gc();
>>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>>> +
>>>>> +      serializeOutput[i] =  
>>>>> beanJsonLibConverter.convertToString(spa[i]);
>>>>> +    }
>>>>> +
>>>>> +    r.gc();
>>>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>>>> +    long startInput = System.currentTimeMillis();
>>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>>> +        sparesult[i] = beanJsonLibConverter.convertToObject(
>>>>> +          serializeOutput[i], SpecialPerson.class);
>>>>> +    }
>>>>> +    long endInput = System.currentTimeMillis();
>>>>> +    long memend = r.totalMemory()-r.freeMemory();
>>>>> +
>>>>> +    log.info("SF JSON Lib Input "
>>>>> +        + average(startInput, endInput, TEST_SIZE)
>>>>> +        + " ms/conversion, "
>>>>> +        + (average(memstart, memend, TEST_SIZE)- 
>>>>> average(personStart,
>>>>> personEnd, TEST_SIZE))
>>>>> +        + " heap bytes/conversion, person object consumed on  
>>>>> average "
>>>>> +        + average(personStart, personEnd, TEST_SIZE));
>>>>> +  }
>>>>> +
>>>>> +  public void testToJsonOnInheritedClassOutput() throws  
>>>>> Exception {
>>>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>>>>> "nonsense");
>>>>> +    }
>>>>> +    Runtime r = Runtime.getRuntime();
>>>>> +    String[] output = new String[TEST_SIZE];
>>>>> +    r.gc();
>>>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>>>> +    long startOutput = System.currentTimeMillis();
>>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>>> +      output[i]  = ((JSONObject)
>>>>> beanJsonConverter.convertToJson(spa[i])).toString();
>>>>> +    }
>>>>> +    long endOutput = System.currentTimeMillis();
>>>>> +    long memend = r.totalMemory()-r.freeMemory();
>>>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>>>> +    char[] source = output[0].toCharArray();
>>>>> +    r.gc();
>>>>> +
>>>>> +    long stringsizeStart = r.totalMemory()-r.freeMemory();
>>>>> +
>>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>>> +      serializeOutput[i] = new String(source);
>>>>> +    }
>>>>> +    long stringsizeEnd = r.totalMemory()-r.freeMemory();
>>>>> +
>>>>> +    log.info("ORG JSON Lib Output "
>>>>> +        + average(startOutput, endOutput, TEST_SIZE)
>>>>> +        + " ms/conversion, "
>>>>> +        + (average(memstart, memend, TEST_SIZE)- 
>>>>> average(stringsizeStart,
>>>>> stringsizeEnd, TEST_SIZE))
>>>>> +        + " heap bytes/conversion, output packet consumed on  
>>>>> average "
>>>>> +        + average(stringsizeStart, stringsizeEnd, TEST_SIZE)+"  
>>>>> for a
>>>>> string length of "+output[0].length());
>>>>> +    log.info("Output Was ["+output[0]+"]");
>>>>> +  }
>>>>> +
>>>>> +  /**
>>>>> +   * @param endOutput
>>>>> +   * @param startOutput
>>>>> +   * @param testSize
>>>>> +   * @return
>>>>> +   */
>>>>> +  private float average(long start, long end, int testSize) {
>>>>> +    float r = end - start;
>>>>> +    r = r / testSize;
>>>>> +    return r;
>>>>> +  }
>>>>> +
>>>>> +  public void XtestToJsonOnInheritedClassInput() throws  
>>>>> Exception {
>>>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>>>> +    SpecialPerson[] sparesult = new SpecialPerson[TEST_SIZE];
>>>>> +    Runtime r = Runtime.getRuntime();
>>>>> +    r.gc();
>>>>> +    long personStart = r.totalMemory()-r.freeMemory();
>>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>>>>> "nonsense");
>>>>> +    }
>>>>> +    long personEnd = r.totalMemory()-r.freeMemory();
>>>>> +
>>>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>>>> +    r.gc();
>>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>>> +
>>>>> +      serializeOutput[i] =  
>>>>> beanJsonConverter.convertToString(spa[i]);
>>>>> +    }
>>>>> +
>>>>> +    r.gc();
>>>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>>>> +    long startInput = System.currentTimeMillis();
>>>>> +
>>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>>> +      sparesult[i] = beanJsonConverter.convertToObject(
>>>>> +          serializeOutput[i], SpecialPerson.class);
>>>>> +    }
>>>>> +    long endInput = System.currentTimeMillis();
>>>>> +    long memend = r.totalMemory()-r.freeMemory();
>>>>> +
>>>>> +    log.info("SF JSON Lib Input "
>>>>> +        + average(startInput, endInput, TEST_SIZE)
>>>>> +        + " ms/conversion, "
>>>>> +        + (average(memstart, memend, TEST_SIZE)- 
>>>>> average(personStart,
>>>>> personEnd, TEST_SIZE))
>>>>> +        + " heap bytes/conversion, person object consumed on  
>>>>> average "
>>>>> +        + average(personStart, personEnd, TEST_SIZE));
>>>>> +  }
>>>>> +
>>>>> +}
>>>>>
>>>>> Modified: incubator/shindig/trunk/pom.xml
>>>>> URL:
>>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/pom.xml?rev=678158&r1=678157&r2=678158&view=diff
>>>>>
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> = 
>>>>> ==================================================================
>>>>> --- incubator/shindig/trunk/pom.xml (original)
>>>>> +++ incubator/shindig/trunk/pom.xml Sat Jul 19 06:51:03 2008
>>>>> @@ -853,6 +853,16 @@
>>>>>       <artifactId>htmlunit</artifactId>
>>>>>       <version>2.1</version>
>>>>>     </dependency>
>>>>> +      <dependency>
>>>>> +        <groupId>log4j</groupId>
>>>>> +        <artifactId>log4j</artifactId>
>>>>> +        <version>1.2.13</version>
>>>>> +      </dependency>
>>>>> +      <dependency>
>>>>> +        <groupId>rhino</groupId>
>>>>> +        <artifactId>js</artifactId>
>>>>> +        <version>1.6R7</version>
>>>>> +      </dependency>
>>>>>   </dependencies>
>>>>> </dependencyManagement>
>>>>> </project>
>>>>>
>>>>>
>>>>>
>>


Re: svn commit: r678158 - in /incubator/shindig/trunk: ./ java/social-api/ java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/ java/social-api/src/test/java/org/apache/shindig/social/ java/social-api/src/test/java/org/apache/shin

Posted by Ian Boston <ie...@tfd.co.uk>.
I am using git, which said it did a rename on svn commit.

Can you verify that these did come through as moves when you update.

Thanks
Ian



x43543:~/Apache/shindig/trunk ieb$ git svn dcommit
Committing to https://svn.apache.org/repos/asf/incubator/shindig/ 
trunk ...
         R       java/social-api/src/main/java/org/apache/shindig/ 
social/opensocial/util/JSONLibConverterUtils.java => java/social-api/ 
src/main/java/org/apache/shindig/social/opensocial/util/ 
JsonLibConverterUtils.java
         R       java/social-api/src/main/java/org/apache/shindig/ 
social/opensocial/util/JSONObjectToMapMorpher.java => java/social-api/ 
src/main/java/org/apache/shindig/social/opensocial/util/ 
JsonObjectToMapMorpher.java
         R       java/social-api/src/test/java/org/apache/shindig/ 
social/opensocial/util/APIValidator.java => java/social-api/src/test/ 
java/org/apache/shindig/social/opensocial/util/ApiValidator.java
         R       java/social-api/src/test/java/org/apache/shindig/ 
social/opensocial/util/APIValidatorExpcetion.java => java/social-api/ 
src/test/java/org/apache/shindig/social/opensocial/util/ 
ApiValidatorExpcetion.java
         R       java/social-api/src/test/java/org/apache/shindig/ 
social/opensocial/util/APIValidatorTest.java => java/social-api/src/ 
test/java/org/apache/shindig/social/opensocial/util/ 
ApiValidatorTest.java
         M       java/social-api/src/main/java/org/apache/shindig/ 
social/opensocial/util/BeanJsonLibConverter.java
         M       java/social-api/src/test/java/org/apache/shindig/ 
social/opensocial/util/BeanJsonLibConverterTest.java
         M       java/social-api/src/test/java/org/apache/shindig/ 
social/opensocial/util/JsonConverterPerformancePerf.java
Committed r678263

On 20 Jul 2008, at 10:46, Chris Chabot wrote:

> Please make sure to do proper svn move's. Last time we had 2  
> identical file names, but with different casing, everyone on a case  
> insensitive file system got into trouble :)
>
> 	-- Chris
>
> On Jul 20, 2008, at 11:02 AM, Ian Boston wrote:
>
>> Ok will fix.
>> Ian
>>
>> On 19 Jul 2008, at 20:50, Kevin Brown wrote:
>>
>>> Hey Ian,
>>>
>>> The casing is inconsistent here -- it should be Json and Api for  
>>> all cases
>>> rather than JSON or API.
>>>
>>> Thanks!
>>>
>>> On Sat, Jul 19, 2008 at 6:51 AM, <ie...@apache.org> wrote:
>>>
>>>> Author: ieb
>>>> Date: Sat Jul 19 06:51:03 2008
>>>> New Revision: 678158
>>>>
>>>> URL: http://svn.apache.org/viewvc?rev=678158&view=rev
>>>> Log:
>>>> SHINDIG-451
>>>> Applying patch from the JIRA.
>>>>
>>>> Adds a json-lib (net.sf) converter, not wired into social-api at  
>>>> present.
>>>>
>>>> Added:
>>>>
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>>>
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>>>>
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>>>>
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>>>
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/JsonLibTestsGuiceModule.java
>>>>
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/APIValidator.java
>>>>
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>>>>
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/APIValidatorTest.java
>>>>
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>>>
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>>> Modified:
>>>>   incubator/shindig/trunk/java/social-api/pom.xml
>>>>   incubator/shindig/trunk/pom.xml
>>>>
>>>> Modified: incubator/shindig/trunk/java/social-api/pom.xml
>>>> URL:
>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>>>> api/pom.xml?rev=678158&r1=678157&r2=678158&view=diff
>>>>
>>>> =================================================================== 
>>>> ===========
>>>> --- incubator/shindig/trunk/java/social-api/pom.xml (original)
>>>> +++ incubator/shindig/trunk/java/social-api/pom.xml Sat Jul 19  
>>>> 06:51:03
>>>> 2008
>>>> @@ -60,12 +60,31 @@
>>>>      <groupId>org.apache.shindig</groupId>
>>>>      <artifactId>shindig-common</artifactId>
>>>>    </dependency>
>>>> +    <!-- is this Ok, only used in test to load the features -->
>>>> +    <dependency>
>>>> +      <groupId>org.apache.shindig</groupId>
>>>> +      <artifactId>shindig-features</artifactId>
>>>> +      <scope>test</scope>
>>>> +    </dependency>
>>>>
>>>>    <!-- external depenencies -->
>>>>    <dependency>
>>>>      <groupId>org.json</groupId>
>>>>      <artifactId>json</artifactId>
>>>>    </dependency>
>>>> +    <!-- the classifier prevents this working in dep management  
>>>> -->
>>>> +    <dependency>
>>>> +      <groupId>net.sf.json-lib</groupId>
>>>> +      <artifactId>json-lib</artifactId>
>>>> +      <version>2.2</version>
>>>> +      <classifier>jdk15</classifier>
>>>> +      <type>jar</type>
>>>> +    </dependency>
>>>> +    <dependency>
>>>> +      <groupId>rhino</groupId>
>>>> +      <artifactId>js</artifactId>
>>>> +      <scope>test</scope>
>>>> +    </dependency>
>>>>    <dependency>
>>>>      <groupId>com.google.code.guice</groupId>
>>>>      <artifactId>guice</artifactId>
>>>> @@ -112,5 +131,10 @@
>>>>      <artifactId>core</artifactId>
>>>>      <scope>compile</scope>
>>>>    </dependency>
>>>> +    <dependency>
>>>> +      <groupId>log4j</groupId>
>>>> +      <artifactId>log4j</artifactId>
>>>> +      <scope>test</scope>
>>>> +    </dependency>
>>>>  </dependencies>
>>>> </project>
>>>>
>>>> Added:
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>>> URL:
>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>>>> api/src/main/java/org/apache/shindig/social/opensocial/util/ 
>>>> BeanJsonLibConversionException.java?rev=678158&view=auto
>>>>
>>>> =================================================================== 
>>>> ===========
>>>> ---
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>>> (added)
>>>> +++
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>>> Sat Jul 19 06:51:03 2008
>>>> @@ -0,0 +1,43 @@
>>>> +/*
>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>> + * or more contributor license agreements. See the NOTICE file
>>>> + * distributed with this work for additional information
>>>> + * regarding copyright ownership. The ASF licenses this file
>>>> + * to you under the Apache License, Version 2.0 (the
>>>> + * "License"); you may not use this file except in compliance
>>>> + * with the License. You may obtain a copy of the License at
>>>> + *
>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>> + *
>>>> + * 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.apache.shindig.social.opensocial.util;
>>>> +
>>>> +/**
>>>> + * Where a conversion exception happens in the Json Lib  
>>>> conversion, this
>>>> + * exception is thrown.
>>>> + */
>>>> +public class BeanJsonLibConversionException extends  
>>>> RuntimeException {
>>>> +
>>>> +  private static final long serialVersionUID =  
>>>> -8609384443448202372L;
>>>> +
>>>> +  public BeanJsonLibConversionException() {
>>>> +  }
>>>> +
>>>> +  public BeanJsonLibConversionException(String arg0) {
>>>> +    super(arg0);
>>>> +  }
>>>> +
>>>> +  public BeanJsonLibConversionException(Throwable arg0) {
>>>> +    super(arg0);
>>>> +  }
>>>> +
>>>> +  public BeanJsonLibConversionException(String arg0, Throwable  
>>>> arg1) {
>>>> +    super(arg0, arg1);
>>>> +  }
>>>> +
>>>> +}
>>>>
>>>> Added:
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>>>> URL:
>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>>>> api/src/main/java/org/apache/shindig/social/opensocial/util/ 
>>>> BeanJsonLibConverter.java?rev=678158&view=auto
>>>>
>>>> =================================================================== 
>>>> ===========
>>>> ---
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>>>> (added)
>>>> +++
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>>>> Sat Jul 19 06:51:03 2008
>>>> @@ -0,0 +1,286 @@
>>>> +/*
>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>> + * or more contributor license agreements. See the NOTICE file
>>>> + * distributed with this work for additional information
>>>> + * regarding copyright ownership. The ASF licenses this file
>>>> + * to you under the Apache License, Version 2.0 (the
>>>> + * "License"); you may not use this file except in compliance
>>>> + * with the License. You may obtain a copy of the License at
>>>> + *
>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>> + *
>>>> + * 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.apache.shindig.social.opensocial.util;
>>>> +
>>>> +import java.lang.reflect.Array;
>>>> +import java.lang.reflect.InvocationTargetException;
>>>> +import java.util.Collection;
>>>> +import java.util.HashMap;
>>>> +import java.util.List;
>>>> +import java.util.Map;
>>>> +
>>>> +import net.sf.ezmorph.MorpherRegistry;
>>>> +import net.sf.json.JSONArray;
>>>> +import net.sf.json.JSONException;
>>>> +import net.sf.json.JSONObject;
>>>> +import net.sf.json.JsonConfig;
>>>> +import net.sf.json.processors.DefaultValueProcessor;
>>>> +import net.sf.json.util.EnumMorpher;
>>>> +import net.sf.json.util.JSONUtils;
>>>> +import net.sf.json.util.NewBeanInstanceStrategy;
>>>> +import net.sf.json.util.PropertyFilter;
>>>> +
>>>> +import org.apache.commons.logging.Log;
>>>> +import org.apache.commons.logging.LogFactory;
>>>> +import org.apache.shindig.social.opensocial.model.Address;
>>>> +import org.apache.shindig.social.opensocial.model.Email;
>>>> +import org.apache.shindig.social.opensocial.model.Enum;
>>>> +import org.apache.shindig.social.opensocial.model.MediaItem;
>>>> +import org.apache.shindig.social.opensocial.model.Organization;
>>>> +import org.apache.shindig.social.opensocial.model.Phone;
>>>> +import org.apache.shindig.social.opensocial.model.Url;
>>>> +
>>>> +
>>>> +import com.google.inject.Inject;
>>>> +import com.google.inject.Injector;
>>>> +
>>>> +/**
>>>> + *
>>>> + */
>>>> +public class BeanJsonLibConverter implements BeanConverter {
>>>> +
>>>> +  protected static final Log log = LogFactory
>>>> +      .getLog(BeanJsonLibConverter.class);
>>>> +  private Injector injector;
>>>> +  private JsonConfig jsonConfig;
>>>> +  private boolean debugMode = false;
>>>> +
>>>> +  /*
>>>> +   * Register the Enum Morphers so that JSON -> Bean works  
>>>> correctly for
>>>> enums.
>>>> +   */
>>>> +  static {
>>>> +    MorpherRegistry morpherRegistry =  
>>>> JSONUtils.getMorpherRegistry();
>>>> +    morpherRegistry.registerMorpher(new EnumMorpher 
>>>> (Address.Field.class));
>>>> +    morpherRegistry.registerMorpher(new EnumMorpher 
>>>> (Phone.Field.class));
>>>> +    morpherRegistry.registerMorpher(new EnumMorpher 
>>>> (Email.Field.class));
>>>> +    morpherRegistry.registerMorpher(new
>>>> EnumMorpher(MediaItem.Field.class));
>>>> +    morpherRegistry.registerMorpher(new
>>>> EnumMorpher(MediaItem.Type.class));
>>>> +    morpherRegistry.registerMorpher(new EnumMorpher 
>>>> (Enum.Drinker.class));
>>>> +    morpherRegistry.registerMorpher(new EnumMorpher 
>>>> (Enum.Field.class));
>>>> +    morpherRegistry.registerMorpher(new EnumMorpher 
>>>> (Enum.Gender.class));
>>>> +    morpherRegistry
>>>> +        .registerMorpher(new EnumMorpher 
>>>> (Enum.NetworkPresence.class));
>>>> +    morpherRegistry.registerMorpher(new EnumMorpher 
>>>> (Enum.Smoker.class));
>>>> +
>>>> +    morpherRegistry.registerMorpher(new JSONObjectToMapMorpher());
>>>> +  }
>>>> +
>>>> +  @Inject
>>>> +  public BeanJsonLibConverter(Injector injector) {
>>>> +    this.injector = injector;
>>>> +    createJsonConfig();
>>>> +  }
>>>> +
>>>> +  @SuppressWarnings("unchecked")
>>>> +  public <T> T convertToObject(String string, final Class<T>
>>>> rootBeanClass) {
>>>> +
>>>> +    if (string.startsWith("[")) {
>>>> +      JSONArray jsonArray = JSONArray.fromObject(string,  
>>>> jsonConfig);
>>>> +      if (debugMode) {
>>>> +        JSONLibConverterUtils.dumpJsonArray(jsonArray, " ");
>>>> +      }
>>>> +
>>>> +      if (rootBeanClass.isArray()) {
>>>> +        Class<?> componentType = rootBeanClass.getComponentType();
>>>> +        Object rootObject = injector.getInstance(componentType);
>>>> +        List<?> o = JSONArray.toList(jsonArray, rootObject,  
>>>> jsonConfig);
>>>> +        Object[] result = (Object[]) Array.newInstance 
>>>> (componentType,
>>>> o.size());
>>>> +        for (int i = 0; i < o.size(); i++) {
>>>> +          result[i] = o.get(i);
>>>> +        }
>>>> +        return (T) result;
>>>> +
>>>> +      } else {
>>>> +        T rootObject = injector.getInstance(rootBeanClass);
>>>> +        Object o = JSONArray.toArray(jsonArray, rootObject,  
>>>> jsonConfig);
>>>> +        return (T) o;
>>>> +      }
>>>> +    } else {
>>>> +      JSONObject jsonObject = JSONObject.fromObject(string,  
>>>> jsonConfig);
>>>> +
>>>> +      if (debugMode) {
>>>> +        JSONLibConverterUtils.dumpJsonObject(jsonObject, " ");
>>>> +      }
>>>> +
>>>> +      T rootObject = injector.getInstance(rootBeanClass);
>>>> +      Object o = JSONObject.toBean(jsonObject, rootObject,  
>>>> jsonConfig);
>>>> +      return (T) o;
>>>> +
>>>> +    }
>>>> +  }
>>>> +
>>>> +  /**
>>>> +   * @return
>>>> +   */
>>>> +  private void createJsonConfig() {
>>>> +
>>>> +    jsonConfig = new JsonConfig();
>>>> +
>>>> +    /*
>>>> +     * This hook deals with the creation of new beans in the  
>>>> JSON -> Java
>>>> Bean
>>>> +     * conversion
>>>> +     */
>>>> +    jsonConfig.setNewBeanInstanceStrategy(new  
>>>> NewBeanInstanceStrategy() {
>>>> +
>>>> +      @SuppressWarnings("unchecked")
>>>> +      @Override
>>>> +      public Object newInstance(Class beanClass, JSONObject  
>>>> jsonObject)
>>>> +          throws InstantiationException, IllegalAccessException,
>>>> +          SecurityException, NoSuchMethodException,
>>>> InvocationTargetException {
>>>> +        if (beanClass != null) {
>>>> +          Object o =
>>>> BeanJsonLibConverter.this.injector.getInstance(beanClass);
>>>> +          if (debugMode) {
>>>> +            log.info("Created Object " + o + " for " +  
>>>> beanClass + " with
>>>> ["
>>>> +                + jsonObject + "]");
>>>> +          }
>>>> +          return o;
>>>> +        }
>>>> +        return DEFAULT.newInstance(beanClass, jsonObject);
>>>> +      }
>>>> +
>>>> +    });
>>>> +
>>>> +    /*
>>>> +     * We are expecting null for nulls
>>>> +     */
>>>> +    jsonConfig.registerDefaultValueProcessor(String.class,
>>>> +        new DefaultValueProcessor() {
>>>> +          @SuppressWarnings("unchecked")
>>>> +          public Object getDefaultValue(Class target) {
>>>> +            return null;
>>>> +          }
>>>> +        });
>>>> +
>>>> +    jsonConfig.setJsonPropertyFilter(new PropertyFilter() {
>>>> +
>>>> +      public boolean apply(Object source, String name, Object  
>>>> value) {
>>>> +        return filterProperty(source, name, value);
>>>> +      }
>>>> +
>>>> +    });
>>>> +
>>>> +    jsonConfig.setJavaPropertyFilter(new PropertyFilter() {
>>>> +
>>>> +      public boolean apply(Object source, String name, Object  
>>>> value) {
>>>> +        return filterProperty(source,name,value);
>>>> +      }
>>>> +
>>>> +    });
>>>> +
>>>> +    // the classMap deals with the basic json string to bean  
>>>> conversion
>>>> +
>>>> +    Map<String, Class<?>> classMap = new HashMap<String, Class<? 
>>>> >>();
>>>> +
>>>> +    /*
>>>> +     * mappings are required where there is a List of objects  
>>>> in the
>>>> interface
>>>> +     * with no indication of what type the list should contain.  
>>>> At the
>>>> moment,
>>>> +     * we are using 1 map for all json trees, as there is no  
>>>> conflict, but
>>>> if
>>>> +     * there is a map could be selected on the basis of the  
>>>> root object.
>>>> It
>>>> +     * would be better to do this with generics, but this is  
>>>> good enough
>>>> and
>>>> +     * compact enough for the moment.
>>>> +     *
>>>> +     */
>>>> +    //
>>>> +    // activity
>>>> +    classMap.put("mediaItems", MediaItem.class);
>>>> +    // this may not be necessary
>>>> +    classMap.put("templateParams", Map.class);
>>>> +    // BodyType needs no mappings
>>>> +    // Message needs no mappings
>>>> +    // Name needs no mappings
>>>> +    // Organization needs no mappings
>>>> +    // Url needs no mappings
>>>> +    // Email needs no mappings
>>>> +    // Phone Needs no mappings
>>>> +    // Address Needs no mappings
>>>> +    // MediaItem needs no mappings
>>>> +
>>>> +    // Person map
>>>> +    classMap.put("addresses", Address.class);
>>>> +    classMap.put("phoneNumbers", Phone.class);
>>>> +    classMap.put("emails", Email.class);
>>>> +    classMap.put("mediaItems", MediaItem.class);
>>>> +    classMap.put("jobs", Organization.class);
>>>> +    classMap.put("schools", Organization.class);
>>>> +    classMap.put("urls", Url.class);
>>>> +    jsonConfig.setClassMap(classMap);
>>>> +
>>>> +  }
>>>> +
>>>> +  /**
>>>> +   * @param source
>>>> +   * @param name
>>>> +   * @param value
>>>> +   * @return
>>>> +   */
>>>> +  protected boolean filterProperty(Object source, String name,  
>>>> Object
>>>> value) {
>>>> +    if ( value == null ) {
>>>> +      return true;
>>>> +    }
>>>> +    if ( value instanceof JSONArray ) {
>>>> +      JSONArray array = (JSONArray) value;
>>>> +      if ( array.size() == 0 ) {
>>>> +        return true;
>>>> +      }
>>>> +    }
>>>> +    if ( value instanceof JSONObject ) {
>>>> +      JSONObject object = (JSONObject) value;
>>>> +      if ( object.isNullObject() || object.isEmpty()  ) {
>>>> +        return true;
>>>> +      }
>>>> +    }
>>>> +    if ( value instanceof Collection) {
>>>> +      Collection<?> collection = (Collection<?>) value;
>>>> +      if ( collection.size() == 0  ) {
>>>> +        return true;
>>>> +      }
>>>> +    }
>>>> +    if ( value instanceof Object[] ) {
>>>> +      Object[] oarray = (Object[]) value;
>>>> +      if ( oarray.length == 0 ) {
>>>> +        return true;
>>>> +      }
>>>> +    }
>>>> +    return false;
>>>> +  }
>>>> +
>>>> +  public String convertToString(Object pojo) {
>>>> +
>>>> +    try {
>>>> +      JSONObject jsonObject = JSONObject.fromObject(pojo,  
>>>> jsonConfig);
>>>> +      return jsonObject.toString();
>>>> +    } catch (JSONException jse) {
>>>> +      Class<?> pojoClass = pojo.getClass();
>>>> +      if (JSONUtils.isArray(pojoClass)) {
>>>> +        JSONArray jsonArray = JSONArray.fromObject(pojo);
>>>> +        String result = jsonArray.toString();
>>>> +        return result;
>>>> +      }
>>>> +      throw jse;
>>>> +    }
>>>> +  }
>>>> +
>>>> +  /**
>>>> +   * @param string
>>>> +   * @param class1
>>>> +   */
>>>> +  public void addMapping(String key, Class<?> class1) {
>>>> +    jsonConfig.getClassMap().put(key, class1);
>>>> +  }
>>>> +
>>>> +}
>>>>
>>>> Added:
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>>>> URL:
>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>>>> api/src/main/java/org/apache/shindig/social/opensocial/util/ 
>>>> JSONLibConverterUtils.java?rev=678158&view=auto
>>>>
>>>> =================================================================== 
>>>> ===========
>>>> ---
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>>>> (added)
>>>> +++
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>>>> Sat Jul 19 06:51:03 2008
>>>> @@ -0,0 +1,72 @@
>>>> +/*
>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>> + * or more contributor license agreements. See the NOTICE file
>>>> + * distributed with this work for additional information
>>>> + * regarding copyright ownership. The ASF licenses this file
>>>> + * to you under the Apache License, Version 2.0 (the
>>>> + * "License"); you may not use this file except in compliance
>>>> + * with the License. You may obtain a copy of the License at
>>>> + *
>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>> + *
>>>> + * 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.apache.shindig.social.opensocial.util;
>>>> +
>>>> +import org.apache.commons.logging.Log;
>>>> +import org.apache.commons.logging.LogFactory;
>>>> +
>>>> +import net.sf.json.JSONArray;
>>>> +import net.sf.json.JSONObject;
>>>> +
>>>> +/**
>>>> + *
>>>> + */
>>>> +public class JSONLibConverterUtils {
>>>> +  protected static final Log log = LogFactory
>>>> +  .getLog(JSONLibConverterUtils.class);
>>>> +
>>>> +
>>>> +  /**
>>>> +   * @param jsonObject
>>>> +   */
>>>> +  public static final void dumpJsonObject(JSONObject  
>>>> jsonObject, String
>>>> indent) {
>>>> +    for (Object key : jsonObject.keySet()) {
>>>> +      Object value = jsonObject.get(key);
>>>> +      if (value instanceof JSONObject) {
>>>> +        log.info(indent + key + ":JSONObject");
>>>> +        dumpJsonObject((JSONObject) value, indent + "  ");
>>>> +      } else if (value instanceof JSONArray) {
>>>> +        log.info(indent + key + ":JSONArray " + ((JSONArray)
>>>> value).size());
>>>> +        dumpJsonArray((JSONArray) value, indent + "  ");
>>>> +      } else {
>>>> +        log.info(indent + key + ":" + value + ":"
>>>> +            + (value == null ? "na" : value.getClass()));
>>>> +      }
>>>> +    }
>>>> +  }
>>>> +
>>>> +
>>>> +  /**
>>>> +   * @param value
>>>> +   * @param string
>>>> +   */
>>>> +  static void dumpJsonArray(JSONArray array, String indent) {
>>>> +    for (Object value : array) {
>>>> +      if (value instanceof JSONObject) {
>>>> +        log.info(indent + ":JSONObject");
>>>> +        dumpJsonObject((JSONObject) value, indent + "  ");
>>>> +      } else if (value instanceof JSONArray) {
>>>> +        log.info(indent + ":JSONArray " + ((JSONArray)  
>>>> value).size());
>>>> +        dumpJsonArray((JSONArray) value, indent + "  ");
>>>> +      } else {
>>>> +        log.info(indent + ":" + value + ":"
>>>> +            + (value == null ? "na" : value.getClass()));
>>>> +      }
>>>> +    }
>>>> +  }
>>>> +}
>>>>
>>>> Added:
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>>> URL:
>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>>>> api/src/main/java/org/apache/shindig/social/opensocial/util/ 
>>>> JSONObjectToMapMorpher.java?rev=678158&view=auto
>>>>
>>>> =================================================================== 
>>>> ===========
>>>> ---
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>>> (added)
>>>> +++
>>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>>> Sat Jul 19 06:51:03 2008
>>>> @@ -0,0 +1,50 @@
>>>> +/*
>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>> + * or more contributor license agreements. See the NOTICE file
>>>> + * distributed with this work for additional information
>>>> + * regarding copyright ownership. The ASF licenses this file
>>>> + * to you under the Apache License, Version 2.0 (the
>>>> + * "License"); you may not use this file except in compliance
>>>> + * with the License. You may obtain a copy of the License at
>>>> + *
>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>> + *
>>>> + * 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.apache.shindig.social.opensocial.util;
>>>> +
>>>> +import java.util.HashMap;
>>>> +import java.util.Map;
>>>> +
>>>> +import net.sf.ezmorph.Morpher;
>>>> +import net.sf.ezmorph.ObjectMorpher;
>>>> +import net.sf.json.JSONObject;
>>>> +
>>>> +/**
>>>> + *
>>>> + */
>>>> +public class JSONObjectToMapMorpher implements Morpher,  
>>>> ObjectMorpher {
>>>> +
>>>> +  public Class<?> morphsTo() {
>>>> +    return Map.class;
>>>> +  }
>>>> +
>>>> +  @SuppressWarnings("unchecked")
>>>> +  public boolean supports(Class clazz) {
>>>> +    return (JSONObject.class.equals(clazz));
>>>> +  }
>>>> +
>>>> +  public Object morph(Object bean) {
>>>> +    Map<Object, Object> result = new HashMap<Object, Object>();
>>>> +    JSONObject jsonObject = (JSONObject) bean;
>>>> +    for ( Object key : jsonObject.keySet()) {
>>>> +      result.put(key,jsonObject.get(key));
>>>> +    }
>>>> +    return result;
>>>> +  }
>>>> +
>>>> +}
>>>>
>>>> Added:
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/JsonLibTestsGuiceModule.java
>>>> URL:
>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>>>> api/src/test/java/org/apache/shindig/social/ 
>>>> JsonLibTestsGuiceModule.java?rev=678158&view=auto
>>>>
>>>> =================================================================== 
>>>> ===========
>>>> ---
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/JsonLibTestsGuiceModule.java
>>>> (added)
>>>> +++
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/JsonLibTestsGuiceModule.java
>>>> Sat Jul 19 06:51:03 2008
>>>> @@ -0,0 +1,40 @@
>>>> +/*
>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>> + * or more contributor license agreements.  See the NOTICE file
>>>> + * distributed with this work for additional information
>>>> + * regarding copyright ownership.  The ASF licenses this file
>>>> + * to you under the Apache License, Version 2.0 (the
>>>> + * "License"); you may not use this file except in compliance
>>>> + * with the License.  You may obtain a copy of the License at
>>>> + *
>>>> + *   http://www.apache.org/licenses/LICENSE-2.0
>>>> + *
>>>> + * 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.apache.shindig.social;
>>>> +
>>>> +import java.util.ArrayList;
>>>> +import java.util.HashMap;
>>>> +import java.util.List;
>>>> +import java.util.Map;
>>>> +
>>>> +import com.google.inject.AbstractModule;
>>>> +
>>>> +/**
>>>> + * Provides social api component injection for all large tests
>>>> + */
>>>> +public class JsonLibTestsGuiceModule extends AbstractModule {
>>>> +  @Override
>>>> +  protected void configure() {
>>>> +
>>>> +    bind(Map.class).to(HashMap.class);
>>>> +    bind(List.class).to(ArrayList.class);
>>>> +    bind(Map[].class).to(HashMap[].class);
>>>> +  }
>>>> +
>>>> +}
>>>>
>>>> Added:
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/APIValidator.java
>>>> URL:
>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>>>> api/src/test/java/org/apache/shindig/social/opensocial/util/ 
>>>> APIValidator.java?rev=678158&view=auto
>>>>
>>>> =================================================================== 
>>>> ===========
>>>> ---
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/APIValidator.java
>>>> (added)
>>>> +++
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/APIValidator.java
>>>> Sat Jul 19 06:51:03 2008
>>>> @@ -0,0 +1,352 @@
>>>> +/*
>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>> + * or more contributor license agreements. See the NOTICE file
>>>> + * distributed with this work for additional information
>>>> + * regarding copyright ownership. The ASF licenses this file
>>>> + * to you under the Apache License, Version 2.0 (the
>>>> + * "License"); you may not use this file except in compliance
>>>> + * with the License. You may obtain a copy of the License at
>>>> + *
>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>> + *
>>>> + * 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.apache.shindig.social.opensocial.util;
>>>> +
>>>> +import java.io.IOException;
>>>> +import java.io.InputStream;
>>>> +import java.io.InputStreamReader;
>>>> +import java.util.ArrayList;
>>>> +import java.util.HashMap;
>>>> +import java.util.List;
>>>> +import java.util.Map;
>>>> +
>>>> +import javax.xml.parsers.DocumentBuilder;
>>>> +import javax.xml.parsers.DocumentBuilderFactory;
>>>> +import javax.xml.parsers.ParserConfigurationException;
>>>> +
>>>> +import org.apache.commons.logging.Log;
>>>> +import org.apache.commons.logging.LogFactory;
>>>> +import org.mozilla.javascript.Context;
>>>> +import org.mozilla.javascript.EvaluatorException;
>>>> +import org.mozilla.javascript.Script;
>>>> +import org.mozilla.javascript.ScriptableObject;
>>>> +import org.w3c.dom.Document;
>>>> +import org.w3c.dom.NamedNodeMap;
>>>> +import org.w3c.dom.Node;
>>>> +import org.w3c.dom.NodeList;
>>>> +import org.xml.sax.SAXException;
>>>> +
>>>> +/**
>>>> + * A class that loads a feature set from features into a  
>>>> Javascript Parser
>>>> to
>>>> + * make the model available to validate JSON messages against.
>>>> + */
>>>> +public class APIValidator {
>>>> +
>>>> +  private static final Log log = LogFactory.getLog 
>>>> (APIValidator.class);
>>>> +  private Context ctx;
>>>> +  private ScriptableObject scope;
>>>> +
>>>> +  /**
>>>> +   * @param feature
>>>> +   *                The name of the feature are eg "opensocial- 
>>>> reference",
>>>> this
>>>> +   *                is a classpath stub (not starting with /)  
>>>> where the
>>>> location
>>>> +   *                contains a feature.xml file.
>>>> +   * @throws SAXException
>>>> +   *                 if feature.xml is not parsable
>>>> +   * @throws ParserConfigurationException
>>>> +   *                 if the parsers are invalid
>>>> +   * @throws IOException
>>>> +   *                 if feature.xml or the javascript that  
>>>> represents the
>>>> +   *                 feature is missing
>>>> +   *
>>>> +   */
>>>> +  public APIValidator(String feature) throws IOException,
>>>> +      ParserConfigurationException, SAXException {
>>>> +    ctx = Context.enter();
>>>> +    scope = ctx.initStandardObjects();
>>>> +    load(feature);
>>>> +  }
>>>> +
>>>> +  /**
>>>> +   * @param json
>>>> +   *                The json to validate expected in a form  
>>>> { xyz: yyy }
>>>> form
>>>> +   * @param object
>>>> +   *                The json Fields object specifying the  
>>>> structure of the
>>>> json
>>>> +   *                object, each field in this object contains  
>>>> the name of
>>>> the
>>>> +   *                json field in the json structure.
>>>> +   * @param optionalFields
>>>> +   *                If any of the fields that appear in the  
>>>> json structure
>>>> are
>>>> +   *                optional, then they should be defined in this
>>>> parameter.
>>>> +   * @param nullfields
>>>> +   * @throws APIValidatorExpcetion
>>>> +   *                 if there is a problem validating the json
>>>> +   * @return a map so string object pairs containing the fields  
>>>> at the top
>>>> level
>>>> +   *         of the json tree. Where these are native java  
>>>> objects, they
>>>> will
>>>> +   *         appear as native object. Complex json objects will  
>>>> appear as
>>>> Rhino
>>>> +   *         specific objects
>>>> +   */
>>>> +  public Map<String, Object> validate(String json, String object,
>>>> +      String[] optionalFields, String[] nullfields)
>>>> +      throws APIValidatorExpcetion {
>>>> +
>>>> +    /*
>>>> +     * Object[] ids = ScriptableObject.getPropertyIds(scope);  
>>>> for (Object
>>>> id :
>>>> +     * ids) { Object o = ScriptableObject.getProperty(scope,
>>>> +     * String.valueOf(id)); log.debug("ID is " + id + " class " +
>>>> id.getClass() + "
>>>> +     * is " + o); if (o instanceof ScriptableObject) {
>>>> +     * listScriptable(String.valueOf(id), (ScriptableObject)  
>>>> o); } }
>>>> +     */
>>>> +
>>>> +    log.debug("Loading " + json);
>>>> +    json = json.trim();
>>>> +    if (!json.endsWith("}")) {
>>>> +      json = json + "}";
>>>> +    }
>>>> +    if (!json.startsWith("{")) {
>>>> +      json = "{" + json;
>>>> +    }
>>>> +    json = "( testingObject = " + json + " )";
>>>> +
>>>> +    Object so = null;
>>>> +    try {
>>>> +      so = ctx.evaluateString(scope, json, "test json", 0, null);
>>>> +    } catch (EvaluatorException ex) {
>>>> +      log.error("Non parseable JSON " + json);
>>>> +    }
>>>> +    log.debug("Loaded " + so);
>>>> +
>>>> +    return validateOject(so, object, optionalFields, nullfields);
>>>> +
>>>> +  }
>>>> +
>>>> +  /**
>>>> +   * Validate an JSON Object extracted
>>>> +   *
>>>> +   * @param object
>>>> +   * @param string
>>>> +   * @param optional
>>>> +   * @return
>>>> +   * @throws APIValidatorExpcetion
>>>> +   */
>>>> +  public Map<String, Object> validateOject(Object jsonObject,  
>>>> String
>>>> object,
>>>> +      String[] optionalFields, String[] nullFields)
>>>> +      throws APIValidatorExpcetion {
>>>> +    Map<String, String> optional = new HashMap<String, String>();
>>>> +    for (String opt : optionalFields) {
>>>> +      optional.put(opt, opt);
>>>> +    }
>>>> +    Map<String, String> nullf = new HashMap<String, String>();
>>>> +    for (String nf : nullFields) {
>>>> +      nullf.put(nf, nf);
>>>> +    }
>>>> +
>>>> +    ScriptableObject specification = getScriptableObject(object);
>>>> +    log.debug("Looking for  " + object + " found " +  
>>>> specification);
>>>> +    listScriptable(object, specification);
>>>> +
>>>> +    Map<String, Object> resultFields = new HashMap<String,  
>>>> Object>();
>>>> +
>>>> +    if (jsonObject instanceof ScriptableObject) {
>>>> +      ScriptableObject parsedJSONObject = (ScriptableObject)  
>>>> jsonObject;
>>>> +      listScriptable("testingObject", parsedJSONObject);
>>>> +      Object[] fields = specification.getIds();
>>>> +      for (Object f : fields) {
>>>> +        Object fieldName = specification.get(String.valueOf(f),
>>>> specification);
>>>> +        Object o = parsedJSONObject.get(String.valueOf(fieldName),
>>>> +            parsedJSONObject);
>>>> +        if (o == ScriptableObject.NOT_FOUND) {
>>>> +          if (optional.containsKey(fieldName)) {
>>>> +            log.warn("Missing Optional Field " + fieldName);
>>>> +          } else if (!nullf.containsKey(fieldName)) {
>>>> +            log.error("Missing Field " + fieldName);
>>>> +            throw new APIValidatorExpcetion("Missing Field " +  
>>>> fieldName);
>>>> +          }
>>>> +        } else {
>>>> +          if (nullf.containsKey(fieldName)) {
>>>> +            log.error("Field should have been null and was not");
>>>> +          }
>>>> +          if (o == null) {
>>>> +            if (nullf.containsKey(fieldName)) {
>>>> +              log.error("Null Fields has been serialized " +  
>>>> fieldName);
>>>> +            }
>>>> +            log.debug("Got a Null object for Field " + f + ":"  
>>>> + fieldName
>>>> +                + " on json [[" + jsonObject + "]]");
>>>> +
>>>> +          } else {
>>>> +
>>>> +            log.debug("Got JSON Field  Field," + f + ":" +  
>>>> fieldName + "
>>>> as "
>>>> +                + o + " " + o.getClass());
>>>> +          }
>>>> +          resultFields.put(String.valueOf(fieldName), o);
>>>> +        }
>>>> +      }
>>>> +
>>>> +    } else {
>>>> +      throw new APIValidatorExpcetion(
>>>> +          "Parsing JSON resulted in invalid Javascript object,  
>>>> which was "
>>>> +              + jsonObject + " JSON was [[" + jsonObject + "]]");
>>>> +    }
>>>> +    return resultFields;
>>>> +  }
>>>> +
>>>> +  /**
>>>> +   * get an object from the json context and scope.
>>>> +   *
>>>> +   * @param object
>>>> +   *                the name of the object specified as a path  
>>>> from the
>>>> base
>>>> +   *                object
>>>> +   * @return the json object
>>>> +   */
>>>> +  private ScriptableObject getScriptableObject(String object) {
>>>> +    String[] path = object.split("\\.");
>>>> +    log.debug("Looking up " + object + " elements " +  
>>>> path.length);
>>>> +
>>>> +    ScriptableObject s = scope;
>>>> +    for (String pe : path) {
>>>> +      log.debug("Looking up " + pe + " in " + s);
>>>> +      s = (ScriptableObject) s.get(pe, s);
>>>> +      log.debug("Looking for " + pe + " in found " + s);
>>>> +    }
>>>> +    return s;
>>>> +  }
>>>> +
>>>> +  /**
>>>> +   * List a scriptable object at log debug level, constructors  
>>>> will not be
>>>> +   * expanded as this loads to recursion.
>>>> +   *
>>>> +   * @param id
>>>> +   *                The name of the object
>>>> +   * @param scriptableObject
>>>> +   *                the scriptable Object
>>>> +   */
>>>> +  private void listScriptable(String id, ScriptableObject
>>>> scriptableObject) {
>>>> +    log.debug("ID is Scriptable " + id);
>>>> +    if (!id.endsWith("constructor")) {
>>>> +      Object[] allIDs = scriptableObject.getAllIds();
>>>> +      for (Object oid : allIDs) {
>>>> +        log.debug(id + "." + oid);
>>>> +        Object o = scriptableObject.get(String.valueOf(oid),
>>>> scriptableObject);
>>>> +        if (o instanceof ScriptableObject) {
>>>> +          listScriptable(id + "." + String.valueOf(oid),
>>>> (ScriptableObject) o);
>>>> +        }
>>>> +      }
>>>> +    }
>>>> +  }
>>>> +
>>>> +  /**
>>>> +   * Load a feature based on the spec
>>>> +   *
>>>> +   * @param spec
>>>> +   *                The name of the location of the spec in the  
>>>> classpath,
>>>> must
>>>> +   *                not start with a '/' and must should contain a
>>>> feature.xml
>>>> +   *                file in the location
>>>> +   * @throws IOException
>>>> +   *                 If any of the resources cant be found
>>>> +   * @throws ParserConfigurationException
>>>> +   *                 If the parser has a problem being constructed
>>>> +   * @throws SAXException
>>>> +   *                 on a parse error on the features.xml
>>>> +   */
>>>> +  private void load(String spec) throws IOException, SAXException,
>>>> +      ParserConfigurationException {
>>>> +
>>>> +    List<String> scripts = getScripts(spec);
>>>> +
>>>> +    List<Script> compiled = new ArrayList<Script>();
>>>> +    for (String script : scripts) {
>>>> +      String scriptPath = spec + "/" + script;
>>>> +      InputStream in =
>>>> this.getClass().getClassLoader().getResourceAsStream(
>>>> +          scriptPath);
>>>> +      if (in == null) {
>>>> +        in = this.getClass().getClassLoader().getResourceAsStream(
>>>> +            "features/" + scriptPath);
>>>> +        if (in == null) {
>>>> +          throw new IOException("Cant load spec " + spec + " or
>>>> features/"+spec+" from classpath");
>>>> +        }
>>>> +      }
>>>> +      InputStreamReader reader = new InputStreamReader(in);
>>>> +      Script compiledScript = ctx.compileReader(reader, spec,  
>>>> 0, null);
>>>> +      compiled.add(compiledScript);
>>>> +    }
>>>> +
>>>> +    for (Script compiledScript : compiled) {
>>>> +      compiledScript.exec(ctx, scope);
>>>> +    }
>>>> +
>>>> +  }
>>>> +
>>>> +  /**
>>>> +   * Add some javascript to the context, and execute it. If  
>>>> extra custom
>>>> +   * javascript is wanted in the context or scope then this  
>>>> method will
>>>> load it.
>>>> +   *
>>>> +   * @param javascript
>>>> +   */
>>>> +  public void addScript(String javascript) {
>>>> +    Script compileScript = ctx.compileString(javascript,  
>>>> "AdditionalJS",
>>>> 0,
>>>> +        null);
>>>> +    compileScript.exec(ctx, scope);
>>>> +  }
>>>> +
>>>> +  /**
>>>> +   * Get an ordered list of javascript resources from a feature  
>>>> sets.
>>>> +   *
>>>> +   * @param spec
>>>> +   *                The spec location
>>>> +   * @return An ordered list of javascript resources, these are  
>>>> relative
>>>> to
>>>> +   *         specification file.
>>>> +   * @throws IOException
>>>> +   *                 If any of the resources can't be loaded.
>>>> +   * @throws SAXException
>>>> +   *                 Where the feature.xml file is not parsable
>>>> +   * @throws ParserConfigurationException
>>>> +   *                 where the parser can't be constructed.
>>>> +   * @return An ordered list of script that need to be loaded  
>>>> and executed
>>>> to
>>>> +   *         make the feature available in the context.
>>>> +   */
>>>> +  private List<String> getScripts(String spec) throws  
>>>> SAXException,
>>>> +      IOException, ParserConfigurationException {
>>>> +    String features = spec + "/feature.xml";
>>>> +    InputStream in = this.getClass().getClassLoader 
>>>> ().getResourceAsStream(
>>>> +        features);
>>>> +    if (in == null) {
>>>> +      in = this.getClass().getClassLoader().getResourceAsStream(
>>>> +          "features/"+features);
>>>> +      if (in == null) {
>>>> +        throw new IOException("Cant find " + features + " or  
>>>> features/" +
>>>> features+ " in classpath ");
>>>> +      }
>>>> +    }
>>>> +    DocumentBuilderFactory builderFactory = DocumentBuilderFactory
>>>> +        .newInstance();
>>>> +    DocumentBuilder documentBuilder =  
>>>> builderFactory.newDocumentBuilder();
>>>> +    Document doc = documentBuilder.parse(in);
>>>> +    NodeList nl = doc.getElementsByTagName("script");
>>>> +    List<String> scripts = new ArrayList<String>();
>>>> +    for (int i = 0; i < nl.getLength(); i++) {
>>>> +      Node scriptNode = nl.item(i);
>>>> +      NamedNodeMap attributes = scriptNode.getAttributes();
>>>> +      Node scriptAttr = attributes.getNamedItem("src");
>>>> +      String script = scriptAttr.getNodeValue();
>>>> +      scripts.add(script);
>>>> +    }
>>>> +    return scripts;
>>>> +  }
>>>> +
>>>> +  /**
>>>> +   * @param nameJSON
>>>> +   */
>>>> +  public static void dump(Map<?, ?> nameJSON) {
>>>> +    if (log.isDebugEnabled()) {
>>>> +      for (Object k : nameJSON.keySet()) {
>>>> +        Object o = nameJSON.get(k);
>>>> +        log.info("Key [" + k + "] value:["
>>>> +            + (o == null ? o : o + ":" + o.getClass()) + "]");
>>>> +      }
>>>> +    }
>>>> +  }
>>>> +
>>>> +}
>>>>
>>>> Added:
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>>>> URL:
>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>>>> api/src/test/java/org/apache/shindig/social/opensocial/util/ 
>>>> APIValidatorExpcetion.java?rev=678158&view=auto
>>>>
>>>> =================================================================== 
>>>> ===========
>>>> ---
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>>>> (added)
>>>> +++
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>>>> Sat Jul 19 06:51:03 2008
>>>> @@ -0,0 +1,42 @@
>>>> +/*
>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>> + * or more contributor license agreements. See the NOTICE file
>>>> + * distributed with this work for additional information
>>>> + * regarding copyright ownership. The ASF licenses this file
>>>> + * to you under the Apache License, Version 2.0 (the
>>>> + * "License"); you may not use this file except in compliance
>>>> + * with the License. You may obtain a copy of the License at
>>>> + *
>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>> + *
>>>> + * 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.apache.shindig.social.opensocial.util;
>>>> +
>>>> +/**
>>>> + * Thrown when there is a validation exception on one of the apis
>>>> + */
>>>> +public class APIValidatorExpcetion extends Exception {
>>>> +
>>>> +  private static final long serialVersionUID =  
>>>> -8969858718669454612L;
>>>> +
>>>> +  public APIValidatorExpcetion() {
>>>> +  }
>>>> +
>>>> +  public APIValidatorExpcetion(String message) {
>>>> +    super(message);
>>>> +  }
>>>> +
>>>> +  public APIValidatorExpcetion(Throwable cause) {
>>>> +    super(cause);
>>>> +  }
>>>> +
>>>> +  public APIValidatorExpcetion(String message, Throwable cause) {
>>>> +    super(message, cause);
>>>> +  }
>>>> +
>>>> +}
>>>>
>>>> Added:
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/APIValidatorTest.java
>>>> URL:
>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>>>> api/src/test/java/org/apache/shindig/social/opensocial/util/ 
>>>> APIValidatorTest.java?rev=678158&view=auto
>>>>
>>>> =================================================================== 
>>>> ===========
>>>> ---
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/APIValidatorTest.java
>>>> (added)
>>>> +++
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/APIValidatorTest.java
>>>> Sat Jul 19 06:51:03 2008
>>>> @@ -0,0 +1,89 @@
>>>> +/*
>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>> + * or more contributor license agreements. See the NOTICE file
>>>> + * distributed with this work for additional information
>>>> + * regarding copyright ownership. The ASF licenses this file
>>>> + * to you under the Apache License, Version 2.0 (the
>>>> + * "License"); you may not use this file except in compliance
>>>> + * with the License. You may obtain a copy of the License at
>>>> + *
>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>> + *
>>>> + * 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.apache.shindig.social.opensocial.util;
>>>> +
>>>> +
>>>> +import java.io.IOException;
>>>> +import java.util.Map;
>>>> +
>>>> +import javax.xml.parsers.ParserConfigurationException;
>>>> +
>>>> +import org.junit.Assert;
>>>> +import org.junit.Test;
>>>> +import org.xml.sax.SAXException;
>>>> +
>>>> +/**
>>>> + * Test the api validator to make certain it behaves as is  
>>>> expected.
>>>> + */
>>>> +public class APIValidatorTest {
>>>> +
>>>> +  /**
>>>> +   * A definition of the test json used in this unit test.
>>>> +   */
>>>> +  private static final String TEST_DEFINITION =
>>>> +    "var TestDef = {}; TestDef.Field = { FIELD1 : \"json\",  
>>>> FIELD2 :
>>>> \"xyz\", FIELD3 : \"shouldBeMissing\" };";
>>>> +
>>>> +  /**
>>>> +   * test the validator for successful validation
>>>> +   * @throws APIValidatorExpcetion
>>>> +   * @throws IOException
>>>> +   * @throws ParserConfigurationException
>>>> +   * @throws SAXException
>>>> +   */
>>>> +  @Test
>>>> +  public void testValidator() throws APIValidatorExpcetion,  
>>>> IOException,
>>>> ParserConfigurationException, SAXException {
>>>> +    APIValidator apiVal = new APIValidator("opensocial- 
>>>> reference");
>>>> +    apiVal.addScript(TEST_DEFINITION);
>>>> +    String[] optional = {"shouldBeMissing"};
>>>> +    String[] nullfields = {};
>>>> +     Map<String, Object> result = apiVal.validate("{ json: \"A  
>>>> Test
>>>> JSON\", xyz : 123 }", "TestDef.Field", optional, nullfields );
>>>> +     Assert.assertNotNull(result);
>>>> +     Assert.assertNotNull(result.get("json"));
>>>> +     Assert.assertNotNull(result.get("xyz"));
>>>> +     Assert.assertEquals(String.class,result.get 
>>>> ("json").getClass());
>>>> +     Assert.assertEquals(Integer.class,result.get 
>>>> ("xyz").getClass());
>>>> +     Assert.assertEquals("A Test JSON",result.get("json"));
>>>> +     Assert.assertEquals(123,((Integer)result.get 
>>>> ("xyz")).intValue());
>>>> +
>>>> +
>>>> +  }
>>>> +
>>>> +  /**
>>>> +   * Test for a failing validation
>>>> +   * @throws APIValidatorExpcetion
>>>> +   * @throws IOException
>>>> +   * @throws ParserConfigurationException
>>>> +   * @throws SAXException
>>>> +   */
>>>> +  @Test
>>>> +  public void testValidatorFail() throws APIValidatorExpcetion,
>>>> IOException, ParserConfigurationException, SAXException {
>>>> +    APIValidator apiVal = new APIValidator("opensocial- 
>>>> reference");
>>>> +    apiVal.addScript(TEST_DEFINITION);
>>>> +    String[] optional = {};
>>>> +    String[] nullfields = {};
>>>> +    try {
>>>> +      apiVal.validate("{ jsonIsMissing: \"A Test JSON\", xyz :  
>>>> 123 }",
>>>> "TestDef.Field", optional, nullfields );
>>>> +      Assert.fail("Should have Generated an  
>>>> APIValidatorException ");
>>>> +    } catch ( APIValidatorExpcetion ex ) {
>>>> +
>>>> +    }
>>>> +
>>>> +
>>>> +  }
>>>> +
>>>> +}
>>>>
>>>> Added:
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>>> URL:
>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>>>> api/src/test/java/org/apache/shindig/social/opensocial/util/ 
>>>> BeanJsonLibConverterTest.java?rev=678158&view=auto
>>>>
>>>> =================================================================== 
>>>> ===========
>>>> ---
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>>> (added)
>>>> +++
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>>> Sat Jul 19 06:51:03 2008
>>>> @@ -0,0 +1,359 @@
>>>> +/*
>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>> + * or more contributor license agreements. See the NOTICE file
>>>> + * distributed with this work for additional information
>>>> + * regarding copyright ownership. The ASF licenses this file
>>>> + * to you under the Apache License, Version 2.0 (the
>>>> + * "License"); you may not use this file except in compliance
>>>> + * with the License. You may obtain a copy of the License at
>>>> + *
>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>> + *
>>>> + * 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.apache.shindig.social.opensocial.util;
>>>> +
>>>> +import java.util.ArrayList;
>>>> +import java.util.List;
>>>> +import java.util.Map;
>>>> +
>>>> +import junit.framework.TestCase;
>>>> +
>>>> +import org.apache.commons.logging.Log;
>>>> +import org.apache.commons.logging.LogFactory;
>>>> +import org.apache.shindig.social.JsonLibTestsGuiceModule;
>>>> +import org.apache.shindig.social.opensocial.model.Activity;
>>>> +import org.apache.shindig.social.opensocial.model.ActivityImpl;
>>>> +import org.apache.shindig.social.opensocial.model.Address;
>>>> +import org.apache.shindig.social.opensocial.model.AddressImpl;
>>>> +import org.apache.shindig.social.opensocial.model.Email;
>>>> +import org.apache.shindig.social.opensocial.model.EmailImpl;
>>>> +import org.apache.shindig.social.opensocial.model.MediaItem;
>>>> +import org.apache.shindig.social.opensocial.model.MediaItemImpl;
>>>> +import org.apache.shindig.social.opensocial.model.Name;
>>>> +import org.apache.shindig.social.opensocial.model.NameImpl;
>>>> +import org.apache.shindig.social.opensocial.model.Person;
>>>> +import org.apache.shindig.social.opensocial.model.PersonImpl;
>>>> +import org.apache.shindig.social.opensocial.model.Phone;
>>>> +import org.apache.shindig.social.opensocial.model.PhoneImpl;
>>>> +
>>>> +import com.google.common.collect.Lists;
>>>> +import com.google.common.collect.Maps;
>>>> +import com.google.inject.Guice;
>>>> +
>>>> +public class BeanJsonLibConverterTest extends TestCase {
>>>> +
>>>> +  private static final Log log = LogFactory
>>>> +      .getLog(BeanJsonLibConverterTest.class);
>>>> +  private Person johnDoe;
>>>> +  private Activity activity;
>>>> +
>>>> +  private BeanJsonLibConverter beanJsonConverter;
>>>> +  private APIValidator apiValidator;
>>>> +  // set to true to get loging output at info level
>>>> +  private boolean outputInfo = false;
>>>> +
>>>> +  @Override
>>>> +  public void setUp() throws Exception {
>>>> +    super.setUp();
>>>> +    johnDoe = new PersonImpl("johnDoeId", new NameImpl("John  
>>>> Doe"));
>>>> +    johnDoe.setPhoneNumbers(Lists.<Phone> newArrayList(new  
>>>> PhoneImpl(
>>>> +        "+33H000000000", "home"), new PhoneImpl("+33M000000000",
>>>> "mobile"),
>>>> +        new PhoneImpl("+33W000000000", "work")));
>>>> +
>>>> +    johnDoe.setAddresses(Lists.<Address> newArrayList(new  
>>>> AddressImpl(
>>>> +        "My home address")));
>>>> +
>>>> +    johnDoe.setEmails(Lists.<Email> newArrayList(new EmailImpl(
>>>> +        "john.doe@work.bar", "work"),
>>>> +        new EmailImpl("john.doe@home.bar", "home")));
>>>> +
>>>> +    activity = new ActivityImpl("activityId", johnDoe.getId());
>>>> +
>>>> +    activity.setMediaItems(Lists.<MediaItem> newArrayList(new
>>>> MediaItemImpl(
>>>> +        "image/jpg", MediaItem.Type.IMAGE, "http://foo.bar")));
>>>> +
>>>> +    beanJsonConverter = new BeanJsonLibConverter(Guice
>>>> +        .createInjector(new JsonLibTestsGuiceModule()));
>>>> +
>>>> +    apiValidator = new APIValidator("opensocial-reference");
>>>> +
>>>> +  }
>>>> +
>>>> +  public static class SpecialPerson extends PersonImpl {
>>>> +    public static final String[] OPTIONALFIELDS = {};
>>>> +    public static final String[] NULLFIELDS  =
>>>> {"jobInterests","nickname","romance","religion","timeZone",
>>>> +
>>>> "relationshipStatus","tags","networkPresence","books","quotes","pho 
>>>> neNumbers","languagesSpoken",
>>>> +
>>>> "activities","jobs","dateOfBirth","profileVideo","bodyType","urls", 
>>>> "schools","music","addresses",
>>>> +
>>>> "livingArrangement","thumbnailUrl","humor","sports","scaredOf","mov 
>>>> ies","age","pets","hasApp","turnOffs",
>>>> +
>>>> "gender","fashion","drinker","aboutMe","children","sexualOrientatio 
>>>> n","heroes","profileSong","lookingFor",
>>>> +
>>>> "cars","turnOns","tvShows","profileUrl","status","currentLocation", 
>>>> "smoker","happiestWhen","ethnicity",
>>>> +
>>>> "food","emails","politicalViews","interests","familyName","honorifi 
>>>> cSuffix","additionalName","honorificPrefix","givenName"};
>>>> +
>>>> +    private String newfield;
>>>> +
>>>> +    public SpecialPerson() {
>>>> +      super();
>>>> +    }
>>>> +
>>>> +    public SpecialPerson(String id, String name, String  
>>>> newfield) {
>>>> +      super(id, new NameImpl(name));
>>>> +      this.newfield = newfield;
>>>> +    }
>>>> +
>>>> +    public String getNewfield() {
>>>> +      return newfield;
>>>> +    }
>>>> +
>>>> +    public void setNewfield(String newfield) {
>>>> +      this.newfield = newfield;
>>>> +    }
>>>> +
>>>> +  }
>>>> +
>>>> +  public void testToJsonOnInheritedClass() throws Exception {
>>>> +    SpecialPerson cassie = new SpecialPerson("5", "robot",  
>>>> "nonsense");
>>>> +
>>>> +    String result = beanJsonConverter.convertToString(cassie);
>>>> +
>>>> +    validatePerson(result, "5", "robot",  
>>>> SpecialPerson.OPTIONALFIELDS,
>>>> SpecialPerson.NULLFIELDS);
>>>> +
>>>> +    apiValidator.addScript(" specialPerson = { SPECIAL :  
>>>> \"newfield\" };
>>>> ");
>>>> +    String[] optional = {};
>>>> +    String[] nullfields = {};
>>>> +    Map<String, Object> special = apiValidator.validate(result,
>>>> +        "specialPerson", optional,nullfields);
>>>> +    assertNotNull(special.get("newfield"));
>>>> +    assertEquals(String.class, special.get("newfield").getClass 
>>>> ());
>>>> +    assertEquals("nonsense", special.get("newfield"));
>>>> +
>>>> +    // convert back into an object Tree
>>>> +
>>>> +    SpecialPerson parseCassie =  
>>>> beanJsonConverter.convertToObject(result,
>>>> +        SpecialPerson.class);
>>>> +
>>>> +    assertNotNull(parseCassie);
>>>> +    assertEquals(cassie.getId(), parseCassie.getId());
>>>> +    assertEquals(cassie.getNewfield(), parseCassie.getNewfield());
>>>> +
>>>> +    Name name = parseCassie.getName();
>>>> +    Name cassieName = cassie.getName();
>>>> +    assertNotNull(name);
>>>> +    assertEquals(cassieName.getUnstructured(),  
>>>> name.getUnstructured());
>>>> +    assertEquals(cassieName.getAdditionalName(),
>>>> name.getAdditionalName());
>>>> +    assertEquals(cassieName.getFamilyName(), name.getFamilyName 
>>>> ());
>>>> +    assertEquals(cassieName.getGivenName(), name.getGivenName());
>>>> +    assertEquals(cassieName.getHonorificPrefix(),
>>>> name.getHonorificPrefix());
>>>> +    assertEquals(cassieName.getHonorificSuffix(),
>>>> name.getHonorificSuffix());
>>>> +
>>>> +  }
>>>> +
>>>> +  /**
>>>> +   * @param result
>>>> +   * @throws APIValidatorExpcetion
>>>> +   */
>>>> +  private void validatePerson(String result, String id, String  
>>>> name,
>>>> String[] optional, String[] nullfields)
>>>> +      throws APIValidatorExpcetion {
>>>> +
>>>> +    Map<String, Object> standard = apiValidator.validate(result,
>>>> +        "opensocial.Person.Field", optional,nullfields);
>>>> +    assertNotNull(standard.get("id"));
>>>> +    assertEquals(String.class, standard.get("id").getClass());
>>>> +    assertEquals(id, standard.get("id"));
>>>> +
>>>> +    assertNotNull(standard.get("name"));
>>>> +    Map<String, Object> nameJSON = apiValidator.validateOject 
>>>> (standard
>>>> +        .get("name"), "opensocial.Name.Field",  
>>>> optional,nullfields);
>>>> +    APIValidator.dump(nameJSON);
>>>> +
>>>> +    assertNotNull(nameJSON.get("unstructured"));
>>>> +    assertEquals(String.class, nameJSON.get 
>>>> ("unstructured").getClass());
>>>> +    assertEquals(name, nameJSON.get("unstructured"));
>>>> +
>>>> +    // additional name
>>>> +    assertNull(nameJSON.get("additionalName"));
>>>> +
>>>> +  }
>>>> +
>>>> +  public void testPersonToJson() throws Exception {
>>>> +    String result = beanJsonConverter.convertToString(johnDoe);
>>>> +    if (outputInfo) {
>>>> +      log.info("JSON (" + result + ")");
>>>> +    }
>>>> +    Person parsedPerson = beanJsonConverter.convertToObject 
>>>> (result,
>>>> +        Person.class);
>>>> +
>>>> +    assertEquals(johnDoe.getId(), parsedPerson.getId());
>>>> +    assertEquals(johnDoe.getName().getUnstructured(),
>>>> parsedPerson.getName()
>>>> +        .getUnstructured());
>>>> +
>>>> +    List<Address> addresses = parsedPerson.getAddresses();
>>>> +    if (outputInfo) {
>>>> +      for (Object o : addresses) {
>>>> +        log.info("Address " + o);
>>>> +      }
>>>> +    }
>>>> +
>>>> +    assertEquals(1, addresses.size());
>>>> +    Address address = addresses.get(0);
>>>> +    String unstructured = address.getUnstructuredAddress();
>>>> +
>>>> +    assertNotNull(unstructured);
>>>> +    assertEquals(johnDoe.getAddresses().get 
>>>> (0).getUnstructuredAddress(),
>>>> +        parsedPerson.getAddresses().get 
>>>> (0).getUnstructuredAddress());
>>>> +
>>>> +    assertEquals(3, parsedPerson.getPhoneNumbers().size());
>>>> +
>>>> +    for (int i = 0; i < johnDoe.getPhoneNumbers().size(); i++) {
>>>> +      Phone expectedPhone = johnDoe.getPhoneNumbers().get(i);
>>>> +      Phone actualPhone = parsedPerson.getPhoneNumbers().get(i);
>>>> +      assertEquals(expectedPhone.getType(), actualPhone.getType 
>>>> ());
>>>> +      assertEquals(expectedPhone.getNumber(),  
>>>> actualPhone.getNumber());
>>>> +    }
>>>> +
>>>> +    assertEquals(2, parsedPerson.getEmails().size());
>>>> +
>>>> +    for (int i = 0; i < johnDoe.getEmails().size(); i++) {
>>>> +      Email expectedEmail = johnDoe.getEmails().get(i);
>>>> +      Email actualEmail = parsedPerson.getEmails().get(i);
>>>> +      assertEquals(expectedEmail.getType(), actualEmail.getType 
>>>> ());
>>>> +      assertEquals(expectedEmail.getAddress(),  
>>>> actualEmail.getAddress());
>>>> +    }
>>>> +  }
>>>> +
>>>> +  public void testActivityToJson() throws Exception {
>>>> +
>>>> +    String result = beanJsonConverter.convertToString(activity);
>>>> +    if (outputInfo) {
>>>> +      log.info("JSON (" + result + ")");
>>>> +    }
>>>> +    Activity parsedActivity = beanJsonConverter.convertToObject 
>>>> (result,
>>>> +        Activity.class);
>>>> +    assertEquals(activity.getUserId(), parsedActivity.getUserId 
>>>> ());
>>>> +    assertEquals(activity.getId(), parsedActivity.getId());
>>>> +
>>>> +    assertEquals(1, parsedActivity.getMediaItems().size());
>>>> +
>>>> +    MediaItem expectedItem = activity.getMediaItems().get(0);
>>>> +    MediaItem actualItem = parsedActivity.getMediaItems().get(0);
>>>> +
>>>> +    assertEquals(expectedItem.getUrl(), actualItem.getUrl());
>>>> +    assertEquals(expectedItem.getMimeType(),  
>>>> actualItem.getMimeType());
>>>> +    assertEquals(expectedItem.getType().toString(),  
>>>> actualItem.getType()
>>>> +        .toString());
>>>> +  }
>>>> +
>>>> +  public void testMapsToJson() throws Exception {
>>>> +    Map<String, Map<String, String>> map = Maps.newHashMap();
>>>> +
>>>> +    Map<String, String> item1Map = Maps.newHashMap();
>>>> +    item1Map.put("value", "1");
>>>> +
>>>> +    // Null values shouldn't cause exceptions
>>>> +    item1Map.put("value2", null);
>>>> +    map.put("item1", item1Map);
>>>> +
>>>> +    Map<String, String> item2Map = Maps.newHashMap();
>>>> +    item2Map.put("value", "2");
>>>> +    map.put("item2", item2Map);
>>>> +
>>>> +    String result = beanJsonConverter.convertToString(map);
>>>> +    if (outputInfo) {
>>>> +      log.info("JSON (" + result + ")");
>>>> +    }
>>>> +    // there is introspection that can tell jsonobject -> bean  
>>>> converter
>>>> what a
>>>> +    // map should contain, so we have to tell it
>>>> +    beanJsonConverter.addMapping("item1", Map.class);
>>>> +    beanJsonConverter.addMapping("item2", Map.class);
>>>> +    Map<?, ?> parsedMap = beanJsonConverter
>>>> +        .convertToObject(result, Map.class);
>>>> +
>>>> +    if (outputInfo) {
>>>> +      log.info("Dumping Map (" + parsedMap + ")");
>>>> +    }
>>>> +    APIValidator.dump(parsedMap);
>>>> +
>>>> +    assertEquals("1", ((Map<?,?>)parsedMap.get("item1")).get 
>>>> ("value"));
>>>> +    assertEquals("2", ((Map<?,?>)parsedMap.get("item2")).get 
>>>> ("value"));
>>>> +  }
>>>> +
>>>> +  public void testListsToJson() throws Exception {
>>>> +    Map<String, String> item1Map = Maps.newHashMap();
>>>> +    item1Map.put("value", "1");
>>>> +
>>>> +    Map<String, String> item2Map = Maps.newHashMap();
>>>> +    item2Map.put("value", "2");
>>>> +
>>>> +    // put the list into a container before serializing, top  
>>>> level lists
>>>> dont
>>>> +    // appear
>>>> +    // to be allowed in json
>>>> +    // just check that the list is in the holder correctly
>>>> +    List<Map<String, String>> list = new ArrayList<Map<String,  
>>>> String>>();
>>>> +    list.add(item1Map);
>>>> +    list.add(item2Map);
>>>> +    String result = beanJsonConverter.convertToString(list);
>>>> +    if (outputInfo) {
>>>> +      log.info("JSON (" + result + ")");
>>>> +    }
>>>> +    Map<?, ?>[] parsedList = beanJsonConverter.convertToObject(
>>>> +        result, Map[].class);
>>>> +
>>>> +    assertEquals("1", parsedList[0].get("value"));
>>>> +    assertEquals("2", parsedList[1].get("value"));
>>>> +  }
>>>> +
>>>> +  public void testArrayToJson() throws Exception {
>>>> +    String[] colors = { "blue", "green", "aquamarine" };
>>>> +    String result = beanJsonConverter.convertToString(colors);
>>>> +    if (outputInfo) {
>>>> +      log.info("JSON (" + result + ")");
>>>> +    }
>>>> +    String[] parsedColors = beanJsonConverter.convertToObject 
>>>> (result,
>>>> +        String[].class);
>>>> +    assertEquals(colors.length, parsedColors.length);
>>>> +    assertEquals(colors[0], parsedColors[0]);
>>>> +    assertEquals(colors[1], parsedColors[1]);
>>>> +    assertEquals(colors[2], parsedColors[2]);
>>>> +  }
>>>> +
>>>> +  public void testJsonToActivity() throws Exception {
>>>> +    String jsonActivity = "{userId : 5, id : 6, mediaItems : ["
>>>> +        + "{url : 'hello', mimeType : 'mimey', type : 'VIDEO'}"  
>>>> + "]}";
>>>> +    Activity result = beanJsonConverter.convertToObject 
>>>> (jsonActivity,
>>>> +        Activity.class);
>>>> +
>>>> +    assertEquals("5", result.getUserId());
>>>> +    assertEquals("6", result.getId());
>>>> +
>>>> +    assertEquals(1, result.getMediaItems().size());
>>>> +
>>>> +    MediaItem actualItem = result.getMediaItems().get(0);
>>>> +
>>>> +    assertEquals("hello", actualItem.getUrl());
>>>> +    assertEquals("mimey", actualItem.getMimeType());
>>>> +    assertEquals("video", actualItem.getType().toString());
>>>> +  }
>>>> +
>>>> +  public void testJsonToMap() throws Exception {
>>>> +    String jsonActivity = "{count : 0, favoriteColor : 'yellow'}";
>>>> +    Map<String, String> data = Maps.newHashMap();
>>>> +    data = beanJsonConverter.convertToObject(jsonActivity,
>>>> +        (Class<Map<String, String>>) data.getClass());
>>>> +
>>>> +    assertEquals(2, data.size());
>>>> +
>>>> +    for (String key : data.keySet()) {
>>>> +      Object value = data.get(key);
>>>> +      if (key.equals("count")) {
>>>> +        assertEquals(0, value);
>>>> +      } else if (key.equals("favoriteColor")) {
>>>> +        assertEquals("yellow", value);
>>>> +      }
>>>> +    }
>>>> +  }
>>>> +
>>>> +}
>>>>
>>>> Added:
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>>> URL:
>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>>>> api/src/test/java/org/apache/shindig/social/opensocial/util/ 
>>>> JsonConverterPerformancePerf.java?rev=678158&view=auto
>>>>
>>>> =================================================================== 
>>>> ===========
>>>> ---
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>>> (added)
>>>> +++
>>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>>> Sat Jul 19 06:51:03 2008
>>>> @@ -0,0 +1,271 @@
>>>> +/*
>>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>>> + * or more contributor license agreements. See the NOTICE file
>>>> + * distributed with this work for additional information
>>>> + * regarding copyright ownership. The ASF licenses this file
>>>> + * to you under the Apache License, Version 2.0 (the
>>>> + * "License"); you may not use this file except in compliance
>>>> + * with the License. You may obtain a copy of the License at
>>>> + *
>>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>>> + *
>>>> + * 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.apache.shindig.social.opensocial.util;
>>>> +
>>>> +import junit.framework.TestCase;
>>>> +
>>>> +import org.apache.commons.logging.Log;
>>>> +import org.apache.commons.logging.LogFactory;
>>>> +import org.apache.shindig.social.JsonLibTestsGuiceModule;
>>>> +import org.apache.shindig.social.SocialApiTestsGuiceModule;
>>>> +import org.apache.shindig.social.opensocial.model.Activity;
>>>> +import org.apache.shindig.social.opensocial.model.ActivityImpl;
>>>> +import org.apache.shindig.social.opensocial.model.Address;
>>>> +import org.apache.shindig.social.opensocial.model.AddressImpl;
>>>> +import org.apache.shindig.social.opensocial.model.Email;
>>>> +import org.apache.shindig.social.opensocial.model.EmailImpl;
>>>> +import org.apache.shindig.social.opensocial.model.MediaItem;
>>>> +import org.apache.shindig.social.opensocial.model.MediaItemImpl;
>>>> +import org.apache.shindig.social.opensocial.model.NameImpl;
>>>> +import org.apache.shindig.social.opensocial.model.Person;
>>>> +import org.apache.shindig.social.opensocial.model.PersonImpl;
>>>> +import org.apache.shindig.social.opensocial.model.Phone;
>>>> +import org.apache.shindig.social.opensocial.model.PhoneImpl;
>>>> +import org.json.JSONObject;
>>>> +
>>>> +import com.google.common.collect.Lists;
>>>> +import com.google.inject.Guice;
>>>> +
>>>> +public class JsonConverterPerformancePerf extends TestCase {
>>>> +
>>>> +  private static final Log log = LogFactory
>>>> +      .getLog(JsonConverterPerformancePerf.class);
>>>> +  private static final int TEST_SIZE = 10000;
>>>> +  private Person johnDoe;
>>>> +  private Activity activity;
>>>> +
>>>> +  private BeanJsonLibConverter beanJsonLibConverter;
>>>> +  private APIValidator apiValidator;
>>>> +  // set to true to get loging output at info level
>>>> +  private boolean outputInfo = false;
>>>> +  private BeanJsonConverter beanJsonConverter;
>>>> +
>>>> +  @Override
>>>> +  public void setUp() throws Exception {
>>>> +    super.setUp();
>>>> +    johnDoe = new PersonImpl("johnDoeId", new NameImpl("John  
>>>> Doe"));
>>>> +    johnDoe.setPhoneNumbers(Lists.<Phone> newArrayList(new  
>>>> PhoneImpl(
>>>> +        "+33H000000000", "home"), new PhoneImpl("+33M000000000",
>>>> "mobile"),
>>>> +        new PhoneImpl("+33W000000000", "work")));
>>>> +
>>>> +    johnDoe.setAddresses(Lists.<Address> newArrayList(new  
>>>> AddressImpl(
>>>> +        "My home address")));
>>>> +
>>>> +    johnDoe.setEmails(Lists.<Email> newArrayList(new EmailImpl(
>>>> +        "john.doe@work.bar", "work"),
>>>> +        new EmailImpl("john.doe@home.bar", "home")));
>>>> +
>>>> +    activity = new ActivityImpl("activityId", johnDoe.getId());
>>>> +
>>>> +    activity.setMediaItems(Lists.<MediaItem> newArrayList(new
>>>> MediaItemImpl(
>>>> +        "image/jpg", MediaItem.Type.IMAGE, "http://foo.bar")));
>>>> +
>>>> +    beanJsonLibConverter = new BeanJsonLibConverter(Guice
>>>> +        .createInjector(new JsonLibTestsGuiceModule()));
>>>> +
>>>> +    beanJsonConverter = new BeanJsonConverter(Guice
>>>> +        .createInjector(new SocialApiTestsGuiceModule()));
>>>> +
>>>> +    apiValidator = new APIValidator("opensocial-reference");
>>>> +
>>>> +  }
>>>> +
>>>> +  public static class SpecialPerson extends PersonImpl {
>>>> +    private String newfield;
>>>> +
>>>> +    public SpecialPerson() {
>>>> +      super();
>>>> +    }
>>>> +
>>>> +    public SpecialPerson(String id, String name, String  
>>>> newfield) {
>>>> +      super(id, new NameImpl(name));
>>>> +      this.newfield = newfield;
>>>> +    }
>>>> +
>>>> +    public String getNewfield() {
>>>> +      return newfield;
>>>> +    }
>>>> +
>>>> +    public void setNewfield(String newfield) {
>>>> +      this.newfield = newfield;
>>>> +    }
>>>> +
>>>> +  }
>>>> +
>>>> +  public void testToJsonLibOnInheritedClassOutput() throws  
>>>> Exception {
>>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>>>> "nonsense");
>>>> +    }
>>>> +    Runtime r = Runtime.getRuntime();
>>>> +    r.gc();
>>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>>> +    long startOutput = System.currentTimeMillis();
>>>> +    String[] output = new String[TEST_SIZE];
>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>> +      output[i] = beanJsonLibConverter.convertToString(spa[i]);
>>>> +    }
>>>> +    long endOutput = System.currentTimeMillis();
>>>> +    long memend = r.totalMemory()-r.freeMemory();
>>>> +
>>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>>> +    char[] source = output[0].toCharArray();
>>>> +    r.gc();
>>>> +
>>>> +    long stringsizeStart = r.totalMemory()-r.freeMemory();
>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>> +      serializeOutput[i] = new String(source);
>>>> +    }
>>>> +    long stringsizeEnd = r.totalMemory()-r.freeMemory();
>>>> +
>>>> +    /*
>>>> +     * Output the time per conversion and the memory usage -  
>>>> the output
>>>> per
>>>> +     * conversion.
>>>> +     *
>>>> +     */
>>>> +
>>>> +    log.info("SF JSON Lib Output "
>>>> +        + average(startOutput, endOutput, TEST_SIZE)
>>>> +        + " ms/conversion, "
>>>> +        + (average(memstart, memend, TEST_SIZE)-average 
>>>> (stringsizeStart,
>>>> stringsizeEnd, TEST_SIZE))
>>>> +        + " heap bytes/conversion, output packet consumed on  
>>>> average "
>>>> +        + average(stringsizeStart, stringsizeEnd, TEST_SIZE)+"  
>>>> for a
>>>> string length of "+output[0].length());
>>>> +    log.info("Output Was ["+output[0]+"]");
>>>> +  }
>>>> +
>>>> +  public void testToJsonLibOnInheritedClassInput() throws  
>>>> Exception {
>>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>>> +    SpecialPerson[] sparesult = new SpecialPerson[TEST_SIZE];
>>>> +    Runtime r = Runtime.getRuntime();
>>>> +    r.gc();
>>>> +    long personStart = r.totalMemory()-r.freeMemory();
>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>>>> "nonsense");
>>>> +    }
>>>> +    long personEnd = r.totalMemory()-r.freeMemory();
>>>> +
>>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>>> +    r.gc();
>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>> +
>>>> +      serializeOutput[i] = beanJsonLibConverter.convertToString 
>>>> (spa[i]);
>>>> +    }
>>>> +
>>>> +    r.gc();
>>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>>> +    long startInput = System.currentTimeMillis();
>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>> +        sparesult[i] = beanJsonLibConverter.convertToObject(
>>>> +          serializeOutput[i], SpecialPerson.class);
>>>> +    }
>>>> +    long endInput = System.currentTimeMillis();
>>>> +    long memend = r.totalMemory()-r.freeMemory();
>>>> +
>>>> +    log.info("SF JSON Lib Input "
>>>> +        + average(startInput, endInput, TEST_SIZE)
>>>> +        + " ms/conversion, "
>>>> +        + (average(memstart, memend, TEST_SIZE)-average 
>>>> (personStart,
>>>> personEnd, TEST_SIZE))
>>>> +        + " heap bytes/conversion, person object consumed on  
>>>> average "
>>>> +        + average(personStart, personEnd, TEST_SIZE));
>>>> +  }
>>>> +
>>>> +  public void testToJsonOnInheritedClassOutput() throws  
>>>> Exception {
>>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>>>> "nonsense");
>>>> +    }
>>>> +    Runtime r = Runtime.getRuntime();
>>>> +    String[] output = new String[TEST_SIZE];
>>>> +    r.gc();
>>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>>> +    long startOutput = System.currentTimeMillis();
>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>> +      output[i]  = ((JSONObject)
>>>> beanJsonConverter.convertToJson(spa[i])).toString();
>>>> +    }
>>>> +    long endOutput = System.currentTimeMillis();
>>>> +    long memend = r.totalMemory()-r.freeMemory();
>>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>>> +    char[] source = output[0].toCharArray();
>>>> +    r.gc();
>>>> +
>>>> +    long stringsizeStart = r.totalMemory()-r.freeMemory();
>>>> +
>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>> +      serializeOutput[i] = new String(source);
>>>> +    }
>>>> +    long stringsizeEnd = r.totalMemory()-r.freeMemory();
>>>> +
>>>> +    log.info("ORG JSON Lib Output "
>>>> +        + average(startOutput, endOutput, TEST_SIZE)
>>>> +        + " ms/conversion, "
>>>> +        + (average(memstart, memend, TEST_SIZE)-average 
>>>> (stringsizeStart,
>>>> stringsizeEnd, TEST_SIZE))
>>>> +        + " heap bytes/conversion, output packet consumed on  
>>>> average "
>>>> +        + average(stringsizeStart, stringsizeEnd, TEST_SIZE)+"  
>>>> for a
>>>> string length of "+output[0].length());
>>>> +    log.info("Output Was ["+output[0]+"]");
>>>> +  }
>>>> +
>>>> +  /**
>>>> +   * @param endOutput
>>>> +   * @param startOutput
>>>> +   * @param testSize
>>>> +   * @return
>>>> +   */
>>>> +  private float average(long start, long end, int testSize) {
>>>> +    float r = end - start;
>>>> +    r = r / testSize;
>>>> +    return r;
>>>> +  }
>>>> +
>>>> +  public void XtestToJsonOnInheritedClassInput() throws  
>>>> Exception {
>>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>>> +    SpecialPerson[] sparesult = new SpecialPerson[TEST_SIZE];
>>>> +    Runtime r = Runtime.getRuntime();
>>>> +    r.gc();
>>>> +    long personStart = r.totalMemory()-r.freeMemory();
>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>>>> "nonsense");
>>>> +    }
>>>> +    long personEnd = r.totalMemory()-r.freeMemory();
>>>> +
>>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>>> +    r.gc();
>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>> +
>>>> +      serializeOutput[i] = beanJsonConverter.convertToString(spa 
>>>> [i]);
>>>> +    }
>>>> +
>>>> +    r.gc();
>>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>>> +    long startInput = System.currentTimeMillis();
>>>> +
>>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>>> +      sparesult[i] = beanJsonConverter.convertToObject(
>>>> +          serializeOutput[i], SpecialPerson.class);
>>>> +    }
>>>> +    long endInput = System.currentTimeMillis();
>>>> +    long memend = r.totalMemory()-r.freeMemory();
>>>> +
>>>> +    log.info("SF JSON Lib Input "
>>>> +        + average(startInput, endInput, TEST_SIZE)
>>>> +        + " ms/conversion, "
>>>> +        + (average(memstart, memend, TEST_SIZE)-average 
>>>> (personStart,
>>>> personEnd, TEST_SIZE))
>>>> +        + " heap bytes/conversion, person object consumed on  
>>>> average "
>>>> +        + average(personStart, personEnd, TEST_SIZE));
>>>> +  }
>>>> +
>>>> +}
>>>>
>>>> Modified: incubator/shindig/trunk/pom.xml
>>>> URL:
>>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/pom.xml? 
>>>> rev=678158&r1=678157&r2=678158&view=diff
>>>>
>>>> =================================================================== 
>>>> ===========
>>>> --- incubator/shindig/trunk/pom.xml (original)
>>>> +++ incubator/shindig/trunk/pom.xml Sat Jul 19 06:51:03 2008
>>>> @@ -853,6 +853,16 @@
>>>>        <artifactId>htmlunit</artifactId>
>>>>        <version>2.1</version>
>>>>      </dependency>
>>>> +      <dependency>
>>>> +        <groupId>log4j</groupId>
>>>> +        <artifactId>log4j</artifactId>
>>>> +        <version>1.2.13</version>
>>>> +      </dependency>
>>>> +      <dependency>
>>>> +        <groupId>rhino</groupId>
>>>> +        <artifactId>js</artifactId>
>>>> +        <version>1.6R7</version>
>>>> +      </dependency>
>>>>    </dependencies>
>>>>  </dependencyManagement>
>>>> </project>
>>>>
>>>>
>>>>
>


Re: svn commit: r678158 - in /incubator/shindig/trunk: ./ java/social-api/ java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/ java/social-api/src/test/java/org/apache/shindig/social/ java/social-api/src/test/java/org/apache/shin

Posted by Chris Chabot <ch...@xs4all.nl>.
Please make sure to do proper svn move's. Last time we had 2 identical  
file names, but with different casing, everyone on a case insensitive  
file system got into trouble :)

	-- Chris

On Jul 20, 2008, at 11:02 AM, Ian Boston wrote:

> Ok will fix.
> Ian
>
> On 19 Jul 2008, at 20:50, Kevin Brown wrote:
>
>> Hey Ian,
>>
>> The casing is inconsistent here -- it should be Json and Api for  
>> all cases
>> rather than JSON or API.
>>
>> Thanks!
>>
>> On Sat, Jul 19, 2008 at 6:51 AM, <ie...@apache.org> wrote:
>>
>>> Author: ieb
>>> Date: Sat Jul 19 06:51:03 2008
>>> New Revision: 678158
>>>
>>> URL: http://svn.apache.org/viewvc?rev=678158&view=rev
>>> Log:
>>> SHINDIG-451
>>> Applying patch from the JIRA.
>>>
>>> Adds a json-lib (net.sf) converter, not wired into social-api at  
>>> present.
>>>
>>> Added:
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/JsonLibTestsGuiceModule.java
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/APIValidator.java
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/APIValidatorTest.java
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>> Modified:
>>>   incubator/shindig/trunk/java/social-api/pom.xml
>>>   incubator/shindig/trunk/pom.xml
>>>
>>> Modified: incubator/shindig/trunk/java/social-api/pom.xml
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/pom.xml?rev=678158&r1=678157&r2=678158&view=diff
>>>
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> ====================================================================
>>> --- incubator/shindig/trunk/java/social-api/pom.xml (original)
>>> +++ incubator/shindig/trunk/java/social-api/pom.xml Sat Jul 19  
>>> 06:51:03
>>> 2008
>>> @@ -60,12 +60,31 @@
>>>      <groupId>org.apache.shindig</groupId>
>>>      <artifactId>shindig-common</artifactId>
>>>    </dependency>
>>> +    <!-- is this Ok, only used in test to load the features -->
>>> +    <dependency>
>>> +      <groupId>org.apache.shindig</groupId>
>>> +      <artifactId>shindig-features</artifactId>
>>> +      <scope>test</scope>
>>> +    </dependency>
>>>
>>>    <!-- external depenencies -->
>>>    <dependency>
>>>      <groupId>org.json</groupId>
>>>      <artifactId>json</artifactId>
>>>    </dependency>
>>> +    <!-- the classifier prevents this working in dep management -->
>>> +    <dependency>
>>> +      <groupId>net.sf.json-lib</groupId>
>>> +      <artifactId>json-lib</artifactId>
>>> +      <version>2.2</version>
>>> +      <classifier>jdk15</classifier>
>>> +      <type>jar</type>
>>> +    </dependency>
>>> +    <dependency>
>>> +      <groupId>rhino</groupId>
>>> +      <artifactId>js</artifactId>
>>> +      <scope>test</scope>
>>> +    </dependency>
>>>    <dependency>
>>>      <groupId>com.google.code.guice</groupId>
>>>      <artifactId>guice</artifactId>
>>> @@ -112,5 +131,10 @@
>>>      <artifactId>core</artifactId>
>>>      <scope>compile</scope>
>>>    </dependency>
>>> +    <dependency>
>>> +      <groupId>log4j</groupId>
>>> +      <artifactId>log4j</artifactId>
>>> +      <scope>test</scope>
>>> +    </dependency>
>>>  </dependencies>
>>> </project>
>>>
>>> Added:
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConversionException.java?rev=678158&view=auto
>>>
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> ====================================================================
>>> ---
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>> (added)
>>> +++
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,43 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +/**
>>> + * Where a conversion exception happens in the Json Lib  
>>> conversion, this
>>> + * exception is thrown.
>>> + */
>>> +public class BeanJsonLibConversionException extends  
>>> RuntimeException {
>>> +
>>> +  private static final long serialVersionUID =  
>>> -8609384443448202372L;
>>> +
>>> +  public BeanJsonLibConversionException() {
>>> +  }
>>> +
>>> +  public BeanJsonLibConversionException(String arg0) {
>>> +    super(arg0);
>>> +  }
>>> +
>>> +  public BeanJsonLibConversionException(Throwable arg0) {
>>> +    super(arg0);
>>> +  }
>>> +
>>> +  public BeanJsonLibConversionException(String arg0, Throwable  
>>> arg1) {
>>> +    super(arg0, arg1);
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverter.java?rev=678158&view=auto
>>>
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> ====================================================================
>>> ---
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>>> (added)
>>> +++
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,286 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +import java.lang.reflect.Array;
>>> +import java.lang.reflect.InvocationTargetException;
>>> +import java.util.Collection;
>>> +import java.util.HashMap;
>>> +import java.util.List;
>>> +import java.util.Map;
>>> +
>>> +import net.sf.ezmorph.MorpherRegistry;
>>> +import net.sf.json.JSONArray;
>>> +import net.sf.json.JSONException;
>>> +import net.sf.json.JSONObject;
>>> +import net.sf.json.JsonConfig;
>>> +import net.sf.json.processors.DefaultValueProcessor;
>>> +import net.sf.json.util.EnumMorpher;
>>> +import net.sf.json.util.JSONUtils;
>>> +import net.sf.json.util.NewBeanInstanceStrategy;
>>> +import net.sf.json.util.PropertyFilter;
>>> +
>>> +import org.apache.commons.logging.Log;
>>> +import org.apache.commons.logging.LogFactory;
>>> +import org.apache.shindig.social.opensocial.model.Address;
>>> +import org.apache.shindig.social.opensocial.model.Email;
>>> +import org.apache.shindig.social.opensocial.model.Enum;
>>> +import org.apache.shindig.social.opensocial.model.MediaItem;
>>> +import org.apache.shindig.social.opensocial.model.Organization;
>>> +import org.apache.shindig.social.opensocial.model.Phone;
>>> +import org.apache.shindig.social.opensocial.model.Url;
>>> +
>>> +
>>> +import com.google.inject.Inject;
>>> +import com.google.inject.Injector;
>>> +
>>> +/**
>>> + *
>>> + */
>>> +public class BeanJsonLibConverter implements BeanConverter {
>>> +
>>> +  protected static final Log log = LogFactory
>>> +      .getLog(BeanJsonLibConverter.class);
>>> +  private Injector injector;
>>> +  private JsonConfig jsonConfig;
>>> +  private boolean debugMode = false;
>>> +
>>> +  /*
>>> +   * Register the Enum Morphers so that JSON -> Bean works  
>>> correctly for
>>> enums.
>>> +   */
>>> +  static {
>>> +    MorpherRegistry morpherRegistry =  
>>> JSONUtils.getMorpherRegistry();
>>> +    morpherRegistry.registerMorpher(new  
>>> EnumMorpher(Address.Field.class));
>>> +    morpherRegistry.registerMorpher(new  
>>> EnumMorpher(Phone.Field.class));
>>> +    morpherRegistry.registerMorpher(new  
>>> EnumMorpher(Email.Field.class));
>>> +    morpherRegistry.registerMorpher(new
>>> EnumMorpher(MediaItem.Field.class));
>>> +    morpherRegistry.registerMorpher(new
>>> EnumMorpher(MediaItem.Type.class));
>>> +    morpherRegistry.registerMorpher(new  
>>> EnumMorpher(Enum.Drinker.class));
>>> +    morpherRegistry.registerMorpher(new  
>>> EnumMorpher(Enum.Field.class));
>>> +    morpherRegistry.registerMorpher(new  
>>> EnumMorpher(Enum.Gender.class));
>>> +    morpherRegistry
>>> +        .registerMorpher(new  
>>> EnumMorpher(Enum.NetworkPresence.class));
>>> +    morpherRegistry.registerMorpher(new  
>>> EnumMorpher(Enum.Smoker.class));
>>> +
>>> +    morpherRegistry.registerMorpher(new JSONObjectToMapMorpher());
>>> +  }
>>> +
>>> +  @Inject
>>> +  public BeanJsonLibConverter(Injector injector) {
>>> +    this.injector = injector;
>>> +    createJsonConfig();
>>> +  }
>>> +
>>> +  @SuppressWarnings("unchecked")
>>> +  public <T> T convertToObject(String string, final Class<T>
>>> rootBeanClass) {
>>> +
>>> +    if (string.startsWith("[")) {
>>> +      JSONArray jsonArray = JSONArray.fromObject(string,  
>>> jsonConfig);
>>> +      if (debugMode) {
>>> +        JSONLibConverterUtils.dumpJsonArray(jsonArray, " ");
>>> +      }
>>> +
>>> +      if (rootBeanClass.isArray()) {
>>> +        Class<?> componentType = rootBeanClass.getComponentType();
>>> +        Object rootObject = injector.getInstance(componentType);
>>> +        List<?> o = JSONArray.toList(jsonArray, rootObject,  
>>> jsonConfig);
>>> +        Object[] result = (Object[])  
>>> Array.newInstance(componentType,
>>> o.size());
>>> +        for (int i = 0; i < o.size(); i++) {
>>> +          result[i] = o.get(i);
>>> +        }
>>> +        return (T) result;
>>> +
>>> +      } else {
>>> +        T rootObject = injector.getInstance(rootBeanClass);
>>> +        Object o = JSONArray.toArray(jsonArray, rootObject,  
>>> jsonConfig);
>>> +        return (T) o;
>>> +      }
>>> +    } else {
>>> +      JSONObject jsonObject = JSONObject.fromObject(string,  
>>> jsonConfig);
>>> +
>>> +      if (debugMode) {
>>> +        JSONLibConverterUtils.dumpJsonObject(jsonObject, " ");
>>> +      }
>>> +
>>> +      T rootObject = injector.getInstance(rootBeanClass);
>>> +      Object o = JSONObject.toBean(jsonObject, rootObject,  
>>> jsonConfig);
>>> +      return (T) o;
>>> +
>>> +    }
>>> +  }
>>> +
>>> +  /**
>>> +   * @return
>>> +   */
>>> +  private void createJsonConfig() {
>>> +
>>> +    jsonConfig = new JsonConfig();
>>> +
>>> +    /*
>>> +     * This hook deals with the creation of new beans in the JSON  
>>> -> Java
>>> Bean
>>> +     * conversion
>>> +     */
>>> +    jsonConfig.setNewBeanInstanceStrategy(new  
>>> NewBeanInstanceStrategy() {
>>> +
>>> +      @SuppressWarnings("unchecked")
>>> +      @Override
>>> +      public Object newInstance(Class beanClass, JSONObject  
>>> jsonObject)
>>> +          throws InstantiationException, IllegalAccessException,
>>> +          SecurityException, NoSuchMethodException,
>>> InvocationTargetException {
>>> +        if (beanClass != null) {
>>> +          Object o =
>>> BeanJsonLibConverter.this.injector.getInstance(beanClass);
>>> +          if (debugMode) {
>>> +            log.info("Created Object " + o + " for " + beanClass  
>>> + " with
>>> ["
>>> +                + jsonObject + "]");
>>> +          }
>>> +          return o;
>>> +        }
>>> +        return DEFAULT.newInstance(beanClass, jsonObject);
>>> +      }
>>> +
>>> +    });
>>> +
>>> +    /*
>>> +     * We are expecting null for nulls
>>> +     */
>>> +    jsonConfig.registerDefaultValueProcessor(String.class,
>>> +        new DefaultValueProcessor() {
>>> +          @SuppressWarnings("unchecked")
>>> +          public Object getDefaultValue(Class target) {
>>> +            return null;
>>> +          }
>>> +        });
>>> +
>>> +    jsonConfig.setJsonPropertyFilter(new PropertyFilter() {
>>> +
>>> +      public boolean apply(Object source, String name, Object  
>>> value) {
>>> +        return filterProperty(source, name, value);
>>> +      }
>>> +
>>> +    });
>>> +
>>> +    jsonConfig.setJavaPropertyFilter(new PropertyFilter() {
>>> +
>>> +      public boolean apply(Object source, String name, Object  
>>> value) {
>>> +        return filterProperty(source,name,value);
>>> +      }
>>> +
>>> +    });
>>> +
>>> +    // the classMap deals with the basic json string to bean  
>>> conversion
>>> +
>>> +    Map<String, Class<?>> classMap = new HashMap<String, Class<? 
>>> >>();
>>> +
>>> +    /*
>>> +     * mappings are required where there is a List of objects in  
>>> the
>>> interface
>>> +     * with no indication of what type the list should contain.  
>>> At the
>>> moment,
>>> +     * we are using 1 map for all json trees, as there is no  
>>> conflict, but
>>> if
>>> +     * there is a map could be selected on the basis of the root  
>>> object.
>>> It
>>> +     * would be better to do this with generics, but this is good  
>>> enough
>>> and
>>> +     * compact enough for the moment.
>>> +     *
>>> +     */
>>> +    //
>>> +    // activity
>>> +    classMap.put("mediaItems", MediaItem.class);
>>> +    // this may not be necessary
>>> +    classMap.put("templateParams", Map.class);
>>> +    // BodyType needs no mappings
>>> +    // Message needs no mappings
>>> +    // Name needs no mappings
>>> +    // Organization needs no mappings
>>> +    // Url needs no mappings
>>> +    // Email needs no mappings
>>> +    // Phone Needs no mappings
>>> +    // Address Needs no mappings
>>> +    // MediaItem needs no mappings
>>> +
>>> +    // Person map
>>> +    classMap.put("addresses", Address.class);
>>> +    classMap.put("phoneNumbers", Phone.class);
>>> +    classMap.put("emails", Email.class);
>>> +    classMap.put("mediaItems", MediaItem.class);
>>> +    classMap.put("jobs", Organization.class);
>>> +    classMap.put("schools", Organization.class);
>>> +    classMap.put("urls", Url.class);
>>> +    jsonConfig.setClassMap(classMap);
>>> +
>>> +  }
>>> +
>>> +  /**
>>> +   * @param source
>>> +   * @param name
>>> +   * @param value
>>> +   * @return
>>> +   */
>>> +  protected boolean filterProperty(Object source, String name,  
>>> Object
>>> value) {
>>> +    if ( value == null ) {
>>> +      return true;
>>> +    }
>>> +    if ( value instanceof JSONArray ) {
>>> +      JSONArray array = (JSONArray) value;
>>> +      if ( array.size() == 0 ) {
>>> +        return true;
>>> +      }
>>> +    }
>>> +    if ( value instanceof JSONObject ) {
>>> +      JSONObject object = (JSONObject) value;
>>> +      if ( object.isNullObject() || object.isEmpty()  ) {
>>> +        return true;
>>> +      }
>>> +    }
>>> +    if ( value instanceof Collection) {
>>> +      Collection<?> collection = (Collection<?>) value;
>>> +      if ( collection.size() == 0  ) {
>>> +        return true;
>>> +      }
>>> +    }
>>> +    if ( value instanceof Object[] ) {
>>> +      Object[] oarray = (Object[]) value;
>>> +      if ( oarray.length == 0 ) {
>>> +        return true;
>>> +      }
>>> +    }
>>> +    return false;
>>> +  }
>>> +
>>> +  public String convertToString(Object pojo) {
>>> +
>>> +    try {
>>> +      JSONObject jsonObject = JSONObject.fromObject(pojo,  
>>> jsonConfig);
>>> +      return jsonObject.toString();
>>> +    } catch (JSONException jse) {
>>> +      Class<?> pojoClass = pojo.getClass();
>>> +      if (JSONUtils.isArray(pojoClass)) {
>>> +        JSONArray jsonArray = JSONArray.fromObject(pojo);
>>> +        String result = jsonArray.toString();
>>> +        return result;
>>> +      }
>>> +      throw jse;
>>> +    }
>>> +  }
>>> +
>>> +  /**
>>> +   * @param string
>>> +   * @param class1
>>> +   */
>>> +  public void addMapping(String key, Class<?> class1) {
>>> +    jsonConfig.getClassMap().put(key, class1);
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONLibConverterUtils.java?rev=678158&view=auto
>>>
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> ====================================================================
>>> ---
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>>> (added)
>>> +++
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,72 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +import org.apache.commons.logging.Log;
>>> +import org.apache.commons.logging.LogFactory;
>>> +
>>> +import net.sf.json.JSONArray;
>>> +import net.sf.json.JSONObject;
>>> +
>>> +/**
>>> + *
>>> + */
>>> +public class JSONLibConverterUtils {
>>> +  protected static final Log log = LogFactory
>>> +  .getLog(JSONLibConverterUtils.class);
>>> +
>>> +
>>> +  /**
>>> +   * @param jsonObject
>>> +   */
>>> +  public static final void dumpJsonObject(JSONObject jsonObject,  
>>> String
>>> indent) {
>>> +    for (Object key : jsonObject.keySet()) {
>>> +      Object value = jsonObject.get(key);
>>> +      if (value instanceof JSONObject) {
>>> +        log.info(indent + key + ":JSONObject");
>>> +        dumpJsonObject((JSONObject) value, indent + "  ");
>>> +      } else if (value instanceof JSONArray) {
>>> +        log.info(indent + key + ":JSONArray " + ((JSONArray)
>>> value).size());
>>> +        dumpJsonArray((JSONArray) value, indent + "  ");
>>> +      } else {
>>> +        log.info(indent + key + ":" + value + ":"
>>> +            + (value == null ? "na" : value.getClass()));
>>> +      }
>>> +    }
>>> +  }
>>> +
>>> +
>>> +  /**
>>> +   * @param value
>>> +   * @param string
>>> +   */
>>> +  static void dumpJsonArray(JSONArray array, String indent) {
>>> +    for (Object value : array) {
>>> +      if (value instanceof JSONObject) {
>>> +        log.info(indent + ":JSONObject");
>>> +        dumpJsonObject((JSONObject) value, indent + "  ");
>>> +      } else if (value instanceof JSONArray) {
>>> +        log.info(indent + ":JSONArray " + ((JSONArray)  
>>> value).size());
>>> +        dumpJsonArray((JSONArray) value, indent + "  ");
>>> +      } else {
>>> +        log.info(indent + ":" + value + ":"
>>> +            + (value == null ? "na" : value.getClass()));
>>> +      }
>>> +    }
>>> +  }
>>> +}
>>>
>>> Added:
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONObjectToMapMorpher.java?rev=678158&view=auto
>>>
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> ====================================================================
>>> ---
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>> (added)
>>> +++
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,50 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +import java.util.HashMap;
>>> +import java.util.Map;
>>> +
>>> +import net.sf.ezmorph.Morpher;
>>> +import net.sf.ezmorph.ObjectMorpher;
>>> +import net.sf.json.JSONObject;
>>> +
>>> +/**
>>> + *
>>> + */
>>> +public class JSONObjectToMapMorpher implements Morpher,  
>>> ObjectMorpher {
>>> +
>>> +  public Class<?> morphsTo() {
>>> +    return Map.class;
>>> +  }
>>> +
>>> +  @SuppressWarnings("unchecked")
>>> +  public boolean supports(Class clazz) {
>>> +    return (JSONObject.class.equals(clazz));
>>> +  }
>>> +
>>> +  public Object morph(Object bean) {
>>> +    Map<Object, Object> result = new HashMap<Object, Object>();
>>> +    JSONObject jsonObject = (JSONObject) bean;
>>> +    for ( Object key : jsonObject.keySet()) {
>>> +      result.put(key,jsonObject.get(key));
>>> +    }
>>> +    return result;
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/JsonLibTestsGuiceModule.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/JsonLibTestsGuiceModule.java?rev=678158&view=auto
>>>
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> ====================================================================
>>> ---
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/JsonLibTestsGuiceModule.java
>>> (added)
>>> +++
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/JsonLibTestsGuiceModule.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,40 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements.  See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership.  The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License.  You may obtain a copy of the License at
>>> + *
>>> + *   http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social;
>>> +
>>> +import java.util.ArrayList;
>>> +import java.util.HashMap;
>>> +import java.util.List;
>>> +import java.util.Map;
>>> +
>>> +import com.google.inject.AbstractModule;
>>> +
>>> +/**
>>> + * Provides social api component injection for all large tests
>>> + */
>>> +public class JsonLibTestsGuiceModule extends AbstractModule {
>>> +  @Override
>>> +  protected void configure() {
>>> +
>>> +    bind(Map.class).to(HashMap.class);
>>> +    bind(List.class).to(ArrayList.class);
>>> +    bind(Map[].class).to(HashMap[].class);
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/APIValidator.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidator.java?rev=678158&view=auto
>>>
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> ====================================================================
>>> ---
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/APIValidator.java
>>> (added)
>>> +++
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/APIValidator.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,352 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +import java.io.IOException;
>>> +import java.io.InputStream;
>>> +import java.io.InputStreamReader;
>>> +import java.util.ArrayList;
>>> +import java.util.HashMap;
>>> +import java.util.List;
>>> +import java.util.Map;
>>> +
>>> +import javax.xml.parsers.DocumentBuilder;
>>> +import javax.xml.parsers.DocumentBuilderFactory;
>>> +import javax.xml.parsers.ParserConfigurationException;
>>> +
>>> +import org.apache.commons.logging.Log;
>>> +import org.apache.commons.logging.LogFactory;
>>> +import org.mozilla.javascript.Context;
>>> +import org.mozilla.javascript.EvaluatorException;
>>> +import org.mozilla.javascript.Script;
>>> +import org.mozilla.javascript.ScriptableObject;
>>> +import org.w3c.dom.Document;
>>> +import org.w3c.dom.NamedNodeMap;
>>> +import org.w3c.dom.Node;
>>> +import org.w3c.dom.NodeList;
>>> +import org.xml.sax.SAXException;
>>> +
>>> +/**
>>> + * A class that loads a feature set from features into a  
>>> Javascript Parser
>>> to
>>> + * make the model available to validate JSON messages against.
>>> + */
>>> +public class APIValidator {
>>> +
>>> +  private static final Log log =  
>>> LogFactory.getLog(APIValidator.class);
>>> +  private Context ctx;
>>> +  private ScriptableObject scope;
>>> +
>>> +  /**
>>> +   * @param feature
>>> +   *                The name of the feature are eg "opensocial- 
>>> reference",
>>> this
>>> +   *                is a classpath stub (not starting with /)  
>>> where the
>>> location
>>> +   *                contains a feature.xml file.
>>> +   * @throws SAXException
>>> +   *                 if feature.xml is not parsable
>>> +   * @throws ParserConfigurationException
>>> +   *                 if the parsers are invalid
>>> +   * @throws IOException
>>> +   *                 if feature.xml or the javascript that  
>>> represents the
>>> +   *                 feature is missing
>>> +   *
>>> +   */
>>> +  public APIValidator(String feature) throws IOException,
>>> +      ParserConfigurationException, SAXException {
>>> +    ctx = Context.enter();
>>> +    scope = ctx.initStandardObjects();
>>> +    load(feature);
>>> +  }
>>> +
>>> +  /**
>>> +   * @param json
>>> +   *                The json to validate expected in a form  
>>> { xyz: yyy }
>>> form
>>> +   * @param object
>>> +   *                The json Fields object specifying the  
>>> structure of the
>>> json
>>> +   *                object, each field in this object contains  
>>> the name of
>>> the
>>> +   *                json field in the json structure.
>>> +   * @param optionalFields
>>> +   *                If any of the fields that appear in the json  
>>> structure
>>> are
>>> +   *                optional, then they should be defined in this
>>> parameter.
>>> +   * @param nullfields
>>> +   * @throws APIValidatorExpcetion
>>> +   *                 if there is a problem validating the json
>>> +   * @return a map so string object pairs containing the fields  
>>> at the top
>>> level
>>> +   *         of the json tree. Where these are native java  
>>> objects, they
>>> will
>>> +   *         appear as native object. Complex json objects will  
>>> appear as
>>> Rhino
>>> +   *         specific objects
>>> +   */
>>> +  public Map<String, Object> validate(String json, String object,
>>> +      String[] optionalFields, String[] nullfields)
>>> +      throws APIValidatorExpcetion {
>>> +
>>> +    /*
>>> +     * Object[] ids = ScriptableObject.getPropertyIds(scope); for  
>>> (Object
>>> id :
>>> +     * ids) { Object o = ScriptableObject.getProperty(scope,
>>> +     * String.valueOf(id)); log.debug("ID is " + id + " class " +
>>> id.getClass() + "
>>> +     * is " + o); if (o instanceof ScriptableObject) {
>>> +     * listScriptable(String.valueOf(id), (ScriptableObject)  
>>> o); } }
>>> +     */
>>> +
>>> +    log.debug("Loading " + json);
>>> +    json = json.trim();
>>> +    if (!json.endsWith("}")) {
>>> +      json = json + "}";
>>> +    }
>>> +    if (!json.startsWith("{")) {
>>> +      json = "{" + json;
>>> +    }
>>> +    json = "( testingObject = " + json + " )";
>>> +
>>> +    Object so = null;
>>> +    try {
>>> +      so = ctx.evaluateString(scope, json, "test json", 0, null);
>>> +    } catch (EvaluatorException ex) {
>>> +      log.error("Non parseable JSON " + json);
>>> +    }
>>> +    log.debug("Loaded " + so);
>>> +
>>> +    return validateOject(so, object, optionalFields, nullfields);
>>> +
>>> +  }
>>> +
>>> +  /**
>>> +   * Validate an JSON Object extracted
>>> +   *
>>> +   * @param object
>>> +   * @param string
>>> +   * @param optional
>>> +   * @return
>>> +   * @throws APIValidatorExpcetion
>>> +   */
>>> +  public Map<String, Object> validateOject(Object jsonObject,  
>>> String
>>> object,
>>> +      String[] optionalFields, String[] nullFields)
>>> +      throws APIValidatorExpcetion {
>>> +    Map<String, String> optional = new HashMap<String, String>();
>>> +    for (String opt : optionalFields) {
>>> +      optional.put(opt, opt);
>>> +    }
>>> +    Map<String, String> nullf = new HashMap<String, String>();
>>> +    for (String nf : nullFields) {
>>> +      nullf.put(nf, nf);
>>> +    }
>>> +
>>> +    ScriptableObject specification = getScriptableObject(object);
>>> +    log.debug("Looking for  " + object + " found " +  
>>> specification);
>>> +    listScriptable(object, specification);
>>> +
>>> +    Map<String, Object> resultFields = new HashMap<String,  
>>> Object>();
>>> +
>>> +    if (jsonObject instanceof ScriptableObject) {
>>> +      ScriptableObject parsedJSONObject = (ScriptableObject)  
>>> jsonObject;
>>> +      listScriptable("testingObject", parsedJSONObject);
>>> +      Object[] fields = specification.getIds();
>>> +      for (Object f : fields) {
>>> +        Object fieldName = specification.get(String.valueOf(f),
>>> specification);
>>> +        Object o = parsedJSONObject.get(String.valueOf(fieldName),
>>> +            parsedJSONObject);
>>> +        if (o == ScriptableObject.NOT_FOUND) {
>>> +          if (optional.containsKey(fieldName)) {
>>> +            log.warn("Missing Optional Field " + fieldName);
>>> +          } else if (!nullf.containsKey(fieldName)) {
>>> +            log.error("Missing Field " + fieldName);
>>> +            throw new APIValidatorExpcetion("Missing Field " +  
>>> fieldName);
>>> +          }
>>> +        } else {
>>> +          if (nullf.containsKey(fieldName)) {
>>> +            log.error("Field should have been null and was not");
>>> +          }
>>> +          if (o == null) {
>>> +            if (nullf.containsKey(fieldName)) {
>>> +              log.error("Null Fields has been serialized " +  
>>> fieldName);
>>> +            }
>>> +            log.debug("Got a Null object for Field " + f + ":" +  
>>> fieldName
>>> +                + " on json [[" + jsonObject + "]]");
>>> +
>>> +          } else {
>>> +
>>> +            log.debug("Got JSON Field  Field," + f + ":" +  
>>> fieldName + "
>>> as "
>>> +                + o + " " + o.getClass());
>>> +          }
>>> +          resultFields.put(String.valueOf(fieldName), o);
>>> +        }
>>> +      }
>>> +
>>> +    } else {
>>> +      throw new APIValidatorExpcetion(
>>> +          "Parsing JSON resulted in invalid Javascript object,  
>>> which was "
>>> +              + jsonObject + " JSON was [[" + jsonObject + "]]");
>>> +    }
>>> +    return resultFields;
>>> +  }
>>> +
>>> +  /**
>>> +   * get an object from the json context and scope.
>>> +   *
>>> +   * @param object
>>> +   *                the name of the object specified as a path  
>>> from the
>>> base
>>> +   *                object
>>> +   * @return the json object
>>> +   */
>>> +  private ScriptableObject getScriptableObject(String object) {
>>> +    String[] path = object.split("\\.");
>>> +    log.debug("Looking up " + object + " elements " + path.length);
>>> +
>>> +    ScriptableObject s = scope;
>>> +    for (String pe : path) {
>>> +      log.debug("Looking up " + pe + " in " + s);
>>> +      s = (ScriptableObject) s.get(pe, s);
>>> +      log.debug("Looking for " + pe + " in found " + s);
>>> +    }
>>> +    return s;
>>> +  }
>>> +
>>> +  /**
>>> +   * List a scriptable object at log debug level, constructors  
>>> will not be
>>> +   * expanded as this loads to recursion.
>>> +   *
>>> +   * @param id
>>> +   *                The name of the object
>>> +   * @param scriptableObject
>>> +   *                the scriptable Object
>>> +   */
>>> +  private void listScriptable(String id, ScriptableObject
>>> scriptableObject) {
>>> +    log.debug("ID is Scriptable " + id);
>>> +    if (!id.endsWith("constructor")) {
>>> +      Object[] allIDs = scriptableObject.getAllIds();
>>> +      for (Object oid : allIDs) {
>>> +        log.debug(id + "." + oid);
>>> +        Object o = scriptableObject.get(String.valueOf(oid),
>>> scriptableObject);
>>> +        if (o instanceof ScriptableObject) {
>>> +          listScriptable(id + "." + String.valueOf(oid),
>>> (ScriptableObject) o);
>>> +        }
>>> +      }
>>> +    }
>>> +  }
>>> +
>>> +  /**
>>> +   * Load a feature based on the spec
>>> +   *
>>> +   * @param spec
>>> +   *                The name of the location of the spec in the  
>>> classpath,
>>> must
>>> +   *                not start with a '/' and must should contain a
>>> feature.xml
>>> +   *                file in the location
>>> +   * @throws IOException
>>> +   *                 If any of the resources cant be found
>>> +   * @throws ParserConfigurationException
>>> +   *                 If the parser has a problem being constructed
>>> +   * @throws SAXException
>>> +   *                 on a parse error on the features.xml
>>> +   */
>>> +  private void load(String spec) throws IOException, SAXException,
>>> +      ParserConfigurationException {
>>> +
>>> +    List<String> scripts = getScripts(spec);
>>> +
>>> +    List<Script> compiled = new ArrayList<Script>();
>>> +    for (String script : scripts) {
>>> +      String scriptPath = spec + "/" + script;
>>> +      InputStream in =
>>> this.getClass().getClassLoader().getResourceAsStream(
>>> +          scriptPath);
>>> +      if (in == null) {
>>> +        in = this.getClass().getClassLoader().getResourceAsStream(
>>> +            "features/" + scriptPath);
>>> +        if (in == null) {
>>> +          throw new IOException("Cant load spec " + spec + " or
>>> features/"+spec+" from classpath");
>>> +        }
>>> +      }
>>> +      InputStreamReader reader = new InputStreamReader(in);
>>> +      Script compiledScript = ctx.compileReader(reader, spec, 0,  
>>> null);
>>> +      compiled.add(compiledScript);
>>> +    }
>>> +
>>> +    for (Script compiledScript : compiled) {
>>> +      compiledScript.exec(ctx, scope);
>>> +    }
>>> +
>>> +  }
>>> +
>>> +  /**
>>> +   * Add some javascript to the context, and execute it. If extra  
>>> custom
>>> +   * javascript is wanted in the context or scope then this  
>>> method will
>>> load it.
>>> +   *
>>> +   * @param javascript
>>> +   */
>>> +  public void addScript(String javascript) {
>>> +    Script compileScript = ctx.compileString(javascript,  
>>> "AdditionalJS",
>>> 0,
>>> +        null);
>>> +    compileScript.exec(ctx, scope);
>>> +  }
>>> +
>>> +  /**
>>> +   * Get an ordered list of javascript resources from a feature  
>>> sets.
>>> +   *
>>> +   * @param spec
>>> +   *                The spec location
>>> +   * @return An ordered list of javascript resources, these are  
>>> relative
>>> to
>>> +   *         specification file.
>>> +   * @throws IOException
>>> +   *                 If any of the resources can't be loaded.
>>> +   * @throws SAXException
>>> +   *                 Where the feature.xml file is not parsable
>>> +   * @throws ParserConfigurationException
>>> +   *                 where the parser can't be constructed.
>>> +   * @return An ordered list of script that need to be loaded and  
>>> executed
>>> to
>>> +   *         make the feature available in the context.
>>> +   */
>>> +  private List<String> getScripts(String spec) throws SAXException,
>>> +      IOException, ParserConfigurationException {
>>> +    String features = spec + "/feature.xml";
>>> +    InputStream in =  
>>> this.getClass().getClassLoader().getResourceAsStream(
>>> +        features);
>>> +    if (in == null) {
>>> +      in = this.getClass().getClassLoader().getResourceAsStream(
>>> +          "features/"+features);
>>> +      if (in == null) {
>>> +        throw new IOException("Cant find " + features + " or  
>>> features/" +
>>> features+ " in classpath ");
>>> +      }
>>> +    }
>>> +    DocumentBuilderFactory builderFactory = DocumentBuilderFactory
>>> +        .newInstance();
>>> +    DocumentBuilder documentBuilder =  
>>> builderFactory.newDocumentBuilder();
>>> +    Document doc = documentBuilder.parse(in);
>>> +    NodeList nl = doc.getElementsByTagName("script");
>>> +    List<String> scripts = new ArrayList<String>();
>>> +    for (int i = 0; i < nl.getLength(); i++) {
>>> +      Node scriptNode = nl.item(i);
>>> +      NamedNodeMap attributes = scriptNode.getAttributes();
>>> +      Node scriptAttr = attributes.getNamedItem("src");
>>> +      String script = scriptAttr.getNodeValue();
>>> +      scripts.add(script);
>>> +    }
>>> +    return scripts;
>>> +  }
>>> +
>>> +  /**
>>> +   * @param nameJSON
>>> +   */
>>> +  public static void dump(Map<?, ?> nameJSON) {
>>> +    if (log.isDebugEnabled()) {
>>> +      for (Object k : nameJSON.keySet()) {
>>> +        Object o = nameJSON.get(k);
>>> +        log.info("Key [" + k + "] value:["
>>> +            + (o == null ? o : o + ":" + o.getClass()) + "]");
>>> +      }
>>> +    }
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorExpcetion.java?rev=678158&view=auto
>>>
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> ====================================================================
>>> ---
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>>> (added)
>>> +++
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,42 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +/**
>>> + * Thrown when there is a validation exception on one of the apis
>>> + */
>>> +public class APIValidatorExpcetion extends Exception {
>>> +
>>> +  private static final long serialVersionUID =  
>>> -8969858718669454612L;
>>> +
>>> +  public APIValidatorExpcetion() {
>>> +  }
>>> +
>>> +  public APIValidatorExpcetion(String message) {
>>> +    super(message);
>>> +  }
>>> +
>>> +  public APIValidatorExpcetion(Throwable cause) {
>>> +    super(cause);
>>> +  }
>>> +
>>> +  public APIValidatorExpcetion(String message, Throwable cause) {
>>> +    super(message, cause);
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/APIValidatorTest.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorTest.java?rev=678158&view=auto
>>>
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> ====================================================================
>>> ---
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/APIValidatorTest.java
>>> (added)
>>> +++
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/APIValidatorTest.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,89 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +
>>> +import java.io.IOException;
>>> +import java.util.Map;
>>> +
>>> +import javax.xml.parsers.ParserConfigurationException;
>>> +
>>> +import org.junit.Assert;
>>> +import org.junit.Test;
>>> +import org.xml.sax.SAXException;
>>> +
>>> +/**
>>> + * Test the api validator to make certain it behaves as is  
>>> expected.
>>> + */
>>> +public class APIValidatorTest {
>>> +
>>> +  /**
>>> +   * A definition of the test json used in this unit test.
>>> +   */
>>> +  private static final String TEST_DEFINITION =
>>> +    "var TestDef = {}; TestDef.Field = { FIELD1 : \"json\",  
>>> FIELD2 :
>>> \"xyz\", FIELD3 : \"shouldBeMissing\" };";
>>> +
>>> +  /**
>>> +   * test the validator for successful validation
>>> +   * @throws APIValidatorExpcetion
>>> +   * @throws IOException
>>> +   * @throws ParserConfigurationException
>>> +   * @throws SAXException
>>> +   */
>>> +  @Test
>>> +  public void testValidator() throws APIValidatorExpcetion,  
>>> IOException,
>>> ParserConfigurationException, SAXException {
>>> +    APIValidator apiVal = new APIValidator("opensocial-reference");
>>> +    apiVal.addScript(TEST_DEFINITION);
>>> +    String[] optional = {"shouldBeMissing"};
>>> +    String[] nullfields = {};
>>> +     Map<String, Object> result = apiVal.validate("{ json: \"A Test
>>> JSON\", xyz : 123 }", "TestDef.Field", optional, nullfields );
>>> +     Assert.assertNotNull(result);
>>> +     Assert.assertNotNull(result.get("json"));
>>> +     Assert.assertNotNull(result.get("xyz"));
>>> +      
>>> Assert.assertEquals(String.class,result.get("json").getClass());
>>> +      
>>> Assert.assertEquals(Integer.class,result.get("xyz").getClass());
>>> +     Assert.assertEquals("A Test JSON",result.get("json"));
>>> +     Assert.assertEquals(123, 
>>> ((Integer)result.get("xyz")).intValue());
>>> +
>>> +
>>> +  }
>>> +
>>> +  /**
>>> +   * Test for a failing validation
>>> +   * @throws APIValidatorExpcetion
>>> +   * @throws IOException
>>> +   * @throws ParserConfigurationException
>>> +   * @throws SAXException
>>> +   */
>>> +  @Test
>>> +  public void testValidatorFail() throws APIValidatorExpcetion,
>>> IOException, ParserConfigurationException, SAXException {
>>> +    APIValidator apiVal = new APIValidator("opensocial-reference");
>>> +    apiVal.addScript(TEST_DEFINITION);
>>> +    String[] optional = {};
>>> +    String[] nullfields = {};
>>> +    try {
>>> +      apiVal.validate("{ jsonIsMissing: \"A Test JSON\", xyz :  
>>> 123 }",
>>> "TestDef.Field", optional, nullfields );
>>> +      Assert.fail("Should have Generated an APIValidatorException  
>>> ");
>>> +    } catch ( APIValidatorExpcetion ex ) {
>>> +
>>> +    }
>>> +
>>> +
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverterTest.java?rev=678158&view=auto
>>>
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> ====================================================================
>>> ---
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>> (added)
>>> +++
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,359 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +import java.util.ArrayList;
>>> +import java.util.List;
>>> +import java.util.Map;
>>> +
>>> +import junit.framework.TestCase;
>>> +
>>> +import org.apache.commons.logging.Log;
>>> +import org.apache.commons.logging.LogFactory;
>>> +import org.apache.shindig.social.JsonLibTestsGuiceModule;
>>> +import org.apache.shindig.social.opensocial.model.Activity;
>>> +import org.apache.shindig.social.opensocial.model.ActivityImpl;
>>> +import org.apache.shindig.social.opensocial.model.Address;
>>> +import org.apache.shindig.social.opensocial.model.AddressImpl;
>>> +import org.apache.shindig.social.opensocial.model.Email;
>>> +import org.apache.shindig.social.opensocial.model.EmailImpl;
>>> +import org.apache.shindig.social.opensocial.model.MediaItem;
>>> +import org.apache.shindig.social.opensocial.model.MediaItemImpl;
>>> +import org.apache.shindig.social.opensocial.model.Name;
>>> +import org.apache.shindig.social.opensocial.model.NameImpl;
>>> +import org.apache.shindig.social.opensocial.model.Person;
>>> +import org.apache.shindig.social.opensocial.model.PersonImpl;
>>> +import org.apache.shindig.social.opensocial.model.Phone;
>>> +import org.apache.shindig.social.opensocial.model.PhoneImpl;
>>> +
>>> +import com.google.common.collect.Lists;
>>> +import com.google.common.collect.Maps;
>>> +import com.google.inject.Guice;
>>> +
>>> +public class BeanJsonLibConverterTest extends TestCase {
>>> +
>>> +  private static final Log log = LogFactory
>>> +      .getLog(BeanJsonLibConverterTest.class);
>>> +  private Person johnDoe;
>>> +  private Activity activity;
>>> +
>>> +  private BeanJsonLibConverter beanJsonConverter;
>>> +  private APIValidator apiValidator;
>>> +  // set to true to get loging output at info level
>>> +  private boolean outputInfo = false;
>>> +
>>> +  @Override
>>> +  public void setUp() throws Exception {
>>> +    super.setUp();
>>> +    johnDoe = new PersonImpl("johnDoeId", new NameImpl("John  
>>> Doe"));
>>> +    johnDoe.setPhoneNumbers(Lists.<Phone> newArrayList(new  
>>> PhoneImpl(
>>> +        "+33H000000000", "home"), new PhoneImpl("+33M000000000",
>>> "mobile"),
>>> +        new PhoneImpl("+33W000000000", "work")));
>>> +
>>> +    johnDoe.setAddresses(Lists.<Address> newArrayList(new  
>>> AddressImpl(
>>> +        "My home address")));
>>> +
>>> +    johnDoe.setEmails(Lists.<Email> newArrayList(new EmailImpl(
>>> +        "john.doe@work.bar", "work"),
>>> +        new EmailImpl("john.doe@home.bar", "home")));
>>> +
>>> +    activity = new ActivityImpl("activityId", johnDoe.getId());
>>> +
>>> +    activity.setMediaItems(Lists.<MediaItem> newArrayList(new
>>> MediaItemImpl(
>>> +        "image/jpg", MediaItem.Type.IMAGE, "http://foo.bar")));
>>> +
>>> +    beanJsonConverter = new BeanJsonLibConverter(Guice
>>> +        .createInjector(new JsonLibTestsGuiceModule()));
>>> +
>>> +    apiValidator = new APIValidator("opensocial-reference");
>>> +
>>> +  }
>>> +
>>> +  public static class SpecialPerson extends PersonImpl {
>>> +    public static final String[] OPTIONALFIELDS = {};
>>> +    public static final String[] NULLFIELDS  =
>>> {"jobInterests","nickname","romance","religion","timeZone",
>>> +
>>> "relationshipStatus 
>>> ","tags 
>>> ","networkPresence 
>>> ","books","quotes","phoneNumbers","languagesSpoken",
>>> +
>>> "activities 
>>> ","jobs 
>>> ","dateOfBirth 
>>> ","profileVideo","bodyType","urls","schools","music","addresses",
>>> +
>>> "livingArrangement 
>>> ","thumbnailUrl 
>>> ","humor 
>>> ","sports","scaredOf","movies","age","pets","hasApp","turnOffs",
>>> +
>>> "gender 
>>> ","fashion 
>>> ","drinker 
>>> ","aboutMe 
>>> ","children 
>>> ","sexualOrientation","heroes","profileSong","lookingFor",
>>> +
>>> "cars 
>>> ","turnOns 
>>> ","tvShows 
>>> ","profileUrl 
>>> ","status","currentLocation","smoker","happiestWhen","ethnicity",
>>> +
>>> "food 
>>> ","emails 
>>> ","politicalViews 
>>> ","interests 
>>> ","familyName 
>>> ","honorificSuffix","additionalName","honorificPrefix","givenName"};
>>> +
>>> +    private String newfield;
>>> +
>>> +    public SpecialPerson() {
>>> +      super();
>>> +    }
>>> +
>>> +    public SpecialPerson(String id, String name, String newfield) {
>>> +      super(id, new NameImpl(name));
>>> +      this.newfield = newfield;
>>> +    }
>>> +
>>> +    public String getNewfield() {
>>> +      return newfield;
>>> +    }
>>> +
>>> +    public void setNewfield(String newfield) {
>>> +      this.newfield = newfield;
>>> +    }
>>> +
>>> +  }
>>> +
>>> +  public void testToJsonOnInheritedClass() throws Exception {
>>> +    SpecialPerson cassie = new SpecialPerson("5", "robot",  
>>> "nonsense");
>>> +
>>> +    String result = beanJsonConverter.convertToString(cassie);
>>> +
>>> +    validatePerson(result, "5", "robot",  
>>> SpecialPerson.OPTIONALFIELDS,
>>> SpecialPerson.NULLFIELDS);
>>> +
>>> +    apiValidator.addScript(" specialPerson = { SPECIAL :  
>>> \"newfield\" };
>>> ");
>>> +    String[] optional = {};
>>> +    String[] nullfields = {};
>>> +    Map<String, Object> special = apiValidator.validate(result,
>>> +        "specialPerson", optional,nullfields);
>>> +    assertNotNull(special.get("newfield"));
>>> +    assertEquals(String.class, special.get("newfield").getClass());
>>> +    assertEquals("nonsense", special.get("newfield"));
>>> +
>>> +    // convert back into an object Tree
>>> +
>>> +    SpecialPerson parseCassie =  
>>> beanJsonConverter.convertToObject(result,
>>> +        SpecialPerson.class);
>>> +
>>> +    assertNotNull(parseCassie);
>>> +    assertEquals(cassie.getId(), parseCassie.getId());
>>> +    assertEquals(cassie.getNewfield(), parseCassie.getNewfield());
>>> +
>>> +    Name name = parseCassie.getName();
>>> +    Name cassieName = cassie.getName();
>>> +    assertNotNull(name);
>>> +    assertEquals(cassieName.getUnstructured(),  
>>> name.getUnstructured());
>>> +    assertEquals(cassieName.getAdditionalName(),
>>> name.getAdditionalName());
>>> +    assertEquals(cassieName.getFamilyName(), name.getFamilyName());
>>> +    assertEquals(cassieName.getGivenName(), name.getGivenName());
>>> +    assertEquals(cassieName.getHonorificPrefix(),
>>> name.getHonorificPrefix());
>>> +    assertEquals(cassieName.getHonorificSuffix(),
>>> name.getHonorificSuffix());
>>> +
>>> +  }
>>> +
>>> +  /**
>>> +   * @param result
>>> +   * @throws APIValidatorExpcetion
>>> +   */
>>> +  private void validatePerson(String result, String id, String  
>>> name,
>>> String[] optional, String[] nullfields)
>>> +      throws APIValidatorExpcetion {
>>> +
>>> +    Map<String, Object> standard = apiValidator.validate(result,
>>> +        "opensocial.Person.Field", optional,nullfields);
>>> +    assertNotNull(standard.get("id"));
>>> +    assertEquals(String.class, standard.get("id").getClass());
>>> +    assertEquals(id, standard.get("id"));
>>> +
>>> +    assertNotNull(standard.get("name"));
>>> +    Map<String, Object> nameJSON =  
>>> apiValidator.validateOject(standard
>>> +        .get("name"), "opensocial.Name.Field",  
>>> optional,nullfields);
>>> +    APIValidator.dump(nameJSON);
>>> +
>>> +    assertNotNull(nameJSON.get("unstructured"));
>>> +    assertEquals(String.class,  
>>> nameJSON.get("unstructured").getClass());
>>> +    assertEquals(name, nameJSON.get("unstructured"));
>>> +
>>> +    // additional name
>>> +    assertNull(nameJSON.get("additionalName"));
>>> +
>>> +  }
>>> +
>>> +  public void testPersonToJson() throws Exception {
>>> +    String result = beanJsonConverter.convertToString(johnDoe);
>>> +    if (outputInfo) {
>>> +      log.info("JSON (" + result + ")");
>>> +    }
>>> +    Person parsedPerson = beanJsonConverter.convertToObject(result,
>>> +        Person.class);
>>> +
>>> +    assertEquals(johnDoe.getId(), parsedPerson.getId());
>>> +    assertEquals(johnDoe.getName().getUnstructured(),
>>> parsedPerson.getName()
>>> +        .getUnstructured());
>>> +
>>> +    List<Address> addresses = parsedPerson.getAddresses();
>>> +    if (outputInfo) {
>>> +      for (Object o : addresses) {
>>> +        log.info("Address " + o);
>>> +      }
>>> +    }
>>> +
>>> +    assertEquals(1, addresses.size());
>>> +    Address address = addresses.get(0);
>>> +    String unstructured = address.getUnstructuredAddress();
>>> +
>>> +    assertNotNull(unstructured);
>>> +     
>>> assertEquals(johnDoe.getAddresses().get(0).getUnstructuredAddress(),
>>> +         
>>> parsedPerson.getAddresses().get(0).getUnstructuredAddress());
>>> +
>>> +    assertEquals(3, parsedPerson.getPhoneNumbers().size());
>>> +
>>> +    for (int i = 0; i < johnDoe.getPhoneNumbers().size(); i++) {
>>> +      Phone expectedPhone = johnDoe.getPhoneNumbers().get(i);
>>> +      Phone actualPhone = parsedPerson.getPhoneNumbers().get(i);
>>> +      assertEquals(expectedPhone.getType(), actualPhone.getType());
>>> +      assertEquals(expectedPhone.getNumber(),  
>>> actualPhone.getNumber());
>>> +    }
>>> +
>>> +    assertEquals(2, parsedPerson.getEmails().size());
>>> +
>>> +    for (int i = 0; i < johnDoe.getEmails().size(); i++) {
>>> +      Email expectedEmail = johnDoe.getEmails().get(i);
>>> +      Email actualEmail = parsedPerson.getEmails().get(i);
>>> +      assertEquals(expectedEmail.getType(), actualEmail.getType());
>>> +      assertEquals(expectedEmail.getAddress(),  
>>> actualEmail.getAddress());
>>> +    }
>>> +  }
>>> +
>>> +  public void testActivityToJson() throws Exception {
>>> +
>>> +    String result = beanJsonConverter.convertToString(activity);
>>> +    if (outputInfo) {
>>> +      log.info("JSON (" + result + ")");
>>> +    }
>>> +    Activity parsedActivity =  
>>> beanJsonConverter.convertToObject(result,
>>> +        Activity.class);
>>> +    assertEquals(activity.getUserId(), parsedActivity.getUserId());
>>> +    assertEquals(activity.getId(), parsedActivity.getId());
>>> +
>>> +    assertEquals(1, parsedActivity.getMediaItems().size());
>>> +
>>> +    MediaItem expectedItem = activity.getMediaItems().get(0);
>>> +    MediaItem actualItem = parsedActivity.getMediaItems().get(0);
>>> +
>>> +    assertEquals(expectedItem.getUrl(), actualItem.getUrl());
>>> +    assertEquals(expectedItem.getMimeType(),  
>>> actualItem.getMimeType());
>>> +    assertEquals(expectedItem.getType().toString(),  
>>> actualItem.getType()
>>> +        .toString());
>>> +  }
>>> +
>>> +  public void testMapsToJson() throws Exception {
>>> +    Map<String, Map<String, String>> map = Maps.newHashMap();
>>> +
>>> +    Map<String, String> item1Map = Maps.newHashMap();
>>> +    item1Map.put("value", "1");
>>> +
>>> +    // Null values shouldn't cause exceptions
>>> +    item1Map.put("value2", null);
>>> +    map.put("item1", item1Map);
>>> +
>>> +    Map<String, String> item2Map = Maps.newHashMap();
>>> +    item2Map.put("value", "2");
>>> +    map.put("item2", item2Map);
>>> +
>>> +    String result = beanJsonConverter.convertToString(map);
>>> +    if (outputInfo) {
>>> +      log.info("JSON (" + result + ")");
>>> +    }
>>> +    // there is introspection that can tell jsonobject -> bean  
>>> converter
>>> what a
>>> +    // map should contain, so we have to tell it
>>> +    beanJsonConverter.addMapping("item1", Map.class);
>>> +    beanJsonConverter.addMapping("item2", Map.class);
>>> +    Map<?, ?> parsedMap = beanJsonConverter
>>> +        .convertToObject(result, Map.class);
>>> +
>>> +    if (outputInfo) {
>>> +      log.info("Dumping Map (" + parsedMap + ")");
>>> +    }
>>> +    APIValidator.dump(parsedMap);
>>> +
>>> +    assertEquals("1", ((Map<?,? 
>>> >)parsedMap.get("item1")).get("value"));
>>> +    assertEquals("2", ((Map<?,? 
>>> >)parsedMap.get("item2")).get("value"));
>>> +  }
>>> +
>>> +  public void testListsToJson() throws Exception {
>>> +    Map<String, String> item1Map = Maps.newHashMap();
>>> +    item1Map.put("value", "1");
>>> +
>>> +    Map<String, String> item2Map = Maps.newHashMap();
>>> +    item2Map.put("value", "2");
>>> +
>>> +    // put the list into a container before serializing, top  
>>> level lists
>>> dont
>>> +    // appear
>>> +    // to be allowed in json
>>> +    // just check that the list is in the holder correctly
>>> +    List<Map<String, String>> list = new ArrayList<Map<String,  
>>> String>>();
>>> +    list.add(item1Map);
>>> +    list.add(item2Map);
>>> +    String result = beanJsonConverter.convertToString(list);
>>> +    if (outputInfo) {
>>> +      log.info("JSON (" + result + ")");
>>> +    }
>>> +    Map<?, ?>[] parsedList = beanJsonConverter.convertToObject(
>>> +        result, Map[].class);
>>> +
>>> +    assertEquals("1", parsedList[0].get("value"));
>>> +    assertEquals("2", parsedList[1].get("value"));
>>> +  }
>>> +
>>> +  public void testArrayToJson() throws Exception {
>>> +    String[] colors = { "blue", "green", "aquamarine" };
>>> +    String result = beanJsonConverter.convertToString(colors);
>>> +    if (outputInfo) {
>>> +      log.info("JSON (" + result + ")");
>>> +    }
>>> +    String[] parsedColors =  
>>> beanJsonConverter.convertToObject(result,
>>> +        String[].class);
>>> +    assertEquals(colors.length, parsedColors.length);
>>> +    assertEquals(colors[0], parsedColors[0]);
>>> +    assertEquals(colors[1], parsedColors[1]);
>>> +    assertEquals(colors[2], parsedColors[2]);
>>> +  }
>>> +
>>> +  public void testJsonToActivity() throws Exception {
>>> +    String jsonActivity = "{userId : 5, id : 6, mediaItems : ["
>>> +        + "{url : 'hello', mimeType : 'mimey', type : 'VIDEO'}" +  
>>> "]}";
>>> +    Activity result =  
>>> beanJsonConverter.convertToObject(jsonActivity,
>>> +        Activity.class);
>>> +
>>> +    assertEquals("5", result.getUserId());
>>> +    assertEquals("6", result.getId());
>>> +
>>> +    assertEquals(1, result.getMediaItems().size());
>>> +
>>> +    MediaItem actualItem = result.getMediaItems().get(0);
>>> +
>>> +    assertEquals("hello", actualItem.getUrl());
>>> +    assertEquals("mimey", actualItem.getMimeType());
>>> +    assertEquals("video", actualItem.getType().toString());
>>> +  }
>>> +
>>> +  public void testJsonToMap() throws Exception {
>>> +    String jsonActivity = "{count : 0, favoriteColor : 'yellow'}";
>>> +    Map<String, String> data = Maps.newHashMap();
>>> +    data = beanJsonConverter.convertToObject(jsonActivity,
>>> +        (Class<Map<String, String>>) data.getClass());
>>> +
>>> +    assertEquals(2, data.size());
>>> +
>>> +    for (String key : data.keySet()) {
>>> +      Object value = data.get(key);
>>> +      if (key.equals("count")) {
>>> +        assertEquals(0, value);
>>> +      } else if (key.equals("favoriteColor")) {
>>> +        assertEquals("yellow", value);
>>> +      }
>>> +    }
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/JsonConverterPerformancePerf.java?rev=678158&view=auto
>>>
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> ====================================================================
>>> ---
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>> (added)
>>> +++
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,271 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +import junit.framework.TestCase;
>>> +
>>> +import org.apache.commons.logging.Log;
>>> +import org.apache.commons.logging.LogFactory;
>>> +import org.apache.shindig.social.JsonLibTestsGuiceModule;
>>> +import org.apache.shindig.social.SocialApiTestsGuiceModule;
>>> +import org.apache.shindig.social.opensocial.model.Activity;
>>> +import org.apache.shindig.social.opensocial.model.ActivityImpl;
>>> +import org.apache.shindig.social.opensocial.model.Address;
>>> +import org.apache.shindig.social.opensocial.model.AddressImpl;
>>> +import org.apache.shindig.social.opensocial.model.Email;
>>> +import org.apache.shindig.social.opensocial.model.EmailImpl;
>>> +import org.apache.shindig.social.opensocial.model.MediaItem;
>>> +import org.apache.shindig.social.opensocial.model.MediaItemImpl;
>>> +import org.apache.shindig.social.opensocial.model.NameImpl;
>>> +import org.apache.shindig.social.opensocial.model.Person;
>>> +import org.apache.shindig.social.opensocial.model.PersonImpl;
>>> +import org.apache.shindig.social.opensocial.model.Phone;
>>> +import org.apache.shindig.social.opensocial.model.PhoneImpl;
>>> +import org.json.JSONObject;
>>> +
>>> +import com.google.common.collect.Lists;
>>> +import com.google.inject.Guice;
>>> +
>>> +public class JsonConverterPerformancePerf extends TestCase {
>>> +
>>> +  private static final Log log = LogFactory
>>> +      .getLog(JsonConverterPerformancePerf.class);
>>> +  private static final int TEST_SIZE = 10000;
>>> +  private Person johnDoe;
>>> +  private Activity activity;
>>> +
>>> +  private BeanJsonLibConverter beanJsonLibConverter;
>>> +  private APIValidator apiValidator;
>>> +  // set to true to get loging output at info level
>>> +  private boolean outputInfo = false;
>>> +  private BeanJsonConverter beanJsonConverter;
>>> +
>>> +  @Override
>>> +  public void setUp() throws Exception {
>>> +    super.setUp();
>>> +    johnDoe = new PersonImpl("johnDoeId", new NameImpl("John  
>>> Doe"));
>>> +    johnDoe.setPhoneNumbers(Lists.<Phone> newArrayList(new  
>>> PhoneImpl(
>>> +        "+33H000000000", "home"), new PhoneImpl("+33M000000000",
>>> "mobile"),
>>> +        new PhoneImpl("+33W000000000", "work")));
>>> +
>>> +    johnDoe.setAddresses(Lists.<Address> newArrayList(new  
>>> AddressImpl(
>>> +        "My home address")));
>>> +
>>> +    johnDoe.setEmails(Lists.<Email> newArrayList(new EmailImpl(
>>> +        "john.doe@work.bar", "work"),
>>> +        new EmailImpl("john.doe@home.bar", "home")));
>>> +
>>> +    activity = new ActivityImpl("activityId", johnDoe.getId());
>>> +
>>> +    activity.setMediaItems(Lists.<MediaItem> newArrayList(new
>>> MediaItemImpl(
>>> +        "image/jpg", MediaItem.Type.IMAGE, "http://foo.bar")));
>>> +
>>> +    beanJsonLibConverter = new BeanJsonLibConverter(Guice
>>> +        .createInjector(new JsonLibTestsGuiceModule()));
>>> +
>>> +    beanJsonConverter = new BeanJsonConverter(Guice
>>> +        .createInjector(new SocialApiTestsGuiceModule()));
>>> +
>>> +    apiValidator = new APIValidator("opensocial-reference");
>>> +
>>> +  }
>>> +
>>> +  public static class SpecialPerson extends PersonImpl {
>>> +    private String newfield;
>>> +
>>> +    public SpecialPerson() {
>>> +      super();
>>> +    }
>>> +
>>> +    public SpecialPerson(String id, String name, String newfield) {
>>> +      super(id, new NameImpl(name));
>>> +      this.newfield = newfield;
>>> +    }
>>> +
>>> +    public String getNewfield() {
>>> +      return newfield;
>>> +    }
>>> +
>>> +    public void setNewfield(String newfield) {
>>> +      this.newfield = newfield;
>>> +    }
>>> +
>>> +  }
>>> +
>>> +  public void testToJsonLibOnInheritedClassOutput() throws  
>>> Exception {
>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>>> "nonsense");
>>> +    }
>>> +    Runtime r = Runtime.getRuntime();
>>> +    r.gc();
>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>> +    long startOutput = System.currentTimeMillis();
>>> +    String[] output = new String[TEST_SIZE];
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      output[i] = beanJsonLibConverter.convertToString(spa[i]);
>>> +    }
>>> +    long endOutput = System.currentTimeMillis();
>>> +    long memend = r.totalMemory()-r.freeMemory();
>>> +
>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>> +    char[] source = output[0].toCharArray();
>>> +    r.gc();
>>> +
>>> +    long stringsizeStart = r.totalMemory()-r.freeMemory();
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      serializeOutput[i] = new String(source);
>>> +    }
>>> +    long stringsizeEnd = r.totalMemory()-r.freeMemory();
>>> +
>>> +    /*
>>> +     * Output the time per conversion and the memory usage - the  
>>> output
>>> per
>>> +     * conversion.
>>> +     *
>>> +     */
>>> +
>>> +    log.info("SF JSON Lib Output "
>>> +        + average(startOutput, endOutput, TEST_SIZE)
>>> +        + " ms/conversion, "
>>> +        + (average(memstart, memend, TEST_SIZE)- 
>>> average(stringsizeStart,
>>> stringsizeEnd, TEST_SIZE))
>>> +        + " heap bytes/conversion, output packet consumed on  
>>> average "
>>> +        + average(stringsizeStart, stringsizeEnd, TEST_SIZE)+"  
>>> for a
>>> string length of "+output[0].length());
>>> +    log.info("Output Was ["+output[0]+"]");
>>> +  }
>>> +
>>> +  public void testToJsonLibOnInheritedClassInput() throws  
>>> Exception {
>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>> +    SpecialPerson[] sparesult = new SpecialPerson[TEST_SIZE];
>>> +    Runtime r = Runtime.getRuntime();
>>> +    r.gc();
>>> +    long personStart = r.totalMemory()-r.freeMemory();
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>>> "nonsense");
>>> +    }
>>> +    long personEnd = r.totalMemory()-r.freeMemory();
>>> +
>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>> +    r.gc();
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +
>>> +      serializeOutput[i] =  
>>> beanJsonLibConverter.convertToString(spa[i]);
>>> +    }
>>> +
>>> +    r.gc();
>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>> +    long startInput = System.currentTimeMillis();
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +        sparesult[i] = beanJsonLibConverter.convertToObject(
>>> +          serializeOutput[i], SpecialPerson.class);
>>> +    }
>>> +    long endInput = System.currentTimeMillis();
>>> +    long memend = r.totalMemory()-r.freeMemory();
>>> +
>>> +    log.info("SF JSON Lib Input "
>>> +        + average(startInput, endInput, TEST_SIZE)
>>> +        + " ms/conversion, "
>>> +        + (average(memstart, memend, TEST_SIZE)- 
>>> average(personStart,
>>> personEnd, TEST_SIZE))
>>> +        + " heap bytes/conversion, person object consumed on  
>>> average "
>>> +        + average(personStart, personEnd, TEST_SIZE));
>>> +  }
>>> +
>>> +  public void testToJsonOnInheritedClassOutput() throws Exception {
>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>>> "nonsense");
>>> +    }
>>> +    Runtime r = Runtime.getRuntime();
>>> +    String[] output = new String[TEST_SIZE];
>>> +    r.gc();
>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>> +    long startOutput = System.currentTimeMillis();
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      output[i]  = ((JSONObject)
>>> beanJsonConverter.convertToJson(spa[i])).toString();
>>> +    }
>>> +    long endOutput = System.currentTimeMillis();
>>> +    long memend = r.totalMemory()-r.freeMemory();
>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>> +    char[] source = output[0].toCharArray();
>>> +    r.gc();
>>> +
>>> +    long stringsizeStart = r.totalMemory()-r.freeMemory();
>>> +
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      serializeOutput[i] = new String(source);
>>> +    }
>>> +    long stringsizeEnd = r.totalMemory()-r.freeMemory();
>>> +
>>> +    log.info("ORG JSON Lib Output "
>>> +        + average(startOutput, endOutput, TEST_SIZE)
>>> +        + " ms/conversion, "
>>> +        + (average(memstart, memend, TEST_SIZE)- 
>>> average(stringsizeStart,
>>> stringsizeEnd, TEST_SIZE))
>>> +        + " heap bytes/conversion, output packet consumed on  
>>> average "
>>> +        + average(stringsizeStart, stringsizeEnd, TEST_SIZE)+"  
>>> for a
>>> string length of "+output[0].length());
>>> +    log.info("Output Was ["+output[0]+"]");
>>> +  }
>>> +
>>> +  /**
>>> +   * @param endOutput
>>> +   * @param startOutput
>>> +   * @param testSize
>>> +   * @return
>>> +   */
>>> +  private float average(long start, long end, int testSize) {
>>> +    float r = end - start;
>>> +    r = r / testSize;
>>> +    return r;
>>> +  }
>>> +
>>> +  public void XtestToJsonOnInheritedClassInput() throws Exception {
>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>> +    SpecialPerson[] sparesult = new SpecialPerson[TEST_SIZE];
>>> +    Runtime r = Runtime.getRuntime();
>>> +    r.gc();
>>> +    long personStart = r.totalMemory()-r.freeMemory();
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>>> "nonsense");
>>> +    }
>>> +    long personEnd = r.totalMemory()-r.freeMemory();
>>> +
>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>> +    r.gc();
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +
>>> +      serializeOutput[i] =  
>>> beanJsonConverter.convertToString(spa[i]);
>>> +    }
>>> +
>>> +    r.gc();
>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>> +    long startInput = System.currentTimeMillis();
>>> +
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      sparesult[i] = beanJsonConverter.convertToObject(
>>> +          serializeOutput[i], SpecialPerson.class);
>>> +    }
>>> +    long endInput = System.currentTimeMillis();
>>> +    long memend = r.totalMemory()-r.freeMemory();
>>> +
>>> +    log.info("SF JSON Lib Input "
>>> +        + average(startInput, endInput, TEST_SIZE)
>>> +        + " ms/conversion, "
>>> +        + (average(memstart, memend, TEST_SIZE)- 
>>> average(personStart,
>>> personEnd, TEST_SIZE))
>>> +        + " heap bytes/conversion, person object consumed on  
>>> average "
>>> +        + average(personStart, personEnd, TEST_SIZE));
>>> +  }
>>> +
>>> +}
>>>
>>> Modified: incubator/shindig/trunk/pom.xml
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/pom.xml?rev=678158&r1=678157&r2=678158&view=diff
>>>
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> = 
>>> ====================================================================
>>> --- incubator/shindig/trunk/pom.xml (original)
>>> +++ incubator/shindig/trunk/pom.xml Sat Jul 19 06:51:03 2008
>>> @@ -853,6 +853,16 @@
>>>        <artifactId>htmlunit</artifactId>
>>>        <version>2.1</version>
>>>      </dependency>
>>> +      <dependency>
>>> +        <groupId>log4j</groupId>
>>> +        <artifactId>log4j</artifactId>
>>> +        <version>1.2.13</version>
>>> +      </dependency>
>>> +      <dependency>
>>> +        <groupId>rhino</groupId>
>>> +        <artifactId>js</artifactId>
>>> +        <version>1.6R7</version>
>>> +      </dependency>
>>>    </dependencies>
>>>  </dependencyManagement>
>>> </project>
>>>
>>>
>>>


Re: svn commit: r678158 - in /incubator/shindig/trunk: ./ java/social-api/ java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/ java/social-api/src/test/java/org/apache/shindig/social/ java/social-api/src/test/java/org/apache/shin

Posted by Kevin Brown <et...@google.com>.
Thanks!

On Sun, Jul 20, 2008 at 2:02 AM, Ian Boston <ie...@tfd.co.uk> wrote:

> Ok will fix.
> Ian
>
>
> On 19 Jul 2008, at 20:50, Kevin Brown wrote:
>
>  Hey Ian,
>>
>> The casing is inconsistent here -- it should be Json and Api for all cases
>> rather than JSON or API.
>>
>> Thanks!
>>
>> On Sat, Jul 19, 2008 at 6:51 AM, <ie...@apache.org> wrote:
>>
>>  Author: ieb
>>> Date: Sat Jul 19 06:51:03 2008
>>> New Revision: 678158
>>>
>>> URL: http://svn.apache.org/viewvc?rev=678158&view=rev
>>> Log:
>>> SHINDIG-451
>>> Applying patch from the JIRA.
>>>
>>> Adds a json-lib (net.sf) converter, not wired into social-api at present.
>>>
>>> Added:
>>>
>>>
>>>  incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>>
>>>
>>>  incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverter.java
>>>
>>>
>>>  incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONLibConverterUtils.java
>>>
>>>
>>>  incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>>
>>>
>>>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/JsonLibTestsGuiceModule.java
>>>
>>>
>>>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidator.java
>>>
>>>
>>>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorExpcetion.java
>>>
>>>
>>>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorTest.java
>>>
>>>
>>>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>>
>>>
>>>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>> Modified:
>>>   incubator/shindig/trunk/java/social-api/pom.xml
>>>   incubator/shindig/trunk/pom.xml
>>>
>>> Modified: incubator/shindig/trunk/java/social-api/pom.xml
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-
>>> api/pom.xml?rev=678158&r1=678157&r2=678158&view=diff
>>>
>>>
>>> ==============================================================================
>>> --- incubator/shindig/trunk/java/social-api/pom.xml (original)
>>> +++ incubator/shindig/trunk/java/social-api/pom.xml Sat Jul 19 06:51:03
>>> 2008
>>> @@ -60,12 +60,31 @@
>>>      <groupId>org.apache.shindig</groupId>
>>>      <artifactId>shindig-common</artifactId>
>>>    </dependency>
>>> +    <!-- is this Ok, only used in test to load the features -->
>>> +    <dependency>
>>> +      <groupId>org.apache.shindig</groupId>
>>> +      <artifactId>shindig-features</artifactId>
>>> +      <scope>test</scope>
>>> +    </dependency>
>>>
>>>    <!-- external depenencies -->
>>>    <dependency>
>>>      <groupId>org.json</groupId>
>>>      <artifactId>json</artifactId>
>>>    </dependency>
>>> +    <!-- the classifier prevents this working in dep management -->
>>> +    <dependency>
>>> +      <groupId>net.sf.json-lib</groupId>
>>> +      <artifactId>json-lib</artifactId>
>>> +      <version>2.2</version>
>>> +      <classifier>jdk15</classifier>
>>> +      <type>jar</type>
>>> +    </dependency>
>>> +    <dependency>
>>> +      <groupId>rhino</groupId>
>>> +      <artifactId>js</artifactId>
>>> +      <scope>test</scope>
>>> +    </dependency>
>>>    <dependency>
>>>      <groupId>com.google.code.guice</groupId>
>>>      <artifactId>guice</artifactId>
>>> @@ -112,5 +131,10 @@
>>>      <artifactId>core</artifactId>
>>>      <scope>compile</scope>
>>>    </dependency>
>>> +    <dependency>
>>> +      <groupId>log4j</groupId>
>>> +      <artifactId>log4j</artifactId>
>>> +      <scope>test</scope>
>>> +    </dependency>
>>>  </dependencies>
>>>  </project>
>>>
>>> Added:
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-
>>> api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConversionException.java?rev=678158&view=auto
>>>
>>>
>>> ==============================================================================
>>> ---
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>> (added)
>>> +++
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,43 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +/**
>>> + * Where a conversion exception happens in the Json Lib conversion, this
>>> + * exception is thrown.
>>> + */
>>> +public class BeanJsonLibConversionException extends RuntimeException {
>>> +
>>> +  private static final long serialVersionUID = -8609384443448202372L;
>>> +
>>> +  public BeanJsonLibConversionException() {
>>> +  }
>>> +
>>> +  public BeanJsonLibConversionException(String arg0) {
>>> +    super(arg0);
>>> +  }
>>> +
>>> +  public BeanJsonLibConversionException(Throwable arg0) {
>>> +    super(arg0);
>>> +  }
>>> +
>>> +  public BeanJsonLibConversionException(String arg0, Throwable arg1) {
>>> +    super(arg0, arg1);
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverter.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-
>>> api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverter.java?rev=678158&view=auto
>>>
>>>
>>> ==============================================================================
>>> ---
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverter.java
>>> (added)
>>> +++
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverter.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,286 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +import java.lang.reflect.Array;
>>> +import java.lang.reflect.InvocationTargetException;
>>> +import java.util.Collection;
>>> +import java.util.HashMap;
>>> +import java.util.List;
>>> +import java.util.Map;
>>> +
>>> +import net.sf.ezmorph.MorpherRegistry;
>>> +import net.sf.json.JSONArray;
>>> +import net.sf.json.JSONException;
>>> +import net.sf.json.JSONObject;
>>> +import net.sf.json.JsonConfig;
>>> +import net.sf.json.processors.DefaultValueProcessor;
>>> +import net.sf.json.util.EnumMorpher;
>>> +import net.sf.json.util.JSONUtils;
>>> +import net.sf.json.util.NewBeanInstanceStrategy;
>>> +import net.sf.json.util.PropertyFilter;
>>> +
>>> +import org.apache.commons.logging.Log;
>>> +import org.apache.commons.logging.LogFactory;
>>> +import org.apache.shindig.social.opensocial.model.Address;
>>> +import org.apache.shindig.social.opensocial.model.Email;
>>> +import org.apache.shindig.social.opensocial.model.Enum;
>>> +import org.apache.shindig.social.opensocial.model.MediaItem;
>>> +import org.apache.shindig.social.opensocial.model.Organization;
>>> +import org.apache.shindig.social.opensocial.model.Phone;
>>> +import org.apache.shindig.social.opensocial.model.Url;
>>> +
>>> +
>>> +import com.google.inject.Inject;
>>> +import com.google.inject.Injector;
>>> +
>>> +/**
>>> + *
>>> + */
>>> +public class BeanJsonLibConverter implements BeanConverter {
>>> +
>>> +  protected static final Log log = LogFactory
>>> +      .getLog(BeanJsonLibConverter.class);
>>> +  private Injector injector;
>>> +  private JsonConfig jsonConfig;
>>> +  private boolean debugMode = false;
>>> +
>>> +  /*
>>> +   * Register the Enum Morphers so that JSON -> Bean works correctly for
>>> enums.
>>> +   */
>>> +  static {
>>> +    MorpherRegistry morpherRegistry = JSONUtils.getMorpherRegistry();
>>> +    morpherRegistry.registerMorpher(new
>>> EnumMorpher(Address.Field.class));
>>> +    morpherRegistry.registerMorpher(new EnumMorpher(Phone.Field.class));
>>> +    morpherRegistry.registerMorpher(new EnumMorpher(Email.Field.class));
>>> +    morpherRegistry.registerMorpher(new
>>> EnumMorpher(MediaItem.Field.class));
>>> +    morpherRegistry.registerMorpher(new
>>> EnumMorpher(MediaItem.Type.class));
>>> +    morpherRegistry.registerMorpher(new
>>> EnumMorpher(Enum.Drinker.class));
>>> +    morpherRegistry.registerMorpher(new EnumMorpher(Enum.Field.class));
>>> +    morpherRegistry.registerMorpher(new EnumMorpher(Enum.Gender.class));
>>> +    morpherRegistry
>>> +        .registerMorpher(new EnumMorpher(Enum.NetworkPresence.class));
>>> +    morpherRegistry.registerMorpher(new EnumMorpher(Enum.Smoker.class));
>>> +
>>> +    morpherRegistry.registerMorpher(new JSONObjectToMapMorpher());
>>> +  }
>>> +
>>> +  @Inject
>>> +  public BeanJsonLibConverter(Injector injector) {
>>> +    this.injector = injector;
>>> +    createJsonConfig();
>>> +  }
>>> +
>>> +  @SuppressWarnings("unchecked")
>>> +  public <T> T convertToObject(String string, final Class<T>
>>> rootBeanClass) {
>>> +
>>> +    if (string.startsWith("[")) {
>>> +      JSONArray jsonArray = JSONArray.fromObject(string, jsonConfig);
>>> +      if (debugMode) {
>>> +        JSONLibConverterUtils.dumpJsonArray(jsonArray, " ");
>>> +      }
>>> +
>>> +      if (rootBeanClass.isArray()) {
>>> +        Class<?> componentType = rootBeanClass.getComponentType();
>>> +        Object rootObject = injector.getInstance(componentType);
>>> +        List<?> o = JSONArray.toList(jsonArray, rootObject, jsonConfig);
>>> +        Object[] result = (Object[]) Array.newInstance(componentType,
>>> o.size());
>>> +        for (int i = 0; i < o.size(); i++) {
>>> +          result[i] = o.get(i);
>>> +        }
>>> +        return (T) result;
>>> +
>>> +      } else {
>>> +        T rootObject = injector.getInstance(rootBeanClass);
>>> +        Object o = JSONArray.toArray(jsonArray, rootObject, jsonConfig);
>>> +        return (T) o;
>>> +      }
>>> +    } else {
>>> +      JSONObject jsonObject = JSONObject.fromObject(string, jsonConfig);
>>> +
>>> +      if (debugMode) {
>>> +        JSONLibConverterUtils.dumpJsonObject(jsonObject, " ");
>>> +      }
>>> +
>>> +      T rootObject = injector.getInstance(rootBeanClass);
>>> +      Object o = JSONObject.toBean(jsonObject, rootObject, jsonConfig);
>>> +      return (T) o;
>>> +
>>> +    }
>>> +  }
>>> +
>>> +  /**
>>> +   * @return
>>> +   */
>>> +  private void createJsonConfig() {
>>> +
>>> +    jsonConfig = new JsonConfig();
>>> +
>>> +    /*
>>> +     * This hook deals with the creation of new beans in the JSON ->
>>> Java
>>> Bean
>>> +     * conversion
>>> +     */
>>> +    jsonConfig.setNewBeanInstanceStrategy(new NewBeanInstanceStrategy()
>>> {
>>> +
>>> +      @SuppressWarnings("unchecked")
>>> +      @Override
>>> +      public Object newInstance(Class beanClass, JSONObject jsonObject)
>>> +          throws InstantiationException, IllegalAccessException,
>>> +          SecurityException, NoSuchMethodException,
>>> InvocationTargetException {
>>> +        if (beanClass != null) {
>>> +          Object o =
>>> BeanJsonLibConverter.this.injector.getInstance(beanClass);
>>> +          if (debugMode) {
>>> +            log.info("Created Object " + o + " for " + beanClass + "
>>> with
>>> ["
>>> +                + jsonObject + "]");
>>> +          }
>>> +          return o;
>>> +        }
>>> +        return DEFAULT.newInstance(beanClass, jsonObject);
>>> +      }
>>> +
>>> +    });
>>> +
>>> +    /*
>>> +     * We are expecting null for nulls
>>> +     */
>>> +    jsonConfig.registerDefaultValueProcessor(String.class,
>>> +        new DefaultValueProcessor() {
>>> +          @SuppressWarnings("unchecked")
>>> +          public Object getDefaultValue(Class target) {
>>> +            return null;
>>> +          }
>>> +        });
>>> +
>>> +    jsonConfig.setJsonPropertyFilter(new PropertyFilter() {
>>> +
>>> +      public boolean apply(Object source, String name, Object value) {
>>> +        return filterProperty(source, name, value);
>>> +      }
>>> +
>>> +    });
>>> +
>>> +    jsonConfig.setJavaPropertyFilter(new PropertyFilter() {
>>> +
>>> +      public boolean apply(Object source, String name, Object value) {
>>> +        return filterProperty(source,name,value);
>>> +      }
>>> +
>>> +    });
>>> +
>>> +    // the classMap deals with the basic json string to bean conversion
>>> +
>>> +    Map<String, Class<?>> classMap = new HashMap<String, Class<?>>();
>>> +
>>> +    /*
>>> +     * mappings are required where there is a List of objects in the
>>> interface
>>> +     * with no indication of what type the list should contain. At the
>>> moment,
>>> +     * we are using 1 map for all json trees, as there is no conflict,
>>> but
>>> if
>>> +     * there is a map could be selected on the basis of the root object.
>>> It
>>> +     * would be better to do this with generics, but this is good enough
>>> and
>>> +     * compact enough for the moment.
>>> +     *
>>> +     */
>>> +    //
>>> +    // activity
>>> +    classMap.put("mediaItems", MediaItem.class);
>>> +    // this may not be necessary
>>> +    classMap.put("templateParams", Map.class);
>>> +    // BodyType needs no mappings
>>> +    // Message needs no mappings
>>> +    // Name needs no mappings
>>> +    // Organization needs no mappings
>>> +    // Url needs no mappings
>>> +    // Email needs no mappings
>>> +    // Phone Needs no mappings
>>> +    // Address Needs no mappings
>>> +    // MediaItem needs no mappings
>>> +
>>> +    // Person map
>>> +    classMap.put("addresses", Address.class);
>>> +    classMap.put("phoneNumbers", Phone.class);
>>> +    classMap.put("emails", Email.class);
>>> +    classMap.put("mediaItems", MediaItem.class);
>>> +    classMap.put("jobs", Organization.class);
>>> +    classMap.put("schools", Organization.class);
>>> +    classMap.put("urls", Url.class);
>>> +    jsonConfig.setClassMap(classMap);
>>> +
>>> +  }
>>> +
>>> +  /**
>>> +   * @param source
>>> +   * @param name
>>> +   * @param value
>>> +   * @return
>>> +   */
>>> +  protected boolean filterProperty(Object source, String name, Object
>>> value) {
>>> +    if ( value == null ) {
>>> +      return true;
>>> +    }
>>> +    if ( value instanceof JSONArray ) {
>>> +      JSONArray array = (JSONArray) value;
>>> +      if ( array.size() == 0 ) {
>>> +        return true;
>>> +      }
>>> +    }
>>> +    if ( value instanceof JSONObject ) {
>>> +      JSONObject object = (JSONObject) value;
>>> +      if ( object.isNullObject() || object.isEmpty()  ) {
>>> +        return true;
>>> +      }
>>> +    }
>>> +    if ( value instanceof Collection) {
>>> +      Collection<?> collection = (Collection<?>) value;
>>> +      if ( collection.size() == 0  ) {
>>> +        return true;
>>> +      }
>>> +    }
>>> +    if ( value instanceof Object[] ) {
>>> +      Object[] oarray = (Object[]) value;
>>> +      if ( oarray.length == 0 ) {
>>> +        return true;
>>> +      }
>>> +    }
>>> +    return false;
>>> +  }
>>> +
>>> +  public String convertToString(Object pojo) {
>>> +
>>> +    try {
>>> +      JSONObject jsonObject = JSONObject.fromObject(pojo, jsonConfig);
>>> +      return jsonObject.toString();
>>> +    } catch (JSONException jse) {
>>> +      Class<?> pojoClass = pojo.getClass();
>>> +      if (JSONUtils.isArray(pojoClass)) {
>>> +        JSONArray jsonArray = JSONArray.fromObject(pojo);
>>> +        String result = jsonArray.toString();
>>> +        return result;
>>> +      }
>>> +      throw jse;
>>> +    }
>>> +  }
>>> +
>>> +  /**
>>> +   * @param string
>>> +   * @param class1
>>> +   */
>>> +  public void addMapping(String key, Class<?> class1) {
>>> +    jsonConfig.getClassMap().put(key, class1);
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONLibConverterUtils.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-
>>> api/src/main/java/org/apache/shindig/social/opensocial/util/JSONLibConverterUtils.java?rev=678158&view=auto
>>>
>>>
>>> ==============================================================================
>>> ---
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONLibConverterUtils.java
>>> (added)
>>> +++
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONLibConverterUtils.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,72 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +import org.apache.commons.logging.Log;
>>> +import org.apache.commons.logging.LogFactory;
>>> +
>>> +import net.sf.json.JSONArray;
>>> +import net.sf.json.JSONObject;
>>> +
>>> +/**
>>> + *
>>> + */
>>> +public class JSONLibConverterUtils {
>>> +  protected static final Log log = LogFactory
>>> +  .getLog(JSONLibConverterUtils.class);
>>> +
>>> +
>>> +  /**
>>> +   * @param jsonObject
>>> +   */
>>> +  public static final void dumpJsonObject(JSONObject jsonObject, String
>>> indent) {
>>> +    for (Object key : jsonObject.keySet()) {
>>> +      Object value = jsonObject.get(key);
>>> +      if (value instanceof JSONObject) {
>>> +        log.info(indent + key + ":JSONObject");
>>> +        dumpJsonObject((JSONObject) value, indent + "  ");
>>> +      } else if (value instanceof JSONArray) {
>>> +        log.info(indent + key + ":JSONArray " + ((JSONArray)
>>> value).size());
>>> +        dumpJsonArray((JSONArray) value, indent + "  ");
>>> +      } else {
>>> +        log.info(indent + key + ":" + value + ":"
>>> +            + (value == null ? "na" : value.getClass()));
>>> +      }
>>> +    }
>>> +  }
>>> +
>>> +
>>> +  /**
>>> +   * @param value
>>> +   * @param string
>>> +   */
>>> +  static void dumpJsonArray(JSONArray array, String indent) {
>>> +    for (Object value : array) {
>>> +      if (value instanceof JSONObject) {
>>> +        log.info(indent + ":JSONObject");
>>> +        dumpJsonObject((JSONObject) value, indent + "  ");
>>> +      } else if (value instanceof JSONArray) {
>>> +        log.info(indent + ":JSONArray " + ((JSONArray) value).size());
>>> +        dumpJsonArray((JSONArray) value, indent + "  ");
>>> +      } else {
>>> +        log.info(indent + ":" + value + ":"
>>> +            + (value == null ? "na" : value.getClass()));
>>> +      }
>>> +    }
>>> +  }
>>> +}
>>>
>>> Added:
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-
>>> api/src/main/java/org/apache/shindig/social/opensocial/util/JSONObjectToMapMorpher.java?rev=678158&view=auto
>>>
>>>
>>> ==============================================================================
>>> ---
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>> (added)
>>> +++
>>>
>>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,50 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +import java.util.HashMap;
>>> +import java.util.Map;
>>> +
>>> +import net.sf.ezmorph.Morpher;
>>> +import net.sf.ezmorph.ObjectMorpher;
>>> +import net.sf.json.JSONObject;
>>> +
>>> +/**
>>> + *
>>> + */
>>> +public class JSONObjectToMapMorpher implements Morpher, ObjectMorpher {
>>> +
>>> +  public Class<?> morphsTo() {
>>> +    return Map.class;
>>> +  }
>>> +
>>> +  @SuppressWarnings("unchecked")
>>> +  public boolean supports(Class clazz) {
>>> +    return (JSONObject.class.equals(clazz));
>>> +  }
>>> +
>>> +  public Object morph(Object bean) {
>>> +    Map<Object, Object> result = new HashMap<Object, Object>();
>>> +    JSONObject jsonObject = (JSONObject) bean;
>>> +    for ( Object key : jsonObject.keySet()) {
>>> +      result.put(key,jsonObject.get(key));
>>> +    }
>>> +    return result;
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/JsonLibTestsGuiceModule.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-
>>> api/src/test/java/org/apache/shindig/social/JsonLibTestsGuiceModule.java?rev=678158&view=auto
>>>
>>>
>>> ==============================================================================
>>> ---
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/JsonLibTestsGuiceModule.java
>>> (added)
>>> +++
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/JsonLibTestsGuiceModule.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,40 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements.  See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership.  The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License.  You may obtain a copy of the License at
>>> + *
>>> + *   http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social;
>>> +
>>> +import java.util.ArrayList;
>>> +import java.util.HashMap;
>>> +import java.util.List;
>>> +import java.util.Map;
>>> +
>>> +import com.google.inject.AbstractModule;
>>> +
>>> +/**
>>> + * Provides social api component injection for all large tests
>>> + */
>>> +public class JsonLibTestsGuiceModule extends AbstractModule {
>>> +  @Override
>>> +  protected void configure() {
>>> +
>>> +    bind(Map.class).to(HashMap.class);
>>> +    bind(List.class).to(ArrayList.class);
>>> +    bind(Map[].class).to(HashMap[].class);
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidator.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-
>>> api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidator.java?rev=678158&view=auto
>>>
>>>
>>> ==============================================================================
>>> ---
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidator.java
>>> (added)
>>> +++
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidator.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,352 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +import java.io.IOException;
>>> +import java.io.InputStream;
>>> +import java.io.InputStreamReader;
>>> +import java.util.ArrayList;
>>> +import java.util.HashMap;
>>> +import java.util.List;
>>> +import java.util.Map;
>>> +
>>> +import javax.xml.parsers.DocumentBuilder;
>>> +import javax.xml.parsers.DocumentBuilderFactory;
>>> +import javax.xml.parsers.ParserConfigurationException;
>>> +
>>> +import org.apache.commons.logging.Log;
>>> +import org.apache.commons.logging.LogFactory;
>>> +import org.mozilla.javascript.Context;
>>> +import org.mozilla.javascript.EvaluatorException;
>>> +import org.mozilla.javascript.Script;
>>> +import org.mozilla.javascript.ScriptableObject;
>>> +import org.w3c.dom.Document;
>>> +import org.w3c.dom.NamedNodeMap;
>>> +import org.w3c.dom.Node;
>>> +import org.w3c.dom.NodeList;
>>> +import org.xml.sax.SAXException;
>>> +
>>> +/**
>>> + * A class that loads a feature set from features into a Javascript
>>> Parser
>>> to
>>> + * make the model available to validate JSON messages against.
>>> + */
>>> +public class APIValidator {
>>> +
>>> +  private static final Log log = LogFactory.getLog(APIValidator.class);
>>> +  private Context ctx;
>>> +  private ScriptableObject scope;
>>> +
>>> +  /**
>>> +   * @param feature
>>> +   *                The name of the feature are eg
>>> "opensocial-reference",
>>> this
>>> +   *                is a classpath stub (not starting with /) where the
>>> location
>>> +   *                contains a feature.xml file.
>>> +   * @throws SAXException
>>> +   *                 if feature.xml is not parsable
>>> +   * @throws ParserConfigurationException
>>> +   *                 if the parsers are invalid
>>> +   * @throws IOException
>>> +   *                 if feature.xml or the javascript that represents
>>> the
>>> +   *                 feature is missing
>>> +   *
>>> +   */
>>> +  public APIValidator(String feature) throws IOException,
>>> +      ParserConfigurationException, SAXException {
>>> +    ctx = Context.enter();
>>> +    scope = ctx.initStandardObjects();
>>> +    load(feature);
>>> +  }
>>> +
>>> +  /**
>>> +   * @param json
>>> +   *                The json to validate expected in a form { xyz: yyy }
>>> form
>>> +   * @param object
>>> +   *                The json Fields object specifying the structure of
>>> the
>>> json
>>> +   *                object, each field in this object contains the name
>>> of
>>> the
>>> +   *                json field in the json structure.
>>> +   * @param optionalFields
>>> +   *                If any of the fields that appear in the json
>>> structure
>>> are
>>> +   *                optional, then they should be defined in this
>>> parameter.
>>> +   * @param nullfields
>>> +   * @throws APIValidatorExpcetion
>>> +   *                 if there is a problem validating the json
>>> +   * @return a map so string object pairs containing the fields at the
>>> top
>>> level
>>> +   *         of the json tree. Where these are native java objects, they
>>> will
>>> +   *         appear as native object. Complex json objects will appear
>>> as
>>> Rhino
>>> +   *         specific objects
>>> +   */
>>> +  public Map<String, Object> validate(String json, String object,
>>> +      String[] optionalFields, String[] nullfields)
>>> +      throws APIValidatorExpcetion {
>>> +
>>> +    /*
>>> +     * Object[] ids = ScriptableObject.getPropertyIds(scope); for
>>> (Object
>>> id :
>>> +     * ids) { Object o = ScriptableObject.getProperty(scope,
>>> +     * String.valueOf(id)); log.debug("ID is " + id + " class " +
>>> id.getClass() + "
>>> +     * is " + o); if (o instanceof ScriptableObject) {
>>> +     * listScriptable(String.valueOf(id), (ScriptableObject) o); } }
>>> +     */
>>> +
>>> +    log.debug("Loading " + json);
>>> +    json = json.trim();
>>> +    if (!json.endsWith("}")) {
>>> +      json = json + "}";
>>> +    }
>>> +    if (!json.startsWith("{")) {
>>> +      json = "{" + json;
>>> +    }
>>> +    json = "( testingObject = " + json + " )";
>>> +
>>> +    Object so = null;
>>> +    try {
>>> +      so = ctx.evaluateString(scope, json, "test json", 0, null);
>>> +    } catch (EvaluatorException ex) {
>>> +      log.error("Non parseable JSON " + json);
>>> +    }
>>> +    log.debug("Loaded " + so);
>>> +
>>> +    return validateOject(so, object, optionalFields, nullfields);
>>> +
>>> +  }
>>> +
>>> +  /**
>>> +   * Validate an JSON Object extracted
>>> +   *
>>> +   * @param object
>>> +   * @param string
>>> +   * @param optional
>>> +   * @return
>>> +   * @throws APIValidatorExpcetion
>>> +   */
>>> +  public Map<String, Object> validateOject(Object jsonObject, String
>>> object,
>>> +      String[] optionalFields, String[] nullFields)
>>> +      throws APIValidatorExpcetion {
>>> +    Map<String, String> optional = new HashMap<String, String>();
>>> +    for (String opt : optionalFields) {
>>> +      optional.put(opt, opt);
>>> +    }
>>> +    Map<String, String> nullf = new HashMap<String, String>();
>>> +    for (String nf : nullFields) {
>>> +      nullf.put(nf, nf);
>>> +    }
>>> +
>>> +    ScriptableObject specification = getScriptableObject(object);
>>> +    log.debug("Looking for  " + object + " found " + specification);
>>> +    listScriptable(object, specification);
>>> +
>>> +    Map<String, Object> resultFields = new HashMap<String, Object>();
>>> +
>>> +    if (jsonObject instanceof ScriptableObject) {
>>> +      ScriptableObject parsedJSONObject = (ScriptableObject) jsonObject;
>>> +      listScriptable("testingObject", parsedJSONObject);
>>> +      Object[] fields = specification.getIds();
>>> +      for (Object f : fields) {
>>> +        Object fieldName = specification.get(String.valueOf(f),
>>> specification);
>>> +        Object o = parsedJSONObject.get(String.valueOf(fieldName),
>>> +            parsedJSONObject);
>>> +        if (o == ScriptableObject.NOT_FOUND) {
>>> +          if (optional.containsKey(fieldName)) {
>>> +            log.warn("Missing Optional Field " + fieldName);
>>> +          } else if (!nullf.containsKey(fieldName)) {
>>> +            log.error("Missing Field " + fieldName);
>>> +            throw new APIValidatorExpcetion("Missing Field " +
>>> fieldName);
>>> +          }
>>> +        } else {
>>> +          if (nullf.containsKey(fieldName)) {
>>> +            log.error("Field should have been null and was not");
>>> +          }
>>> +          if (o == null) {
>>> +            if (nullf.containsKey(fieldName)) {
>>> +              log.error("Null Fields has been serialized " + fieldName);
>>> +            }
>>> +            log.debug("Got a Null object for Field " + f + ":" +
>>> fieldName
>>> +                + " on json [[" + jsonObject + "]]");
>>> +
>>> +          } else {
>>> +
>>> +            log.debug("Got JSON Field  Field," + f + ":" + fieldName + "
>>> as "
>>> +                + o + " " + o.getClass());
>>> +          }
>>> +          resultFields.put(String.valueOf(fieldName), o);
>>> +        }
>>> +      }
>>> +
>>> +    } else {
>>> +      throw new APIValidatorExpcetion(
>>> +          "Parsing JSON resulted in invalid Javascript object, which was
>>> "
>>> +              + jsonObject + " JSON was [[" + jsonObject + "]]");
>>> +    }
>>> +    return resultFields;
>>> +  }
>>> +
>>> +  /**
>>> +   * get an object from the json context and scope.
>>> +   *
>>> +   * @param object
>>> +   *                the name of the object specified as a path from the
>>> base
>>> +   *                object
>>> +   * @return the json object
>>> +   */
>>> +  private ScriptableObject getScriptableObject(String object) {
>>> +    String[] path = object.split("\\.");
>>> +    log.debug("Looking up " + object + " elements " + path.length);
>>> +
>>> +    ScriptableObject s = scope;
>>> +    for (String pe : path) {
>>> +      log.debug("Looking up " + pe + " in " + s);
>>> +      s = (ScriptableObject) s.get(pe, s);
>>> +      log.debug("Looking for " + pe + " in found " + s);
>>> +    }
>>> +    return s;
>>> +  }
>>> +
>>> +  /**
>>> +   * List a scriptable object at log debug level, constructors will not
>>> be
>>> +   * expanded as this loads to recursion.
>>> +   *
>>> +   * @param id
>>> +   *                The name of the object
>>> +   * @param scriptableObject
>>> +   *                the scriptable Object
>>> +   */
>>> +  private void listScriptable(String id, ScriptableObject
>>> scriptableObject) {
>>> +    log.debug("ID is Scriptable " + id);
>>> +    if (!id.endsWith("constructor")) {
>>> +      Object[] allIDs = scriptableObject.getAllIds();
>>> +      for (Object oid : allIDs) {
>>> +        log.debug(id + "." + oid);
>>> +        Object o = scriptableObject.get(String.valueOf(oid),
>>> scriptableObject);
>>> +        if (o instanceof ScriptableObject) {
>>> +          listScriptable(id + "." + String.valueOf(oid),
>>> (ScriptableObject) o);
>>> +        }
>>> +      }
>>> +    }
>>> +  }
>>> +
>>> +  /**
>>> +   * Load a feature based on the spec
>>> +   *
>>> +   * @param spec
>>> +   *                The name of the location of the spec in the
>>> classpath,
>>> must
>>> +   *                not start with a '/' and must should contain a
>>> feature.xml
>>> +   *                file in the location
>>> +   * @throws IOException
>>> +   *                 If any of the resources cant be found
>>> +   * @throws ParserConfigurationException
>>> +   *                 If the parser has a problem being constructed
>>> +   * @throws SAXException
>>> +   *                 on a parse error on the features.xml
>>> +   */
>>> +  private void load(String spec) throws IOException, SAXException,
>>> +      ParserConfigurationException {
>>> +
>>> +    List<String> scripts = getScripts(spec);
>>> +
>>> +    List<Script> compiled = new ArrayList<Script>();
>>> +    for (String script : scripts) {
>>> +      String scriptPath = spec + "/" + script;
>>> +      InputStream in =
>>> this.getClass().getClassLoader().getResourceAsStream(
>>> +          scriptPath);
>>> +      if (in == null) {
>>> +        in = this.getClass().getClassLoader().getResourceAsStream(
>>> +            "features/" + scriptPath);
>>> +        if (in == null) {
>>> +          throw new IOException("Cant load spec " + spec + " or
>>> features/"+spec+" from classpath");
>>> +        }
>>> +      }
>>> +      InputStreamReader reader = new InputStreamReader(in);
>>> +      Script compiledScript = ctx.compileReader(reader, spec, 0, null);
>>> +      compiled.add(compiledScript);
>>> +    }
>>> +
>>> +    for (Script compiledScript : compiled) {
>>> +      compiledScript.exec(ctx, scope);
>>> +    }
>>> +
>>> +  }
>>> +
>>> +  /**
>>> +   * Add some javascript to the context, and execute it. If extra custom
>>> +   * javascript is wanted in the context or scope then this method will
>>> load it.
>>> +   *
>>> +   * @param javascript
>>> +   */
>>> +  public void addScript(String javascript) {
>>> +    Script compileScript = ctx.compileString(javascript, "AdditionalJS",
>>> 0,
>>> +        null);
>>> +    compileScript.exec(ctx, scope);
>>> +  }
>>> +
>>> +  /**
>>> +   * Get an ordered list of javascript resources from a feature sets.
>>> +   *
>>> +   * @param spec
>>> +   *                The spec location
>>> +   * @return An ordered list of javascript resources, these are relative
>>> to
>>> +   *         specification file.
>>> +   * @throws IOException
>>> +   *                 If any of the resources can't be loaded.
>>> +   * @throws SAXException
>>> +   *                 Where the feature.xml file is not parsable
>>> +   * @throws ParserConfigurationException
>>> +   *                 where the parser can't be constructed.
>>> +   * @return An ordered list of script that need to be loaded and
>>> executed
>>> to
>>> +   *         make the feature available in the context.
>>> +   */
>>> +  private List<String> getScripts(String spec) throws SAXException,
>>> +      IOException, ParserConfigurationException {
>>> +    String features = spec + "/feature.xml";
>>> +    InputStream in =
>>> this.getClass().getClassLoader().getResourceAsStream(
>>> +        features);
>>> +    if (in == null) {
>>> +      in = this.getClass().getClassLoader().getResourceAsStream(
>>> +          "features/"+features);
>>> +      if (in == null) {
>>> +        throw new IOException("Cant find " + features + " or features/"
>>> +
>>> features+ " in classpath ");
>>> +      }
>>> +    }
>>> +    DocumentBuilderFactory builderFactory = DocumentBuilderFactory
>>> +        .newInstance();
>>> +    DocumentBuilder documentBuilder =
>>> builderFactory.newDocumentBuilder();
>>> +    Document doc = documentBuilder.parse(in);
>>> +    NodeList nl = doc.getElementsByTagName("script");
>>> +    List<String> scripts = new ArrayList<String>();
>>> +    for (int i = 0; i < nl.getLength(); i++) {
>>> +      Node scriptNode = nl.item(i);
>>> +      NamedNodeMap attributes = scriptNode.getAttributes();
>>> +      Node scriptAttr = attributes.getNamedItem("src");
>>> +      String script = scriptAttr.getNodeValue();
>>> +      scripts.add(script);
>>> +    }
>>> +    return scripts;
>>> +  }
>>> +
>>> +  /**
>>> +   * @param nameJSON
>>> +   */
>>> +  public static void dump(Map<?, ?> nameJSON) {
>>> +    if (log.isDebugEnabled()) {
>>> +      for (Object k : nameJSON.keySet()) {
>>> +        Object o = nameJSON.get(k);
>>> +        log.info("Key [" + k + "] value:["
>>> +            + (o == null ? o : o + ":" + o.getClass()) + "]");
>>> +      }
>>> +    }
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorExpcetion.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-
>>> api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorExpcetion.java?rev=678158&view=auto
>>>
>>>
>>> ==============================================================================
>>> ---
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorExpcetion.java
>>> (added)
>>> +++
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorExpcetion.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,42 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +/**
>>> + * Thrown when there is a validation exception on one of the apis
>>> + */
>>> +public class APIValidatorExpcetion extends Exception {
>>> +
>>> +  private static final long serialVersionUID = -8969858718669454612L;
>>> +
>>> +  public APIValidatorExpcetion() {
>>> +  }
>>> +
>>> +  public APIValidatorExpcetion(String message) {
>>> +    super(message);
>>> +  }
>>> +
>>> +  public APIValidatorExpcetion(Throwable cause) {
>>> +    super(cause);
>>> +  }
>>> +
>>> +  public APIValidatorExpcetion(String message, Throwable cause) {
>>> +    super(message, cause);
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorTest.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-
>>> api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorTest.java?rev=678158&view=auto
>>>
>>>
>>> ==============================================================================
>>> ---
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorTest.java
>>> (added)
>>> +++
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/APIValidatorTest.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,89 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +
>>> +import java.io.IOException;
>>> +import java.util.Map;
>>> +
>>> +import javax.xml.parsers.ParserConfigurationException;
>>> +
>>> +import org.junit.Assert;
>>> +import org.junit.Test;
>>> +import org.xml.sax.SAXException;
>>> +
>>> +/**
>>> + * Test the api validator to make certain it behaves as is expected.
>>> + */
>>> +public class APIValidatorTest {
>>> +
>>> +  /**
>>> +   * A definition of the test json used in this unit test.
>>> +   */
>>> +  private static final String TEST_DEFINITION =
>>> +    "var TestDef = {}; TestDef.Field = { FIELD1 : \"json\", FIELD2 :
>>> \"xyz\", FIELD3 : \"shouldBeMissing\" };";
>>> +
>>> +  /**
>>> +   * test the validator for successful validation
>>> +   * @throws APIValidatorExpcetion
>>> +   * @throws IOException
>>> +   * @throws ParserConfigurationException
>>> +   * @throws SAXException
>>> +   */
>>> +  @Test
>>> +  public void testValidator() throws APIValidatorExpcetion, IOException,
>>> ParserConfigurationException, SAXException {
>>> +    APIValidator apiVal = new APIValidator("opensocial-reference");
>>> +    apiVal.addScript(TEST_DEFINITION);
>>> +    String[] optional = {"shouldBeMissing"};
>>> +    String[] nullfields = {};
>>> +     Map<String, Object> result = apiVal.validate("{ json: \"A Test
>>> JSON\", xyz : 123 }", "TestDef.Field", optional, nullfields );
>>> +     Assert.assertNotNull(result);
>>> +     Assert.assertNotNull(result.get("json"));
>>> +     Assert.assertNotNull(result.get("xyz"));
>>> +     Assert.assertEquals(String.class,result.get("json").getClass());
>>> +     Assert.assertEquals(Integer.class,result.get("xyz").getClass());
>>> +     Assert.assertEquals("A Test JSON",result.get("json"));
>>> +     Assert.assertEquals(123,((Integer)result.get("xyz")).intValue());
>>> +
>>> +
>>> +  }
>>> +
>>> +  /**
>>> +   * Test for a failing validation
>>> +   * @throws APIValidatorExpcetion
>>> +   * @throws IOException
>>> +   * @throws ParserConfigurationException
>>> +   * @throws SAXException
>>> +   */
>>> +  @Test
>>> +  public void testValidatorFail() throws APIValidatorExpcetion,
>>> IOException, ParserConfigurationException, SAXException {
>>> +    APIValidator apiVal = new APIValidator("opensocial-reference");
>>> +    apiVal.addScript(TEST_DEFINITION);
>>> +    String[] optional = {};
>>> +    String[] nullfields = {};
>>> +    try {
>>> +      apiVal.validate("{ jsonIsMissing: \"A Test JSON\", xyz : 123 }",
>>> "TestDef.Field", optional, nullfields );
>>> +      Assert.fail("Should have Generated an APIValidatorException ");
>>> +    } catch ( APIValidatorExpcetion ex ) {
>>> +
>>> +    }
>>> +
>>> +
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-
>>> api/src/test/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverterTest.java?rev=678158&view=auto
>>>
>>>
>>> ==============================================================================
>>> ---
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>> (added)
>>> +++
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,359 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +import java.util.ArrayList;
>>> +import java.util.List;
>>> +import java.util.Map;
>>> +
>>> +import junit.framework.TestCase;
>>> +
>>> +import org.apache.commons.logging.Log;
>>> +import org.apache.commons.logging.LogFactory;
>>> +import org.apache.shindig.social.JsonLibTestsGuiceModule;
>>> +import org.apache.shindig.social.opensocial.model.Activity;
>>> +import org.apache.shindig.social.opensocial.model.ActivityImpl;
>>> +import org.apache.shindig.social.opensocial.model.Address;
>>> +import org.apache.shindig.social.opensocial.model.AddressImpl;
>>> +import org.apache.shindig.social.opensocial.model.Email;
>>> +import org.apache.shindig.social.opensocial.model.EmailImpl;
>>> +import org.apache.shindig.social.opensocial.model.MediaItem;
>>> +import org.apache.shindig.social.opensocial.model.MediaItemImpl;
>>> +import org.apache.shindig.social.opensocial.model.Name;
>>> +import org.apache.shindig.social.opensocial.model.NameImpl;
>>> +import org.apache.shindig.social.opensocial.model.Person;
>>> +import org.apache.shindig.social.opensocial.model.PersonImpl;
>>> +import org.apache.shindig.social.opensocial.model.Phone;
>>> +import org.apache.shindig.social.opensocial.model.PhoneImpl;
>>> +
>>> +import com.google.common.collect.Lists;
>>> +import com.google.common.collect.Maps;
>>> +import com.google.inject.Guice;
>>> +
>>> +public class BeanJsonLibConverterTest extends TestCase {
>>> +
>>> +  private static final Log log = LogFactory
>>> +      .getLog(BeanJsonLibConverterTest.class);
>>> +  private Person johnDoe;
>>> +  private Activity activity;
>>> +
>>> +  private BeanJsonLibConverter beanJsonConverter;
>>> +  private APIValidator apiValidator;
>>> +  // set to true to get loging output at info level
>>> +  private boolean outputInfo = false;
>>> +
>>> +  @Override
>>> +  public void setUp() throws Exception {
>>> +    super.setUp();
>>> +    johnDoe = new PersonImpl("johnDoeId", new NameImpl("John Doe"));
>>> +    johnDoe.setPhoneNumbers(Lists.<Phone> newArrayList(new PhoneImpl(
>>> +        "+33H000000000", "home"), new PhoneImpl("+33M000000000",
>>> "mobile"),
>>> +        new PhoneImpl("+33W000000000", "work")));
>>> +
>>> +    johnDoe.setAddresses(Lists.<Address> newArrayList(new AddressImpl(
>>> +        "My home address")));
>>> +
>>> +    johnDoe.setEmails(Lists.<Email> newArrayList(new EmailImpl(
>>> +        "john.doe@work.bar", "work"),
>>> +        new EmailImpl("john.doe@home.bar", "home")));
>>> +
>>> +    activity = new ActivityImpl("activityId", johnDoe.getId());
>>> +
>>> +    activity.setMediaItems(Lists.<MediaItem> newArrayList(new
>>> MediaItemImpl(
>>> +        "image/jpg", MediaItem.Type.IMAGE, "http://foo.bar")));
>>> +
>>> +    beanJsonConverter = new BeanJsonLibConverter(Guice
>>> +        .createInjector(new JsonLibTestsGuiceModule()));
>>> +
>>> +    apiValidator = new APIValidator("opensocial-reference");
>>> +
>>> +  }
>>> +
>>> +  public static class SpecialPerson extends PersonImpl {
>>> +    public static final String[] OPTIONALFIELDS = {};
>>> +    public static final String[] NULLFIELDS  =
>>> {"jobInterests","nickname","romance","religion","timeZone",
>>> +
>>>
>>>  "relationshipStatus","tags","networkPresence","books","quotes","phoneNumbers","languagesSpoken",
>>> +
>>>
>>>  "activities","jobs","dateOfBirth","profileVideo","bodyType","urls","schools","music","addresses",
>>> +
>>>
>>>  "livingArrangement","thumbnailUrl","humor","sports","scaredOf","movies","age","pets","hasApp","turnOffs",
>>> +
>>>
>>>  "gender","fashion","drinker","aboutMe","children","sexualOrientation","heroes","profileSong","lookingFor",
>>> +
>>>
>>>  "cars","turnOns","tvShows","profileUrl","status","currentLocation","smoker","happiestWhen","ethnicity",
>>> +
>>>
>>>  "food","emails","politicalViews","interests","familyName","honorificSuffix","additionalName","honorificPrefix","givenName"};
>>> +
>>> +    private String newfield;
>>> +
>>> +    public SpecialPerson() {
>>> +      super();
>>> +    }
>>> +
>>> +    public SpecialPerson(String id, String name, String newfield) {
>>> +      super(id, new NameImpl(name));
>>> +      this.newfield = newfield;
>>> +    }
>>> +
>>> +    public String getNewfield() {
>>> +      return newfield;
>>> +    }
>>> +
>>> +    public void setNewfield(String newfield) {
>>> +      this.newfield = newfield;
>>> +    }
>>> +
>>> +  }
>>> +
>>> +  public void testToJsonOnInheritedClass() throws Exception {
>>> +    SpecialPerson cassie = new SpecialPerson("5", "robot", "nonsense");
>>> +
>>> +    String result = beanJsonConverter.convertToString(cassie);
>>> +
>>> +    validatePerson(result, "5", "robot", SpecialPerson.OPTIONALFIELDS,
>>> SpecialPerson.NULLFIELDS);
>>> +
>>> +    apiValidator.addScript(" specialPerson = { SPECIAL : \"newfield\" };
>>> ");
>>> +    String[] optional = {};
>>> +    String[] nullfields = {};
>>> +    Map<String, Object> special = apiValidator.validate(result,
>>> +        "specialPerson", optional,nullfields);
>>> +    assertNotNull(special.get("newfield"));
>>> +    assertEquals(String.class, special.get("newfield").getClass());
>>> +    assertEquals("nonsense", special.get("newfield"));
>>> +
>>> +    // convert back into an object Tree
>>> +
>>> +    SpecialPerson parseCassie =
>>> beanJsonConverter.convertToObject(result,
>>> +        SpecialPerson.class);
>>> +
>>> +    assertNotNull(parseCassie);
>>> +    assertEquals(cassie.getId(), parseCassie.getId());
>>> +    assertEquals(cassie.getNewfield(), parseCassie.getNewfield());
>>> +
>>> +    Name name = parseCassie.getName();
>>> +    Name cassieName = cassie.getName();
>>> +    assertNotNull(name);
>>> +    assertEquals(cassieName.getUnstructured(), name.getUnstructured());
>>> +    assertEquals(cassieName.getAdditionalName(),
>>> name.getAdditionalName());
>>> +    assertEquals(cassieName.getFamilyName(), name.getFamilyName());
>>> +    assertEquals(cassieName.getGivenName(), name.getGivenName());
>>> +    assertEquals(cassieName.getHonorificPrefix(),
>>> name.getHonorificPrefix());
>>> +    assertEquals(cassieName.getHonorificSuffix(),
>>> name.getHonorificSuffix());
>>> +
>>> +  }
>>> +
>>> +  /**
>>> +   * @param result
>>> +   * @throws APIValidatorExpcetion
>>> +   */
>>> +  private void validatePerson(String result, String id, String name,
>>> String[] optional, String[] nullfields)
>>> +      throws APIValidatorExpcetion {
>>> +
>>> +    Map<String, Object> standard = apiValidator.validate(result,
>>> +        "opensocial.Person.Field", optional,nullfields);
>>> +    assertNotNull(standard.get("id"));
>>> +    assertEquals(String.class, standard.get("id").getClass());
>>> +    assertEquals(id, standard.get("id"));
>>> +
>>> +    assertNotNull(standard.get("name"));
>>> +    Map<String, Object> nameJSON = apiValidator.validateOject(standard
>>> +        .get("name"), "opensocial.Name.Field", optional,nullfields);
>>> +    APIValidator.dump(nameJSON);
>>> +
>>> +    assertNotNull(nameJSON.get("unstructured"));
>>> +    assertEquals(String.class, nameJSON.get("unstructured").getClass());
>>> +    assertEquals(name, nameJSON.get("unstructured"));
>>> +
>>> +    // additional name
>>> +    assertNull(nameJSON.get("additionalName"));
>>> +
>>> +  }
>>> +
>>> +  public void testPersonToJson() throws Exception {
>>> +    String result = beanJsonConverter.convertToString(johnDoe);
>>> +    if (outputInfo) {
>>> +      log.info("JSON (" + result + ")");
>>> +    }
>>> +    Person parsedPerson = beanJsonConverter.convertToObject(result,
>>> +        Person.class);
>>> +
>>> +    assertEquals(johnDoe.getId(), parsedPerson.getId());
>>> +    assertEquals(johnDoe.getName().getUnstructured(),
>>> parsedPerson.getName()
>>> +        .getUnstructured());
>>> +
>>> +    List<Address> addresses = parsedPerson.getAddresses();
>>> +    if (outputInfo) {
>>> +      for (Object o : addresses) {
>>> +        log.info("Address " + o);
>>> +      }
>>> +    }
>>> +
>>> +    assertEquals(1, addresses.size());
>>> +    Address address = addresses.get(0);
>>> +    String unstructured = address.getUnstructuredAddress();
>>> +
>>> +    assertNotNull(unstructured);
>>> +    assertEquals(johnDoe.getAddresses().get(0).getUnstructuredAddress(),
>>> +        parsedPerson.getAddresses().get(0).getUnstructuredAddress());
>>> +
>>> +    assertEquals(3, parsedPerson.getPhoneNumbers().size());
>>> +
>>> +    for (int i = 0; i < johnDoe.getPhoneNumbers().size(); i++) {
>>> +      Phone expectedPhone = johnDoe.getPhoneNumbers().get(i);
>>> +      Phone actualPhone = parsedPerson.getPhoneNumbers().get(i);
>>> +      assertEquals(expectedPhone.getType(), actualPhone.getType());
>>> +      assertEquals(expectedPhone.getNumber(), actualPhone.getNumber());
>>> +    }
>>> +
>>> +    assertEquals(2, parsedPerson.getEmails().size());
>>> +
>>> +    for (int i = 0; i < johnDoe.getEmails().size(); i++) {
>>> +      Email expectedEmail = johnDoe.getEmails().get(i);
>>> +      Email actualEmail = parsedPerson.getEmails().get(i);
>>> +      assertEquals(expectedEmail.getType(), actualEmail.getType());
>>> +      assertEquals(expectedEmail.getAddress(),
>>> actualEmail.getAddress());
>>> +    }
>>> +  }
>>> +
>>> +  public void testActivityToJson() throws Exception {
>>> +
>>> +    String result = beanJsonConverter.convertToString(activity);
>>> +    if (outputInfo) {
>>> +      log.info("JSON (" + result + ")");
>>> +    }
>>> +    Activity parsedActivity = beanJsonConverter.convertToObject(result,
>>> +        Activity.class);
>>> +    assertEquals(activity.getUserId(), parsedActivity.getUserId());
>>> +    assertEquals(activity.getId(), parsedActivity.getId());
>>> +
>>> +    assertEquals(1, parsedActivity.getMediaItems().size());
>>> +
>>> +    MediaItem expectedItem = activity.getMediaItems().get(0);
>>> +    MediaItem actualItem = parsedActivity.getMediaItems().get(0);
>>> +
>>> +    assertEquals(expectedItem.getUrl(), actualItem.getUrl());
>>> +    assertEquals(expectedItem.getMimeType(), actualItem.getMimeType());
>>> +    assertEquals(expectedItem.getType().toString(), actualItem.getType()
>>> +        .toString());
>>> +  }
>>> +
>>> +  public void testMapsToJson() throws Exception {
>>> +    Map<String, Map<String, String>> map = Maps.newHashMap();
>>> +
>>> +    Map<String, String> item1Map = Maps.newHashMap();
>>> +    item1Map.put("value", "1");
>>> +
>>> +    // Null values shouldn't cause exceptions
>>> +    item1Map.put("value2", null);
>>> +    map.put("item1", item1Map);
>>> +
>>> +    Map<String, String> item2Map = Maps.newHashMap();
>>> +    item2Map.put("value", "2");
>>> +    map.put("item2", item2Map);
>>> +
>>> +    String result = beanJsonConverter.convertToString(map);
>>> +    if (outputInfo) {
>>> +      log.info("JSON (" + result + ")");
>>> +    }
>>> +    // there is introspection that can tell jsonobject -> bean converter
>>> what a
>>> +    // map should contain, so we have to tell it
>>> +    beanJsonConverter.addMapping("item1", Map.class);
>>> +    beanJsonConverter.addMapping("item2", Map.class);
>>> +    Map<?, ?> parsedMap = beanJsonConverter
>>> +        .convertToObject(result, Map.class);
>>> +
>>> +    if (outputInfo) {
>>> +      log.info("Dumping Map (" + parsedMap + ")");
>>> +    }
>>> +    APIValidator.dump(parsedMap);
>>> +
>>> +    assertEquals("1", ((Map<?,?>)parsedMap.get("item1")).get("value"));
>>> +    assertEquals("2", ((Map<?,?>)parsedMap.get("item2")).get("value"));
>>> +  }
>>> +
>>> +  public void testListsToJson() throws Exception {
>>> +    Map<String, String> item1Map = Maps.newHashMap();
>>> +    item1Map.put("value", "1");
>>> +
>>> +    Map<String, String> item2Map = Maps.newHashMap();
>>> +    item2Map.put("value", "2");
>>> +
>>> +    // put the list into a container before serializing, top level lists
>>> dont
>>> +    // appear
>>> +    // to be allowed in json
>>> +    // just check that the list is in the holder correctly
>>> +    List<Map<String, String>> list = new ArrayList<Map<String,
>>> String>>();
>>> +    list.add(item1Map);
>>> +    list.add(item2Map);
>>> +    String result = beanJsonConverter.convertToString(list);
>>> +    if (outputInfo) {
>>> +      log.info("JSON (" + result + ")");
>>> +    }
>>> +    Map<?, ?>[] parsedList = beanJsonConverter.convertToObject(
>>> +        result, Map[].class);
>>> +
>>> +    assertEquals("1", parsedList[0].get("value"));
>>> +    assertEquals("2", parsedList[1].get("value"));
>>> +  }
>>> +
>>> +  public void testArrayToJson() throws Exception {
>>> +    String[] colors = { "blue", "green", "aquamarine" };
>>> +    String result = beanJsonConverter.convertToString(colors);
>>> +    if (outputInfo) {
>>> +      log.info("JSON (" + result + ")");
>>> +    }
>>> +    String[] parsedColors = beanJsonConverter.convertToObject(result,
>>> +        String[].class);
>>> +    assertEquals(colors.length, parsedColors.length);
>>> +    assertEquals(colors[0], parsedColors[0]);
>>> +    assertEquals(colors[1], parsedColors[1]);
>>> +    assertEquals(colors[2], parsedColors[2]);
>>> +  }
>>> +
>>> +  public void testJsonToActivity() throws Exception {
>>> +    String jsonActivity = "{userId : 5, id : 6, mediaItems : ["
>>> +        + "{url : 'hello', mimeType : 'mimey', type : 'VIDEO'}" + "]}";
>>> +    Activity result = beanJsonConverter.convertToObject(jsonActivity,
>>> +        Activity.class);
>>> +
>>> +    assertEquals("5", result.getUserId());
>>> +    assertEquals("6", result.getId());
>>> +
>>> +    assertEquals(1, result.getMediaItems().size());
>>> +
>>> +    MediaItem actualItem = result.getMediaItems().get(0);
>>> +
>>> +    assertEquals("hello", actualItem.getUrl());
>>> +    assertEquals("mimey", actualItem.getMimeType());
>>> +    assertEquals("video", actualItem.getType().toString());
>>> +  }
>>> +
>>> +  public void testJsonToMap() throws Exception {
>>> +    String jsonActivity = "{count : 0, favoriteColor : 'yellow'}";
>>> +    Map<String, String> data = Maps.newHashMap();
>>> +    data = beanJsonConverter.convertToObject(jsonActivity,
>>> +        (Class<Map<String, String>>) data.getClass());
>>> +
>>> +    assertEquals(2, data.size());
>>> +
>>> +    for (String key : data.keySet()) {
>>> +      Object value = data.get(key);
>>> +      if (key.equals("count")) {
>>> +        assertEquals(0, value);
>>> +      } else if (key.equals("favoriteColor")) {
>>> +        assertEquals("yellow", value);
>>> +      }
>>> +    }
>>> +  }
>>> +
>>> +}
>>>
>>> Added:
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>> URL:
>>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social-
>>> api/src/test/java/org/apache/shindig/social/opensocial/util/JsonConverterPerformancePerf.java?rev=678158&view=auto
>>>
>>>
>>> ==============================================================================
>>> ---
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>> (added)
>>> +++
>>>
>>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>>> Sat Jul 19 06:51:03 2008
>>> @@ -0,0 +1,271 @@
>>> +/*
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + *     http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * 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.apache.shindig.social.opensocial.util;
>>> +
>>> +import junit.framework.TestCase;
>>> +
>>> +import org.apache.commons.logging.Log;
>>> +import org.apache.commons.logging.LogFactory;
>>> +import org.apache.shindig.social.JsonLibTestsGuiceModule;
>>> +import org.apache.shindig.social.SocialApiTestsGuiceModule;
>>> +import org.apache.shindig.social.opensocial.model.Activity;
>>> +import org.apache.shindig.social.opensocial.model.ActivityImpl;
>>> +import org.apache.shindig.social.opensocial.model.Address;
>>> +import org.apache.shindig.social.opensocial.model.AddressImpl;
>>> +import org.apache.shindig.social.opensocial.model.Email;
>>> +import org.apache.shindig.social.opensocial.model.EmailImpl;
>>> +import org.apache.shindig.social.opensocial.model.MediaItem;
>>> +import org.apache.shindig.social.opensocial.model.MediaItemImpl;
>>> +import org.apache.shindig.social.opensocial.model.NameImpl;
>>> +import org.apache.shindig.social.opensocial.model.Person;
>>> +import org.apache.shindig.social.opensocial.model.PersonImpl;
>>> +import org.apache.shindig.social.opensocial.model.Phone;
>>> +import org.apache.shindig.social.opensocial.model.PhoneImpl;
>>> +import org.json.JSONObject;
>>> +
>>> +import com.google.common.collect.Lists;
>>> +import com.google.inject.Guice;
>>> +
>>> +public class JsonConverterPerformancePerf extends TestCase {
>>> +
>>> +  private static final Log log = LogFactory
>>> +      .getLog(JsonConverterPerformancePerf.class);
>>> +  private static final int TEST_SIZE = 10000;
>>> +  private Person johnDoe;
>>> +  private Activity activity;
>>> +
>>> +  private BeanJsonLibConverter beanJsonLibConverter;
>>> +  private APIValidator apiValidator;
>>> +  // set to true to get loging output at info level
>>> +  private boolean outputInfo = false;
>>> +  private BeanJsonConverter beanJsonConverter;
>>> +
>>> +  @Override
>>> +  public void setUp() throws Exception {
>>> +    super.setUp();
>>> +    johnDoe = new PersonImpl("johnDoeId", new NameImpl("John Doe"));
>>> +    johnDoe.setPhoneNumbers(Lists.<Phone> newArrayList(new PhoneImpl(
>>> +        "+33H000000000", "home"), new PhoneImpl("+33M000000000",
>>> "mobile"),
>>> +        new PhoneImpl("+33W000000000", "work")));
>>> +
>>> +    johnDoe.setAddresses(Lists.<Address> newArrayList(new AddressImpl(
>>> +        "My home address")));
>>> +
>>> +    johnDoe.setEmails(Lists.<Email> newArrayList(new EmailImpl(
>>> +        "john.doe@work.bar", "work"),
>>> +        new EmailImpl("john.doe@home.bar", "home")));
>>> +
>>> +    activity = new ActivityImpl("activityId", johnDoe.getId());
>>> +
>>> +    activity.setMediaItems(Lists.<MediaItem> newArrayList(new
>>> MediaItemImpl(
>>> +        "image/jpg", MediaItem.Type.IMAGE, "http://foo.bar")));
>>> +
>>> +    beanJsonLibConverter = new BeanJsonLibConverter(Guice
>>> +        .createInjector(new JsonLibTestsGuiceModule()));
>>> +
>>> +    beanJsonConverter = new BeanJsonConverter(Guice
>>> +        .createInjector(new SocialApiTestsGuiceModule()));
>>> +
>>> +    apiValidator = new APIValidator("opensocial-reference");
>>> +
>>> +  }
>>> +
>>> +  public static class SpecialPerson extends PersonImpl {
>>> +    private String newfield;
>>> +
>>> +    public SpecialPerson() {
>>> +      super();
>>> +    }
>>> +
>>> +    public SpecialPerson(String id, String name, String newfield) {
>>> +      super(id, new NameImpl(name));
>>> +      this.newfield = newfield;
>>> +    }
>>> +
>>> +    public String getNewfield() {
>>> +      return newfield;
>>> +    }
>>> +
>>> +    public void setNewfield(String newfield) {
>>> +      this.newfield = newfield;
>>> +    }
>>> +
>>> +  }
>>> +
>>> +  public void testToJsonLibOnInheritedClassOutput() throws Exception {
>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",
>>> "nonsense");
>>> +    }
>>> +    Runtime r = Runtime.getRuntime();
>>> +    r.gc();
>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>> +    long startOutput = System.currentTimeMillis();
>>> +    String[] output = new String[TEST_SIZE];
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      output[i] = beanJsonLibConverter.convertToString(spa[i]);
>>> +    }
>>> +    long endOutput = System.currentTimeMillis();
>>> +    long memend = r.totalMemory()-r.freeMemory();
>>> +
>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>> +    char[] source = output[0].toCharArray();
>>> +    r.gc();
>>> +
>>> +    long stringsizeStart = r.totalMemory()-r.freeMemory();
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      serializeOutput[i] = new String(source);
>>> +    }
>>> +    long stringsizeEnd = r.totalMemory()-r.freeMemory();
>>> +
>>> +    /*
>>> +     * Output the time per conversion and the memory usage - the output
>>> per
>>> +     * conversion.
>>> +     *
>>> +     */
>>> +
>>> +    log.info("SF JSON Lib Output "
>>> +        + average(startOutput, endOutput, TEST_SIZE)
>>> +        + " ms/conversion, "
>>> +        + (average(memstart, memend, TEST_SIZE)-average(stringsizeStart,
>>> stringsizeEnd, TEST_SIZE))
>>> +        + " heap bytes/conversion, output packet consumed on average "
>>> +        + average(stringsizeStart, stringsizeEnd, TEST_SIZE)+" for a
>>> string length of "+output[0].length());
>>> +    log.info("Output Was ["+output[0]+"]");
>>> +  }
>>> +
>>> +  public void testToJsonLibOnInheritedClassInput() throws Exception {
>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>> +    SpecialPerson[] sparesult = new SpecialPerson[TEST_SIZE];
>>> +    Runtime r = Runtime.getRuntime();
>>> +    r.gc();
>>> +    long personStart = r.totalMemory()-r.freeMemory();
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",
>>> "nonsense");
>>> +    }
>>> +    long personEnd = r.totalMemory()-r.freeMemory();
>>> +
>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>> +    r.gc();
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +
>>> +      serializeOutput[i] = beanJsonLibConverter.convertToString(spa[i]);
>>> +    }
>>> +
>>> +    r.gc();
>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>> +    long startInput = System.currentTimeMillis();
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +        sparesult[i] = beanJsonLibConverter.convertToObject(
>>> +          serializeOutput[i], SpecialPerson.class);
>>> +    }
>>> +    long endInput = System.currentTimeMillis();
>>> +    long memend = r.totalMemory()-r.freeMemory();
>>> +
>>> +    log.info("SF JSON Lib Input "
>>> +        + average(startInput, endInput, TEST_SIZE)
>>> +        + " ms/conversion, "
>>> +        + (average(memstart, memend, TEST_SIZE)-average(personStart,
>>> personEnd, TEST_SIZE))
>>> +        + " heap bytes/conversion, person object consumed on average "
>>> +        + average(personStart, personEnd, TEST_SIZE));
>>> +  }
>>> +
>>> +  public void testToJsonOnInheritedClassOutput() throws Exception {
>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",
>>> "nonsense");
>>> +    }
>>> +    Runtime r = Runtime.getRuntime();
>>> +    String[] output = new String[TEST_SIZE];
>>> +    r.gc();
>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>> +    long startOutput = System.currentTimeMillis();
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      output[i]  = ((JSONObject)
>>> beanJsonConverter.convertToJson(spa[i])).toString();
>>> +    }
>>> +    long endOutput = System.currentTimeMillis();
>>> +    long memend = r.totalMemory()-r.freeMemory();
>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>> +    char[] source = output[0].toCharArray();
>>> +    r.gc();
>>> +
>>> +    long stringsizeStart = r.totalMemory()-r.freeMemory();
>>> +
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      serializeOutput[i] = new String(source);
>>> +    }
>>> +    long stringsizeEnd = r.totalMemory()-r.freeMemory();
>>> +
>>> +    log.info("ORG JSON Lib Output "
>>> +        + average(startOutput, endOutput, TEST_SIZE)
>>> +        + " ms/conversion, "
>>> +        + (average(memstart, memend, TEST_SIZE)-average(stringsizeStart,
>>> stringsizeEnd, TEST_SIZE))
>>> +        + " heap bytes/conversion, output packet consumed on average "
>>> +        + average(stringsizeStart, stringsizeEnd, TEST_SIZE)+" for a
>>> string length of "+output[0].length());
>>> +    log.info("Output Was ["+output[0]+"]");
>>> +  }
>>> +
>>> +  /**
>>> +   * @param endOutput
>>> +   * @param startOutput
>>> +   * @param testSize
>>> +   * @return
>>> +   */
>>> +  private float average(long start, long end, int testSize) {
>>> +    float r = end - start;
>>> +    r = r / testSize;
>>> +    return r;
>>> +  }
>>> +
>>> +  public void XtestToJsonOnInheritedClassInput() throws Exception {
>>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>>> +    SpecialPerson[] sparesult = new SpecialPerson[TEST_SIZE];
>>> +    Runtime r = Runtime.getRuntime();
>>> +    r.gc();
>>> +    long personStart = r.totalMemory()-r.freeMemory();
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",
>>> "nonsense");
>>> +    }
>>> +    long personEnd = r.totalMemory()-r.freeMemory();
>>> +
>>> +    String[] serializeOutput = new String[TEST_SIZE];
>>> +    r.gc();
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +
>>> +      serializeOutput[i] = beanJsonConverter.convertToString(spa[i]);
>>> +    }
>>> +
>>> +    r.gc();
>>> +    long memstart = r.totalMemory()-r.freeMemory();
>>> +    long startInput = System.currentTimeMillis();
>>> +
>>> +    for (int i = 0; i < TEST_SIZE; i++) {
>>> +      sparesult[i] = beanJsonConverter.convertToObject(
>>> +          serializeOutput[i], SpecialPerson.class);
>>> +    }
>>> +    long endInput = System.currentTimeMillis();
>>> +    long memend = r.totalMemory()-r.freeMemory();
>>> +
>>> +    log.info("SF JSON Lib Input "
>>> +        + average(startInput, endInput, TEST_SIZE)
>>> +        + " ms/conversion, "
>>> +        + (average(memstart, memend, TEST_SIZE)-average(personStart,
>>> personEnd, TEST_SIZE))
>>> +        + " heap bytes/conversion, person object consumed on average "
>>> +        + average(personStart, personEnd, TEST_SIZE));
>>> +  }
>>> +
>>> +}
>>>
>>> Modified: incubator/s
>>
>> ...
>
> [Message clipped]

Re: svn commit: r678158 - in /incubator/shindig/trunk: ./ java/social-api/ java/social-api/src/main/java/org/apache/shindig/social/opensocial/util/ java/social-api/src/test/java/org/apache/shindig/social/ java/social-api/src/test/java/org/apache/shin

Posted by Ian Boston <ie...@tfd.co.uk>.
Ok will fix.
Ian

On 19 Jul 2008, at 20:50, Kevin Brown wrote:

> Hey Ian,
>
> The casing is inconsistent here -- it should be Json and Api for  
> all cases
> rather than JSON or API.
>
> Thanks!
>
> On Sat, Jul 19, 2008 at 6:51 AM, <ie...@apache.org> wrote:
>
>> Author: ieb
>> Date: Sat Jul 19 06:51:03 2008
>> New Revision: 678158
>>
>> URL: http://svn.apache.org/viewvc?rev=678158&view=rev
>> Log:
>> SHINDIG-451
>> Applying patch from the JIRA.
>>
>> Adds a json-lib (net.sf) converter, not wired into social-api at  
>> present.
>>
>> Added:
>>
>>  incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>>
>>  incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>>
>>  incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>>
>>  incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>>
>>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/JsonLibTestsGuiceModule.java
>>
>>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/APIValidator.java
>>
>>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>>
>>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/APIValidatorTest.java
>>
>>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>>
>>  incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>> Modified:
>>    incubator/shindig/trunk/java/social-api/pom.xml
>>    incubator/shindig/trunk/pom.xml
>>
>> Modified: incubator/shindig/trunk/java/social-api/pom.xml
>> URL:
>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>> api/pom.xml?rev=678158&r1=678157&r2=678158&view=diff
>>
>> ===================================================================== 
>> =========
>> --- incubator/shindig/trunk/java/social-api/pom.xml (original)
>> +++ incubator/shindig/trunk/java/social-api/pom.xml Sat Jul 19  
>> 06:51:03
>> 2008
>> @@ -60,12 +60,31 @@
>>       <groupId>org.apache.shindig</groupId>
>>       <artifactId>shindig-common</artifactId>
>>     </dependency>
>> +    <!-- is this Ok, only used in test to load the features -->
>> +    <dependency>
>> +      <groupId>org.apache.shindig</groupId>
>> +      <artifactId>shindig-features</artifactId>
>> +      <scope>test</scope>
>> +    </dependency>
>>
>>     <!-- external depenencies -->
>>     <dependency>
>>       <groupId>org.json</groupId>
>>       <artifactId>json</artifactId>
>>     </dependency>
>> +    <!-- the classifier prevents this working in dep management -->
>> +    <dependency>
>> +      <groupId>net.sf.json-lib</groupId>
>> +      <artifactId>json-lib</artifactId>
>> +      <version>2.2</version>
>> +      <classifier>jdk15</classifier>
>> +      <type>jar</type>
>> +    </dependency>
>> +    <dependency>
>> +      <groupId>rhino</groupId>
>> +      <artifactId>js</artifactId>
>> +      <scope>test</scope>
>> +    </dependency>
>>     <dependency>
>>       <groupId>com.google.code.guice</groupId>
>>       <artifactId>guice</artifactId>
>> @@ -112,5 +131,10 @@
>>       <artifactId>core</artifactId>
>>       <scope>compile</scope>
>>     </dependency>
>> +    <dependency>
>> +      <groupId>log4j</groupId>
>> +      <artifactId>log4j</artifactId>
>> +      <scope>test</scope>
>> +    </dependency>
>>   </dependencies>
>>  </project>
>>
>> Added:
>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>> URL:
>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>> api/src/main/java/org/apache/shindig/social/opensocial/util/ 
>> BeanJsonLibConversionException.java?rev=678158&view=auto
>>
>> ===================================================================== 
>> =========
>> ---
>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>> (added)
>> +++
>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/BeanJsonLibConversionException.java
>> Sat Jul 19 06:51:03 2008
>> @@ -0,0 +1,43 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one
>> + * or more contributor license agreements. See the NOTICE file
>> + * distributed with this work for additional information
>> + * regarding copyright ownership. The ASF licenses this file
>> + * to you under the Apache License, Version 2.0 (the
>> + * "License"); you may not use this file except in compliance
>> + * with the License. You may obtain a copy of the License at
>> + *
>> + *     http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * 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.apache.shindig.social.opensocial.util;
>> +
>> +/**
>> + * Where a conversion exception happens in the Json Lib  
>> conversion, this
>> + * exception is thrown.
>> + */
>> +public class BeanJsonLibConversionException extends  
>> RuntimeException {
>> +
>> +  private static final long serialVersionUID =  
>> -8609384443448202372L;
>> +
>> +  public BeanJsonLibConversionException() {
>> +  }
>> +
>> +  public BeanJsonLibConversionException(String arg0) {
>> +    super(arg0);
>> +  }
>> +
>> +  public BeanJsonLibConversionException(Throwable arg0) {
>> +    super(arg0);
>> +  }
>> +
>> +  public BeanJsonLibConversionException(String arg0, Throwable  
>> arg1) {
>> +    super(arg0, arg1);
>> +  }
>> +
>> +}
>>
>> Added:
>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>> URL:
>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>> api/src/main/java/org/apache/shindig/social/opensocial/util/ 
>> BeanJsonLibConverter.java?rev=678158&view=auto
>>
>> ===================================================================== 
>> =========
>> ---
>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>> (added)
>> +++
>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/BeanJsonLibConverter.java
>> Sat Jul 19 06:51:03 2008
>> @@ -0,0 +1,286 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one
>> + * or more contributor license agreements. See the NOTICE file
>> + * distributed with this work for additional information
>> + * regarding copyright ownership. The ASF licenses this file
>> + * to you under the Apache License, Version 2.0 (the
>> + * "License"); you may not use this file except in compliance
>> + * with the License. You may obtain a copy of the License at
>> + *
>> + *     http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * 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.apache.shindig.social.opensocial.util;
>> +
>> +import java.lang.reflect.Array;
>> +import java.lang.reflect.InvocationTargetException;
>> +import java.util.Collection;
>> +import java.util.HashMap;
>> +import java.util.List;
>> +import java.util.Map;
>> +
>> +import net.sf.ezmorph.MorpherRegistry;
>> +import net.sf.json.JSONArray;
>> +import net.sf.json.JSONException;
>> +import net.sf.json.JSONObject;
>> +import net.sf.json.JsonConfig;
>> +import net.sf.json.processors.DefaultValueProcessor;
>> +import net.sf.json.util.EnumMorpher;
>> +import net.sf.json.util.JSONUtils;
>> +import net.sf.json.util.NewBeanInstanceStrategy;
>> +import net.sf.json.util.PropertyFilter;
>> +
>> +import org.apache.commons.logging.Log;
>> +import org.apache.commons.logging.LogFactory;
>> +import org.apache.shindig.social.opensocial.model.Address;
>> +import org.apache.shindig.social.opensocial.model.Email;
>> +import org.apache.shindig.social.opensocial.model.Enum;
>> +import org.apache.shindig.social.opensocial.model.MediaItem;
>> +import org.apache.shindig.social.opensocial.model.Organization;
>> +import org.apache.shindig.social.opensocial.model.Phone;
>> +import org.apache.shindig.social.opensocial.model.Url;
>> +
>> +
>> +import com.google.inject.Inject;
>> +import com.google.inject.Injector;
>> +
>> +/**
>> + *
>> + */
>> +public class BeanJsonLibConverter implements BeanConverter {
>> +
>> +  protected static final Log log = LogFactory
>> +      .getLog(BeanJsonLibConverter.class);
>> +  private Injector injector;
>> +  private JsonConfig jsonConfig;
>> +  private boolean debugMode = false;
>> +
>> +  /*
>> +   * Register the Enum Morphers so that JSON -> Bean works  
>> correctly for
>> enums.
>> +   */
>> +  static {
>> +    MorpherRegistry morpherRegistry = JSONUtils.getMorpherRegistry 
>> ();
>> +    morpherRegistry.registerMorpher(new EnumMorpher 
>> (Address.Field.class));
>> +    morpherRegistry.registerMorpher(new EnumMorpher 
>> (Phone.Field.class));
>> +    morpherRegistry.registerMorpher(new EnumMorpher 
>> (Email.Field.class));
>> +    morpherRegistry.registerMorpher(new
>> EnumMorpher(MediaItem.Field.class));
>> +    morpherRegistry.registerMorpher(new
>> EnumMorpher(MediaItem.Type.class));
>> +    morpherRegistry.registerMorpher(new EnumMorpher 
>> (Enum.Drinker.class));
>> +    morpherRegistry.registerMorpher(new EnumMorpher 
>> (Enum.Field.class));
>> +    morpherRegistry.registerMorpher(new EnumMorpher 
>> (Enum.Gender.class));
>> +    morpherRegistry
>> +        .registerMorpher(new EnumMorpher 
>> (Enum.NetworkPresence.class));
>> +    morpherRegistry.registerMorpher(new EnumMorpher 
>> (Enum.Smoker.class));
>> +
>> +    morpherRegistry.registerMorpher(new JSONObjectToMapMorpher());
>> +  }
>> +
>> +  @Inject
>> +  public BeanJsonLibConverter(Injector injector) {
>> +    this.injector = injector;
>> +    createJsonConfig();
>> +  }
>> +
>> +  @SuppressWarnings("unchecked")
>> +  public <T> T convertToObject(String string, final Class<T>
>> rootBeanClass) {
>> +
>> +    if (string.startsWith("[")) {
>> +      JSONArray jsonArray = JSONArray.fromObject(string,  
>> jsonConfig);
>> +      if (debugMode) {
>> +        JSONLibConverterUtils.dumpJsonArray(jsonArray, " ");
>> +      }
>> +
>> +      if (rootBeanClass.isArray()) {
>> +        Class<?> componentType = rootBeanClass.getComponentType();
>> +        Object rootObject = injector.getInstance(componentType);
>> +        List<?> o = JSONArray.toList(jsonArray, rootObject,  
>> jsonConfig);
>> +        Object[] result = (Object[]) Array.newInstance 
>> (componentType,
>> o.size());
>> +        for (int i = 0; i < o.size(); i++) {
>> +          result[i] = o.get(i);
>> +        }
>> +        return (T) result;
>> +
>> +      } else {
>> +        T rootObject = injector.getInstance(rootBeanClass);
>> +        Object o = JSONArray.toArray(jsonArray, rootObject,  
>> jsonConfig);
>> +        return (T) o;
>> +      }
>> +    } else {
>> +      JSONObject jsonObject = JSONObject.fromObject(string,  
>> jsonConfig);
>> +
>> +      if (debugMode) {
>> +        JSONLibConverterUtils.dumpJsonObject(jsonObject, " ");
>> +      }
>> +
>> +      T rootObject = injector.getInstance(rootBeanClass);
>> +      Object o = JSONObject.toBean(jsonObject, rootObject,  
>> jsonConfig);
>> +      return (T) o;
>> +
>> +    }
>> +  }
>> +
>> +  /**
>> +   * @return
>> +   */
>> +  private void createJsonConfig() {
>> +
>> +    jsonConfig = new JsonConfig();
>> +
>> +    /*
>> +     * This hook deals with the creation of new beans in the JSON  
>> -> Java
>> Bean
>> +     * conversion
>> +     */
>> +    jsonConfig.setNewBeanInstanceStrategy(new  
>> NewBeanInstanceStrategy() {
>> +
>> +      @SuppressWarnings("unchecked")
>> +      @Override
>> +      public Object newInstance(Class beanClass, JSONObject  
>> jsonObject)
>> +          throws InstantiationException, IllegalAccessException,
>> +          SecurityException, NoSuchMethodException,
>> InvocationTargetException {
>> +        if (beanClass != null) {
>> +          Object o =
>> BeanJsonLibConverter.this.injector.getInstance(beanClass);
>> +          if (debugMode) {
>> +            log.info("Created Object " + o + " for " + beanClass  
>> + " with
>> ["
>> +                + jsonObject + "]");
>> +          }
>> +          return o;
>> +        }
>> +        return DEFAULT.newInstance(beanClass, jsonObject);
>> +      }
>> +
>> +    });
>> +
>> +    /*
>> +     * We are expecting null for nulls
>> +     */
>> +    jsonConfig.registerDefaultValueProcessor(String.class,
>> +        new DefaultValueProcessor() {
>> +          @SuppressWarnings("unchecked")
>> +          public Object getDefaultValue(Class target) {
>> +            return null;
>> +          }
>> +        });
>> +
>> +    jsonConfig.setJsonPropertyFilter(new PropertyFilter() {
>> +
>> +      public boolean apply(Object source, String name, Object  
>> value) {
>> +        return filterProperty(source, name, value);
>> +      }
>> +
>> +    });
>> +
>> +    jsonConfig.setJavaPropertyFilter(new PropertyFilter() {
>> +
>> +      public boolean apply(Object source, String name, Object  
>> value) {
>> +        return filterProperty(source,name,value);
>> +      }
>> +
>> +    });
>> +
>> +    // the classMap deals with the basic json string to bean  
>> conversion
>> +
>> +    Map<String, Class<?>> classMap = new HashMap<String, Class<?>> 
>> ();
>> +
>> +    /*
>> +     * mappings are required where there is a List of objects in the
>> interface
>> +     * with no indication of what type the list should contain.  
>> At the
>> moment,
>> +     * we are using 1 map for all json trees, as there is no  
>> conflict, but
>> if
>> +     * there is a map could be selected on the basis of the root  
>> object.
>> It
>> +     * would be better to do this with generics, but this is good  
>> enough
>> and
>> +     * compact enough for the moment.
>> +     *
>> +     */
>> +    //
>> +    // activity
>> +    classMap.put("mediaItems", MediaItem.class);
>> +    // this may not be necessary
>> +    classMap.put("templateParams", Map.class);
>> +    // BodyType needs no mappings
>> +    // Message needs no mappings
>> +    // Name needs no mappings
>> +    // Organization needs no mappings
>> +    // Url needs no mappings
>> +    // Email needs no mappings
>> +    // Phone Needs no mappings
>> +    // Address Needs no mappings
>> +    // MediaItem needs no mappings
>> +
>> +    // Person map
>> +    classMap.put("addresses", Address.class);
>> +    classMap.put("phoneNumbers", Phone.class);
>> +    classMap.put("emails", Email.class);
>> +    classMap.put("mediaItems", MediaItem.class);
>> +    classMap.put("jobs", Organization.class);
>> +    classMap.put("schools", Organization.class);
>> +    classMap.put("urls", Url.class);
>> +    jsonConfig.setClassMap(classMap);
>> +
>> +  }
>> +
>> +  /**
>> +   * @param source
>> +   * @param name
>> +   * @param value
>> +   * @return
>> +   */
>> +  protected boolean filterProperty(Object source, String name,  
>> Object
>> value) {
>> +    if ( value == null ) {
>> +      return true;
>> +    }
>> +    if ( value instanceof JSONArray ) {
>> +      JSONArray array = (JSONArray) value;
>> +      if ( array.size() == 0 ) {
>> +        return true;
>> +      }
>> +    }
>> +    if ( value instanceof JSONObject ) {
>> +      JSONObject object = (JSONObject) value;
>> +      if ( object.isNullObject() || object.isEmpty()  ) {
>> +        return true;
>> +      }
>> +    }
>> +    if ( value instanceof Collection) {
>> +      Collection<?> collection = (Collection<?>) value;
>> +      if ( collection.size() == 0  ) {
>> +        return true;
>> +      }
>> +    }
>> +    if ( value instanceof Object[] ) {
>> +      Object[] oarray = (Object[]) value;
>> +      if ( oarray.length == 0 ) {
>> +        return true;
>> +      }
>> +    }
>> +    return false;
>> +  }
>> +
>> +  public String convertToString(Object pojo) {
>> +
>> +    try {
>> +      JSONObject jsonObject = JSONObject.fromObject(pojo,  
>> jsonConfig);
>> +      return jsonObject.toString();
>> +    } catch (JSONException jse) {
>> +      Class<?> pojoClass = pojo.getClass();
>> +      if (JSONUtils.isArray(pojoClass)) {
>> +        JSONArray jsonArray = JSONArray.fromObject(pojo);
>> +        String result = jsonArray.toString();
>> +        return result;
>> +      }
>> +      throw jse;
>> +    }
>> +  }
>> +
>> +  /**
>> +   * @param string
>> +   * @param class1
>> +   */
>> +  public void addMapping(String key, Class<?> class1) {
>> +    jsonConfig.getClassMap().put(key, class1);
>> +  }
>> +
>> +}
>>
>> Added:
>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>> URL:
>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>> api/src/main/java/org/apache/shindig/social/opensocial/util/ 
>> JSONLibConverterUtils.java?rev=678158&view=auto
>>
>> ===================================================================== 
>> =========
>> ---
>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>> (added)
>> +++
>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/JSONLibConverterUtils.java
>> Sat Jul 19 06:51:03 2008
>> @@ -0,0 +1,72 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one
>> + * or more contributor license agreements. See the NOTICE file
>> + * distributed with this work for additional information
>> + * regarding copyright ownership. The ASF licenses this file
>> + * to you under the Apache License, Version 2.0 (the
>> + * "License"); you may not use this file except in compliance
>> + * with the License. You may obtain a copy of the License at
>> + *
>> + *     http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * 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.apache.shindig.social.opensocial.util;
>> +
>> +import org.apache.commons.logging.Log;
>> +import org.apache.commons.logging.LogFactory;
>> +
>> +import net.sf.json.JSONArray;
>> +import net.sf.json.JSONObject;
>> +
>> +/**
>> + *
>> + */
>> +public class JSONLibConverterUtils {
>> +  protected static final Log log = LogFactory
>> +  .getLog(JSONLibConverterUtils.class);
>> +
>> +
>> +  /**
>> +   * @param jsonObject
>> +   */
>> +  public static final void dumpJsonObject(JSONObject jsonObject,  
>> String
>> indent) {
>> +    for (Object key : jsonObject.keySet()) {
>> +      Object value = jsonObject.get(key);
>> +      if (value instanceof JSONObject) {
>> +        log.info(indent + key + ":JSONObject");
>> +        dumpJsonObject((JSONObject) value, indent + "  ");
>> +      } else if (value instanceof JSONArray) {
>> +        log.info(indent + key + ":JSONArray " + ((JSONArray)
>> value).size());
>> +        dumpJsonArray((JSONArray) value, indent + "  ");
>> +      } else {
>> +        log.info(indent + key + ":" + value + ":"
>> +            + (value == null ? "na" : value.getClass()));
>> +      }
>> +    }
>> +  }
>> +
>> +
>> +  /**
>> +   * @param value
>> +   * @param string
>> +   */
>> +  static void dumpJsonArray(JSONArray array, String indent) {
>> +    for (Object value : array) {
>> +      if (value instanceof JSONObject) {
>> +        log.info(indent + ":JSONObject");
>> +        dumpJsonObject((JSONObject) value, indent + "  ");
>> +      } else if (value instanceof JSONArray) {
>> +        log.info(indent + ":JSONArray " + ((JSONArray) value).size 
>> ());
>> +        dumpJsonArray((JSONArray) value, indent + "  ");
>> +      } else {
>> +        log.info(indent + ":" + value + ":"
>> +            + (value == null ? "na" : value.getClass()));
>> +      }
>> +    }
>> +  }
>> +}
>>
>> Added:
>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>> URL:
>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>> api/src/main/java/org/apache/shindig/social/opensocial/util/ 
>> JSONObjectToMapMorpher.java?rev=678158&view=auto
>>
>> ===================================================================== 
>> =========
>> ---
>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>> (added)
>> +++
>> incubator/shindig/trunk/java/social-api/src/main/java/org/apache/ 
>> shindig/social/opensocial/util/JSONObjectToMapMorpher.java
>> Sat Jul 19 06:51:03 2008
>> @@ -0,0 +1,50 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one
>> + * or more contributor license agreements. See the NOTICE file
>> + * distributed with this work for additional information
>> + * regarding copyright ownership. The ASF licenses this file
>> + * to you under the Apache License, Version 2.0 (the
>> + * "License"); you may not use this file except in compliance
>> + * with the License. You may obtain a copy of the License at
>> + *
>> + *     http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * 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.apache.shindig.social.opensocial.util;
>> +
>> +import java.util.HashMap;
>> +import java.util.Map;
>> +
>> +import net.sf.ezmorph.Morpher;
>> +import net.sf.ezmorph.ObjectMorpher;
>> +import net.sf.json.JSONObject;
>> +
>> +/**
>> + *
>> + */
>> +public class JSONObjectToMapMorpher implements Morpher,  
>> ObjectMorpher {
>> +
>> +  public Class<?> morphsTo() {
>> +    return Map.class;
>> +  }
>> +
>> +  @SuppressWarnings("unchecked")
>> +  public boolean supports(Class clazz) {
>> +    return (JSONObject.class.equals(clazz));
>> +  }
>> +
>> +  public Object morph(Object bean) {
>> +    Map<Object, Object> result = new HashMap<Object, Object>();
>> +    JSONObject jsonObject = (JSONObject) bean;
>> +    for ( Object key : jsonObject.keySet()) {
>> +      result.put(key,jsonObject.get(key));
>> +    }
>> +    return result;
>> +  }
>> +
>> +}
>>
>> Added:
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/JsonLibTestsGuiceModule.java
>> URL:
>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>> api/src/test/java/org/apache/shindig/social/ 
>> JsonLibTestsGuiceModule.java?rev=678158&view=auto
>>
>> ===================================================================== 
>> =========
>> ---
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/JsonLibTestsGuiceModule.java
>> (added)
>> +++
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/JsonLibTestsGuiceModule.java
>> Sat Jul 19 06:51:03 2008
>> @@ -0,0 +1,40 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one
>> + * or more contributor license agreements.  See the NOTICE file
>> + * distributed with this work for additional information
>> + * regarding copyright ownership.  The ASF licenses this file
>> + * to you under the Apache License, Version 2.0 (the
>> + * "License"); you may not use this file except in compliance
>> + * with the License.  You may obtain a copy of the License at
>> + *
>> + *   http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * 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.apache.shindig.social;
>> +
>> +import java.util.ArrayList;
>> +import java.util.HashMap;
>> +import java.util.List;
>> +import java.util.Map;
>> +
>> +import com.google.inject.AbstractModule;
>> +
>> +/**
>> + * Provides social api component injection for all large tests
>> + */
>> +public class JsonLibTestsGuiceModule extends AbstractModule {
>> +  @Override
>> +  protected void configure() {
>> +
>> +    bind(Map.class).to(HashMap.class);
>> +    bind(List.class).to(ArrayList.class);
>> +    bind(Map[].class).to(HashMap[].class);
>> +  }
>> +
>> +}
>>
>> Added:
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/APIValidator.java
>> URL:
>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>> api/src/test/java/org/apache/shindig/social/opensocial/util/ 
>> APIValidator.java?rev=678158&view=auto
>>
>> ===================================================================== 
>> =========
>> ---
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/APIValidator.java
>> (added)
>> +++
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/APIValidator.java
>> Sat Jul 19 06:51:03 2008
>> @@ -0,0 +1,352 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one
>> + * or more contributor license agreements. See the NOTICE file
>> + * distributed with this work for additional information
>> + * regarding copyright ownership. The ASF licenses this file
>> + * to you under the Apache License, Version 2.0 (the
>> + * "License"); you may not use this file except in compliance
>> + * with the License. You may obtain a copy of the License at
>> + *
>> + *     http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * 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.apache.shindig.social.opensocial.util;
>> +
>> +import java.io.IOException;
>> +import java.io.InputStream;
>> +import java.io.InputStreamReader;
>> +import java.util.ArrayList;
>> +import java.util.HashMap;
>> +import java.util.List;
>> +import java.util.Map;
>> +
>> +import javax.xml.parsers.DocumentBuilder;
>> +import javax.xml.parsers.DocumentBuilderFactory;
>> +import javax.xml.parsers.ParserConfigurationException;
>> +
>> +import org.apache.commons.logging.Log;
>> +import org.apache.commons.logging.LogFactory;
>> +import org.mozilla.javascript.Context;
>> +import org.mozilla.javascript.EvaluatorException;
>> +import org.mozilla.javascript.Script;
>> +import org.mozilla.javascript.ScriptableObject;
>> +import org.w3c.dom.Document;
>> +import org.w3c.dom.NamedNodeMap;
>> +import org.w3c.dom.Node;
>> +import org.w3c.dom.NodeList;
>> +import org.xml.sax.SAXException;
>> +
>> +/**
>> + * A class that loads a feature set from features into a  
>> Javascript Parser
>> to
>> + * make the model available to validate JSON messages against.
>> + */
>> +public class APIValidator {
>> +
>> +  private static final Log log = LogFactory.getLog 
>> (APIValidator.class);
>> +  private Context ctx;
>> +  private ScriptableObject scope;
>> +
>> +  /**
>> +   * @param feature
>> +   *                The name of the feature are eg "opensocial- 
>> reference",
>> this
>> +   *                is a classpath stub (not starting with /)  
>> where the
>> location
>> +   *                contains a feature.xml file.
>> +   * @throws SAXException
>> +   *                 if feature.xml is not parsable
>> +   * @throws ParserConfigurationException
>> +   *                 if the parsers are invalid
>> +   * @throws IOException
>> +   *                 if feature.xml or the javascript that  
>> represents the
>> +   *                 feature is missing
>> +   *
>> +   */
>> +  public APIValidator(String feature) throws IOException,
>> +      ParserConfigurationException, SAXException {
>> +    ctx = Context.enter();
>> +    scope = ctx.initStandardObjects();
>> +    load(feature);
>> +  }
>> +
>> +  /**
>> +   * @param json
>> +   *                The json to validate expected in a form  
>> { xyz: yyy }
>> form
>> +   * @param object
>> +   *                The json Fields object specifying the  
>> structure of the
>> json
>> +   *                object, each field in this object contains  
>> the name of
>> the
>> +   *                json field in the json structure.
>> +   * @param optionalFields
>> +   *                If any of the fields that appear in the json  
>> structure
>> are
>> +   *                optional, then they should be defined in this
>> parameter.
>> +   * @param nullfields
>> +   * @throws APIValidatorExpcetion
>> +   *                 if there is a problem validating the json
>> +   * @return a map so string object pairs containing the fields  
>> at the top
>> level
>> +   *         of the json tree. Where these are native java  
>> objects, they
>> will
>> +   *         appear as native object. Complex json objects will  
>> appear as
>> Rhino
>> +   *         specific objects
>> +   */
>> +  public Map<String, Object> validate(String json, String object,
>> +      String[] optionalFields, String[] nullfields)
>> +      throws APIValidatorExpcetion {
>> +
>> +    /*
>> +     * Object[] ids = ScriptableObject.getPropertyIds(scope); for  
>> (Object
>> id :
>> +     * ids) { Object o = ScriptableObject.getProperty(scope,
>> +     * String.valueOf(id)); log.debug("ID is " + id + " class " +
>> id.getClass() + "
>> +     * is " + o); if (o instanceof ScriptableObject) {
>> +     * listScriptable(String.valueOf(id), (ScriptableObject) o); } }
>> +     */
>> +
>> +    log.debug("Loading " + json);
>> +    json = json.trim();
>> +    if (!json.endsWith("}")) {
>> +      json = json + "}";
>> +    }
>> +    if (!json.startsWith("{")) {
>> +      json = "{" + json;
>> +    }
>> +    json = "( testingObject = " + json + " )";
>> +
>> +    Object so = null;
>> +    try {
>> +      so = ctx.evaluateString(scope, json, "test json", 0, null);
>> +    } catch (EvaluatorException ex) {
>> +      log.error("Non parseable JSON " + json);
>> +    }
>> +    log.debug("Loaded " + so);
>> +
>> +    return validateOject(so, object, optionalFields, nullfields);
>> +
>> +  }
>> +
>> +  /**
>> +   * Validate an JSON Object extracted
>> +   *
>> +   * @param object
>> +   * @param string
>> +   * @param optional
>> +   * @return
>> +   * @throws APIValidatorExpcetion
>> +   */
>> +  public Map<String, Object> validateOject(Object jsonObject, String
>> object,
>> +      String[] optionalFields, String[] nullFields)
>> +      throws APIValidatorExpcetion {
>> +    Map<String, String> optional = new HashMap<String, String>();
>> +    for (String opt : optionalFields) {
>> +      optional.put(opt, opt);
>> +    }
>> +    Map<String, String> nullf = new HashMap<String, String>();
>> +    for (String nf : nullFields) {
>> +      nullf.put(nf, nf);
>> +    }
>> +
>> +    ScriptableObject specification = getScriptableObject(object);
>> +    log.debug("Looking for  " + object + " found " + specification);
>> +    listScriptable(object, specification);
>> +
>> +    Map<String, Object> resultFields = new HashMap<String, Object> 
>> ();
>> +
>> +    if (jsonObject instanceof ScriptableObject) {
>> +      ScriptableObject parsedJSONObject = (ScriptableObject)  
>> jsonObject;
>> +      listScriptable("testingObject", parsedJSONObject);
>> +      Object[] fields = specification.getIds();
>> +      for (Object f : fields) {
>> +        Object fieldName = specification.get(String.valueOf(f),
>> specification);
>> +        Object o = parsedJSONObject.get(String.valueOf(fieldName),
>> +            parsedJSONObject);
>> +        if (o == ScriptableObject.NOT_FOUND) {
>> +          if (optional.containsKey(fieldName)) {
>> +            log.warn("Missing Optional Field " + fieldName);
>> +          } else if (!nullf.containsKey(fieldName)) {
>> +            log.error("Missing Field " + fieldName);
>> +            throw new APIValidatorExpcetion("Missing Field " +  
>> fieldName);
>> +          }
>> +        } else {
>> +          if (nullf.containsKey(fieldName)) {
>> +            log.error("Field should have been null and was not");
>> +          }
>> +          if (o == null) {
>> +            if (nullf.containsKey(fieldName)) {
>> +              log.error("Null Fields has been serialized " +  
>> fieldName);
>> +            }
>> +            log.debug("Got a Null object for Field " + f + ":" +  
>> fieldName
>> +                + " on json [[" + jsonObject + "]]");
>> +
>> +          } else {
>> +
>> +            log.debug("Got JSON Field  Field," + f + ":" +  
>> fieldName + "
>> as "
>> +                + o + " " + o.getClass());
>> +          }
>> +          resultFields.put(String.valueOf(fieldName), o);
>> +        }
>> +      }
>> +
>> +    } else {
>> +      throw new APIValidatorExpcetion(
>> +          "Parsing JSON resulted in invalid Javascript object,  
>> which was "
>> +              + jsonObject + " JSON was [[" + jsonObject + "]]");
>> +    }
>> +    return resultFields;
>> +  }
>> +
>> +  /**
>> +   * get an object from the json context and scope.
>> +   *
>> +   * @param object
>> +   *                the name of the object specified as a path  
>> from the
>> base
>> +   *                object
>> +   * @return the json object
>> +   */
>> +  private ScriptableObject getScriptableObject(String object) {
>> +    String[] path = object.split("\\.");
>> +    log.debug("Looking up " + object + " elements " + path.length);
>> +
>> +    ScriptableObject s = scope;
>> +    for (String pe : path) {
>> +      log.debug("Looking up " + pe + " in " + s);
>> +      s = (ScriptableObject) s.get(pe, s);
>> +      log.debug("Looking for " + pe + " in found " + s);
>> +    }
>> +    return s;
>> +  }
>> +
>> +  /**
>> +   * List a scriptable object at log debug level, constructors  
>> will not be
>> +   * expanded as this loads to recursion.
>> +   *
>> +   * @param id
>> +   *                The name of the object
>> +   * @param scriptableObject
>> +   *                the scriptable Object
>> +   */
>> +  private void listScriptable(String id, ScriptableObject
>> scriptableObject) {
>> +    log.debug("ID is Scriptable " + id);
>> +    if (!id.endsWith("constructor")) {
>> +      Object[] allIDs = scriptableObject.getAllIds();
>> +      for (Object oid : allIDs) {
>> +        log.debug(id + "." + oid);
>> +        Object o = scriptableObject.get(String.valueOf(oid),
>> scriptableObject);
>> +        if (o instanceof ScriptableObject) {
>> +          listScriptable(id + "." + String.valueOf(oid),
>> (ScriptableObject) o);
>> +        }
>> +      }
>> +    }
>> +  }
>> +
>> +  /**
>> +   * Load a feature based on the spec
>> +   *
>> +   * @param spec
>> +   *                The name of the location of the spec in the  
>> classpath,
>> must
>> +   *                not start with a '/' and must should contain a
>> feature.xml
>> +   *                file in the location
>> +   * @throws IOException
>> +   *                 If any of the resources cant be found
>> +   * @throws ParserConfigurationException
>> +   *                 If the parser has a problem being constructed
>> +   * @throws SAXException
>> +   *                 on a parse error on the features.xml
>> +   */
>> +  private void load(String spec) throws IOException, SAXException,
>> +      ParserConfigurationException {
>> +
>> +    List<String> scripts = getScripts(spec);
>> +
>> +    List<Script> compiled = new ArrayList<Script>();
>> +    for (String script : scripts) {
>> +      String scriptPath = spec + "/" + script;
>> +      InputStream in =
>> this.getClass().getClassLoader().getResourceAsStream(
>> +          scriptPath);
>> +      if (in == null) {
>> +        in = this.getClass().getClassLoader().getResourceAsStream(
>> +            "features/" + scriptPath);
>> +        if (in == null) {
>> +          throw new IOException("Cant load spec " + spec + " or
>> features/"+spec+" from classpath");
>> +        }
>> +      }
>> +      InputStreamReader reader = new InputStreamReader(in);
>> +      Script compiledScript = ctx.compileReader(reader, spec, 0,  
>> null);
>> +      compiled.add(compiledScript);
>> +    }
>> +
>> +    for (Script compiledScript : compiled) {
>> +      compiledScript.exec(ctx, scope);
>> +    }
>> +
>> +  }
>> +
>> +  /**
>> +   * Add some javascript to the context, and execute it. If extra  
>> custom
>> +   * javascript is wanted in the context or scope then this  
>> method will
>> load it.
>> +   *
>> +   * @param javascript
>> +   */
>> +  public void addScript(String javascript) {
>> +    Script compileScript = ctx.compileString(javascript,  
>> "AdditionalJS",
>> 0,
>> +        null);
>> +    compileScript.exec(ctx, scope);
>> +  }
>> +
>> +  /**
>> +   * Get an ordered list of javascript resources from a feature  
>> sets.
>> +   *
>> +   * @param spec
>> +   *                The spec location
>> +   * @return An ordered list of javascript resources, these are  
>> relative
>> to
>> +   *         specification file.
>> +   * @throws IOException
>> +   *                 If any of the resources can't be loaded.
>> +   * @throws SAXException
>> +   *                 Where the feature.xml file is not parsable
>> +   * @throws ParserConfigurationException
>> +   *                 where the parser can't be constructed.
>> +   * @return An ordered list of script that need to be loaded and  
>> executed
>> to
>> +   *         make the feature available in the context.
>> +   */
>> +  private List<String> getScripts(String spec) throws SAXException,
>> +      IOException, ParserConfigurationException {
>> +    String features = spec + "/feature.xml";
>> +    InputStream in = this.getClass().getClassLoader 
>> ().getResourceAsStream(
>> +        features);
>> +    if (in == null) {
>> +      in = this.getClass().getClassLoader().getResourceAsStream(
>> +          "features/"+features);
>> +      if (in == null) {
>> +        throw new IOException("Cant find " + features + " or  
>> features/" +
>> features+ " in classpath ");
>> +      }
>> +    }
>> +    DocumentBuilderFactory builderFactory = DocumentBuilderFactory
>> +        .newInstance();
>> +    DocumentBuilder documentBuilder =  
>> builderFactory.newDocumentBuilder();
>> +    Document doc = documentBuilder.parse(in);
>> +    NodeList nl = doc.getElementsByTagName("script");
>> +    List<String> scripts = new ArrayList<String>();
>> +    for (int i = 0; i < nl.getLength(); i++) {
>> +      Node scriptNode = nl.item(i);
>> +      NamedNodeMap attributes = scriptNode.getAttributes();
>> +      Node scriptAttr = attributes.getNamedItem("src");
>> +      String script = scriptAttr.getNodeValue();
>> +      scripts.add(script);
>> +    }
>> +    return scripts;
>> +  }
>> +
>> +  /**
>> +   * @param nameJSON
>> +   */
>> +  public static void dump(Map<?, ?> nameJSON) {
>> +    if (log.isDebugEnabled()) {
>> +      for (Object k : nameJSON.keySet()) {
>> +        Object o = nameJSON.get(k);
>> +        log.info("Key [" + k + "] value:["
>> +            + (o == null ? o : o + ":" + o.getClass()) + "]");
>> +      }
>> +    }
>> +  }
>> +
>> +}
>>
>> Added:
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>> URL:
>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>> api/src/test/java/org/apache/shindig/social/opensocial/util/ 
>> APIValidatorExpcetion.java?rev=678158&view=auto
>>
>> ===================================================================== 
>> =========
>> ---
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>> (added)
>> +++
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/APIValidatorExpcetion.java
>> Sat Jul 19 06:51:03 2008
>> @@ -0,0 +1,42 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one
>> + * or more contributor license agreements. See the NOTICE file
>> + * distributed with this work for additional information
>> + * regarding copyright ownership. The ASF licenses this file
>> + * to you under the Apache License, Version 2.0 (the
>> + * "License"); you may not use this file except in compliance
>> + * with the License. You may obtain a copy of the License at
>> + *
>> + *     http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * 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.apache.shindig.social.opensocial.util;
>> +
>> +/**
>> + * Thrown when there is a validation exception on one of the apis
>> + */
>> +public class APIValidatorExpcetion extends Exception {
>> +
>> +  private static final long serialVersionUID =  
>> -8969858718669454612L;
>> +
>> +  public APIValidatorExpcetion() {
>> +  }
>> +
>> +  public APIValidatorExpcetion(String message) {
>> +    super(message);
>> +  }
>> +
>> +  public APIValidatorExpcetion(Throwable cause) {
>> +    super(cause);
>> +  }
>> +
>> +  public APIValidatorExpcetion(String message, Throwable cause) {
>> +    super(message, cause);
>> +  }
>> +
>> +}
>>
>> Added:
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/APIValidatorTest.java
>> URL:
>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>> api/src/test/java/org/apache/shindig/social/opensocial/util/ 
>> APIValidatorTest.java?rev=678158&view=auto
>>
>> ===================================================================== 
>> =========
>> ---
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/APIValidatorTest.java
>> (added)
>> +++
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/APIValidatorTest.java
>> Sat Jul 19 06:51:03 2008
>> @@ -0,0 +1,89 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one
>> + * or more contributor license agreements. See the NOTICE file
>> + * distributed with this work for additional information
>> + * regarding copyright ownership. The ASF licenses this file
>> + * to you under the Apache License, Version 2.0 (the
>> + * "License"); you may not use this file except in compliance
>> + * with the License. You may obtain a copy of the License at
>> + *
>> + *     http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * 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.apache.shindig.social.opensocial.util;
>> +
>> +
>> +import java.io.IOException;
>> +import java.util.Map;
>> +
>> +import javax.xml.parsers.ParserConfigurationException;
>> +
>> +import org.junit.Assert;
>> +import org.junit.Test;
>> +import org.xml.sax.SAXException;
>> +
>> +/**
>> + * Test the api validator to make certain it behaves as is expected.
>> + */
>> +public class APIValidatorTest {
>> +
>> +  /**
>> +   * A definition of the test json used in this unit test.
>> +   */
>> +  private static final String TEST_DEFINITION =
>> +    "var TestDef = {}; TestDef.Field = { FIELD1 : \"json\", FIELD2 :
>> \"xyz\", FIELD3 : \"shouldBeMissing\" };";
>> +
>> +  /**
>> +   * test the validator for successful validation
>> +   * @throws APIValidatorExpcetion
>> +   * @throws IOException
>> +   * @throws ParserConfigurationException
>> +   * @throws SAXException
>> +   */
>> +  @Test
>> +  public void testValidator() throws APIValidatorExpcetion,  
>> IOException,
>> ParserConfigurationException, SAXException {
>> +    APIValidator apiVal = new APIValidator("opensocial-reference");
>> +    apiVal.addScript(TEST_DEFINITION);
>> +    String[] optional = {"shouldBeMissing"};
>> +    String[] nullfields = {};
>> +     Map<String, Object> result = apiVal.validate("{ json: \"A Test
>> JSON\", xyz : 123 }", "TestDef.Field", optional, nullfields );
>> +     Assert.assertNotNull(result);
>> +     Assert.assertNotNull(result.get("json"));
>> +     Assert.assertNotNull(result.get("xyz"));
>> +     Assert.assertEquals(String.class,result.get("json").getClass 
>> ());
>> +     Assert.assertEquals(Integer.class,result.get("xyz").getClass 
>> ());
>> +     Assert.assertEquals("A Test JSON",result.get("json"));
>> +     Assert.assertEquals(123,((Integer)result.get("xyz")).intValue 
>> ());
>> +
>> +
>> +  }
>> +
>> +  /**
>> +   * Test for a failing validation
>> +   * @throws APIValidatorExpcetion
>> +   * @throws IOException
>> +   * @throws ParserConfigurationException
>> +   * @throws SAXException
>> +   */
>> +  @Test
>> +  public void testValidatorFail() throws APIValidatorExpcetion,
>> IOException, ParserConfigurationException, SAXException {
>> +    APIValidator apiVal = new APIValidator("opensocial-reference");
>> +    apiVal.addScript(TEST_DEFINITION);
>> +    String[] optional = {};
>> +    String[] nullfields = {};
>> +    try {
>> +      apiVal.validate("{ jsonIsMissing: \"A Test JSON\", xyz :  
>> 123 }",
>> "TestDef.Field", optional, nullfields );
>> +      Assert.fail("Should have Generated an APIValidatorException  
>> ");
>> +    } catch ( APIValidatorExpcetion ex ) {
>> +
>> +    }
>> +
>> +
>> +  }
>> +
>> +}
>>
>> Added:
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>> URL:
>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>> api/src/test/java/org/apache/shindig/social/opensocial/util/ 
>> BeanJsonLibConverterTest.java?rev=678158&view=auto
>>
>> ===================================================================== 
>> =========
>> ---
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>> (added)
>> +++
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/BeanJsonLibConverterTest.java
>> Sat Jul 19 06:51:03 2008
>> @@ -0,0 +1,359 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one
>> + * or more contributor license agreements. See the NOTICE file
>> + * distributed with this work for additional information
>> + * regarding copyright ownership. The ASF licenses this file
>> + * to you under the Apache License, Version 2.0 (the
>> + * "License"); you may not use this file except in compliance
>> + * with the License. You may obtain a copy of the License at
>> + *
>> + *     http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * 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.apache.shindig.social.opensocial.util;
>> +
>> +import java.util.ArrayList;
>> +import java.util.List;
>> +import java.util.Map;
>> +
>> +import junit.framework.TestCase;
>> +
>> +import org.apache.commons.logging.Log;
>> +import org.apache.commons.logging.LogFactory;
>> +import org.apache.shindig.social.JsonLibTestsGuiceModule;
>> +import org.apache.shindig.social.opensocial.model.Activity;
>> +import org.apache.shindig.social.opensocial.model.ActivityImpl;
>> +import org.apache.shindig.social.opensocial.model.Address;
>> +import org.apache.shindig.social.opensocial.model.AddressImpl;
>> +import org.apache.shindig.social.opensocial.model.Email;
>> +import org.apache.shindig.social.opensocial.model.EmailImpl;
>> +import org.apache.shindig.social.opensocial.model.MediaItem;
>> +import org.apache.shindig.social.opensocial.model.MediaItemImpl;
>> +import org.apache.shindig.social.opensocial.model.Name;
>> +import org.apache.shindig.social.opensocial.model.NameImpl;
>> +import org.apache.shindig.social.opensocial.model.Person;
>> +import org.apache.shindig.social.opensocial.model.PersonImpl;
>> +import org.apache.shindig.social.opensocial.model.Phone;
>> +import org.apache.shindig.social.opensocial.model.PhoneImpl;
>> +
>> +import com.google.common.collect.Lists;
>> +import com.google.common.collect.Maps;
>> +import com.google.inject.Guice;
>> +
>> +public class BeanJsonLibConverterTest extends TestCase {
>> +
>> +  private static final Log log = LogFactory
>> +      .getLog(BeanJsonLibConverterTest.class);
>> +  private Person johnDoe;
>> +  private Activity activity;
>> +
>> +  private BeanJsonLibConverter beanJsonConverter;
>> +  private APIValidator apiValidator;
>> +  // set to true to get loging output at info level
>> +  private boolean outputInfo = false;
>> +
>> +  @Override
>> +  public void setUp() throws Exception {
>> +    super.setUp();
>> +    johnDoe = new PersonImpl("johnDoeId", new NameImpl("John Doe"));
>> +    johnDoe.setPhoneNumbers(Lists.<Phone> newArrayList(new  
>> PhoneImpl(
>> +        "+33H000000000", "home"), new PhoneImpl("+33M000000000",
>> "mobile"),
>> +        new PhoneImpl("+33W000000000", "work")));
>> +
>> +    johnDoe.setAddresses(Lists.<Address> newArrayList(new  
>> AddressImpl(
>> +        "My home address")));
>> +
>> +    johnDoe.setEmails(Lists.<Email> newArrayList(new EmailImpl(
>> +        "john.doe@work.bar", "work"),
>> +        new EmailImpl("john.doe@home.bar", "home")));
>> +
>> +    activity = new ActivityImpl("activityId", johnDoe.getId());
>> +
>> +    activity.setMediaItems(Lists.<MediaItem> newArrayList(new
>> MediaItemImpl(
>> +        "image/jpg", MediaItem.Type.IMAGE, "http://foo.bar")));
>> +
>> +    beanJsonConverter = new BeanJsonLibConverter(Guice
>> +        .createInjector(new JsonLibTestsGuiceModule()));
>> +
>> +    apiValidator = new APIValidator("opensocial-reference");
>> +
>> +  }
>> +
>> +  public static class SpecialPerson extends PersonImpl {
>> +    public static final String[] OPTIONALFIELDS = {};
>> +    public static final String[] NULLFIELDS  =
>> {"jobInterests","nickname","romance","religion","timeZone",
>> +
>>   
>> "relationshipStatus","tags","networkPresence","books","quotes","phone 
>> Numbers","languagesSpoken",
>> +
>>   
>> "activities","jobs","dateOfBirth","profileVideo","bodyType","urls","s 
>> chools","music","addresses",
>> +
>>   
>> "livingArrangement","thumbnailUrl","humor","sports","scaredOf","movie 
>> s","age","pets","hasApp","turnOffs",
>> +
>>   
>> "gender","fashion","drinker","aboutMe","children","sexualOrientation" 
>> ,"heroes","profileSong","lookingFor",
>> +
>>   
>> "cars","turnOns","tvShows","profileUrl","status","currentLocation","s 
>> moker","happiestWhen","ethnicity",
>> +
>>   
>> "food","emails","politicalViews","interests","familyName","honorificS 
>> uffix","additionalName","honorificPrefix","givenName"};
>> +
>> +    private String newfield;
>> +
>> +    public SpecialPerson() {
>> +      super();
>> +    }
>> +
>> +    public SpecialPerson(String id, String name, String newfield) {
>> +      super(id, new NameImpl(name));
>> +      this.newfield = newfield;
>> +    }
>> +
>> +    public String getNewfield() {
>> +      return newfield;
>> +    }
>> +
>> +    public void setNewfield(String newfield) {
>> +      this.newfield = newfield;
>> +    }
>> +
>> +  }
>> +
>> +  public void testToJsonOnInheritedClass() throws Exception {
>> +    SpecialPerson cassie = new SpecialPerson("5", "robot",  
>> "nonsense");
>> +
>> +    String result = beanJsonConverter.convertToString(cassie);
>> +
>> +    validatePerson(result, "5", "robot",  
>> SpecialPerson.OPTIONALFIELDS,
>> SpecialPerson.NULLFIELDS);
>> +
>> +    apiValidator.addScript(" specialPerson = { SPECIAL :  
>> \"newfield\" };
>> ");
>> +    String[] optional = {};
>> +    String[] nullfields = {};
>> +    Map<String, Object> special = apiValidator.validate(result,
>> +        "specialPerson", optional,nullfields);
>> +    assertNotNull(special.get("newfield"));
>> +    assertEquals(String.class, special.get("newfield").getClass());
>> +    assertEquals("nonsense", special.get("newfield"));
>> +
>> +    // convert back into an object Tree
>> +
>> +    SpecialPerson parseCassie = beanJsonConverter.convertToObject 
>> (result,
>> +        SpecialPerson.class);
>> +
>> +    assertNotNull(parseCassie);
>> +    assertEquals(cassie.getId(), parseCassie.getId());
>> +    assertEquals(cassie.getNewfield(), parseCassie.getNewfield());
>> +
>> +    Name name = parseCassie.getName();
>> +    Name cassieName = cassie.getName();
>> +    assertNotNull(name);
>> +    assertEquals(cassieName.getUnstructured(),  
>> name.getUnstructured());
>> +    assertEquals(cassieName.getAdditionalName(),
>> name.getAdditionalName());
>> +    assertEquals(cassieName.getFamilyName(), name.getFamilyName());
>> +    assertEquals(cassieName.getGivenName(), name.getGivenName());
>> +    assertEquals(cassieName.getHonorificPrefix(),
>> name.getHonorificPrefix());
>> +    assertEquals(cassieName.getHonorificSuffix(),
>> name.getHonorificSuffix());
>> +
>> +  }
>> +
>> +  /**
>> +   * @param result
>> +   * @throws APIValidatorExpcetion
>> +   */
>> +  private void validatePerson(String result, String id, String name,
>> String[] optional, String[] nullfields)
>> +      throws APIValidatorExpcetion {
>> +
>> +    Map<String, Object> standard = apiValidator.validate(result,
>> +        "opensocial.Person.Field", optional,nullfields);
>> +    assertNotNull(standard.get("id"));
>> +    assertEquals(String.class, standard.get("id").getClass());
>> +    assertEquals(id, standard.get("id"));
>> +
>> +    assertNotNull(standard.get("name"));
>> +    Map<String, Object> nameJSON = apiValidator.validateOject 
>> (standard
>> +        .get("name"), "opensocial.Name.Field", optional,nullfields);
>> +    APIValidator.dump(nameJSON);
>> +
>> +    assertNotNull(nameJSON.get("unstructured"));
>> +    assertEquals(String.class, nameJSON.get 
>> ("unstructured").getClass());
>> +    assertEquals(name, nameJSON.get("unstructured"));
>> +
>> +    // additional name
>> +    assertNull(nameJSON.get("additionalName"));
>> +
>> +  }
>> +
>> +  public void testPersonToJson() throws Exception {
>> +    String result = beanJsonConverter.convertToString(johnDoe);
>> +    if (outputInfo) {
>> +      log.info("JSON (" + result + ")");
>> +    }
>> +    Person parsedPerson = beanJsonConverter.convertToObject(result,
>> +        Person.class);
>> +
>> +    assertEquals(johnDoe.getId(), parsedPerson.getId());
>> +    assertEquals(johnDoe.getName().getUnstructured(),
>> parsedPerson.getName()
>> +        .getUnstructured());
>> +
>> +    List<Address> addresses = parsedPerson.getAddresses();
>> +    if (outputInfo) {
>> +      for (Object o : addresses) {
>> +        log.info("Address " + o);
>> +      }
>> +    }
>> +
>> +    assertEquals(1, addresses.size());
>> +    Address address = addresses.get(0);
>> +    String unstructured = address.getUnstructuredAddress();
>> +
>> +    assertNotNull(unstructured);
>> +    assertEquals(johnDoe.getAddresses().get 
>> (0).getUnstructuredAddress(),
>> +        parsedPerson.getAddresses().get(0).getUnstructuredAddress 
>> ());
>> +
>> +    assertEquals(3, parsedPerson.getPhoneNumbers().size());
>> +
>> +    for (int i = 0; i < johnDoe.getPhoneNumbers().size(); i++) {
>> +      Phone expectedPhone = johnDoe.getPhoneNumbers().get(i);
>> +      Phone actualPhone = parsedPerson.getPhoneNumbers().get(i);
>> +      assertEquals(expectedPhone.getType(), actualPhone.getType());
>> +      assertEquals(expectedPhone.getNumber(),  
>> actualPhone.getNumber());
>> +    }
>> +
>> +    assertEquals(2, parsedPerson.getEmails().size());
>> +
>> +    for (int i = 0; i < johnDoe.getEmails().size(); i++) {
>> +      Email expectedEmail = johnDoe.getEmails().get(i);
>> +      Email actualEmail = parsedPerson.getEmails().get(i);
>> +      assertEquals(expectedEmail.getType(), actualEmail.getType());
>> +      assertEquals(expectedEmail.getAddress(),  
>> actualEmail.getAddress());
>> +    }
>> +  }
>> +
>> +  public void testActivityToJson() throws Exception {
>> +
>> +    String result = beanJsonConverter.convertToString(activity);
>> +    if (outputInfo) {
>> +      log.info("JSON (" + result + ")");
>> +    }
>> +    Activity parsedActivity = beanJsonConverter.convertToObject 
>> (result,
>> +        Activity.class);
>> +    assertEquals(activity.getUserId(), parsedActivity.getUserId());
>> +    assertEquals(activity.getId(), parsedActivity.getId());
>> +
>> +    assertEquals(1, parsedActivity.getMediaItems().size());
>> +
>> +    MediaItem expectedItem = activity.getMediaItems().get(0);
>> +    MediaItem actualItem = parsedActivity.getMediaItems().get(0);
>> +
>> +    assertEquals(expectedItem.getUrl(), actualItem.getUrl());
>> +    assertEquals(expectedItem.getMimeType(),  
>> actualItem.getMimeType());
>> +    assertEquals(expectedItem.getType().toString(),  
>> actualItem.getType()
>> +        .toString());
>> +  }
>> +
>> +  public void testMapsToJson() throws Exception {
>> +    Map<String, Map<String, String>> map = Maps.newHashMap();
>> +
>> +    Map<String, String> item1Map = Maps.newHashMap();
>> +    item1Map.put("value", "1");
>> +
>> +    // Null values shouldn't cause exceptions
>> +    item1Map.put("value2", null);
>> +    map.put("item1", item1Map);
>> +
>> +    Map<String, String> item2Map = Maps.newHashMap();
>> +    item2Map.put("value", "2");
>> +    map.put("item2", item2Map);
>> +
>> +    String result = beanJsonConverter.convertToString(map);
>> +    if (outputInfo) {
>> +      log.info("JSON (" + result + ")");
>> +    }
>> +    // there is introspection that can tell jsonobject -> bean  
>> converter
>> what a
>> +    // map should contain, so we have to tell it
>> +    beanJsonConverter.addMapping("item1", Map.class);
>> +    beanJsonConverter.addMapping("item2", Map.class);
>> +    Map<?, ?> parsedMap = beanJsonConverter
>> +        .convertToObject(result, Map.class);
>> +
>> +    if (outputInfo) {
>> +      log.info("Dumping Map (" + parsedMap + ")");
>> +    }
>> +    APIValidator.dump(parsedMap);
>> +
>> +    assertEquals("1", ((Map<?,?>)parsedMap.get("item1")).get 
>> ("value"));
>> +    assertEquals("2", ((Map<?,?>)parsedMap.get("item2")).get 
>> ("value"));
>> +  }
>> +
>> +  public void testListsToJson() throws Exception {
>> +    Map<String, String> item1Map = Maps.newHashMap();
>> +    item1Map.put("value", "1");
>> +
>> +    Map<String, String> item2Map = Maps.newHashMap();
>> +    item2Map.put("value", "2");
>> +
>> +    // put the list into a container before serializing, top  
>> level lists
>> dont
>> +    // appear
>> +    // to be allowed in json
>> +    // just check that the list is in the holder correctly
>> +    List<Map<String, String>> list = new ArrayList<Map<String,  
>> String>>();
>> +    list.add(item1Map);
>> +    list.add(item2Map);
>> +    String result = beanJsonConverter.convertToString(list);
>> +    if (outputInfo) {
>> +      log.info("JSON (" + result + ")");
>> +    }
>> +    Map<?, ?>[] parsedList = beanJsonConverter.convertToObject(
>> +        result, Map[].class);
>> +
>> +    assertEquals("1", parsedList[0].get("value"));
>> +    assertEquals("2", parsedList[1].get("value"));
>> +  }
>> +
>> +  public void testArrayToJson() throws Exception {
>> +    String[] colors = { "blue", "green", "aquamarine" };
>> +    String result = beanJsonConverter.convertToString(colors);
>> +    if (outputInfo) {
>> +      log.info("JSON (" + result + ")");
>> +    }
>> +    String[] parsedColors = beanJsonConverter.convertToObject 
>> (result,
>> +        String[].class);
>> +    assertEquals(colors.length, parsedColors.length);
>> +    assertEquals(colors[0], parsedColors[0]);
>> +    assertEquals(colors[1], parsedColors[1]);
>> +    assertEquals(colors[2], parsedColors[2]);
>> +  }
>> +
>> +  public void testJsonToActivity() throws Exception {
>> +    String jsonActivity = "{userId : 5, id : 6, mediaItems : ["
>> +        + "{url : 'hello', mimeType : 'mimey', type : 'VIDEO'}" +  
>> "]}";
>> +    Activity result = beanJsonConverter.convertToObject 
>> (jsonActivity,
>> +        Activity.class);
>> +
>> +    assertEquals("5", result.getUserId());
>> +    assertEquals("6", result.getId());
>> +
>> +    assertEquals(1, result.getMediaItems().size());
>> +
>> +    MediaItem actualItem = result.getMediaItems().get(0);
>> +
>> +    assertEquals("hello", actualItem.getUrl());
>> +    assertEquals("mimey", actualItem.getMimeType());
>> +    assertEquals("video", actualItem.getType().toString());
>> +  }
>> +
>> +  public void testJsonToMap() throws Exception {
>> +    String jsonActivity = "{count : 0, favoriteColor : 'yellow'}";
>> +    Map<String, String> data = Maps.newHashMap();
>> +    data = beanJsonConverter.convertToObject(jsonActivity,
>> +        (Class<Map<String, String>>) data.getClass());
>> +
>> +    assertEquals(2, data.size());
>> +
>> +    for (String key : data.keySet()) {
>> +      Object value = data.get(key);
>> +      if (key.equals("count")) {
>> +        assertEquals(0, value);
>> +      } else if (key.equals("favoriteColor")) {
>> +        assertEquals("yellow", value);
>> +      }
>> +    }
>> +  }
>> +
>> +}
>>
>> Added:
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>> URL:
>> http://svn.apache.org/viewvc/incubator/shindig/trunk/java/social- 
>> api/src/test/java/org/apache/shindig/social/opensocial/util/ 
>> JsonConverterPerformancePerf.java?rev=678158&view=auto
>>
>> ===================================================================== 
>> =========
>> ---
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>> (added)
>> +++
>> incubator/shindig/trunk/java/social-api/src/test/java/org/apache/ 
>> shindig/social/opensocial/util/JsonConverterPerformancePerf.java
>> Sat Jul 19 06:51:03 2008
>> @@ -0,0 +1,271 @@
>> +/*
>> + * Licensed to the Apache Software Foundation (ASF) under one
>> + * or more contributor license agreements. See the NOTICE file
>> + * distributed with this work for additional information
>> + * regarding copyright ownership. The ASF licenses this file
>> + * to you under the Apache License, Version 2.0 (the
>> + * "License"); you may not use this file except in compliance
>> + * with the License. You may obtain a copy of the License at
>> + *
>> + *     http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * 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.apache.shindig.social.opensocial.util;
>> +
>> +import junit.framework.TestCase;
>> +
>> +import org.apache.commons.logging.Log;
>> +import org.apache.commons.logging.LogFactory;
>> +import org.apache.shindig.social.JsonLibTestsGuiceModule;
>> +import org.apache.shindig.social.SocialApiTestsGuiceModule;
>> +import org.apache.shindig.social.opensocial.model.Activity;
>> +import org.apache.shindig.social.opensocial.model.ActivityImpl;
>> +import org.apache.shindig.social.opensocial.model.Address;
>> +import org.apache.shindig.social.opensocial.model.AddressImpl;
>> +import org.apache.shindig.social.opensocial.model.Email;
>> +import org.apache.shindig.social.opensocial.model.EmailImpl;
>> +import org.apache.shindig.social.opensocial.model.MediaItem;
>> +import org.apache.shindig.social.opensocial.model.MediaItemImpl;
>> +import org.apache.shindig.social.opensocial.model.NameImpl;
>> +import org.apache.shindig.social.opensocial.model.Person;
>> +import org.apache.shindig.social.opensocial.model.PersonImpl;
>> +import org.apache.shindig.social.opensocial.model.Phone;
>> +import org.apache.shindig.social.opensocial.model.PhoneImpl;
>> +import org.json.JSONObject;
>> +
>> +import com.google.common.collect.Lists;
>> +import com.google.inject.Guice;
>> +
>> +public class JsonConverterPerformancePerf extends TestCase {
>> +
>> +  private static final Log log = LogFactory
>> +      .getLog(JsonConverterPerformancePerf.class);
>> +  private static final int TEST_SIZE = 10000;
>> +  private Person johnDoe;
>> +  private Activity activity;
>> +
>> +  private BeanJsonLibConverter beanJsonLibConverter;
>> +  private APIValidator apiValidator;
>> +  // set to true to get loging output at info level
>> +  private boolean outputInfo = false;
>> +  private BeanJsonConverter beanJsonConverter;
>> +
>> +  @Override
>> +  public void setUp() throws Exception {
>> +    super.setUp();
>> +    johnDoe = new PersonImpl("johnDoeId", new NameImpl("John Doe"));
>> +    johnDoe.setPhoneNumbers(Lists.<Phone> newArrayList(new  
>> PhoneImpl(
>> +        "+33H000000000", "home"), new PhoneImpl("+33M000000000",
>> "mobile"),
>> +        new PhoneImpl("+33W000000000", "work")));
>> +
>> +    johnDoe.setAddresses(Lists.<Address> newArrayList(new  
>> AddressImpl(
>> +        "My home address")));
>> +
>> +    johnDoe.setEmails(Lists.<Email> newArrayList(new EmailImpl(
>> +        "john.doe@work.bar", "work"),
>> +        new EmailImpl("john.doe@home.bar", "home")));
>> +
>> +    activity = new ActivityImpl("activityId", johnDoe.getId());
>> +
>> +    activity.setMediaItems(Lists.<MediaItem> newArrayList(new
>> MediaItemImpl(
>> +        "image/jpg", MediaItem.Type.IMAGE, "http://foo.bar")));
>> +
>> +    beanJsonLibConverter = new BeanJsonLibConverter(Guice
>> +        .createInjector(new JsonLibTestsGuiceModule()));
>> +
>> +    beanJsonConverter = new BeanJsonConverter(Guice
>> +        .createInjector(new SocialApiTestsGuiceModule()));
>> +
>> +    apiValidator = new APIValidator("opensocial-reference");
>> +
>> +  }
>> +
>> +  public static class SpecialPerson extends PersonImpl {
>> +    private String newfield;
>> +
>> +    public SpecialPerson() {
>> +      super();
>> +    }
>> +
>> +    public SpecialPerson(String id, String name, String newfield) {
>> +      super(id, new NameImpl(name));
>> +      this.newfield = newfield;
>> +    }
>> +
>> +    public String getNewfield() {
>> +      return newfield;
>> +    }
>> +
>> +    public void setNewfield(String newfield) {
>> +      this.newfield = newfield;
>> +    }
>> +
>> +  }
>> +
>> +  public void testToJsonLibOnInheritedClassOutput() throws  
>> Exception {
>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>> +    for (int i = 0; i < TEST_SIZE; i++) {
>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>> "nonsense");
>> +    }
>> +    Runtime r = Runtime.getRuntime();
>> +    r.gc();
>> +    long memstart = r.totalMemory()-r.freeMemory();
>> +    long startOutput = System.currentTimeMillis();
>> +    String[] output = new String[TEST_SIZE];
>> +    for (int i = 0; i < TEST_SIZE; i++) {
>> +      output[i] = beanJsonLibConverter.convertToString(spa[i]);
>> +    }
>> +    long endOutput = System.currentTimeMillis();
>> +    long memend = r.totalMemory()-r.freeMemory();
>> +
>> +    String[] serializeOutput = new String[TEST_SIZE];
>> +    char[] source = output[0].toCharArray();
>> +    r.gc();
>> +
>> +    long stringsizeStart = r.totalMemory()-r.freeMemory();
>> +    for (int i = 0; i < TEST_SIZE; i++) {
>> +      serializeOutput[i] = new String(source);
>> +    }
>> +    long stringsizeEnd = r.totalMemory()-r.freeMemory();
>> +
>> +    /*
>> +     * Output the time per conversion and the memory usage - the  
>> output
>> per
>> +     * conversion.
>> +     *
>> +     */
>> +
>> +    log.info("SF JSON Lib Output "
>> +        + average(startOutput, endOutput, TEST_SIZE)
>> +        + " ms/conversion, "
>> +        + (average(memstart, memend, TEST_SIZE)-average 
>> (stringsizeStart,
>> stringsizeEnd, TEST_SIZE))
>> +        + " heap bytes/conversion, output packet consumed on  
>> average "
>> +        + average(stringsizeStart, stringsizeEnd, TEST_SIZE)+" for a
>> string length of "+output[0].length());
>> +    log.info("Output Was ["+output[0]+"]");
>> +  }
>> +
>> +  public void testToJsonLibOnInheritedClassInput() throws  
>> Exception {
>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>> +    SpecialPerson[] sparesult = new SpecialPerson[TEST_SIZE];
>> +    Runtime r = Runtime.getRuntime();
>> +    r.gc();
>> +    long personStart = r.totalMemory()-r.freeMemory();
>> +    for (int i = 0; i < TEST_SIZE; i++) {
>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>> "nonsense");
>> +    }
>> +    long personEnd = r.totalMemory()-r.freeMemory();
>> +
>> +    String[] serializeOutput = new String[TEST_SIZE];
>> +    r.gc();
>> +    for (int i = 0; i < TEST_SIZE; i++) {
>> +
>> +      serializeOutput[i] = beanJsonLibConverter.convertToString 
>> (spa[i]);
>> +    }
>> +
>> +    r.gc();
>> +    long memstart = r.totalMemory()-r.freeMemory();
>> +    long startInput = System.currentTimeMillis();
>> +    for (int i = 0; i < TEST_SIZE; i++) {
>> +        sparesult[i] = beanJsonLibConverter.convertToObject(
>> +          serializeOutput[i], SpecialPerson.class);
>> +    }
>> +    long endInput = System.currentTimeMillis();
>> +    long memend = r.totalMemory()-r.freeMemory();
>> +
>> +    log.info("SF JSON Lib Input "
>> +        + average(startInput, endInput, TEST_SIZE)
>> +        + " ms/conversion, "
>> +        + (average(memstart, memend, TEST_SIZE)-average(personStart,
>> personEnd, TEST_SIZE))
>> +        + " heap bytes/conversion, person object consumed on  
>> average "
>> +        + average(personStart, personEnd, TEST_SIZE));
>> +  }
>> +
>> +  public void testToJsonOnInheritedClassOutput() throws Exception {
>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>> +    for (int i = 0; i < TEST_SIZE; i++) {
>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>> "nonsense");
>> +    }
>> +    Runtime r = Runtime.getRuntime();
>> +    String[] output = new String[TEST_SIZE];
>> +    r.gc();
>> +    long memstart = r.totalMemory()-r.freeMemory();
>> +    long startOutput = System.currentTimeMillis();
>> +    for (int i = 0; i < TEST_SIZE; i++) {
>> +      output[i]  = ((JSONObject)
>> beanJsonConverter.convertToJson(spa[i])).toString();
>> +    }
>> +    long endOutput = System.currentTimeMillis();
>> +    long memend = r.totalMemory()-r.freeMemory();
>> +    String[] serializeOutput = new String[TEST_SIZE];
>> +    char[] source = output[0].toCharArray();
>> +    r.gc();
>> +
>> +    long stringsizeStart = r.totalMemory()-r.freeMemory();
>> +
>> +    for (int i = 0; i < TEST_SIZE; i++) {
>> +      serializeOutput[i] = new String(source);
>> +    }
>> +    long stringsizeEnd = r.totalMemory()-r.freeMemory();
>> +
>> +    log.info("ORG JSON Lib Output "
>> +        + average(startOutput, endOutput, TEST_SIZE)
>> +        + " ms/conversion, "
>> +        + (average(memstart, memend, TEST_SIZE)-average 
>> (stringsizeStart,
>> stringsizeEnd, TEST_SIZE))
>> +        + " heap bytes/conversion, output packet consumed on  
>> average "
>> +        + average(stringsizeStart, stringsizeEnd, TEST_SIZE)+" for a
>> string length of "+output[0].length());
>> +    log.info("Output Was ["+output[0]+"]");
>> +  }
>> +
>> +  /**
>> +   * @param endOutput
>> +   * @param startOutput
>> +   * @param testSize
>> +   * @return
>> +   */
>> +  private float average(long start, long end, int testSize) {
>> +    float r = end - start;
>> +    r = r / testSize;
>> +    return r;
>> +  }
>> +
>> +  public void XtestToJsonOnInheritedClassInput() throws Exception {
>> +    SpecialPerson[] spa = new SpecialPerson[TEST_SIZE];
>> +    SpecialPerson[] sparesult = new SpecialPerson[TEST_SIZE];
>> +    Runtime r = Runtime.getRuntime();
>> +    r.gc();
>> +    long personStart = r.totalMemory()-r.freeMemory();
>> +    for (int i = 0; i < TEST_SIZE; i++) {
>> +      spa[i] = new SpecialPerson(String.valueOf(i), "robot",  
>> "nonsense");
>> +    }
>> +    long personEnd = r.totalMemory()-r.freeMemory();
>> +
>> +    String[] serializeOutput = new String[TEST_SIZE];
>> +    r.gc();
>> +    for (int i = 0; i < TEST_SIZE; i++) {
>> +
>> +      serializeOutput[i] = beanJsonConverter.convertToString(spa 
>> [i]);
>> +    }
>> +
>> +    r.gc();
>> +    long memstart = r.totalMemory()-r.freeMemory();
>> +    long startInput = System.currentTimeMillis();
>> +
>> +    for (int i = 0; i < TEST_SIZE; i++) {
>> +      sparesult[i] = beanJsonConverter.convertToObject(
>> +          serializeOutput[i], SpecialPerson.class);
>> +    }
>> +    long endInput = System.currentTimeMillis();
>> +    long memend = r.totalMemory()-r.freeMemory();
>> +
>> +    log.info("SF JSON Lib Input "
>> +        + average(startInput, endInput, TEST_SIZE)
>> +        + " ms/conversion, "
>> +        + (average(memstart, memend, TEST_SIZE)-average(personStart,
>> personEnd, TEST_SIZE))
>> +        + " heap bytes/conversion, person object consumed on  
>> average "
>> +        + average(personStart, personEnd, TEST_SIZE));
>> +  }
>> +
>> +}
>>
>> Modified: incubator/shindig/trunk/pom.xml
>> URL:
>> http://svn.apache.org/viewvc/incubator/shindig/trunk/pom.xml? 
>> rev=678158&r1=678157&r2=678158&view=diff
>>
>> ===================================================================== 
>> =========
>> --- incubator/shindig/trunk/pom.xml (original)
>> +++ incubator/shindig/trunk/pom.xml Sat Jul 19 06:51:03 2008
>> @@ -853,6 +853,16 @@
>>         <artifactId>htmlunit</artifactId>
>>         <version>2.1</version>
>>       </dependency>
>> +      <dependency>
>> +        <groupId>log4j</groupId>
>> +        <artifactId>log4j</artifactId>
>> +        <version>1.2.13</version>
>> +      </dependency>
>> +      <dependency>
>> +        <groupId>rhino</groupId>
>> +        <artifactId>js</artifactId>
>> +        <version>1.6R7</version>
>> +      </dependency>
>>     </dependencies>
>>   </dependencyManagement>
>>  </project>
>>
>>
>>