001/*
002 * ============================================================================
003 *  Copyright © 2002-2026 by Thomas Thrien.
004 *  All Rights Reserved.
005 * ============================================================================
006 *  Licensed to the public under the agreements of the GNU Lesser General Public
007 *  License, version 3.0 (the "License"). You may obtain a copy of the License at
008 *
009 *       http://www.gnu.org/licenses/lgpl.html
010 *
011 *  Unless required by applicable law or agreed to in writing, software
012 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014 *  License for the specific language governing permissions and limitations
015 *  under the License.
016 */
017
018package org.tquadrat.foundation.jsonbuilder;
019
020import static org.apiguardian.api.API.Status.STABLE;
021import static org.tquadrat.foundation.jsonbuilder.JSONLiteral.FALSE;
022import static org.tquadrat.foundation.jsonbuilder.JSONLiteral.NULL;
023import static org.tquadrat.foundation.jsonbuilder.JSONLiteral.TRUE;
024import static org.tquadrat.foundation.lang.Objects.mapFromNull;
025import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument;
026
027import java.math.BigDecimal;
028import java.math.BigInteger;
029import java.util.Collection;
030import java.util.Formatter;
031import java.util.function.Function;
032import java.util.function.Supplier;
033
034import org.apiguardian.api.API;
035import org.tquadrat.foundation.annotation.ClassVersion;
036import org.tquadrat.foundation.jsonbuilder.internal.JSONArrayImpl;
037import org.tquadrat.foundation.jsonbuilder.internal.JSONBuilderImpl;
038import org.tquadrat.foundation.jsonbuilder.internal.JSONObjectImpl;
039import org.tquadrat.foundation.lang.value.Dimension;
040import org.tquadrat.foundation.lang.value.DimensionedValue;
041
042/**
043 *  <p>{@summary This sealed interface is the main API for the Foundation JSON
044 *  Builder Library.}</p>
045 *  <p>{@link #getInstance()} returns an instance of an implementation for the
046 *  interface.</p>
047 *  <p>Basically, the instances of {@code JSONBuilder} are stateless, and
048 *  therefore they can be treated as thread-safe. Only the
049 *  {@linkplain #getIndentation() indentation}
050 *  that is used for pretty-printing the resulting JSON values may cause issues
051 *  when different threads are using different values.</p>
052 *  <p>The different implementations of
053 *  {@link JSONValue}
054 *  – particularly
055 *  {@link JSONObject}
056 *  and
057 *  {@link JSONArray}
058 *  are <i>not</i> thread-safe.</p>
059 *
060 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
061 *  @version $Id: JSONBuilder.java 1258 2026-06-04 18:33:06Z tquadrat $
062 *  @since 0.25.0
063 *
064 *  @UMLGraph.link
065 */
066@ClassVersion( sourceVersion = "$Id: JSONBuilder.java 1258 2026-06-04 18:33:06Z tquadrat $" )
067@API( status = STABLE, since = "0.25.0" )
068public sealed interface JSONBuilder
069    permits JSONBuilderImpl
070{
071        /*-----------*\
072    ====** Constants **========================================================
073        \*-----------*/
074    /**
075     *  The indentation that is used when a
076     *  {@link JSONValue}
077     *  is formatted: {@value}.
078     *
079     *  @see JSONValue#formatTo(Formatter,int,int,int)
080     */
081    public static final int DEFAULT_INDENTATION = 2;
082
083    /**
084     *  The name of the JSON String that holds the unit for the dimension from
085     *  a
086     *  {@link DimensionedValue}:
087     *  {@value}.
088     *
089     *  @see #valueOf(DimensionedValue,Dimension)
090     */
091    public static final String JSONField_Unit = "Unit";
092
093    /**
094     *  The name of the JSON Number that holds the value from a
095     *  {@link DimensionedValue}:
096     *  {@value}.
097     *
098     *  @see #valueOf(DimensionedValue,Dimension)
099     */
100    public static final String JSONField_Value = "Value";
101
102        /*---------*\
103    ====** Methods **==========================================================
104        \*---------*/
105    /**
106     *  <p>{@summary Returns a deep copy of the given JSON array.}</p>
107     *
108     *  @param  source  The array to copy.
109     *  @return The deep copy.
110     */
111    public default JSONArray copyArray( final JSONArray source )
112    {
113        final var retValue = new JSONArrayImpl( (JSONArrayImpl) requireNonNullArgument( source, "source" ) );
114
115        //---* Done *----------------------------------------------------------
116        return retValue;
117    }   //  copyArray()
118
119    /**
120     *  <p>{@summary Returns a deep copy of the given JSON object.}</p>
121     *
122     *  @param  source  The object to copy.
123     *  @return The deep copy.
124     */
125    public default JSONObject copyObject( final JSONObject source )
126    {
127        final var retValue = new JSONObjectImpl( (JSONObjectImpl) requireNonNullArgument( source, "source" ) );
128
129        //---* Done *----------------------------------------------------------
130        return retValue;
131    }   //  copyObject()
132
133    /**
134     *  <p>{@summary Returns a new empty instance of
135     *  {@link JSONArray}.}</p>
136     *
137     *  @return The new array.
138     */
139    public JSONArray createArray();
140
141    /**
142     *  <p>{@summary Returns a new instance of
143     *  {@link JSONArray}
144     *  with the given number of elements, all set to
145     *  {@link JSONLiteral#NULL}.}</p>
146     *
147     *  @param  elementCount    The number of elements for the new array.
148     *  @return The new array.
149     */
150    public default JSONArray createArray( final int elementCount )
151    {
152        final var retValue = createArray();
153        for( var i = 0; i < elementCount; ++i ) retValue.add( NULL );
154
155        //---* Done *----------------------------------------------------------
156        return retValue;
157    }   //  createArray()
158
159    /**
160     *  <p>{@summary Returns a new instance of
161     *  {@link JSONArray}
162     *  that is populated with the values from the given array.}</p>
163     *
164     *  @param  values  The values.
165     *  @return The new array.
166     */
167    public default JSONArray createArray( final BigDecimal [] values )
168    {
169        final var retValue = createArray();
170        for( final var value : requireNonNullArgument( values, "values" ) )
171        {
172            retValue.add( mapFromNull( valueOf( value ), NULL ) );
173        }
174
175        //---* Done *----------------------------------------------------------
176        return retValue;
177    }   //  createArray()
178
179    /**
180     *  <p>{@summary Returns a new instance of
181     *  {@link JSONArray}
182     *  that is populated with the values from the given array.}</p>
183     *
184     *  @param  values  The values.
185     *  @return The new array.
186     */
187    public default JSONArray createArray( final BigInteger [] values )
188    {
189        final var retValue = createArray();
190        for( final var value : requireNonNullArgument( values, "values" ) )
191        {
192            retValue.add( mapFromNull( valueOf( value ), NULL ) );
193        }
194
195        //---* Done *----------------------------------------------------------
196        return retValue;
197    }   //  createArray()
198
199    /**
200     *  <p>{@summary Returns a new instance of
201     *  {@link JSONArray}
202     *  that is populated with the values from the given array.}</p>
203     *
204     *  @param  values  The values.
205     *  @return The new array.
206     */
207    public default JSONArray createArray( final double [] values )
208    {
209        final var retValue = createArray();
210        for( final var value : requireNonNullArgument( values, "values" ) )
211        {
212            retValue.add( valueOf( value ) );
213        }
214
215        //---* Done *----------------------------------------------------------
216        return retValue;
217    }   //  createArray()
218
219    /**
220     *  <p>{@summary Returns a new instance of
221     *  {@link JSONArray}
222     *  that is populated with the values from the given array.}</p>
223     *
224     *  @param  values  The values.
225     *  @return The new array.
226     */
227    public default JSONArray createArray( final Double [] values )
228    {
229        final var retValue = createArray();
230        for( final var value : requireNonNullArgument( values, "values" ) )
231        {
232            retValue.add( mapFromNull( valueOf( value ), NULL ) );
233        }
234
235        //---* Done *----------------------------------------------------------
236        return retValue;
237    }   //  createArray()
238
239    /**
240     *  <p>{@summary Returns a new instance of
241     *  {@link JSONArray}
242     *  that is populated with the values from the given array.}</p>
243     *
244     *  @param  values  The values.
245     *  @return The new array.
246     */
247    public default JSONArray createArray( final float [] values )
248    {
249        final var retValue = createArray();
250        for( final var value : requireNonNullArgument( values, "values" ) )
251        {
252            retValue.add( valueOf( value ) );
253        }
254
255        //---* Done *----------------------------------------------------------
256        return retValue;
257    }   //  createArray()
258
259    /**
260     *  <p>{@summary Returns a new instance of
261     *  {@link JSONArray}
262     *  that is populated with the values from the given array.}</p>
263     *
264     *  @param  values  The values.
265     *  @return The new array.
266     */
267    public default JSONArray createArray( final Float [] values )
268    {
269        final var retValue = createArray();
270        for( final var value : requireNonNullArgument( values, "values" ) )
271        {
272            retValue.add( mapFromNull( valueOf( value ), NULL ) );
273        }
274
275        //---* Done *----------------------------------------------------------
276        return retValue;
277    }   //  createArray()
278
279    /**
280     *  <p>{@summary Returns a new instance of
281     *  {@link JSONArray}
282     *  that is populated with the values from the given array.}</p>
283     *
284     *  @param  values  The values.
285     *  @return The new array.
286     */
287    public default JSONArray createArray( final int [] values )
288    {
289        final var retValue = createArray();
290        for( final var value : requireNonNullArgument( values, "values" ) )
291        {
292            retValue.add( valueOf( value ) );
293        }
294
295        //---* Done *----------------------------------------------------------
296        return retValue;
297    }   //  createArray()
298
299    /**
300     *  <p>{@summary Returns a new instance of
301     *  {@link JSONArray}
302     *  that is populated with the values from the given array.}</p>
303     *
304     *  @param  values  The values.
305     *  @return The new array.
306     */
307    public default JSONArray createArray( final Integer [] values )
308    {
309        final var retValue = createArray();
310        for( final var value : requireNonNullArgument( values, "values" ) )
311        {
312            retValue.add( mapFromNull( valueOf( value ), NULL ) );
313        }
314
315        //---* Done *----------------------------------------------------------
316        return retValue;
317    }   //  createArray()
318
319    /**
320     *  <p>{@summary Returns a new instance of
321     *  {@link JSONArray}
322     *  that is populated with the values from the given array.}</p>
323     *
324     *  @param  values  The values.
325     *  @return The new array.
326     */
327    public default JSONArray createArray( final JSONValue [] values )
328    {
329        final var retValue = createArray();
330        for( final var value : requireNonNullArgument( values, "values" ) )
331        {
332            retValue.add( mapFromNull( value, NULL ) );
333        }
334
335        //---* Done *----------------------------------------------------------
336        return retValue;
337    }   //  createArray()
338
339    /**
340     *  <p>{@summary Returns a new instance of
341     *  {@link JSONArray}
342     *  that is populated with the values from the given array.}</p>
343     *
344     *  @param  values  The values.
345     *  @return The new array.
346     */
347    public default JSONArray createArray( final long [] values )
348    {
349        final var retValue = createArray();
350        for( final var value : requireNonNullArgument( values, "values" ) )
351        {
352            retValue.add( valueOf( value ) );
353        }
354
355        //---* Done *----------------------------------------------------------
356        return retValue;
357    }   //  createArray()
358
359    /**
360     *  <p>{@summary Returns a new instance of
361     *  {@link JSONArray}
362     *  that is populated with the values from the given array.}</p>
363     *
364     *  @param  values  The values.
365     *  @return The new array.
366     */
367    public default JSONArray createArray( final Long [] values )
368    {
369        final var retValue = createArray();
370        for( final var value : requireNonNullArgument( values, "values" ) )
371        {
372            retValue.add( mapFromNull( valueOf( value ), NULL ) );
373        }
374
375        //---* Done *----------------------------------------------------------
376        return retValue;
377    }   //  createArray()
378
379    /**
380     *  <p>{@summary Returns a new instance of
381     *  {@link JSONArray}
382     *  that is populated with the return value from the given
383     *  {@link Supplier Supplier&lt;JSONValue []&gt;}.}</p>
384     *
385     *  @param  supplier    The supplier for the array.
386     *  @return The new array.
387     */
388    public default JSONArray createArray( final Supplier<JSONValue []> supplier )
389    {
390        final var retValue = createArray();
391        for( final var value : requireNonNullArgument( supplier, "supplier" ).get() )
392        {
393            retValue.add( mapFromNull( value, NULL ) );
394        }
395
396        //---* Done *----------------------------------------------------------
397        return retValue;
398    }   //  createArray()
399
400    /**
401     *  <p>{@summary Returns a new instance of
402     *  {@link JSONArray}
403     *  that is populated with the values from the given array.}</p>
404     *
405     *  @param  values  The values.
406     *  @return The new array.
407     */
408    public default JSONArray createArray( final String... values )
409    {
410        final var retValue = createArray();
411        for( final var value : requireNonNullArgument( values, "values" ) )
412        {
413            retValue.add( mapFromNull( valueOf( value ), NULL ) );
414        }
415
416        //---* Done *----------------------------------------------------------
417        return retValue;
418    }   //  createArray()
419
420    /**
421     *  <p>{@summary Returns a new empty instance of
422     *  {@link JSONObject}.}</p>
423     *
424     *  @return The new object.
425     */
426    public JSONObject createObject();
427
428    /**
429     *  <p>{@summary Returns a new instance of
430     *  {@link JSONObject}
431     *  that is populated with the values returned by the given
432     *  {@link Function}.}</p>
433     *  <p>The function's argument is the name of the new member, provided by
434     *  the {@code names} argument to this method.</p>
435     *
436     *  @param  names   The member names for the new object.
437     *  @param  provider    The function that returns the value for the member
438     *      with the given name.
439     *  @return The new object.
440     */
441    public default JSONObject createObject( final Collection<String> names, final Function<String,JSONValue> provider )
442    {
443        requireNonNullArgument( provider, "provider" );
444        final var retValue = createObject();
445        for( final var name : requireNonNullArgument( names, "names" ) )
446        {
447            retValue.set( name, provider.apply( name ) );
448        }
449
450        //---* Done *----------------------------------------------------------
451        return retValue;
452    }   //  createObject()
453
454    /**
455     *  <p>{@summary Returns the indentation that is used when a
456     *  {@link JSONValue}
457     *  is formatted.} If not set explicitly through a call to
458     *  {@link #setIndentation(int)},
459     *  the default value
460     *  ({@value DEFAULT_INDENTATION})
461     *  will be returned.</p>
462     *
463     *  @return The indentation.
464     *
465     *  @see #DEFAULT_INDENTATION
466     *  @see JSONValue#formatTo(Formatter,int,int,int)
467     */
468    public int getIndentation();
469
470    /**
471     *  <p>{@summary Sets the indentation that is used when a
472     *  {@link JSONValue}
473      *  is formatted for pretty-printing.}
474     *
475     *  @param  value   The indentation.
476     *
477     *  @see JSONValue#formatTo(Formatter,int,int,int)
478     */
479    public void setIndentation( final int value );
480
481    /**
482     *  <p>{@summary Creates an instance of {@code JSONBuilder}.}</p>
483     *  <p>Each call to this method will return a new instance of
484     *  {@code JSONBuilder}.</p>
485     *
486     *  @return A new instance of {@code JSONBuilder}.
487     */
488    public static JSONBuilder getInstance() { return new JSONBuilderImpl(); }
489
490    /**
491     *  Returns a
492     *  {@link JSONValue}
493     *  instance that represents the given
494     *  {@link BigDecimal}
495     *  value.
496     *
497     *  @param  value   The value.
498     *  @return The JSON value that represents the given value.
499     */
500    public JSONNumber valueOf( final BigDecimal value );
501
502    /**
503     *  Returns a
504     *  {@link JSONValue}
505     *  instance that represents the given
506     *  {@link BigInteger}
507     *  value.
508     *
509     *  @param  value   The value
510     *  @return The JSON value that represents the given value.
511     */
512    public JSONNumber valueOf( final BigInteger value );
513
514    /**
515     *  Returns a
516     *  {@link JSONValue}
517     *  instance that represents the given {@code boolean} value.
518     *
519     *  @param  value   The value
520     *  @return The JSON value that represents the given value.
521     */
522    public default JSONLiteral valueOf( final boolean value )
523    {
524        final var retValue = value ? TRUE : FALSE;
525
526        //---* Done *----------------------------------------------------------
527        return retValue;
528    }   //  valueOf()
529
530    /**
531     *  <p>{@summary Returns a
532     *  {@link JSONValue}
533     *  instance (more precisely, an instance of
534     *  {@link JSONObject})
535     *  that represents the given
536     *  {@link DimensionedValue}
537     *  instance.}</p>
538     *  <p>The member names are
539     *  {@value #JSONField_Unit}
540     *  for the dimension, and
541     *  {@value #JSONField_Value}
542     *  for the numerical value.</p>
543     *
544     *  @param  <T> The type of the dimension for the value.
545     *  @param  value   The value.
546     *  @param  targetUnit  The dimension for the output.
547     *  @return The resulting JSON object.
548     */
549    public default <T extends Dimension> JSONObject valueOf( final DimensionedValue<T> value, final T targetUnit )
550    {
551        final var retValue = createObject();
552        retValue.set( JSONField_Unit, requireNonNullArgument( targetUnit, "targetUnit" ).unitSymbolForPrinting() );
553        retValue.set( JSONField_Value, requireNonNullArgument( value, "value" ).convert( targetUnit ) );
554
555        //---* Done *----------------------------------------------------------
556        return retValue;
557    }   //  valueOf()
558
559    /**
560     *  Returns a
561     *  {@link JSONValue}
562     *  instance that represents the given {@code double} value.
563     *
564     *  @param  value   The value
565     *  @return The JSON value that represents the given value.
566     */
567    public JSONNumber valueOf( final double value );
568
569    /**
570     *  Returns a
571     *  {@link JSONValue}
572     *  instance that represents the given
573     *  {@link Double}
574     *  value.
575     *
576     *  @param  value   The value
577     *  @return The JSON value that represents the given value.
578     */
579    public JSONNumber valueOf( final Double value );
580
581    /**
582     *  Returns a
583     *  {@link JSONValue}
584     *  instance that represents the given {@code float} value.
585     *
586     *  @param  value   The value
587     *  @return The JSON value that represents the given value.
588     */
589    public JSONNumber valueOf( final float value );
590
591    /**
592     *  Returns a
593     *  {@link JSONValue}
594     *  instance that represents the given
595     *  {@link Float}
596     *  value.
597     *
598     *  @param  value   The value
599     *  @return The JSON value that represents the given value.
600     */
601    public JSONNumber valueOf( final Float value );
602
603    /**
604     *  Returns a
605     *  {@link JSONValue}
606     *  instance that represents the given {@code int} value.
607     *
608     *  @param  value   The value
609     *  @return The JSON value that represents the given value.
610     */
611    public JSONNumber valueOf( final int value );
612
613    /**
614     *  Returns a
615     *  {@link JSONValue}
616     *  instance that represents the given
617     *  {@link Integer}
618     *  value.
619     *
620     *  @param  value   The value
621     *  @return The JSON value that represents the given value.
622     */
623    public JSONNumber valueOf( final Integer value );
624
625    /**
626     *  Returns a
627     *  {@link JSONValue}
628     *  instance that represents the given {@code long} value.
629     *
630     *  @param  value   The value
631     *  @return The JSON value that represents the given value.
632     */
633    public JSONNumber valueOf( final long value );
634
635    /**
636     *  Returns a
637     *  {@link JSONValue}
638     *  instance that represents the given
639     *  {@link Long}
640     *  value.
641     *
642     *  @param  value   The value
643     *  @return The JSON value that represents the given value.
644     */
645    public JSONNumber valueOf( final Long value );
646
647    /**
648     *  Returns a
649     *  {@link JSONValue}
650     *  instance that represents the given
651     *  {@link String}
652     *  value.
653     *
654     *  @param  value   The value
655     *  @return The JSON value that represents the given value.
656     */
657    public JSONString valueOf( final String value );
658
659    /**
660     *  Returns a
661     *  {@link JSONValue}
662     *  instance that represents the {@null} value.
663     *
664     *  @return The JSON value that represents {@null}.
665     */
666    public default JSONLiteral valueOfNull() { return NULL; }
667}
668//  interface JSONBuilder
669
670/*
671 *  End of File
672 */