geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kl...@apache.org
Subject [40/50] [abbrv] geode git commit: GEODE-2282 Added ability to sort JSON fields while creating pdxtype.
Date Fri, 20 Jan 2017 22:53:36 GMT
GEODE-2282 Added ability to sort JSON fields while creating pdxtype.

One can enable this feature by setting java system property(
gemfire.pdx.mapper.sort-json-field-names=true. In this way geode will
not create multiple pdx type ids for JSON document, if different JSON
document has same fields in different order.

Added unit test for it.

updated


Project: http://git-wip-us.apache.org/repos/asf/geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/8b303e43
Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/8b303e43
Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/8b303e43

Branch: refs/heads/feature/GEODE-1930-2
Commit: 8b303e43bce0518f4cd290b688f7ee93ebe2da3e
Parents: e06bf2d
Author: Hitesh Khamesra <hkhamesra@pivotal.io>
Authored: Tue Jan 10 11:27:30 2017 -0800
Committer: Hitesh Khamesra <hkhamesra@pivotal.io>
Committed: Thu Jan 19 11:09:35 2017 -0800

----------------------------------------------------------------------
 .../org/apache/geode/pdx/JSONFormatter.java     |  36 +-
 .../pdx/internal/json/JSONToPdxMapper.java      |  48 +++
 .../pdx/internal/json/PdxInstanceHelper.java    |  10 +-
 .../internal/json/PdxInstanceSortedHelper.java  | 381 +++++++++++++++++++
 .../geode/pdx/internal/json/PdxListHelper.java  |   2 +-
 .../geode/pdx/JSONFormatterJUnitTest.java       |  48 +++
 .../geode/pdx/JSONPdxClientServerDUnitTest.java |  53 ++-
 7 files changed, 563 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/geode/blob/8b303e43/geode-core/src/main/java/org/apache/geode/pdx/JSONFormatter.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/pdx/JSONFormatter.java b/geode-core/src/main/java/org/apache/geode/pdx/JSONFormatter.java
index a96e111..9ee32c9 100755
--- a/geode-core/src/main/java/org/apache/geode/pdx/JSONFormatter.java
+++ b/geode-core/src/main/java/org/apache/geode/pdx/JSONFormatter.java
@@ -17,14 +17,20 @@ package org.apache.geode.pdx;
 import java.io.IOException;
 import java.math.BigDecimal;
 import java.math.BigInteger;
+import java.util.Properties;
+
 import com.fasterxml.jackson.core.JsonFactory;
 import com.fasterxml.jackson.core.JsonParseException;
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonParser.Feature;
 import com.fasterxml.jackson.core.JsonParser.NumberType;
 import com.fasterxml.jackson.core.JsonToken;
+
+import org.apache.geode.distributed.internal.DistributionConfig;
 import org.apache.geode.pdx.PdxInstance;
+import org.apache.geode.pdx.internal.json.JSONToPdxMapper;
 import org.apache.geode.pdx.internal.json.PdxInstanceHelper;
+import org.apache.geode.pdx.internal.json.PdxInstanceSortedHelper;
 import org.apache.geode.pdx.internal.json.PdxListHelper;
 import org.apache.geode.pdx.internal.json.PdxToJSON;
 
@@ -92,6 +98,14 @@ public class JSONFormatter {
 
   public static final String JSON_CLASSNAME = "__GEMFIRE_JSON";
 
+  /***
+   * By setting "gemfire.sort-json-field-names" to true, enables serialization of JSON field
in JSON
+   * document to be sorted. That can help to reduce the number of pdx typeId generation if
different
+   * JSON documents have same fields in the different order.
+   */
+  public static final String SORT_JSON_FIELD_NAMES_PROPERTY =
+      DistributionConfig.GEMFIRE_PREFIX + "pdx.mapper.sort-json-field-names";
+
   enum states {
     NONE, ObJECT_START, FIELD_NAME, SCALER_FOUND, LIST_FOUND, LIST_ENDS, OBJECT_ENDS
   };
@@ -179,11 +193,19 @@ public class JSONFormatter {
     }
   }
 
-  private PdxInstanceHelper getPdxInstance(JsonParser jp, states currentState,
-      PdxInstanceHelper currentPdxInstance) throws JsonParseException, IOException {
+  private static JSONToPdxMapper createJSONToPdxMapper(String className, JSONToPdxMapper
parent) {
+    if (Boolean.getBoolean(SORT_JSON_FIELD_NAMES_PROPERTY)) {
+      return new PdxInstanceSortedHelper(className, parent);
+    } else {
+      return new PdxInstanceHelper(className, parent);
+    }
+  }
+
+  private JSONToPdxMapper getPdxInstance(JsonParser jp, states currentState,
+      JSONToPdxMapper currentPdxInstance) throws JsonParseException, IOException {
     String currentFieldName = null;
     if (currentState == states.ObJECT_START && currentPdxInstance == null)
-      currentPdxInstance = new PdxInstanceHelper(null, null);// from getlist
+      currentPdxInstance = createJSONToPdxMapper(null, null);// from getlist
     while (true) {
       JsonToken nt = jp.nextToken();
 
@@ -197,7 +219,7 @@ public class JSONFormatter {
           // need to create new PdxInstance
           // root object will not name, so create classname lazily from all members.
           // child object will have name; but create this as well lazily from all members
-          PdxInstanceHelper tmp = new PdxInstanceHelper(currentFieldName, currentPdxInstance);
+          JSONToPdxMapper tmp = createJSONToPdxMapper(currentFieldName, currentPdxInstance);
           currentPdxInstance = tmp;
           break;
         }
@@ -208,7 +230,7 @@ public class JSONFormatter {
           currentPdxInstance.endObjectField("endobject");
           if (currentPdxInstance.getParent() == null)
             return currentPdxInstance;// inner pdxinstance in list
-          PdxInstanceHelper tmp = currentPdxInstance;
+          JSONToPdxMapper tmp = currentPdxInstance;
           currentPdxInstance = currentPdxInstance.getParent();
           currentPdxInstance.addObjectField(tmp.getPdxFieldName(), tmp.getPdxInstance());
           break;
@@ -304,7 +326,7 @@ public class JSONFormatter {
     }
   }
 
-  private void setNumberField(JsonParser jp, PdxInstanceHelper pih, String fieldName)
+  private void setNumberField(JsonParser jp, JSONToPdxMapper pih, String fieldName)
       throws IOException {
     try {
       NumberType nt = jp.getNumberType();
@@ -408,7 +430,7 @@ public class JSONFormatter {
           // need to create new PdxInstance
           // root object will not name, so create classname lazily from all members.
           // child object will have name; but create this as well lazily from all members
-          PdxInstanceHelper tmp = getPdxInstance(jp, currentState, null);
+          JSONToPdxMapper tmp = getPdxInstance(jp, currentState, null);
           currentPdxList.addObjectField(currentFieldName, tmp);
           currentState = states.OBJECT_ENDS;
           break;

http://git-wip-us.apache.org/repos/asf/geode/blob/8b303e43/geode-core/src/main/java/org/apache/geode/pdx/internal/json/JSONToPdxMapper.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/pdx/internal/json/JSONToPdxMapper.java
b/geode-core/src/main/java/org/apache/geode/pdx/internal/json/JSONToPdxMapper.java
new file mode 100644
index 0000000..0bdc889
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/pdx/internal/json/JSONToPdxMapper.java
@@ -0,0 +1,48 @@
+package org.apache.geode.pdx.internal.json;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.apache.geode.pdx.PdxInstance;
+
+public interface JSONToPdxMapper {
+
+  JSONToPdxMapper getParent();
+
+  void setPdxFieldName(String name);
+
+  void addStringField(String fieldName, String value);
+
+  void addByteField(String fieldName, byte value);
+
+  void addShortField(String fieldName, short value);
+
+  void addIntField(String fieldName, int value);
+
+  void addLongField(String fieldName, long value);
+
+  void addBigDecimalField(String fieldName, BigDecimal value);
+
+  void addBigIntegerField(String fieldName, BigInteger value);
+
+  void addBooleanField(String fieldName, boolean value);
+
+  void addFloatField(String fieldName, float value);
+
+  void addDoubleField(String fieldName, double value);
+
+  void addNullField(String fieldName);
+
+  void addListField(String fieldName, PdxListHelper list);
+
+  void endListField(String fieldName);
+
+  void addObjectField(String fieldName, Object member);
+
+  void endObjectField(String fieldName);
+
+  PdxInstance getPdxInstance();
+
+  String getPdxFieldName();
+
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/8b303e43/geode-core/src/main/java/org/apache/geode/pdx/internal/json/PdxInstanceHelper.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/pdx/internal/json/PdxInstanceHelper.java
b/geode-core/src/main/java/org/apache/geode/pdx/internal/json/PdxInstanceHelper.java
index a91fbd4..39d16a5 100755
--- a/geode-core/src/main/java/org/apache/geode/pdx/internal/json/PdxInstanceHelper.java
+++ b/geode-core/src/main/java/org/apache/geode/pdx/internal/json/PdxInstanceHelper.java
@@ -29,15 +29,15 @@ import org.apache.geode.pdx.internal.PdxInstanceFactoryImpl;
 /*
  * This class is intermediate class to create PdxInstance.
  */
-public class PdxInstanceHelper {
+public class PdxInstanceHelper implements JSONToPdxMapper {
   private static final Logger logger = LogService.getLogger();
 
-  PdxInstanceHelper m_parent;
+  JSONToPdxMapper m_parent;
   PdxInstanceFactoryImpl m_pdxInstanceFactory;
   PdxInstance m_pdxInstance;
   String m_PdxName;// when pdx is member, else null if part of lists
 
-  public PdxInstanceHelper(String className, PdxInstanceHelper parent) {
+  public PdxInstanceHelper(String className, JSONToPdxMapper parent) {
     GemFireCacheImpl gci = (GemFireCacheImpl) CacheFactory.getAnyInstance();
     if (logger.isTraceEnabled()) {
       logger.trace("ClassName {}", className);
@@ -48,7 +48,7 @@ public class PdxInstanceHelper {
         (PdxInstanceFactoryImpl) gci.createPdxInstanceFactory(JSONFormatter.JSON_CLASSNAME,
false);
   }
 
-  public PdxInstanceHelper getParent() {
+  public JSONToPdxMapper getParent() {
     return m_parent;
   }
 
@@ -63,7 +63,7 @@ public class PdxInstanceHelper {
     if (logger.isTraceEnabled()) {
       logger.trace("addStringField fieldName: {}; value: {}", fieldName, value);
     }
-    m_pdxInstanceFactory.writeString(fieldName, value);
+    m_pdxInstanceFactory.writeObject(fieldName, value);
   }
 
   public void addByteField(String fieldName, byte value) {

http://git-wip-us.apache.org/repos/asf/geode/blob/8b303e43/geode-core/src/main/java/org/apache/geode/pdx/internal/json/PdxInstanceSortedHelper.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/pdx/internal/json/PdxInstanceSortedHelper.java
b/geode-core/src/main/java/org/apache/geode/pdx/internal/json/PdxInstanceSortedHelper.java
new file mode 100644
index 0000000..7f510da
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/pdx/internal/json/PdxInstanceSortedHelper.java
@@ -0,0 +1,381 @@
+/*
+ * 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.geode.pdx.internal.json;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.SortedMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+
+import org.apache.logging.log4j.Logger;
+
+import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.internal.cache.GemFireCacheImpl;
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.pdx.FieldType;
+import org.apache.geode.pdx.JSONFormatter;
+import org.apache.geode.pdx.PdxInstance;
+import org.apache.geode.pdx.PdxInstanceFactory;
+import org.apache.geode.pdx.internal.PdxInstanceFactoryImpl;
+
+/*
+ * This class is intermediate class to create PdxInstance.
+ */
+public class PdxInstanceSortedHelper implements JSONToPdxMapper {
+  private static final Logger logger = LogService.getLogger();
+
+  JSONToPdxMapper m_parent;
+  LinkedList<JSONFieldHolder<?>> fieldList = new LinkedList<>();
+  PdxInstance m_pdxInstance;
+  String m_PdxName;// when pdx is member, else null if part of lists
+
+  public PdxInstanceSortedHelper(String className, JSONToPdxMapper parent) {
+    GemFireCacheImpl gci = (GemFireCacheImpl) CacheFactory.getAnyInstance();
+    if (logger.isTraceEnabled()) {
+      logger.trace("ClassName {}", className);
+    }
+    m_PdxName = className;
+    m_parent = parent;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#getParent()
+   */
+  @Override
+  public JSONToPdxMapper getParent() {
+    return m_parent;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#setPdxFieldName(java.lang.String)
+   */
+  @Override
+  public void setPdxFieldName(String name) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("setPdxClassName : {}", name);
+    }
+    m_PdxName = name;
+  }
+
+  static class JSONFieldHolder<T> implements Comparable<JSONFieldHolder> {
+    private String fieldName;
+    private T value;
+    private FieldType type;
+
+    public JSONFieldHolder(String fn, T v, FieldType ft) {
+      this.fieldName = fn;
+      this.value = v;
+      this.type = ft;
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Override
+    public int compareTo(JSONFieldHolder other) {
+      return fieldName.compareTo(other.fieldName);
+    }
+
+    @Override
+    public String toString() {
+      return "JSONFieldHolder [fieldName=" + fieldName + ", value=" + value + ", type=" +
type
+          + "]";
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#addStringField(java.lang.String,
+   * java.lang.String)
+   */
+  @Override
+  public void addStringField(String fieldName, String value) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("addStringField fieldName: {}; value: {}", fieldName, value);
+    }
+    fieldList.add(new JSONFieldHolder(fieldName, value, FieldType.STRING));
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#addByteField(java.lang.String,
byte)
+   */
+  @Override
+  public void addByteField(String fieldName, byte value) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("addByteField fieldName: {}; value: {}", fieldName, value);
+    }
+    fieldList.add(new JSONFieldHolder(fieldName, value, FieldType.BYTE));
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#addShortField(java.lang.String,
short)
+   */
+  @Override
+  public void addShortField(String fieldName, short value) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("addShortField fieldName: {}; value: {}", fieldName, value);
+    }
+    fieldList.add(new JSONFieldHolder(fieldName, value, FieldType.SHORT));
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#addIntField(java.lang.String,
int)
+   */
+  @Override
+  public void addIntField(String fieldName, int value) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("addIntField fieldName: {}; value: {}", fieldName, value);
+    }
+    fieldList.add(new JSONFieldHolder(fieldName, value, FieldType.INT));
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#addLongField(java.lang.String,
long)
+   */
+  @Override
+  public void addLongField(String fieldName, long value) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("addLongField fieldName: {}; value: {}", fieldName, value);
+    }
+    fieldList.add(new JSONFieldHolder(fieldName, value, FieldType.LONG));
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#addBigDecimalField(java.lang.String,
+   * java.math.BigDecimal)
+   */
+  @Override
+  public void addBigDecimalField(String fieldName, BigDecimal value) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("addBigDecimalField fieldName: {}; value: {}", fieldName, value);
+    }
+    fieldList.add(new JSONFieldHolder(fieldName, value, FieldType.OBJECT));
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#addBigIntegerField(java.lang.String,
+   * java.math.BigInteger)
+   */
+  @Override
+  public void addBigIntegerField(String fieldName, BigInteger value) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("addBigIntegerField fieldName: {}; value: {}", fieldName, value);
+    }
+    fieldList.add(new JSONFieldHolder(fieldName, value, FieldType.OBJECT));
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#addBooleanField(java.lang.String,
+   * boolean)
+   */
+  @Override
+  public void addBooleanField(String fieldName, boolean value) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("addBooleanField fieldName: {}; value: {}", fieldName, value);
+    }
+    fieldList.add(new JSONFieldHolder(fieldName, value, FieldType.BOOLEAN));
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#addFloatField(java.lang.String,
float)
+   */
+  @Override
+  public void addFloatField(String fieldName, float value) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("addFloatField fieldName: {}; value: {}", fieldName, value);
+    }
+    fieldList.add(new JSONFieldHolder(fieldName, value, FieldType.FLOAT));
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#addDoubleField(java.lang.String,
+   * double)
+   */
+  @Override
+  public void addDoubleField(String fieldName, double value) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("addDoubleField fieldName: {}; value: {}", fieldName, value);
+    }
+    fieldList.add(new JSONFieldHolder(fieldName, value, FieldType.DOUBLE));
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#addNullField(java.lang.String)
+   */
+  @Override
+  public void addNullField(String fieldName) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("addNullField fieldName: {}; value: NULL", fieldName);
+    }
+    fieldList.add(new JSONFieldHolder(fieldName, null, FieldType.OBJECT));
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#addListField(java.lang.String,
+   * org.apache.geode.pdx.internal.json.PdxListHelper)
+   */
+  @Override
+  public void addListField(String fieldName, PdxListHelper list) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("addListField fieldName: {}", fieldName);
+    }
+    // fieldNameVsType.put(fieldName, list.getList());
+    fieldList.add(new JSONFieldHolder(fieldName, list.getList(), FieldType.OBJECT));
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#endListField(java.lang.String)
+   */
+  @Override
+  public void endListField(String fieldName) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("endListField fieldName: {}", fieldName);
+    }
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#addObjectField(java.lang.String,
+   * org.apache.geode.pdx.PdxInstance)
+   */
+  @Override
+  public void addObjectField(String fieldName, Object member) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("addObjectField fieldName: {}", fieldName);
+    }
+    if (fieldName == null) {
+      throw new IllegalStateException("addObjectField:Object should have fieldname");
+    }
+    fieldList.add(new JSONFieldHolder(fieldName, member, FieldType.OBJECT));
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#endObjectField(java.lang.String)
+   */
+  @Override
+  public void endObjectField(String fieldName) {
+    if (logger.isTraceEnabled()) {
+      logger.trace("endObjectField fieldName: {}", fieldName);
+    }
+    // m_pdxInstance = m_pdxInstanceFactory.create();
+    m_pdxInstance = createPdxInstance();
+  }
+
+  private PdxInstance createPdxInstance() {
+    Collections.sort(fieldList);
+    PdxInstanceFactory factory = createPdxInstanceFactory();
+    for (JSONFieldHolder<?> f : fieldList) {
+      filldata(factory, f);
+    }
+    return factory.create();
+  }
+
+  private void filldata(PdxInstanceFactory factory, JSONFieldHolder key) {
+    switch (key.type) {
+      case BOOLEAN:
+        factory.writeBoolean(key.fieldName, (boolean) key.value);
+        break;
+      case BYTE:
+        factory.writeByte(key.fieldName, (byte) key.value);
+        break;
+      case SHORT:
+        factory.writeShort(key.fieldName, (short) key.value);
+        break;
+      case INT:
+        factory.writeInt(key.fieldName, (int) key.value);
+        break;
+      case LONG:
+        factory.writeLong(key.fieldName, (long) key.value);
+        break;
+      case FLOAT:
+        factory.writeFloat(key.fieldName, (float) key.value);
+        break;
+      case DOUBLE:
+        factory.writeDouble(key.fieldName, (double) key.value);
+        break;
+      case STRING:
+      case OBJECT:
+        factory.writeObject(key.fieldName, key.value);
+        break;
+      default:
+        new RuntimeException("Unable to convert json field " + key);
+        break;
+    }
+  }
+
+
+  static PdxInstanceFactory createPdxInstanceFactory() {
+    GemFireCacheImpl gci = (GemFireCacheImpl) CacheFactory.getAnyInstance();
+    return gci.createPdxInstanceFactory(JSONFormatter.JSON_CLASSNAME, false);
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#getPdxInstance()
+   */
+  @Override
+  public PdxInstance getPdxInstance() {
+    return m_pdxInstance;
+  }
+
+  /*
+   * (non-Javadoc)
+   * 
+   * @see org.apache.geode.pdx.internal.json.JSONToPdxMapper#getPdxFieldName()
+   */
+  @Override
+  public String getPdxFieldName() {
+    // return m_fieldName != null ? m_fieldName : "emptyclassname"; //when object is just
like { }
+    return m_PdxName;
+  }
+}

http://git-wip-us.apache.org/repos/asf/geode/blob/8b303e43/geode-core/src/main/java/org/apache/geode/pdx/internal/json/PdxListHelper.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/pdx/internal/json/PdxListHelper.java
b/geode-core/src/main/java/org/apache/geode/pdx/internal/json/PdxListHelper.java
index caf0dfc..417e56a 100755
--- a/geode-core/src/main/java/org/apache/geode/pdx/internal/json/PdxListHelper.java
+++ b/geode-core/src/main/java/org/apache/geode/pdx/internal/json/PdxListHelper.java
@@ -149,7 +149,7 @@ public class PdxListHelper {
     return m_parent;
   }
 
-  public void addObjectField(String fieldName, PdxInstanceHelper dpi) {
+  public void addObjectField(String fieldName, JSONToPdxMapper dpi) {
     if (fieldName != null)
       throw new IllegalStateException("addObjectField:list should have object no fieldname");
     if (logger.isTraceEnabled()) {

http://git-wip-us.apache.org/repos/asf/geode/blob/8b303e43/geode-core/src/test/java/org/apache/geode/pdx/JSONFormatterJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/pdx/JSONFormatterJUnitTest.java b/geode-core/src/test/java/org/apache/geode/pdx/JSONFormatterJUnitTest.java
index cbe350f..13e8fe8 100755
--- a/geode-core/src/test/java/org/apache/geode/pdx/JSONFormatterJUnitTest.java
+++ b/geode-core/src/test/java/org/apache/geode/pdx/JSONFormatterJUnitTest.java
@@ -18,6 +18,7 @@ import static org.apache.geode.distributed.ConfigurationProperties.*;
 import static org.junit.Assert.*;
 
 import java.text.SimpleDateFormat;
+import java.util.List;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.DeserializationFeature;
@@ -275,6 +276,53 @@ public class JSONFormatterJUnitTest {
 
     assertEquals(pdxTypes + 1, c.getRegion(PeerTypeRegistration.REGION_FULL_PATH).keys().size());
   }
+
+  @Test
+  public void testJSONStringSortedFields() {
+
+    try {
+      System.setProperty(JSONFormatter.SORT_JSON_FIELD_NAMES_PROPERTY, "true");
+
+      Cache c = CacheFactory.getAnyInstance();
+
+      Region region = c.getRegion("primitiveKVStore");
+
+      String js = "{b:\"b\", age:14, c:\"c' go\", bb:23}";
+
+      region.put(1, JSONFormatter.fromJSON(js));
+
+      PdxInstance ret = (PdxInstance) region.get(1);
+      List<String> fieldNames = ret.getFieldNames();
+
+      assertEquals("There should be four fields", 4, fieldNames.size());
+
+      boolean sorted = true;
+      for (int i = 0; i < fieldNames.size() - 1; i++) {
+        if (fieldNames.get(i).compareTo(fieldNames.get(i + 1)) >= 0) {
+          sorted = false;
+        }
+      }
+
+      assertTrue("Json fields should be sorted", sorted);
+
+      // Now do put with another jsonstring with same fields but different order
+      // then verify we don't create another pdxtype
+
+      int pdxTypes = 0;
+
+      if (c.getRegion(PeerTypeRegistration.REGION_FULL_PATH) != null) {
+        pdxTypes = c.getRegion(PeerTypeRegistration.REGION_FULL_PATH).keys().size();
+      }
+
+      String js2 = "{c:\"c' go\", bb:23, b:\"b\", age:14 }";
+      region.put(2, JSONFormatter.fromJSON(js2));
+
+      assertEquals(pdxTypes, c.getRegion(PeerTypeRegistration.REGION_FULL_PATH).keys().size());
+
+    } finally {
+      System.setProperty(JSONFormatter.SORT_JSON_FIELD_NAMES_PROPERTY, "false");
+    }
+  }
 }
 
 

http://git-wip-us.apache.org/repos/asf/geode/blob/8b303e43/geode-core/src/test/java/org/apache/geode/pdx/JSONPdxClientServerDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/pdx/JSONPdxClientServerDUnitTest.java
b/geode-core/src/test/java/org/apache/geode/pdx/JSONPdxClientServerDUnitTest.java
index ae17837..396eb1d 100755
--- a/geode-core/src/test/java/org/apache/geode/pdx/JSONPdxClientServerDUnitTest.java
+++ b/geode-core/src/test/java/org/apache/geode/pdx/JSONPdxClientServerDUnitTest.java
@@ -93,6 +93,46 @@ public class JSONPdxClientServerDUnitTest extends JUnit4CacheTestCase {
     });
   }
 
+  @Test
+  public void testSimplePutWithSortedJSONField() {
+    Host host = Host.getHost(0);
+    VM vm0 = host.getVM(0);
+    VM vm1 = host.getVM(1);
+    VM vm2 = host.getVM(2);
+    VM vm3 = host.getVM(3);
+
+
+    createServerRegion(vm0);
+    int port = createServerRegion(vm3);
+    createClientRegion(vm1, port);
+    createClientRegion(vm2, port);
+
+    vm1.invoke(new SerializableCallable() {
+      public Object call() throws Exception {
+        try {
+          System.setProperty(JSONFormatter.SORT_JSON_FIELD_NAMES_PROPERTY, "true");
+          JSONAllStringTest();
+        } finally {
+          System.setProperty(JSONFormatter.SORT_JSON_FIELD_NAMES_PROPERTY, "false");
+        }
+
+        return null;
+      }
+    });
+
+    vm2.invoke(new SerializableCallable() {
+      public Object call() throws Exception {
+        try {
+          System.setProperty(JSONFormatter.SORT_JSON_FIELD_NAMES_PROPERTY, "true");
+          JSONAllByteArrayTest();
+        } finally {
+          System.setProperty(JSONFormatter.SORT_JSON_FIELD_NAMES_PROPERTY, "false");
+        }
+        return null;
+      }
+    });
+  }
+
   // this is for unquote fielnames in json string
   @Test
   public void testSimplePut2() {
@@ -338,8 +378,14 @@ public class JSONPdxClientServerDUnitTest extends JUnit4CacheTestCase
{
 
     String o1 = jsonParse(jd.getJsonString());
     String o2 = jsonParse(getJsonString);
-    assertEquals("Json Strings are not equal " + jd.getFileName() + " "
-        + Boolean.getBoolean("pdxToJson.unqouteFieldNames"), o1, o2);
+    if (!Boolean.getBoolean(JSONFormatter.SORT_JSON_FIELD_NAMES_PROPERTY)) {
+      assertEquals("Json Strings are not equal " + jd.getFileName() + " "
+          + Boolean.getBoolean("pdxToJson.unqouteFieldNames"), o1, o2);
+    } else {
+      // we just need to compare length as blob will be different because fields are sorted
+      assertEquals("Json Strings are not equal " + jd.getFileName() + " "
+          + Boolean.getBoolean("pdxToJson.unqouteFieldNames"), o1.length(), o2.length());
+    }
 
     PdxInstance pdx2 = JSONFormatter.fromJSON(getJsonString);
 
@@ -397,6 +443,9 @@ public class JSONPdxClientServerDUnitTest extends JUnit4CacheTestCase
{
       throw new IllegalStateException(
           "Json byte array length are not equal " + b1.length + " ; " + b2.length);
 
+    if (Boolean.getBoolean(JSONFormatter.SORT_JSON_FIELD_NAMES_PROPERTY))
+      return;// we just need to compare length as blob will be different because fields are
sorted
+
     for (int i = 0; i < b1.length; i++) {
       if (b1[i] != b2[i])
         throw new IllegalStateException("Json byte arrays are not equal ");


Mime
View raw message