Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 13DDA200C2A for ; Tue, 14 Feb 2017 20:31:37 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 12BF5160B8A; Tue, 14 Feb 2017 19:31:37 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 990BB160B73 for ; Tue, 14 Feb 2017 20:31:35 +0100 (CET) Received: (qmail 40894 invoked by uid 500); 14 Feb 2017 19:31:34 -0000 Mailing-List: contact commits-help@geode.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@geode.apache.org Delivered-To: mailing list commits@geode.apache.org Received: (qmail 40710 invoked by uid 99); 14 Feb 2017 19:31:34 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 14 Feb 2017 19:31:34 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 82978E089D; Tue, 14 Feb 2017 19:31:34 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: hiteshkhamesra@apache.org To: commits@geode.apache.org Date: Tue, 14 Feb 2017 19:31:37 -0000 Message-Id: In-Reply-To: <405b3a7a23b74851a5c68073ae26b81f@git.apache.org> References: <405b3a7a23b74851a5c68073ae26b81f@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [04/50] [abbrv] geode git commit: GEODE-2282 Added ability to sort JSON fields while creating pdxtype. archived-at: Tue, 14 Feb 2017 19:31:37 -0000 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/master Commit: 8b303e43bce0518f4cd290b688f7ee93ebe2da3e Parents: e06bf2d Author: Hitesh Khamesra Authored: Tue Jan 10 11:27:30 2017 -0800 Committer: Hitesh Khamesra 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> 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 implements Comparable { + 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 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 ");