com.phloc.json.impl.JSONObject Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of phloc-json Show documentation
Show all versions of phloc-json Show documentation
Library for read and writing JSON objects in a typesafe manner
/**
* Copyright (C) 2006-2015 phloc systems
* http://www.phloc.com
* office[at]phloc[dot]com
*
* 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.phloc.json.impl;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.phloc.commons.annotations.Nonempty;
import com.phloc.commons.annotations.ReturnsMutableCopy;
import com.phloc.commons.collections.ContainerHelper;
import com.phloc.commons.equals.EqualsUtils;
import com.phloc.commons.hash.HashCodeGenerator;
import com.phloc.commons.state.EChange;
import com.phloc.commons.string.StringHelper;
import com.phloc.commons.string.ToStringGenerator;
import com.phloc.commons.typeconvert.TypeConverter;
import com.phloc.json.IJSONObject;
import com.phloc.json.IJSONProperty;
import com.phloc.json.IJSONPropertyValue;
import com.phloc.json.IJSONPropertyValueList;
import com.phloc.json.IJSONPropertyValueNotParsable;
import com.phloc.json.JSONUtil;
import com.phloc.json.impl.value.AbstractJSONPropertyValue;
import com.phloc.json.impl.value.AbstractJSONPropertyValueNumeric;
import com.phloc.json.impl.value.JSONPropertyValueBigDecimal;
import com.phloc.json.impl.value.JSONPropertyValueBigInteger;
import com.phloc.json.impl.value.JSONPropertyValueBoolean;
import com.phloc.json.impl.value.JSONPropertyValueDouble;
import com.phloc.json.impl.value.JSONPropertyValueFunction;
import com.phloc.json.impl.value.JSONPropertyValueFunctionPrebuild;
import com.phloc.json.impl.value.JSONPropertyValueInteger;
import com.phloc.json.impl.value.JSONPropertyValueJSONObject;
import com.phloc.json.impl.value.JSONPropertyValueKeyword;
import com.phloc.json.impl.value.JSONPropertyValueList;
import com.phloc.json.impl.value.JSONPropertyValueLong;
import com.phloc.json.impl.value.JSONPropertyValueString;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* Represents a JSON object having a map of named JSON properties
*
* @author Boris Gregorcic, philip
*/
@SuppressWarnings ("deprecation")
public class JSONObject extends AbstractJSONPropertyValue implements IJSONObject
{
private static final long serialVersionUID = 6726669796398394782L;
private static final Logger LOG = LoggerFactory.getLogger (JSONObject.class);
private final Map > m_aProperties = new LinkedHashMap > ();
private final List m_aParents = new CopyOnWriteArrayList <> ();
private final List m_aChildren = new CopyOnWriteArrayList <> ();
/**
* Default Ctor. Handle with care as it by default sets a null
* value which is most probable be crashing somewhere inside this class, if no
* data is provided afterwards!
*/
public JSONObject ()
{
super ();
JSONStatistics.getInstance ().onObjectCreated ();
}
public JSONObject (@Nonnull final Iterable extends IJSONProperty >> aProperties)
{
this (aProperties, ECloneStategy.INHERIT);
}
public JSONObject (@Nonnull final Iterable extends IJSONProperty >> aProperties,
final ECloneStategy eCloneStrategy)
{
super ();
if (aProperties == null)
{
throw new NullPointerException ("properties"); //$NON-NLS-1$
}
for (final IJSONProperty > aProperty : aProperties)
{
setProperty (aProperty, eCloneStrategy);
}
JSONStatistics.getInstance ().onObjectCreated ();
}
/**
* Override since otherwise JSONObjects might return null for certain
* constructors
*
* @return this
*/
@Override
@Nonnull
public IJSONObject getData ()
{
return this;
}
@Override
@Nonnull
public JSONObject setProperty (@Nonnull final IJSONProperty > aProperty)
{
return setProperty (aProperty, ECloneStategy.INHERIT);
}
@Nonnull
private JSONObject setProperty (@Nonnull final IJSONProperty > aProperty, final ECloneStategy eCloneStrategy)
{
if (aProperty == null)
{
throw new NullPointerException ("property"); //$NON-NLS-1$
}
final boolean bCloneProperties = JSONSettings.getInstance ().isCloneProperties ();
final boolean bCloneProperty = eCloneStrategy == ECloneStategy.FORCE ||
eCloneStrategy != ECloneStategy.AVOID && bCloneProperties;
List aObjectsInValue = null;
if (!bCloneProperty && JSONSettings.getInstance ().isDetectCycles ())
{
aObjectsInValue = getObjectsInValue (aProperty);
for (final IJSONObject aChild : aObjectsInValue)
{
checkCycle (aChild);
}
}
this.m_aProperties.put (aProperty.getName (), bCloneProperty ? aProperty.getClone () : aProperty);
if (JSONSettings.getInstance ().isDetectCycles () && ContainerHelper.isNotEmpty (aObjectsInValue))
{
for (final JSONObject aChild : aObjectsInValue)
{
aChild.m_aParents.add (this);
this.m_aChildren.add (aChild);
}
}
return this;
}
private static List getObjectsInValue (@Nonnull final IJSONProperty > aProperty)
{
final List aObjects = ContainerHelper.newList ();
final IJSONPropertyValue > aValue = aProperty.getValue ();
if (aValue instanceof JSONObject)
{
aObjects.add ((JSONObject) aValue);
}
else
if (aValue instanceof IJSONPropertyValueList >)
{
for (final Object aListElem : ((IJSONPropertyValueList >) aValue).getDataValues ())
{
if (aListElem instanceof JSONObject)
{
aObjects.add ((JSONObject) aListElem);
}
}
}
return aObjects;
}
@Override
@Nullable
public IJSONProperty > getProperty (@Nullable final String sName)
{
return this.m_aProperties.get (sName);
}
@Override
@Nullable
public Object getPropertyValueData (@Nullable final String sName)
{
final IJSONPropertyValue > aValue = getPropertyValueInternal (sName);
return aValue == null ? null : aValue.getData ();
}
@Override
@Nullable
public Object getNumericProperty (@Nullable final String sName)
{
final IJSONPropertyValue > aValue = getPropertyValueInternal (sName);
if (aValue instanceof AbstractJSONPropertyValueNumeric)
{
return aValue.getData ();
}
return null;
}
@Override
@Nonnull
@ReturnsMutableCopy
public Set getAllPropertyNames ()
{
return ContainerHelper.newOrderedSet (this.m_aProperties.keySet ());
}
@Nullable
private IJSONPropertyValue > getPropertyValueInternal (@Nullable final String sName)
{
final IJSONProperty > aProperty = this.m_aProperties.get (sName);
return aProperty == null ? null : aProperty.getValue ();
}
// we need to differentiate here the case of set boolean values from the case
// the property is not found or of wrong type (null). Un-boxing is prevented
// by PMD anyway and the method is annotated as @Nullable
@Override
@Nullable
@SuppressFBWarnings ("NP_BOOLEAN_RETURN_NULL")
public Boolean getBooleanProperty (@Nullable final String sName)
{
final IJSONPropertyValue > aValue = getPropertyValueInternal (sName);
if (aValue instanceof JSONPropertyValueBoolean)
{
return ((JSONPropertyValueBoolean) aValue).getData ();
}
return null;
}
@Override
public boolean getBoolProperty (@Nullable final String sName, final boolean bDefault)
{
final Boolean aVal = getBooleanProperty (sName);
return aVal == null ? bDefault : aVal.booleanValue ();
}
@Override
@Nonnull
public JSONObject setBooleanProperty (@Nonnull final String sName, final boolean bDataValue)
{
return setProperty (JSONProperty.create (sName, new JSONPropertyValueBoolean (bDataValue), ECloneStategy.AVOID),
ECloneStategy.AVOID);
}
@Override
@Nonnull
public JSONObject setBooleanProperty (@Nonnull final String sName, @Nonnull final Boolean aDataValue)
{
return setProperty (JSONProperty.create (sName, new JSONPropertyValueBoolean (aDataValue), ECloneStategy.AVOID),
ECloneStategy.AVOID);
}
@Override
@Nullable
public Double getDoubleProperty (@Nullable final String sName)
{
final IJSONPropertyValue > aValue = getPropertyValueInternal (sName);
if (aValue instanceof AbstractJSONPropertyValueNumeric)
{
return Double.valueOf (((AbstractJSONPropertyValueNumeric >) aValue).getData ().doubleValue ());
}
return null;
}
@Override
@Nonnull
public JSONObject setDoubleProperty (@Nonnull final String sName, final double nDataValue)
{
return setProperty (JSONProperty.create (sName, new JSONPropertyValueDouble (nDataValue), ECloneStategy.AVOID),
ECloneStategy.AVOID);
}
@Override
@Nonnull
public JSONObject setDoubleProperty (@Nonnull final String sName, @Nonnull final Double aDataValue)
{
return setProperty (JSONProperty.create (sName, new JSONPropertyValueDouble (aDataValue), ECloneStategy.AVOID),
ECloneStategy.AVOID);
}
@Override
@Nullable
public Integer getIntegerProperty (@Nullable final String sName)
{
final IJSONPropertyValue > aValue = getPropertyValueInternal (sName);
if (aValue instanceof AbstractJSONPropertyValueNumeric)
{
return Integer.valueOf (((AbstractJSONPropertyValueNumeric >) aValue).getData ().intValue ());
}
return null;
}
@Override
public int getIntProperty (@Nullable final String sName, final int nDefault)
{
final Integer aVal = getIntegerProperty (sName);
return aVal == null ? nDefault : aVal.intValue ();
}
@Override
@Nonnull
public Integer getIntegerPropertyNonNull (@Nullable final String sName)
{
final Integer aValue = getIntegerProperty (sName);
if (aValue == null)
{
throw new NullPointerException ("No Integer value available for property '" + sName + "'!"); //$NON-NLS-1$ //$NON-NLS-2$
}
return aValue;
}
@Override
@Nonnull
public JSONObject setIntegerProperty (@Nonnull final String sName, final int nDataValue)
{
return setProperty (JSONProperty.create (sName, new JSONPropertyValueInteger (nDataValue), ECloneStategy.AVOID),
ECloneStategy.AVOID);
}
@Override
@Nonnull
public JSONObject setIntegerProperty (@Nonnull final String sName, @Nonnull final Integer aDataValue)
{
return setProperty (JSONProperty.create (sName, new JSONPropertyValueInteger (aDataValue), ECloneStategy.AVOID),
ECloneStategy.AVOID);
}
@Override
@Nullable
public Long getLongProperty (@Nullable final String sName)
{
final IJSONPropertyValue > aValue = getPropertyValueInternal (sName);
if (aValue instanceof AbstractJSONPropertyValueNumeric)
{
return Long.valueOf (((AbstractJSONPropertyValueNumeric >) aValue).getData ().longValue ());
}
return null;
}
@Override
@Nonnull
public JSONObject setLongProperty (@Nonnull final String sName, final long nDataValue)
{
return setProperty (JSONProperty.create (sName, new JSONPropertyValueLong (nDataValue), ECloneStategy.AVOID),
ECloneStategy.AVOID);
}
@Override
@Nonnull
public JSONObject setLongProperty (@Nonnull final String sName, @Nonnull final Long aDataValue)
{
return setProperty (JSONProperty.create (sName, new JSONPropertyValueLong (aDataValue), ECloneStategy.AVOID),
ECloneStategy.AVOID);
}
@Override
@Nullable
public String getKeywordProperty (@Nullable final String sName)
{
final IJSONPropertyValue > aValue = getPropertyValueInternal (sName);
if (aValue instanceof JSONPropertyValueKeyword)
{
return ((JSONPropertyValueKeyword) aValue).getData ();
}
return null;
}
@Override
@Nonnull
public JSONObject setKeywordProperty (@Nonnull final String sName, @Nonnull final String sDataValue)
{
return setProperty (JSONProperty.create (sName, new JSONPropertyValueKeyword (sDataValue), ECloneStategy.AVOID),
ECloneStategy.AVOID);
}
@Override
@Nonnull
public JSONObject setFunctionProperty (@Nonnull final String sName,
@Nonnull final String sBody,
@Nullable final String... aParams)
{
return setProperty (JSONProperty.create (sName,
new JSONPropertyValueFunction (sBody, aParams),
ECloneStategy.AVOID),
ECloneStategy.AVOID);
}
@Override
@Nonnull
public JSONObject setFunctionPrebuildProperty (@Nonnull final String sName, @Nonnull final String sFunctionCode)
{
return setProperty (JSONProperty.create (sName,
new JSONPropertyValueFunctionPrebuild (sFunctionCode),
ECloneStategy.AVOID),
ECloneStategy.AVOID);
}
@Override
@SuppressWarnings ("unchecked")
public List getListProperty (@Nullable final String sName)
{
final IJSONPropertyValue > aValue = getPropertyValueInternal (sName);
if (aValue instanceof IJSONPropertyValueList >)
{
return (List ) ((IJSONPropertyValueList >) aValue).getDataValues ();
}
return null;
}
@Override
@Nonnull
public JSONObject setListProperty (@Nonnull final String sName, @Nonnull final IJSONPropertyValueList > aList)
{
return setProperty (JSONProperty.create (sName, aList, ECloneStategy.INHERIT), ECloneStategy.AVOID);
}
@Override
@Nullable
public IJSONObject getObjectProperty (@Nullable final String sName)
{
final IJSONPropertyValue > aValue = getPropertyValueInternal (sName);
if (aValue instanceof IJSONObject)
{
return (IJSONObject) aValue;
}
if (aValue instanceof JSONPropertyValueJSONObject)
{
return ((JSONPropertyValueJSONObject) aValue).getData ();
}
return null;
}
@Override
@Nonnull
public JSONObject setObjectProperty (@Nonnull final String sName, @Nonnull final IJSONObject aObject)
{
setProperty (JSONProperty.create (sName, aObject, ECloneStategy.INHERIT), ECloneStategy.AVOID);
return this;
}
private List getParentsRecursive ()
{
final List aResult = ContainerHelper.newList ();
for (final JSONObject aParent : this.m_aParents)
{
aResult.add (aParent);
aResult.addAll (aParent.getParentsRecursive ());
}
return aResult;
}
public List getChildrenRecursive ()
{
final List aResult = ContainerHelper.newList ();
for (final JSONObject aChild : this.m_aChildren)
{
aResult.add (aChild);
aResult.addAll (aChild.getChildrenRecursive ());
}
return aResult;
}
private List getWithAncestors ()
{
final List aAncestors = getParentsRecursive ();
aAncestors.add (this);
return aAncestors;
}
private List getWithDescendants ()
{
final List aDescendants = getChildrenRecursive ();
aDescendants.add (this);
return aDescendants;
}
private void checkCycle (final IJSONObject aChild)
{
if (this == aChild)
{
throw new IllegalArgumentException ("Circle detected: Unable to set object reference from A to B when A==B!");
}
if (aChild instanceof JSONObject)
{
final List aAncestors = getWithAncestors ();
final List aDescendents = ((JSONObject) aChild).getWithDescendants ();
final List aCycles = getIntersectedByIdentity (aAncestors, aDescendents);
if (!ContainerHelper.isEmpty (aCycles))
{
throw new IllegalArgumentException ("Circle detected: Unable to set object reference from A to B when B or one of its descendants is the same as A or one of its ancestors!");
}
}
}
private static List getIntersectedByIdentity (final List aObjectsA,
final List aObjectsB)
{
final List aIntersect = ContainerHelper.newList ();
for (final JSONObject aA : aObjectsA)
{
for (final IJSONObject aB : aObjectsB)
{
if (aA == aB)
{
aIntersect.add (aA);
}
}
}
return aIntersect;
}
@Override
@Nullable
public String getStringProperty (@Nullable final String sName)
{
final IJSONPropertyValue > aValue = getPropertyValueInternal (sName);
if (aValue instanceof JSONPropertyValueString)
{
return ((JSONPropertyValueString) aValue).getData ();
}
return null;
}
@Override
public String getStringPropertyNonEmpty (@Nonnull @Nonempty final String sName)
{
if (StringHelper.hasNoText (sName))
{
throw new IllegalArgumentException ("sName must not be null or empty!"); //$NON-NLS-1$
}
final String sValue = getStringProperty (sName);
if (StringHelper.hasNoText (sValue))
{
throw new IllegalArgumentException ("Value for property '" + sName + "' must not be empty or null!"); //$NON-NLS-1$ //$NON-NLS-2$
}
return sValue;
}
@Override
@Nonnull
public JSONObject setStringProperty (@Nonnull final String sName, @Nonnull final String sDataValue)
{
return setProperty (JSONProperty.create (sName, new JSONPropertyValueString (sDataValue), ECloneStategy.AVOID),
ECloneStategy.AVOID);
}
@Override
@Nonnull
public IJSONObject setStringProperties (@Nonnull final Map aMap)
{
for (final Map.Entry aEntry : aMap.entrySet ())
{
setStringProperty (aEntry.getKey (), aEntry.getValue ());
}
return this;
}
@Override
@Nullable
public BigInteger getBigIntegerProperty (@Nullable final String sName)
{
final IJSONPropertyValue > aValue = getPropertyValueInternal (sName);
if (aValue instanceof AbstractJSONPropertyValueNumeric)
{
return BigInteger.valueOf (((AbstractJSONPropertyValueNumeric >) aValue).getData ().longValue ());
}
return null;
}
@Override
@Nonnull
public JSONObject setBigIntegerProperty (@Nonnull final String sName, @Nonnull final BigInteger aDataValue)
{
return setProperty (JSONProperty.create (sName, new JSONPropertyValueBigInteger (aDataValue), ECloneStategy.AVOID),
ECloneStategy.AVOID);
}
@Override
@Nullable
public BigDecimal getBigDecimalProperty (@Nullable final String sName)
{
final IJSONPropertyValue > aValue = getPropertyValueInternal (sName);
if (aValue instanceof AbstractJSONPropertyValueNumeric)
{
return BigDecimal.valueOf (((AbstractJSONPropertyValueNumeric >) aValue).getData ().doubleValue ());
}
return null;
}
@Override
@Nonnull
public JSONObject setBigDecimalProperty (@Nonnull final String sName, @Nonnull final BigDecimal aDataValue)
{
return setProperty (JSONProperty.create (sName, new JSONPropertyValueBigDecimal (aDataValue), ECloneStategy.AVOID),
ECloneStategy.AVOID);
}
@Override
@Nonnull
public JSONObject setProperty (@Nonnull final String sName, @Nullable final Object aValue)
{
// Default: no type converter
return setProperty (sName, aValue, false);
}
@Override
@Nonnull
public JSONObject setProperty (@Nonnull final String sName,
@Nullable final Object aValue,
final boolean bUseTypeConverter)
{
if (aValue == null)
{
removeProperty (sName);
return this;
}
if (aValue instanceof IJSONObject)
{
return setObjectProperty (sName, (IJSONObject) aValue);
}
if (aValue instanceof IJSONPropertyValue >)
{
return setProperty (JSONProperty.create (sName, (IJSONPropertyValue >) aValue, ECloneStategy.INHERIT),
ECloneStategy.AVOID);
}
if (aValue instanceof Boolean)
{
return setBooleanProperty (sName, (Boolean) aValue);
}
if (aValue instanceof BigInteger)
{
return setBigIntegerProperty (sName, (BigInteger) aValue);
}
if (aValue instanceof BigDecimal)
{
return setBigDecimalProperty (sName, (BigDecimal) aValue);
}
if (aValue instanceof Double)
{
return setDoubleProperty (sName, (Double) aValue);
}
if (aValue instanceof Integer)
{
return setIntegerProperty (sName, (Integer) aValue);
}
if (aValue instanceof Long)
{
return setLongProperty (sName, (Long) aValue);
}
if (aValue instanceof String)
{
return setStringProperty (sName, (String) aValue);
}
// Unknown type -> use type converter?
String sValue;
if (bUseTypeConverter)
{
sValue = TypeConverter.convertIfNecessary (aValue, String.class);
}
else
{
LOG.warn ("Setting property of type " + //$NON-NLS-1$
aValue.getClass ().getName () +
" as String without TypeConverter!"); //$NON-NLS-1$
sValue = String.valueOf (aValue);
}
return setStringProperty (sName, sValue);
}
@Override
@Nullable
public List extends IJSONPropertyValue >> getListValues (@Nullable final String sName)
{
final IJSONPropertyValue > aValue = getPropertyValueInternal (sName);
if (aValue instanceof IJSONPropertyValueList >)
{
return ((IJSONPropertyValueList >) aValue).getValues ();
}
return null;
}
@Override
@Nonnull
public JSONObject setObjectListProperty (@Nonnull final String sName,
@Nonnull final Iterable extends IJSONObject> aObjectList)
{
final IJSONPropertyValueList aList = new JSONPropertyValueList ();
for (final IJSONObject aObject : aObjectList)
{
aList.addValue (aObject);
}
setProperty (JSONProperty.create (sName, aList, ECloneStategy.INHERIT), ECloneStategy.AVOID);
return this;
}
@Override
@Nonnull
public List getObjectListProperty (@Nullable final String sName)
{
final List aReturn = new ArrayList <> ();
final List > aList = getListProperty (sName);
if (aList != null)
{
for (final Object aValue : aList)
{
if (aValue instanceof IJSONObject)
{
aReturn.add ((IJSONObject) aValue);
}
}
}
return aReturn;
}
@Override
@Nonnull
public JSONObject setStringListProperty (@Nonnull final String sName, @Nonnull final Iterable aStringList)
{
final IJSONPropertyValueList aList = new JSONPropertyValueList <> ();
for (final String sValue : aStringList)
{
aList.addValue (new JSONPropertyValueString (sValue));
}
return setProperty (JSONProperty.create (sName, aList, ECloneStategy.AVOID), ECloneStategy.AVOID);
}
@Override
@Nonnull
public JSONObject setMixedListProperty (@Nonnull final String sName, @Nonnull final Iterable > aValues)
{
final IJSONPropertyValueList > aList = new JSONPropertyValueList <> ();
for (final Object aValue : aValues)
{
aList.addValue (JSONUtil.getJSONValue (aValue));
}
return setProperty (JSONProperty.create (sName, aList, ECloneStategy.INHERIT), ECloneStategy.AVOID);
}
@Override
@Nonnull
public JSONObject setIntegerListProperty (@Nonnull final String sName, @Nonnull final int [] aIntList)
{
final IJSONPropertyValueList aList = new JSONPropertyValueList <> ();
for (final int nValue : aIntList)
{
aList.addValue (new JSONPropertyValueInteger (nValue));
}
return setProperty (JSONProperty.create (sName, aList, ECloneStategy.AVOID), ECloneStategy.AVOID);
}
@Override
public JSONObject setIntegerListProperty (@Nonnull final String sName, @Nonnull final List aIntegerList)
{
final IJSONPropertyValueList aList = new JSONPropertyValueList <> ();
for (final Integer nValue : aIntegerList)
{
aList.addValue (new JSONPropertyValueInteger (nValue));
}
return setProperty (JSONProperty.create (sName, aList, ECloneStategy.AVOID), ECloneStategy.AVOID);
}
@Override
@Deprecated
@Nonnull
public JSONObject setListOfListProperty (@Nonnull final String sName,
@Nonnull final Iterable extends Iterable > aListOfList)
{
return setListOfStringListProperty (sName, aListOfList);
}
@Override
@Nonnull
public JSONObject setListOfStringListProperty (@Nonnull final String sName,
@Nonnull final Iterable extends Iterable > aListOfList)
{
final JSONPropertyValueList > aList = new JSONPropertyValueList <> ();
for (final Iterable aRow : aListOfList)
{
final IJSONPropertyValueList aRowList = new JSONPropertyValueList <> ();
for (final String aCell : aRow)
{
aRowList.addValue (new JSONPropertyValueString (aCell));
}
aList.addValue (aRowList);
}
return setProperty (JSONProperty.create (sName, aList, ECloneStategy.AVOID), ECloneStategy.AVOID);
}
@Override
public JSONObject set (@Nonnull @Nonempty final String sName, @Nullable final String sValue)
{
return set (sName, sValue, true);
}
@Override
public JSONObject set (@Nonnull @Nonempty final String sName,
@Nullable final String sValue,
final boolean bEmitEmptyValue)
{
if (sValue != null && (bEmitEmptyValue || StringHelper.hasText (sValue)))
{
setStringProperty (sName, sValue);
}
return this;
}
@Override
public JSONObject set (@Nonnull @Nonempty final String sName, @Nullable final IJSONObject aValue)
{
return set (sName, aValue, true);
}
@Override
public JSONObject set (@Nonnull @Nonempty final String sName,
@Nullable final IJSONObject aValue,
final boolean bEmitEmptyValue)
{
if (aValue != null && (bEmitEmptyValue || !aValue.isEmpty ()))
{
setObjectProperty (sName, aValue);
}
return this;
}
@Override
public JSONObject set (@Nonnull @Nonempty final String sName, @Nullable final List aValue)
{
return set (sName, aValue, true);
}
@Override
public JSONObject set (@Nonnull @Nonempty final String sName,
@Nullable final List aValue,
final boolean bEmitEmptyValue)
{
if (aValue != null && (bEmitEmptyValue || !aValue.isEmpty ()))
{
setObjectListProperty (sName, aValue);
}
return this;
}
@Override
public JSONObject set (final @Nonnull @Nonempty String sName, final boolean bValue)
{
return setBooleanProperty (sName, bValue);
}
@Override
public JSONObject set (final @Nonnull @Nonempty String sName, final int nValue)
{
return setIntegerProperty (sName, nValue);
}
@Override
public JSONObject set (final @Nonnull @Nonempty String sName, final @Nullable Integer aValue)
{
if (aValue == null)
{
return this;
}
return setIntegerProperty (sName, aValue);
}
@Override
public void appendJSONString (@Nonnull final StringBuilder aResult, final boolean bAlignAndIndent, final int nLevel)
{
appendNewLine (aResult, bAlignAndIndent);
indent (aResult, nLevel, bAlignAndIndent);
aResult.append (CJSONConstants.OBJECT_START);
appendNewLine (aResult, bAlignAndIndent);
final Set aPropertyNames = getAllPropertyNames ();
int nIndex = 0;
for (final String sProperty : aPropertyNames)
{
final IJSONProperty > aProperty = getProperty (sProperty);
aProperty.appendJSONString (aResult, bAlignAndIndent, nLevel + 1);
if (nIndex < aPropertyNames.size () - 1)
{
aResult.append (CJSONConstants.TOKEN_SEPARATOR);
}
appendNewLine (aResult, bAlignAndIndent);
nIndex++;
}
indent (aResult, nLevel, bAlignAndIndent);
aResult.append (CJSONConstants.OBJECT_END);
}
@Override
@Nonnull
public EChange removeProperty (@Nullable final String sName)
{
final IJSONProperty > aRemoved = this.m_aProperties.remove (sName);
if (aRemoved == null)
{
return EChange.UNCHANGED;
}
if (!JSONSettings.getInstance ().isCloneProperties ())
{
final List aObjectsInValue = getObjectsInValue (aRemoved);
if (JSONSettings.getInstance ().isDetectCycles () && ContainerHelper.isNotEmpty (aObjectsInValue))
{
for (final JSONObject aChild : aObjectsInValue)
{
aChild.m_aParents.remove (this);
this.m_aChildren.remove (aChild);
}
}
}
return EChange.CHANGED;
}
@Override
public EChange apply (@Nullable final IJSONObject aObjectToApply)
{
EChange eChange = EChange.UNCHANGED;
if (aObjectToApply != null)
{
for (final String sPropName : aObjectToApply.getAllPropertyNames ())
{
setProperty (sPropName, aObjectToApply.getProperty (sPropName).getValue ());
eChange = EChange.CHANGED;
}
}
return eChange;
}
@Override
public EChange apply (@Nullable final IJSONObject aObjectToApply, @Nonnull @Nonempty final String sPropertyName)
{
EChange eChange = EChange.UNCHANGED;
if (aObjectToApply != null)
{
final IJSONProperty > aProperty = aObjectToApply.getProperty (sPropertyName);
if (aProperty != null)
{
this.setProperty (aProperty, ECloneStategy.FORCE);
eChange = EChange.CHANGED;
}
}
return eChange;
}
@Override
public boolean containsNotParsableProperty ()
{
for (final IJSONProperty > aProperty : this.m_aProperties.values ())
{
final IJSONPropertyValue > aValue = aProperty.getValue ();
if (aValue instanceof IJSONPropertyValueNotParsable >)
{
return true;
}
if (aValue instanceof IJSONObject && ((IJSONObject) aValue).containsNotParsableProperty ())
{
return true;
}
}
return false;
}
@Override
public boolean isEmpty ()
{
return this.m_aProperties.isEmpty ();
}
@Override
@Nonnegative
public int getPropertyCount ()
{
return this.m_aProperties.size ();
}
@Override
@Nonnull
public JSONObject getClone ()
{
return new JSONObject (this.m_aProperties.values (), ECloneStategy.FORCE);
}
@Override
public boolean equals (final Object aOther)
{
if (aOther == this)
{
return true;
}
if (!super.equals (aOther))
{
return false;
}
final JSONObject rhs = (JSONObject) aOther;
return EqualsUtils.equals (this.m_aProperties, rhs.m_aProperties);
}
@Override
public int hashCode ()
{
return HashCodeGenerator.getDerived (super.hashCode ()).append (this.m_aProperties).getHashCode ();
}
@Override
public String toString ()
{
return ToStringGenerator.getDerived (super.toString ()).append ("properties", this.m_aProperties).toString (); //$NON-NLS-1$
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy