001/*
002 * Copyright 2015-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2015-2024 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2015-2024 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.util.json;
037
038
039
040import java.io.Serializable;
041
042import com.unboundid.util.NotExtensible;
043import com.unboundid.util.NotNull;
044import com.unboundid.util.Nullable;
045import com.unboundid.util.ThreadSafety;
046import com.unboundid.util.ThreadSafetyLevel;
047
048
049
050/**
051 * This class provides the base class for data types that can be used as values
052 * in JSON objects and as elements in JSON arrays.  The types of values defined
053 * in the ECMA-404 specification are:
054 * <UL>
055 *   <LI>
056 *     The {@code null} value, as implemented in the {@link JSONNull} class.
057 *   </LI>
058 *   <LI>
059 *     The Boolean {@code true} and {@code false} values, as implemented in the
060 *     {@link JSONBoolean} class.
061 *   </LI>
062 *   <LI>
063 *     Numeric values, as implemented in the {@link JSONNumber} class.
064 *   </LI>
065 *   <LI>
066 *     String values, as implemented in the {@link JSONString} class.
067 *   </LI>
068 *   <LI>
069 *     Object values (consisting of zero or more name-value pairs), as
070 *     implemented in the {@link JSONObject} class.
071 *   </LI>
072 *   <LI>
073 *     Arrays of JSON values, as implemented in the {@link JSONArray} class.
074 *   </LI>
075 * </UL>
076 */
077@NotExtensible()
078@ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
079public abstract class JSONValue
080       implements Serializable, Comparable<JSONValue>
081{
082  /**
083   * A serial version UID for this serializable class.
084   */
085  private static final long serialVersionUID = -4446120225858980451L;
086
087
088
089  /**
090   * Retrieves a hash code for this JSON value.
091   *
092   * @return  The hash code for this JSON value.
093   */
094  public abstract int hashCode();
095
096
097
098  /**
099   * Indicates whether the provided object is equal to this JSON value.
100   *
101   * @param  o  The object to compare against this JSON value.
102   *
103   * @return  {@code true} if the provided object is considered equal to this
104   *          JSON value, or {@code false} if not.
105   */
106  public abstract boolean equals(@Nullable Object o);
107
108
109
110  /**
111   * Indicates whether this JSON value is considered equal to the provided JSON
112   * value, subject to the specified constraints.  Note that not all constraints
113   * will apply to all data types.
114   *
115   * @param  v                    The JSON value for which to make the
116   *                              determination.  It must not be {@code null}.
117   * @param  ignoreFieldNameCase  Indicates whether to ignore differences in the
118   *                              capitalization of JSON field names.
119   * @param  ignoreValueCase      Indicates whether to ignore differences in
120   *                              the capitalization of JSON values that
121   *                              represent strings.
122   * @param  ignoreArrayOrder     Indicates whether to ignore differences in the
123   *                              order of elements in JSON arrays.
124   *
125   * @return  {@code true} if this JSON value is considered equal to the
126   *          provided JSON value (subject to the specified constraints), or
127   *          {@code false} if not.
128   */
129  public abstract boolean equals(@NotNull JSONValue v,
130                                 boolean ignoreFieldNameCase,
131                                 boolean ignoreValueCase,
132                                 boolean ignoreArrayOrder);
133
134
135
136  /**
137   * Retrieves a string representation of this value as it should appear in a
138   * JSON object, including any necessary quoting, escaping, etc.  If the object
139   * containing this value was decoded from a string, then this method will use
140   * the same string representation as in that original object.  Otherwise, the
141   * string representation will be constructed.
142   *
143   * @return  A string representation of this value as it should appear in a
144   *          JSON object.
145   */
146  @NotNull()
147  public abstract String toString();
148
149
150
151  /**
152   * Appends a string representation of this value (as it should appear in a
153   * JSON object, including any necessary quoting, escaping, etc.) to the
154   * provided buffer.  If the object containing this value was decoded from a
155   * string, then this method will use the same string representation as in that
156   * original object.  Otherwise, the string representation will be constructed.
157   *
158   * @param  buffer  The buffer to which the information should be appended.
159   */
160  public abstract void toString(@NotNull StringBuilder buffer);
161
162
163
164  /**
165   * Retrieves a single-line string representation of this value as it should
166   * appear in a JSON object, including any necessary quoting, escaping, etc.
167   *
168   * @return  A string representation of this value as it should appear in a
169   *          JSON object.
170   */
171  @NotNull()
172  public abstract String toSingleLineString();
173
174
175
176  /**
177   * Appends a single-line string representation of this value (as it should
178   * appear in a JSON object, including any necessary quoting, escaping, etc.)
179   * to the provided buffer.
180   *
181   * @param  buffer  The buffer to which the information should be appended.
182   */
183  public abstract void toSingleLineString(@NotNull StringBuilder buffer);
184
185
186
187  /**
188   * Retrieves a normalized string representation of this value.  All equivalent
189   * JSON values must have equivalent normalized representations, even if there
190   * are other legal representations for the value.
191   *
192   * @return  A normalized string representation of this value.
193   */
194  @NotNull()
195  public abstract String toNormalizedString();
196
197
198
199  /**
200   * Appends a normalized string representation of this value to the provided
201   * buffer.  All equivalent JSON values must have equivalent normalized
202   * representations, even if there are other legal representations for the
203   * value.
204   *
205   * @param  buffer  The buffer to which the information should be appended.
206   */
207  public abstract void toNormalizedString(@NotNull StringBuilder buffer);
208
209
210
211  /**
212   * Retrieves a normalized string representation of this value using the
213   * provided settings.
214   *
215   * @param  ignoreFieldNameCase  Indicates whether field names should be
216   *                              treated in a case-sensitive (if {@code false})
217   *                              or case-insensitive (if {@code true}) manner.
218   * @param  ignoreValueCase      Indicates whether string field values should
219   *                              be treated in a case-sensitive (if
220   *                              {@code false}) or case-insensitive (if
221   *                              {@code true}) manner.
222   * @param  ignoreArrayOrder     Indicates whether the order of elements in an
223   *                              array should be considered significant (if
224   *                              {@code false}) or insignificant (if
225   *                              {@code true}).
226   *
227   * @return  A normalized string representation of this value.
228   */
229  @NotNull()
230  public abstract String toNormalizedString(boolean ignoreFieldNameCase,
231                                            boolean ignoreValueCase,
232                                            boolean ignoreArrayOrder);
233
234
235
236  /**
237   * Appends a normalized string representation of this value to the provided
238   * buffer using the provided settings.
239   *
240   * @param  buffer               The buffer to which the information should be
241   *                              appended.
242   * @param  ignoreFieldNameCase  Indicates whether field names should be
243   *                              treated in a case-sensitive (if {@code false})
244   *                              or case-insensitive (if {@code true}) manner.
245   * @param  ignoreValueCase      Indicates whether string field values should
246   *                              be treated in a case-sensitive (if
247   *                              {@code false}) or case-insensitive (if
248   *                              {@code true}) manner.
249   * @param  ignoreArrayOrder     Indicates whether the order of elements in an
250   *                              array should be considered significant (if
251   *                              {@code false}) or insignificant (if
252   *                              {@code true}).
253   */
254  public abstract void toNormalizedString(@NotNull StringBuilder buffer,
255                                          boolean ignoreFieldNameCase,
256                                          boolean ignoreValueCase,
257                                          boolean ignoreArrayOrder);
258
259
260
261  /**
262   * Retrieves a normalized representation of this value using the provided
263   * settings.
264   *
265   * @param  ignoreFieldNameCase  Indicates whether field names should be
266   *                              treated in a case-sensitive (if {@code false})
267   *                              or case-insensitive (if {@code true}) manner.
268   * @param  ignoreValueCase      Indicates whether string field values should
269   *                              be treated in a case-sensitive (if
270   *                              {@code false}) or case-insensitive (if
271   *                              {@code true}) manner.
272   * @param  ignoreArrayOrder     Indicates whether the order of elements in an
273   *                              array should be considered significant (if
274   *                              {@code false}) or insignificant (if
275   *                              {@code true}).
276   *
277   * @return  A normalized representation of this value using the provided
278   *          settings.
279   */
280  @NotNull()
281  public abstract JSONValue toNormalizedValue(boolean ignoreFieldNameCase,
282                                              boolean ignoreValueCase,
283                                              boolean ignoreArrayOrder);
284
285
286
287  /**
288   * Appends this value to the provided JSON buffer.  This will not include a
289   * field name, so it should only be used for Boolean value elements in an
290   * array.
291   *
292   * @param  buffer  The JSON buffer to which this value should be appended.
293   */
294  public abstract void appendToJSONBuffer(@NotNull JSONBuffer buffer);
295
296
297
298  /**
299   * Appends a field with the given name and this value to the provided JSON
300   * buffer.
301   *
302   * @param  fieldName  The name to use for the field.
303   * @param  buffer     The JSON buffer to which this value should be appended.
304   */
305  public abstract void appendToJSONBuffer(@NotNull String fieldName,
306                                          @NotNull JSONBuffer buffer);
307
308
309
310  /**
311   * Compares the provided value to this value to determine their relative order
312   * in a sorted list.  The comparison will be based purely on a lexicographic
313   * comparison of the normalized representations of the values.
314   *
315   * @param  value  The value to compare to this value.  It must not be
316   *                 {@code null}.
317   *
318   * @return  A negative integer if this value should come before the provided
319   *          value in a sorted list, a positive integer if this value should
320   *          come after the provided value in a sorted list, or zero if the
321   *          provided value can be considered equal to this value.
322   */
323  @Override()
324  public final int compareTo(@NotNull final JSONValue value)
325  {
326    final String thisNormalizedRepresentation =
327         toNormalizedString(false, true, false);
328    final String providedNormalizedRepresentation =
329         value.toNormalizedString(false, true, false);
330    return thisNormalizedRepresentation.compareTo(
331         providedNormalizedRepresentation);
332  }
333}