]> source.dussan.org Git - gwtquery.git/commitdiff
Merge branch 'mcm_styling' into mcm_special_events
authorManolo Carrasco <manolo@apache.org>
Fri, 2 Jan 2015 13:26:04 +0000 (14:26 +0100)
committerManolo Carrasco <manolo@apache.org>
Fri, 2 Jan 2015 13:47:02 +0000 (14:47 +0100)
Conflicts:
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Events.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/LazyEvents.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/EventsListener.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java

12 files changed:
1  2 
gwtquery-core/src/main/java/com/google/gwt/query/client/GQuery.java
gwtquery-core/src/main/java/com/google/gwt/query/client/Properties.java
gwtquery-core/src/main/java/com/google/gwt/query/client/builders/JsonBuilderBase.java
gwtquery-core/src/main/java/com/google/gwt/query/client/impl/DocumentStyleImpl.java
gwtquery-core/src/main/java/com/google/gwt/query/client/js/JsCache.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/Events.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/Transitions.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/effects/TransitionsAnimation.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/EventsListener.java
gwtquery-core/src/main/java/com/google/gwt/query/client/plugins/events/GqEvent.java
gwtquery-core/src/main/java/com/google/gwt/query/vm/JsonBuilderHandler.java
gwtquery-core/src/main/java/com/google/gwt/query/vm/JsonFactoryJre.java

index 0997404e5fd90ee35aae13782253aa81ccdb54af,c9414232494109a9cb24fce53803daa1625b57a9..c75dd23804750312da868c973ebe7f93b581eeef
@@@ -218,6 -218,11 +218,11 @@@ public class Properties extends JavaScr
      }
      return getDataImpl();
    }
 -    return (J)this;
+   
+   @SuppressWarnings("unchecked")
+   public final <J extends IsProperties> J strip() {
++    return (J) this;
+   }
  
    public final <J extends IsProperties> J parse(String json) {
      return load(JsUtils.parseJSON(json));
index 4c25117ac56ac04e33bdef9e3e17a67468af387a,a33f676b8f1b560db52a186eddf1604662ee8e5f..f0c469310a472a0e399f42abff887815f21f731b
@@@ -19,9 -19,19 +19,18 @@@ import com.google.gwt.core.client.JavaS
  import com.google.gwt.core.client.JsArray;
  import com.google.gwt.query.client.IsProperties;
  import com.google.gwt.query.client.Properties;
+ import com.google.gwt.query.client.js.JsCache;
  import com.google.gwt.query.client.js.JsObjectArray;
  import com.google.gwt.query.client.js.JsUtils;
 -import com.google.gwt.user.client.Window;
  
+ import java.util.Arrays;
+ import java.util.List;
+ /**
+  * Common class for all JsonBuilder implementations.
+  *
+  * @param <J>
+  */
  public abstract class JsonBuilderBase<J extends JsonBuilderBase<?>> implements JsonBuilder {
  
    protected Properties p = Properties.create();
      return fix ? parse(Properties.wrapPropertiesString(json)) : parse(json);
    }
  
 -    return (J)this;
+   @SuppressWarnings("unchecked")
+   @Override
+   public J strip() {
+     List<String> names = Arrays.asList(getFieldNames());
+     for (String jsonName : p.getFieldNames()) {
+       // TODO: figure out a way so as we can generate some marks in generated class in
+       // order to call getters to return JsonBuilder object given an an attribute name
+       if (!names.contains(jsonName)) {
+         p.<JsCache>cast().delete(jsonName);
+       }
+     }
++    return (J) this;
+   }
    @SuppressWarnings("unchecked")
    @Override
    public J load(Object prp) {
index 4bd133ec4c242d3d2c51e0e83862539512917552,d7b83337d104894af961da965644b5f002ac2c3f..0a466a07f43f656efed674dfaa64c3f6dd0b46fb
@@@ -208,7 -212,7 +212,7 @@@ public class DocumentStyleImpl 
    }
  
    /**
--   * Return whether the element is visible
++   * Return whether the element is visible.
     */
    public boolean isVisible(Element e) {
      return SelectorEngine.filters.get("visible").f(e, 0);
index dff21481bcf0755930fb800cf0a61cefd45f0338,c3b0c5ce4fcb1f682bf7d01fe42ce6bedce77622..13f6c4a3f56b3ae225466865a68d5829db6c1545
@@@ -231,7 -236,7 +236,7 @@@ public class JsCache extends JavaScript
      checkNull(this);
    }
  
--  private final native JsArrayString keysImpl() /*-{
++  private native JsArrayString keysImpl() /*-{
      var key, keys=[];
      // Chrome in DevMode sets '__gwt_ObjectId' to JS objects
      // GWT sets '$H' when calling getHashCode (see com/google/gwt/core/client/impl/Impl.java)
index a35ebb70fcfee3467486d107235dd483e5bb7edc,84ce65dd04d14a8e904be9c0cc2886c5c997f72d..3983791ac008cf5b1bf629f4ecf968a254dcc5df
@@@ -134,9 -135,8 +134,8 @@@ public class Events extends GQuery 
  
    public GQuery live(int eventbits, String nameSpace, final Object data, Function... funcs) {
      EventsListener.getInstance(Element.is(currentContext) ? (Element) currentContext : body).live(
 -        eventbits, nameSpace, null, null, currentSelector, data, funcs);
 +        eventbits, nameSpace, null, currentSelector, data, funcs);
      return this;
    }
  
    public GQuery live(String eventName, final Object data, Function... funcs) {
     * Trigger a html event in all matched elements.
     *
     * @param htmlEvent An string representing the desired html event.
 -   * @functions a set of function to run if the event is not canceled.
 +   * @param datas a set of object passed as data when executed the handlers
 +   * @param functions a set of function to run.
     */
    public Events triggerHtmlEvent(String htmlEvent, Object[] datas, final Function... functions) {
 -    SpecialEvent specialEvent = EventsListener.special.get(htmlEvent);
 -    boolean isSpecialEvent = specialEvent != null;
 -
 -    String originalEventName = htmlEvent;
 -    String delegateEventName = isSpecialEvent ? specialEvent.getDelegateType() : htmlEvent;
 -
 -    NativeEvent e = document.createHtmlEvent(delegateEventName, true, true);
 -
 -    if (isSpecialEvent) {
 -      GqEvent.setOriginalEventType(e, originalEventName);
 -    }
 -
 -    if ("submit".equals(htmlEvent)) {
 -      Function submitFunction = new Function() {
 -        public void f(Element e) {
 -          // first submit the form then call the others functions
 -          if (FormElement.is(e)) {
 -            e.<FormElement> cast().submit();
 +    for (EventName part : EventName.split(htmlEvent)) {
 +      NativeEvent e = document.createHtmlEvent(part.eventName, true, true);
 +      JsUtils.prop(e, "namespace", part.nameSpace);
-       if ("submit".equals(part.eventName)){
++      if ("submit".equals(part.eventName)) {
 +        Function submitFunction = new Function() {
 +          public void f(Element e) {
 +            // first submit the form then call the others functions
 +            if (FormElement.is(e)) {
 +              e.<FormElement>cast().submit();
 +            }
 +            callHandlers(e, getEvent(), functions);
            }
 -          callHandlers(e, getEvent(), functions);
 -        }
 -      };
 -      dispatchEvent(e, datas, submitFunction);
 -    } else {
 -      dispatchEvent(e, datas, functions);
 +        };
 +        dispatchEvent(e, datas, submitFunction);
 +      } else {
 +        dispatchEvent(e, datas, functions);
 +      }
      }
 +
      return this;
    }
  
index 693990d5909399a04140e63cce3d7229a8017d3a,fed2ffdf1681458b59d2c78c5512a7b358063ee5..cefedcebb10982b05c2625c615fed5cea95ba83d
@@@ -268,7 -268,7 +268,7 @@@ public class Transitions extends GQuer
          t.setFromString(prop, value);
          getStyleImpl().setStyleProperty(e, transform, t.toString());
        }
--    } else if (!invalidTransitionNamesRegex.test(prop)){
++    } else if (!invalidTransitionNamesRegex.test(prop)) {
        super.css(prop, value);
      }
      return this;
  
    private Transform getTransform(Element e, String initial) {
      Transform t = data(e, TRANSFORM);
--    if (t == null || initial != null && !initial.isEmpty() ) {
++    if (t == null || initial != null && !initial.isEmpty()) {
        t = new Transform(initial);
        data(e, TRANSFORM, t);
      }
      final double queuedAt = delay > 0 ? Duration.currentTimeMillis() : 0;
  
      // Use gQuery queue, so as we can chain transitions, animations etc.
--    queue(new Function(){
++    queue(new Function() {
        public void f() {
          // This is called once per element
          final String oldTransitionValue = $(this).css(transition);
          // Recompute delay based on the time spent in the queue
--        int d = Math.max(0, delay - (int)(Duration.currentTimeMillis() - queuedAt));
++        int d = Math.max(0, delay - (int) (Duration.currentTimeMillis() - queuedAt));
          // Generate transition value
          String attribs = duration + "ms" + " "  + ease + " " + d + "ms";
          String newTransitionValue  = "";
index a671d92e85f53e1a020ea7f6f82176878f0393bb,6155540a87310a3293bc1b8db368d6b120596023..4636b12eed6d551a3d84d5eecb151c2e35a90122
@@@ -82,8 -85,8 +85,8 @@@ public class TransitionsAnimation exten
        int bit = currentAction == Action.HIDE ? 1 : 0;
  
        String originX = "left", originY = "top";
--      int scaleXini = 0^bit, scaleYini = scaleXini;
--      int scaleXend = 1^bit, scaleYend = scaleXend;
++      int scaleXini = 0 ^ bit, scaleYini = scaleXini;
++      int scaleXend = 1 ^ bit, scaleYend = scaleXend;
  
        if (direction == Direction.VERTICAL) {
          scaleXini = scaleXend = 1;
            trsStart = "" + st;
  
            double en = Double.parseDouble(trsEnd);
--          trsEnd = "" + (st + n*en);
++          trsEnd = "" + (st + n * en);
          }
  
          // Deal with non px units like "%"
    private Properties getFxProperties(boolean isStart) {
      Properties p = $$();
      for (int i = 0; i < effects.length(); i++) {
--      TransitFx fx = (TransitFx)effects.get(i);
++      TransitFx fx = (TransitFx) effects.get(i);
        String val = isStart ? fx.transitStart : fx.transitEnd;
        if (!val.isEmpty()) {
          p.set(fx.cssprop, val + fx.unit);
  
      // Compute final properties
      p = getFxProperties(false);
--    g.transition(p, duration, easing, delay, new Function(){public void f() {
--      onComplete();
--    }});
++    g.transition(p, duration, easing, delay, new Function() {
++      public void f() {
++        onComplete();
++      }
++    });
    }
  }
index a19142b8eccb2b8573e4038f00ac6ea182f286be,bfb24d2cd352eeb708e1a96e8003c6484c22b242..7d88ac7c3ea612d603b52771b7162f376c10483d
@@@ -48,50 -45,69 +48,50 @@@ import java.util.Map
   */
  public class EventsListener implements EventListener {
  
 -  public interface SpecialEvent {
 -    String getDelegateType();
 -
 -    String getOriginalType();
 -
 -    Function createDelegateHandler(Function originalHandler);
 -  }
 -
    /**
--   * Used for simulating mouseenter and mouseleave events
++   * Used for simulating mouseenter and mouseleave events.
     */
 -  public static class MouseSpecialEvent implements SpecialEvent {
 -
 -    private String originalType;
 -    private String delegateType;
 -
 -    public MouseSpecialEvent(String originalType, String delegateType) {
 -      this.originalType = originalType;
 -      this.delegateType = delegateType;
 -    }
 -
 -    public String getDelegateType() {
 -      return delegateType;
 -    }
 -
 -    public String getOriginalType() {
 -      return originalType;
 -    }
 -
 -    public Function createDelegateHandler(Function originalHandler) {
 -      return new SpecialMouseEventHandler(originalHandler);
 +  private static class MouseSpecialEvent extends DefaultSpecialEvent {
 +    public MouseSpecialEvent(final String type, String delegateType) {
 +      super(type, delegateType);
 +      handler =  new Function() {
 +        public boolean f(Event e, Object... arg) {
 +          EventTarget eventTarget = e.getCurrentEventTarget();
 +          Element target = eventTarget != null ? eventTarget.<Element> cast() : null;
 +
 +          EventTarget relatedEventTarget = e.getRelatedEventTarget();
 +          Element related = relatedEventTarget != null ? relatedEventTarget.<Element> cast() : null;
 +
 +          if (related == null || (related != target && !GQuery.contains(target, related))) {
 +            getInstance(target).dispatchEvent(e, type);
 +          }
 +          return true;
 +        };
 +      };
      }
    }
  
 -  private interface HandlerWrapper {
 -    Function getOriginalHandler();
 -  }
 -  private static class SpecialMouseEventHandler extends Function implements HandlerWrapper {
 -
 -    private Function delegateHandler;
 -
 -    public SpecialMouseEventHandler(Function originalHandler) {
 -      this.delegateHandler = originalHandler;
 -    }
 -
 -    @Override
 -    public boolean f(Event e, Object... data) {
 -      EventTarget eventTarget = e.getCurrentEventTarget();
 -      Element target = eventTarget != null ? eventTarget.<Element> cast() : null;
 -
 -      EventTarget relatedEventTarget = e.getRelatedEventTarget();
 -      Element related = relatedEventTarget != null ? relatedEventTarget.<Element> cast() : null;
 -
 -      // For mousenter/leave call the handler if related is outside the target.
 -      if (related == null || (related != target && !GQuery.contains(target, related))) {
 -        return delegateHandler != null ? delegateHandler.f(e, data) : false;
 +  /**
-    * Utility class to split a list of events with or without namespaces
++   * Utility class to split a list of events with or without namespaces.
 +   */
 +  public static class EventName {
 +    public final String nameSpace;
 +    public final String eventName;
 +    public EventName(String n, String e) {
 +      nameSpace = n;
 +      eventName = e;
 +    }
 +
 +    public static List<EventName> split(String events) {
 +      List<EventName> ret = new ArrayList<EventName>();
 +      String[] parts = events.split("[\\s,]+");
 +      for (String event : parts) {
 +        String[] tmp = event.split("\\.", 2);
 +        String eventName = tmp[0];
 +        String nameSpace = tmp.length > 1 ? tmp[1] : null;
 +        ret.add(new EventName(nameSpace, eventName));
        }
 -
 -      return false;
 -    }
 -
 -    public Function getOriginalHandler() {
 -      return delegateHandler;
 +      return ret;
      }
    }
  
      }
  
      /**
--     * Add a {@link BindFunction} for a specific css selector
++     * Add a {@link BindFunction} for a specific css selector.
       */
      public void addBindFunctionForSelector(String cssSelector, BindFunction f) {
        JsObjectArray<BindFunction> bindFunctions = bindFunctionBySelector.get(cssSelector);
      }
  
      /**
--     * Remove the BindFunction associated to this cssSelector
++     * Remove the BindFunction associated to this cssSelector.
       */
 -    public void removeBindFunctionForSelector(String cssSelector, String nameSpace, String originalEventName) {
 -      if (nameSpace == null && originalEventName == null) {
 +    public void removeBindFunctionForSelector(String cssSelector, String nameSpace) {
 +      if (nameSpace == null) {
          bindFunctionBySelector.delete(cssSelector);
        } else {
          JsObjectArray<BindFunction> functions = bindFunctionBySelector.get(cssSelector);
      }
  
      /**
--     * Tell if no {@link BindFunction} are linked to this object
++     * Tell if no {@link BindFunction} are linked to this object.
       *
       * @return
       */
  
      /**
       * Return the element whose the listener fired last. It represent the context element where the
--     * {@link LiveBindFunction} was binded
++     * {@link LiveBindFunction} was binded.
       *
       */
      private Element getCurrentEventTarget(Event e) {
      }
  
      /**
--     * Return the element that was the actual target of the element
++     * Return the element that was the actual target of the element.
       */
      private Element getEventTarget(Event e) {
        EventTarget eventTarget = e.getEventTarget();
    }
  
    private void maybeRemoveLiveBindFunction(LiveBindFunction liveBindFunction, String cssSelector,
 -      int eventbits, String eventName, String nameSpace, String originalEventName) {
 +      int eventbits, String eventName, String nameSpace) {
      if (liveBindFunction != null) {
 -      liveBindFunction.removeBindFunctionForSelector(cssSelector, nameSpace, originalEventName);
 -      if (liveBindFunction.isEmpty()){
 +      liveBindFunction.removeBindFunctionForSelector(cssSelector, nameSpace);
-       if (liveBindFunction.isEmpty()){
++      if (liveBindFunction.isEmpty()) {
          if (eventbits != BITLESS) {
            liveBindFunctionByEventType.remove(eventbits);
          } else {
index 19f251b4442a5dd7034e1dde337afddf52a04a7d,a93e549124d2fc86313f3d2595368bc25ff2376e..8493fd81e717d2f7d2301e82a9b75a3dc49a3524
@@@ -88,9 -97,9 +88,9 @@@ public class GqEvent extends Event 
     *
     */
    public final int pageX() {
--    if (getTouches() != null && getTouches().length() > 0){
++    if (getTouches() != null && getTouches().length() > 0) {
        return getTouches().get(0).getPageX();
--    }else{
++    } else {
        return getClientX() + GQuery.document.getScrollLeft();
      }
    }
     *
     */
    public final int pageY() {
--    if (getTouches() != null &&  getTouches().length() > 0){
++    if (getTouches() != null &&  getTouches().length() > 0) {
        return getTouches().get(0).getPageY();
--    }else{
++    } else {
        return getClientY() + GQuery.document.getScrollTop();
      }
    }
index 0000000000000000000000000000000000000000,8d9b9a4c6f7c8ad249494e73821468950581884b..adbdd23336aede7b475484d585e65dce121fefcb
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,328 +1,346 @@@
++/*
++ * Copyright 2014, The gwtquery team.
++ *
++ * Licensed 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 com.google.gwt.query.vm;
+ import com.google.gwt.query.client.Function;
+ import com.google.gwt.query.client.IsProperties;
+ import com.google.gwt.query.client.Properties;
+ import com.google.gwt.query.client.builders.JsonBuilder;
+ import com.google.gwt.query.client.builders.Name;
+ import com.google.gwt.query.rebind.JsonBuilderGenerator;
+ import com.google.gwt.query.vm.JsonFactoryJre.JreJsonFunction;
+ import java.lang.reflect.Array;
+ import java.lang.reflect.InvocationHandler;
+ import java.lang.reflect.Method;
+ import java.lang.reflect.ParameterizedType;
+ import java.lang.reflect.Type;
+ import java.util.ArrayList;
+ import java.util.Date;
+ import java.util.HashSet;
+ import java.util.Hashtable;
+ import java.util.List;
+ import elemental.json.Json;
+ import elemental.json.JsonArray;
+ import elemental.json.JsonBoolean;
+ import elemental.json.JsonNull;
+ import elemental.json.JsonNumber;
+ import elemental.json.JsonObject;
+ import elemental.json.JsonString;
+ import elemental.json.JsonValue;
++/**
++ * Reflection handler for JsonBuilder implementation in JVM. 
++ */
+ public class JsonBuilderHandler implements InvocationHandler {
+   static JsonFactoryJre jsonFactory = new JsonFactoryJre();
+   private JsonObject jsonObject;
+   public JsonBuilderHandler() {
+     jsonObject = Json.createObject();
+   }
+   public JsonBuilderHandler(JsonObject j) {
+     jsonObject = j;
+   }
+   public JsonBuilderHandler(String payload) throws Throwable {
+     jsonObject = Json.parse(payload);
+   }
+   @SuppressWarnings("unchecked")
+   private <T> Object jsonArrayToList(JsonArray j, Class<T> ctype, boolean isArray) {
+     List<T> l = new ArrayList<T>();
+     for (int i = 0; j != null && i < j.length(); i++) {
+       l.add((T) getValue(j, i, null, null, ctype, null));
+     }
+     return l.isEmpty() ? null : isArray ? l.toArray((T[]) Array.newInstance(ctype, l.size())) : l;
+   }
+   private Double toDouble(String attr, JsonArray arr, int idx, JsonObject obj) {
+     try {
+       return obj != null ? obj.getNumber(attr) : arr.getNumber(idx);
+     } catch (Exception e) {
+       return Double.valueOf(0d);
+     }
+   }
+   private Object getValue(JsonArray arr, int idx, JsonObject obj, String attr, Class<?> clz,
+       Method method) {
+     if (clz.equals(Boolean.class) || clz == Boolean.TYPE) {
+       try {
+         return obj != null ? obj.getBoolean(attr) : arr.getBoolean(idx);
+       } catch (Exception e) {
+         return Boolean.FALSE;
+       }
+     } else if (clz.equals(Date.class)) {
+       return new Date((long) (obj != null ? obj.getNumber(attr) : arr.getNumber(idx)));
+     } else if (clz.equals(Byte.class) || clz == Byte.TYPE) {
+       return toDouble(attr, arr, idx, obj).byteValue();
+     } else if (clz.equals(Short.class) || clz == Short.TYPE) {
+       return toDouble(attr, arr, idx, obj).shortValue();
+     } else if (clz.equals(Integer.class) || clz == Integer.TYPE) {
+       return toDouble(attr, arr, idx, obj).intValue();
+     } else if (clz.equals(Double.class) || clz == Double.TYPE) {
+       return toDouble(attr, arr, idx, obj);
+     } else if (clz.equals(Float.class) || clz == Float.TYPE) {
+       return toDouble(attr, arr, idx, obj).floatValue();
+     } else if (clz.equals(Long.class) || clz == Long.TYPE) {
+       return toDouble(attr, arr, idx, obj).longValue();
+     }
+     Object ret = obj != null ? obj.get(attr) : arr.get(idx);
+     if (ret instanceof JreJsonFunction || clz.equals(Function.class)) {
+       return ret != null && ret instanceof JreJsonFunction ? ((JreJsonFunction) ret).getFunction()
+           : null;
+     } else if (ret instanceof JsonNull) {
+       return null;
+     } else if (ret instanceof JsonString) {
+       return ((JsonString) ret).asString();
+     } else if (ret instanceof JsonBoolean) {
+       return ((JsonBoolean) ret).asBoolean();
+     } else if (ret instanceof JsonNumber) {
+       return toDouble(attr, arr, idx, obj);
+     } else if (ret instanceof JsonArray || clz.isArray() || clz.equals(List.class)) {
+       Class<?> ctype = Object.class;
+       if (clz.isArray()) {
+         ctype = clz.getComponentType();
+       } else {
+         Type returnType = method.getGenericReturnType();
+         if (returnType instanceof ParameterizedType) {
+           ctype = (Class<?>) ((ParameterizedType) returnType).getActualTypeArguments()[0];
+         }
+       }
+       return jsonArrayToList(obj.getArray(attr), ctype, clz.isArray());
+     } else if (ret instanceof JsonObject) {
+       if (clz == Object.class) {
+         return jsonFactory.createBinder((JsonObject) ret);
+       } else if (IsProperties.class.isAssignableFrom(clz) && !clz.isAssignableFrom(ret.getClass())) {
+         return jsonFactory.create(clz, (JsonObject) ret);
+       }
+     }
+     return ret;
+   }
+   private <T> JsonArray listToJsonArray(Object... l) throws Throwable {
+     JsonArray ret = Json.createArray();
+     for (Object o : l) {
+       setValue(ret, null, null, o);
+     }
+     return ret;
+   }
+   private Object setValue(JsonArray jsArr, JsonObject jsObj, String attr, Object val) {
+     if (val == null) {
+       return Json.createNull();
+     }
+     try {
+       Class<?> valClaz = JsonValue.class;
+       if (val instanceof Number) {
+         val = ((Number) val).doubleValue();
+         valClaz = Double.TYPE;
+       } else if (val instanceof Boolean) {
+         valClaz = Boolean.TYPE;
+       } else if (val instanceof Date) {
+         val = ((Date) val).getTime();
+         valClaz = Double.TYPE;
+       } else if (val instanceof String) {
+         valClaz = String.class;
+       } else if (val instanceof IsProperties) {
+         val = ((IsProperties) val).getDataImpl();
+       } else if (val.getClass().isArray() || val instanceof List) {
+         val =
+             listToJsonArray(val.getClass().isArray() ? (Object[]) val : ((List<?>) val).toArray());
+       } else if (val instanceof Function) {
+         val = new JreJsonFunction((Function) val);
+       }
+       if (jsObj != null) {
+         Method mth = jsObj.getClass().getMethod("put", String.class, valClaz);
+         mth.invoke(jsObj, new Object[] {attr, val});
+         return jsObj;
+       } else {
+         Method mth = jsArr.getClass().getMethod("set", Integer.TYPE, valClaz);
+         mth.invoke(jsArr, new Object[] {new Integer(jsArr.length()), val});
+         return jsArr;
+       }
+     } catch (Throwable e) {
+       e.printStackTrace();
+     }
+     return null;
+   }
+   @Override
+   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+     String mname = method.getName();
+     Class<?>[] classes = method.getParameterTypes();
+     int largs = classes.length;
+     Name name = method.getAnnotation(Name.class);
+     String attr = name != null ? name.value() : methodName2AttrName(mname);
+     if ("getFieldNames".equals(mname)) {
+       return jsonObject.keys();
+     } else if ("as".equals(mname)) {
+       @SuppressWarnings("unchecked")
+       Class<? extends JsonBuilder> clz = (Class<? extends JsonBuilder>) args[0];
+       return jsonFactory.create(clz, jsonObject);
+     } else if ("getJsonName".equals(mname)) {
+       return JsonBuilderGenerator.classNameToJsonName(getDataBindingClassName(proxy.getClass()));
+     } else if (mname.matches("getProperties|getDataImpl")) {
+       return jsonObject;
+     } else if (largs > 0 && ("parse".equals(mname) || "load".equals(mname))) {
+       String json = String.valueOf(args[0]);
+       if (largs > 1 && Boolean.TRUE.equals(args[1])) {
+         json = Properties.wrapPropertiesString(json);
+       }
+       jsonObject = Json.parse(json);
+     } else if ("strip".equals(mname)) {
+       stripProxy((JsonBuilder) proxy);
+     } else if (mname.matches("toString")) {
+       return jsonObject.toString();
+     } else if (mname.matches("toJsonWithName")) {
+       String jsonName =
+           JsonBuilderGenerator.classNameToJsonName(getDataBindingClassName(proxy.getClass()));
+       return "{\"" + jsonName + "\":" + jsonObject.toString() + "}";
+     } else if (mname.matches("toJson")) {
+       return jsonObject.toString();
+     } else if ("toQueryString".equals(mname)) {
+       return param(jsonObject);
+     } else if (largs == 1 && mname.equals("get")) {
+       Class<?> ret = method.getReturnType();
+       attr = String.valueOf(args[0]);
+       return getValue(null, 0, jsonObject, attr, ret, method);
+     } else if (largs == 0 || mname.startsWith("get")) {
+       Class<?> ret = method.getReturnType();
+       return getValue(null, 0, jsonObject, attr, ret, method);
+     } else if (largs == 2 && mname.equals("set")) {
+       setValue(null, jsonObject, String.valueOf(args[0]), args[1]);
+       return proxy;
+     } else if (largs == 1 || mname.startsWith("set")) {
+       setValue(null, jsonObject, attr, args[0]);
+       return proxy;
+     }
+     return null;
+   }
+   public String methodName2AttrName(String s) {
+     return deCapitalize(s.replaceFirst("^[gs]et", ""));
+   }
+   private String deCapitalize(String s) {
+     return s != null && s.length() > 0 ? s.substring(0, 1).toLowerCase() + s.substring(1) : s;
+   }
+   /*
+    * This method removes all the json which is not mapped into a 
+    * method inside the JsonBuilder Object.
+    * Also if the proxy contains another JsonBuilder in their methods
+    * the method strip() is called.
+    */
+   private void stripProxy(JsonBuilder proxy) throws Throwable {
+     Class<?> type = proxy.getClass().getInterfaces()[0];
+     HashSet<String> validAttrs = getAttributeNames(type.getMethods());
+     Hashtable<String, Method> ispropertyGetters = getJsonBuilders(type.getMethods());
+     for (String key : jsonObject.keys()) {
+       String name = methodName2AttrName(key);
+       if (!validAttrs.contains(name)) {
+         jsonObject.remove(key);
+         continue;
+       }
+       Method ispropertyGetter = ispropertyGetters.get(name);
+       if (ispropertyGetter != null) {
+         ((IsProperties) invoke(proxy, ispropertyGetter, new Object[] {})).strip();
+       }
+     }
+   }
+   private String getDataBindingClassName(Class<?> type) {
+     for (Class<?> c : type.getInterfaces()) {
+       if (c.equals(JsonBuilder.class)) {
+         return type.getName();
+       } else {
+         return getDataBindingClassName(c);
+       }
+     }
+     return null;
+   }
+   private String param(JsonObject o) {
+     String ret = "";
+     for (String k : o.keys()) {
+       ret += ret.isEmpty() ? "" : "&";
+       JsonValue v = o.get(k);
+       if (v instanceof JsonArray) {
+         for (int i = 0, l = ((JsonArray) v).length(); i < l; i++) {
+           ret += i > 0 ? "&" : "";
+           JsonValue e = ((JsonArray) v).get(i);
+           ret += k + "[]=" + e.toJson();
+         }
+       } else {
+         if (v != null && !(v instanceof JsonNull)) {
+           ret += k + "=" + v.toJson();
+         }
+       }
+     }
+     return ret;
+   }
+   private HashSet<String> getAttributeNames(Method[] methods) {
+     HashSet<String> valid = new HashSet<String>();
+     if (methods == null || methods.length == 0) {
+       return valid;
+     }
+     for (Method m : methods) {
+       String attr = methodName2AttrName(m.getName());
+       Name annotation = m.getAnnotation(Name.class);
+       if (annotation != null) {
+         attr = annotation.value();
+       }
+       valid.add(attr);
+     }
+     return valid;
+   }
+   private Hashtable<String, Method> getJsonBuilders(Method[] methods) {
+     Hashtable<String, Method> ispropertyGetters = new Hashtable<String, Method>();
+     if (methods == null || methods.length == 0) {
+       return ispropertyGetters;
+     }
+     for (Method m : methods) {
+       Class<?>[] classes = m.getParameterTypes();
+       boolean isJsonBuilder =
+           classes.length == 0 && IsProperties.class.isAssignableFrom(m.getReturnType());
+       if (isJsonBuilder) {
+         String attr = methodName2AttrName(m.getName());
+         ispropertyGetters.put(attr, m);
+       }
+     }
+     return ispropertyGetters;
+   }
+ }
index 0d9763c274c66bfd492844e867262b642996513c,66a8f5bce9a922f81f0afe379ee42bd52b007112..5a976f3fa7c7857d76ee809c1521396a7c42ca3a
@@@ -49,10 -32,10 +32,8 @@@ import elemental.json.impl.JreJsonNull
   * It uses java.util.reflect.Proxy to implement JsonBuilders
   * and elemental light weight json to handle json data.
   */
- public class JsonFactoryJre implements JsonFactory  {
-   static JsonFactoryJre jsonFactory = new JsonFactoryJre();
+ public class JsonFactoryJre implements JsonFactory {
  
 - 
 -
    /**
     * Although functions cannot be serialized to json we use JsonBuilders
     * or IsProperties objects which can be used as settings in Ajax.