/* * 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; } }