001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.parser;
014
015import static org.apache.juneau.internal.CollectionUtils.*;
016import static org.apache.juneau.parser.InputStreamParser.*;
017import static org.apache.juneau.parser.ReaderParser.*;
018
019import java.util.*;
020
021import org.apache.juneau.*;
022import org.apache.juneau.http.*;
023import org.apache.juneau.internal.*;
024
025/**
026 * Builder class for creating instances of {@link ParserGroup}.
027 */
028public class ParserGroupBuilder extends BeanContextBuilder {
029
030   private final List<Object> parsers;
031
032   /**
033    * Create an empty parser group builder.
034    */
035   public ParserGroupBuilder() {
036      this.parsers = new ArrayList<>();
037   }
038
039   /**
040    * Clone an existing parser group builder.
041    *
042    * @param copyFrom The parser group that we're copying settings and parsers from.
043    */
044   public ParserGroupBuilder(ParserGroup copyFrom) {
045      super(copyFrom.getPropertyStore());
046      this.parsers = new ArrayList<>();
047      addReverse(parsers, copyFrom.getParsers());
048   }
049
050   /**
051    * Registers the specified parsers with this group.
052    *
053    * @param p The parsers to append to this group.
054    * @return This object (for method chaining).
055    */
056   public ParserGroupBuilder append(Class<?>...p) {
057      addReverse(parsers, p);
058      return this;
059   }
060
061   /**
062    * Registers the specified parsers with this group.
063    *
064    * <p>
065    * When passing in pre-instantiated parsers to this group, applying properties and transforms to the group
066    * do not affect them.
067    *
068    * @param p The parsers to append to this group.
069    * @return This object (for method chaining).
070    */
071   public ParserGroupBuilder append(Parser...p) {
072      addReverse(parsers, p);
073      return this;
074   }
075
076   /**
077    * Registers the specified parsers with this group.
078    *
079    * <p>
080    * Objects can either be instances of parsers or parser classes.
081    *
082    * @param p The parsers to append to this group.
083    * @return This object (for method chaining).
084    */
085   public ParserGroupBuilder append(List<Object> p) {
086      addReverse(parsers, p);
087      return this;
088   }
089
090   /**
091    * Registers the specified parsers with this group.
092    *
093    * <p>
094    * Objects can either be instances of parsers or parser classes.
095    *
096    * @param p The parsers to append to this group.
097    * @return This object (for method chaining).
098    */
099   public ParserGroupBuilder append(Object...p) {
100      addReverse(parsers, p);
101      return this;
102   }
103
104   /**
105    * Creates a new {@link ParserGroup} object using a snapshot of the settings defined in this builder.
106    *
107    * <p>
108    * This method can be called multiple times to produce multiple parser groups.
109    *
110    * @return A new {@link ParserGroup} object.
111    */
112   @Override /* Context */
113   @SuppressWarnings("unchecked")
114   public ParserGroup build() {
115      List<Parser> l = new ArrayList<>();
116      for (Object p : parsers) {
117         Class<? extends Parser> c = null;
118         PropertyStore ps = getPropertyStore();
119         if (p instanceof Class) {
120            c = (Class<? extends Parser>)p;
121            l.add(ContextCache.INSTANCE.create(c, ps));
122         } else {
123            l.add((Parser)p);
124         }
125      }
126      return new ParserGroup(getPropertyStore(), ArrayUtils.toReverseArray(Parser.class, l));
127   }
128
129
130   //-----------------------------------------------------------------------------------------------------------------
131   // Properties
132   //-----------------------------------------------------------------------------------------------------------------
133
134   /**
135    * Configuration property:  Auto-close streams.
136    *
137    * <p>
138    * If <jk>true</jk>, <l>InputStreams</l> and <l>Readers</l> passed into parsers will be closed
139    * after parsing is complete.
140    *
141    * <h5 class='section'>See Also:</h5>
142    * <ul>
143    *    <li class='jf'>{@link Parser#PARSER_autoCloseStreams}
144    * </ul>
145    *
146    * @param value
147    *    The new value for this property.
148    *    <br>The default value is <jk>false</jk>.
149    * @return This object (for method chaining).
150    */
151   public ParserGroupBuilder autoCloseStreams(boolean value) {
152      return set(PARSER_autoCloseStreams, value);
153   }
154
155   /**
156    * Configuration property:  Auto-close streams.
157    * <p>
158    * Shortcut for calling <code>autoCloseStreams(<jk>true</jk>)</code>.
159    *
160    * <h5 class='section'>See Also:</h5>
161    * <ul>
162    *    <li class='jf'>{@link Parser#PARSER_autoCloseStreams}
163    * </ul>
164    *
165    * @return This object (for method chaining).
166    */
167   public ParserGroupBuilder autoCloseStreams() {
168      return set(PARSER_autoCloseStreams, true);
169   }
170
171   /**
172    * Configuration property:  Debug output lines.
173    *
174    * When parse errors occur, this specifies the number of lines of input before and after the
175    * error location to be printed as part of the exception message.
176    *
177    * <h5 class='section'>See Also:</h5>
178    * <ul>
179    *    <li class='jf'>{@link Parser#PARSER_debugOutputLines}
180    * </ul>
181    *
182    * @param value
183    *    The new value for this property.
184    *    <br>The default value is <code>5</code>.
185    * @return This object (for method chaining).
186    */
187   public ParserGroupBuilder debugOutputLines(int value) {
188      set(PARSER_debugOutputLines, value);
189      return this;
190   }
191
192   /**
193    * Configuration property:  Parser listener.
194    *
195    * <p>
196    * Class used to listen for errors and warnings that occur during parsing.
197    *
198    * <h5 class='section'>See Also:</h5>
199    * <ul>
200    *    <li class='jf'>{@link Parser#PARSER_listener}
201    * </ul>
202    *
203    * @param value The new value for this property.
204    * @return This object (for method chaining).
205    */
206   public ParserGroupBuilder listener(Class<? extends ParserListener> value) {
207      return set(PARSER_listener, value);
208   }
209
210   /**
211    * Configuration property:  Strict mode.
212    *
213    * <p>
214    * If <jk>true</jk>, strict mode for the parsers are enabled.
215    *
216    * <h5 class='section'>See Also:</h5>
217    * <ul>
218    *    <li class='jf'>{@link Parser#PARSER_strict}
219    * </ul>
220    *
221    * @param value
222    *    The new value for this property.
223    *    <br>The default value is <jk>false</jk>.
224    * @return This object (for method chaining).
225    */
226   public ParserGroupBuilder strict(boolean value) {
227      return set(PARSER_strict, value);
228   }
229
230   /**
231    * Configuration property:  Strict mode.
232    *
233    * <p>
234    * Shortcut for calling <code>strict(<jk>true</jk>)</code>.
235    *
236    * <h5 class='section'>See Also:</h5>
237    * <ul>
238    *    <li class='jf'>{@link Parser#PARSER_strict}
239    * </ul>
240    *
241    * @return This object (for method chaining).
242    */
243   public ParserGroupBuilder strict() {
244      return set(PARSER_strict, true);
245   }
246
247   /**
248    * Configuration property:  Trim parsed strings.
249    *
250    * <p>
251    * If <jk>true</jk>, string values will be trimmed of whitespace using {@link String#trim()} before being added to
252    * the POJO.
253    *
254    * <h5 class='section'>See Also:</h5>
255    * <ul>
256    *    <li class='jf'>{@link Parser#PARSER_trimStrings}
257    * </ul>
258    *
259    * @param value
260    *    The new value for this property.
261    *    <br>The default value is <jk>false</jk>.
262    * @return This object (for method chaining).
263    */
264   public ParserGroupBuilder trimStrings(boolean value) {
265      return set(PARSER_trimStrings, value);
266   }
267
268   /**
269    * Configuration property:  Trim parsed strings.
270    *
271    * <p>
272    * Shortcut for calling <code>trimStrings(<jk>true</jk>)</code>.
273    *
274    * <h5 class='section'>See Also:</h5>
275    * <ul>
276    *    <li class='jf'>{@link Parser#PARSER_trimStrings}
277    * </ul>
278    *
279    * @return This object (for method chaining).
280    */
281   public ParserGroupBuilder trimStrings() {
282      return set(PARSER_trimStrings, true);
283   }
284
285   /**
286    * Configuration property:  Unbuffered.
287    *
288    * <p>
289    * If <jk>true</jk>, don't use internal buffering during parsing.
290    *
291    * <h5 class='section'>See Also:</h5>
292    * <ul>
293    *    <li class='jf'>{@link Parser#PARSER_unbuffered}
294    * </ul>
295    *
296    * @param value
297    *    The new value for this property.
298    *    <br>The default value is <jk>false</jk>.
299    * @return This object (for method chaining).
300    */
301   public ParserGroupBuilder unbuffered(boolean value) {
302      return set(PARSER_unbuffered, value);
303   }
304
305   /**
306    * Configuration property:  Unbuffered.
307    *
308    * <p>
309    * Shortcut for calling <code>unbuffered(<jk>true</jk>)</code>.
310    *
311    * <h5 class='section'>See Also:</h5>
312    * <ul>
313    *    <li class='jf'>{@link Parser#PARSER_unbuffered}
314    * </ul>
315    *
316    * @return This object (for method chaining).
317    */
318   public ParserGroupBuilder unbuffered() {
319      return set(PARSER_unbuffered, true);
320   }
321
322   /**
323    * Configuration property:  File charset.
324    *
325    * <p>
326    * The character set to use for reading <code>Files</code> from the file system.
327    *
328    * <h5 class='section'>See Also:</h5>
329    * <ul>
330    *    <li class='jf'>{@link ReaderParser#RPARSER_fileCharset}
331    * </ul>
332    *
333    * @param value
334    *    The new value for this property.
335    *    <br>The default value is <js>"DEFAULT"</js> which causes the system default to be used.
336    * @return This object (for method chaining).
337    */
338   public ParserGroupBuilder fileCharset(String value) {
339      return set(RPARSER_fileCharset, value);
340   }
341
342   /**
343    * Configuration property:  Input stream charset.
344    *
345    * <p>
346    * The character set to use for converting <code>InputStreams</code> and byte arrays to readers.
347    *
348    * <h5 class='section'>See Also:</h5>
349    * <ul>
350    *    <li class='jf'>{@link ReaderParser#RPARSER_inputStreamCharset}
351    * </ul>
352    *
353    * @param value
354    *    The new value for this property.
355    *    <br>The default value is <js>"UTF-8"</js>.
356    * @return This object (for method chaining).
357    */
358   public ParserGroupBuilder inputStreamCharset(String value) {
359      return set(RPARSER_inputStreamCharset, value);
360   }
361
362   /**
363    * Configuration property:  Binary input format.
364    *
365    * <p>
366    * When using the {@link Parser#parse(Object,Class)} method on stream-based parsers and the input is a string, this defines the format to use
367    * when converting the string into a byte array.
368    *
369    * <h5 class='section'>See Also:</h5>
370    * <ul>
371    *    <li class='jf'>{@link InputStreamParser#ISPARSER_binaryFormat}
372    * </ul>
373    *
374    * @param value
375    *    The new value for this property.
376    *    <br>The default value is {@link BinaryFormat#HEX}.
377    * @return This object (for method chaining).
378    */
379   public ParserGroupBuilder binaryFormat(BinaryFormat value) {
380      return set(ISPARSER_binaryFormat, value);
381   }
382
383   @Override /* BeanContextBuilder */
384   public ParserGroupBuilder beanClassVisibility(Visibility value) {
385      super.beanClassVisibility(value);
386      return this;
387   }
388
389   @Override /* BeanContextBuilder */
390   public ParserGroupBuilder beanConstructorVisibility(Visibility value) {
391      super.beanConstructorVisibility(value);
392      return this;
393   }
394
395   @Override /* BeanContextBuilder */
396   public ParserGroupBuilder beanDictionary(boolean append, Object...values) {
397      super.beanDictionary(append, values);
398      return this;
399   }
400
401   @Override /* BeanContextBuilder */
402   public ParserGroupBuilder beanDictionary(Class<?>...values) {
403      super.beanDictionary(values);
404      return this;
405   }
406
407   @Override /* BeanContextBuilder */
408   public ParserGroupBuilder beanDictionary(Object...values) {
409      super.beanDictionary(values);
410      return this;
411   }
412
413   @Override /* BeanContextBuilder */
414   public ParserGroupBuilder beanDictionaryRemove(Object...values) {
415      super.beanDictionaryRemove(values);
416      return this;
417   }
418
419   @Override /* BeanContextBuilder */
420   public ParserGroupBuilder beanFieldVisibility(Visibility value) {
421      super.beanFieldVisibility(value);
422      return this;
423   }
424
425   @Override /* BeanContextBuilder */
426   public ParserGroupBuilder beanFilters(boolean append, Object...values) {
427      super.beanFilters(append, values);
428      return this;
429   }
430
431   @Override /* BeanContextBuilder */
432   public ParserGroupBuilder beanFilters(Class<?>...values) {
433      super.beanFilters(values);
434      return this;
435   }
436
437   @Override /* BeanContextBuilder */
438   public ParserGroupBuilder beanFilters(Object...values) {
439      super.beanFilters(values);
440      return this;
441   }
442
443   @Override /* BeanContextBuilder */
444   public ParserGroupBuilder beanFiltersRemove(Object...values) {
445      super.beanFiltersRemove(values);
446      return this;
447   }
448
449   @Override /* BeanContextBuilder */
450   public ParserGroupBuilder beanMapPutReturnsOldValue(boolean value) {
451      super.beanMapPutReturnsOldValue(value);
452      return this;
453   }
454
455   @Override /* BeanContextBuilder */
456   public ParserGroupBuilder beanMapPutReturnsOldValue() {
457      super.beanMapPutReturnsOldValue();
458      return this;
459   }
460
461   @Override /* BeanContextBuilder */
462   public ParserGroupBuilder beanMethodVisibility(Visibility value) {
463      super.beanMethodVisibility(value);
464      return this;
465   }
466
467   @Override /* BeanContextBuilder */
468   public ParserGroupBuilder beansRequireDefaultConstructor(boolean value) {
469      super.beansRequireDefaultConstructor(value);
470      return this;
471   }
472
473   @Override /* BeanContextBuilder */
474   public ParserGroupBuilder beansRequireDefaultConstructor() {
475      super.beansRequireDefaultConstructor();
476      return this;
477   }
478
479   @Override /* BeanContextBuilder */
480   public ParserGroupBuilder beansRequireSerializable(boolean value) {
481      super.beansRequireSerializable(value);
482      return this;
483   }
484
485   @Override /* BeanContextBuilder */
486   public ParserGroupBuilder beansRequireSerializable() {
487      super.beansRequireSerializable();
488      return this;
489   }
490
491   @Override /* BeanContextBuilder */
492   public ParserGroupBuilder beansRequireSettersForGetters(boolean value) {
493      super.beansRequireSettersForGetters(value);
494      return this;
495   }
496
497   @Override /* BeanContextBuilder */
498   public ParserGroupBuilder beansRequireSettersForGetters() {
499      super.beansRequireSettersForGetters();
500      return this;
501   }
502
503   @Override /* BeanContextBuilder */
504   public ParserGroupBuilder beansRequireSomeProperties(boolean value) {
505      super.beansRequireSomeProperties(value);
506      return this;
507   }
508
509   @Override /* BeanContextBuilder */
510   public ParserGroupBuilder beanTypePropertyName(String value) {
511      super.beanTypePropertyName(value);
512      return this;
513   }
514
515   @Override /* BeanContextBuilder */
516   public ParserGroupBuilder debug() {
517      super.debug();
518      return this;
519   }
520
521   @Override /* BeanContextBuilder */
522   public <T> ParserGroupBuilder example(Class<T> c, T o) {
523      super.example(c, o);
524      return this;
525   }
526
527   @Override /* BeanContextBuilder */
528   public ParserGroupBuilder ignoreInvocationExceptionsOnGetters(boolean value) {
529      super.ignoreInvocationExceptionsOnGetters(value);
530      return this;
531   }
532
533   @Override /* BeanContextBuilder */
534   public ParserGroupBuilder ignoreInvocationExceptionsOnGetters() {
535      super.ignoreInvocationExceptionsOnGetters();
536      return this;
537   }
538
539   @Override /* BeanContextBuilder */
540   public ParserGroupBuilder ignoreInvocationExceptionsOnSetters(boolean value) {
541      super.ignoreInvocationExceptionsOnSetters(value);
542      return this;
543   }
544
545   @Override /* BeanContextBuilder */
546   public ParserGroupBuilder ignoreInvocationExceptionsOnSetters() {
547      super.ignoreInvocationExceptionsOnSetters();
548      return this;
549   }
550
551   @Override /* BeanContextBuilder */
552   public ParserGroupBuilder ignorePropertiesWithoutSetters(boolean value) {
553      super.ignorePropertiesWithoutSetters(value);
554      return this;
555   }
556
557   @Override /* BeanContextBuilder */
558   public ParserGroupBuilder ignoreUnknownBeanProperties(boolean value) {
559      super.ignoreUnknownBeanProperties(value);
560      return this;
561   }
562
563   @Override /* BeanContextBuilder */
564   public ParserGroupBuilder ignoreUnknownBeanProperties() {
565      super.ignoreUnknownBeanProperties();
566      return this;
567   }
568
569   @Override /* BeanContextBuilder */
570   public ParserGroupBuilder ignoreUnknownNullBeanProperties(boolean value) {
571      super.ignoreUnknownNullBeanProperties(value);
572      return this;
573   }
574
575   @Override /* BeanContextBuilder */
576   public <T> ParserGroupBuilder implClass(Class<T> interfaceClass, Class<? extends T> implClass) {
577      super.implClass(interfaceClass, implClass);
578      return this;
579   }
580
581   @Override /* BeanContextBuilder */
582   public ParserGroupBuilder implClasses(Map<String,Class<?>> values) {
583      super.implClasses(values);
584      return this;
585   }
586
587   @Override /* BeanContextBuilder */
588   public ParserGroupBuilder locale(Locale value) {
589      super.locale(value);
590      return this;
591   }
592
593   @Override /* BeanContextBuilder */
594   public ParserGroupBuilder mediaType(MediaType value) {
595      super.mediaType(value);
596      return this;
597   }
598
599   @Override /* BeanContextBuilder */
600   public ParserGroupBuilder notBeanClasses(boolean append, Object...values) {
601      super.notBeanClasses(append, values);
602      return this;
603   }
604
605   @Override /* BeanContextBuilder */
606   public ParserGroupBuilder notBeanClasses(Class<?>...values) {
607      super.notBeanClasses(values);
608      return this;
609   }
610
611   @Override /* BeanContextBuilder */
612   public ParserGroupBuilder notBeanClasses(Object...values) {
613      super.notBeanClasses(values);
614      return this;
615   }
616
617   @Override /* BeanContextBuilder */
618   public ParserGroupBuilder notBeanClassesRemove(Object...values) {
619      super.notBeanClassesRemove(values);
620      return this;
621   }
622
623   @Override /* BeanContextBuilder */
624   public ParserGroupBuilder notBeanPackages(boolean append, Object...values) {
625      super.notBeanPackages(append, values);
626      return this;
627   }
628
629   @Override /* BeanContextBuilder */
630   public ParserGroupBuilder notBeanPackages(Object...values) {
631      super.notBeanPackages(values);
632      return this;
633   }
634
635   @Override /* BeanContextBuilder */
636   public ParserGroupBuilder notBeanPackages(String...values) {
637      super.notBeanPackages(values);
638      return this;
639   }
640
641   @Override /* BeanContextBuilder */
642   public ParserGroupBuilder notBeanPackagesRemove(Object...values) {
643      super.notBeanPackagesRemove(values);
644      return this;
645   }
646
647   @Override /* BeanContextBuilder */
648   public ParserGroupBuilder pojoSwaps(boolean append, Object...values) {
649      super.pojoSwaps(append, values);
650      return this;
651   }
652
653   @Override /* BeanContextBuilder */
654   public ParserGroupBuilder pojoSwaps(Class<?>...values) {
655      super.pojoSwaps(values);
656      return this;
657   }
658
659   @Override /* BeanContextBuilder */
660   public ParserGroupBuilder pojoSwaps(Object...values) {
661      super.pojoSwaps(values);
662      return this;
663   }
664
665   @Override /* BeanContextBuilder */
666   public ParserGroupBuilder pojoSwapsRemove(Object...values) {
667      super.pojoSwapsRemove(values);
668      return this;
669   }
670
671   @Override /* BeanContextBuilder */
672   public ParserGroupBuilder sortProperties(boolean value) {
673      super.sortProperties(value);
674      return this;
675   }
676
677   @Override /* BeanContextBuilder */
678   public ParserGroupBuilder sortProperties() {
679      super.sortProperties();
680      return this;
681   }
682
683   @Override /* BeanContextBuilder */
684   public ParserGroupBuilder timeZone(TimeZone value) {
685      super.timeZone(value);
686      return this;
687   }
688
689   @Override /* BeanContextBuilder */
690   public ParserGroupBuilder useEnumNames() {
691      super.useEnumNames();
692      return this;
693   }
694
695   @Override /* BeanContextBuilder */
696   public ParserGroupBuilder useInterfaceProxies(boolean value) {
697      super.useInterfaceProxies(value);
698      return this;
699   }
700
701   @Override /* BeanContextBuilder */
702   public ParserGroupBuilder useJavaBeanIntrospector(boolean value) {
703      super.useJavaBeanIntrospector(value);
704      return this;
705   }
706
707   @Override /* BeanContextBuilder */
708   public ParserGroupBuilder useJavaBeanIntrospector() {
709      super.useJavaBeanIntrospector();
710      return this;
711   }
712
713   @Override /* ContextBuilder */
714   public ParserGroupBuilder set(String name, Object value) {
715      super.set(name, value);
716      return this;
717   }
718
719   @Override /* ContextBuilder */
720   public ParserGroupBuilder set(boolean append, String name, Object value) {
721      super.set(append, name, value);
722      return this;
723   }
724
725   @Override /* ContextBuilder */
726   public ParserGroupBuilder set(Map<String,Object> properties) {
727      super.set(properties);
728      return this;
729   }
730
731   @Override /* ContextBuilder */
732   public ParserGroupBuilder add(Map<String,Object> properties) {
733      super.add(properties);
734      return this;
735   }
736
737   @Override /* ContextBuilder */
738   public ParserGroupBuilder addTo(String name, Object value) {
739      super.addTo(name, value);
740      return this;
741   }
742
743   @Override /* ContextBuilder */
744   public ParserGroupBuilder addTo(String name, String key, Object value) {
745      super.addTo(name, key, value);
746      return this;
747   }
748
749   @Override /* ContextBuilder */
750   public ParserGroupBuilder removeFrom(String name, Object value) {
751      super.removeFrom(name, value);
752      return this;
753   }
754
755   @Override /* ContextBuilder */
756   public ParserGroupBuilder apply(PropertyStore copyFrom) {
757      super.apply(copyFrom);
758      return this;
759   }
760}