001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
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,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.plaintext;
018
019import static org.apache.juneau.commons.utils.AssertionUtils.*;
020
021import java.lang.annotation.*;
022import java.nio.charset.*;
023import java.util.*;
024import java.util.concurrent.*;
025
026import org.apache.juneau.*;
027import org.apache.juneau.commons.collections.*;
028import org.apache.juneau.commons.function.*;
029import org.apache.juneau.commons.reflect.*;
030import org.apache.juneau.parser.*;
031import org.apache.juneau.swap.*;
032
033/**
034 * Parsers HTTP plain text request bodies into Group 5 POJOs.
035 *
036 * <p>
037 * See <a class="doclink" href="https://juneau.apache.org/docs/topics/PojoCategories">POJO Categories</a>.
038 *
039 * <h5 class='topic'>Media types</h5>
040 *
041 * Handles <c>Accept</c> types:  <bc>text/plain</bc>
042 * <p>
043 * Produces <c>Content-Type</c> types:  <bc>text/plain</bc>
044 *
045 * <h5 class='topic'>Description</h5>
046 *
047 * Essentially just converts plain text to POJOs via static <c>fromString()</c> or <c>valueOf()</c>, or
048 * through constructors that take a single string argument.
049 *
050 * <p>
051 * Also parses objects using a transform if the object class has an {@link ObjectSwap ObjectSwap&lt;?,String&gt;} transform
052 * defined on it.
053 *
054 * <h5 class='section'>Notes:</h5><ul>
055 *    <li class='note'>This class is thread safe and reusable.
056 * </ul>
057 *
058 */
059public class PlainTextParser extends ReaderParser implements PlainTextMetaProvider {
060   /**
061    * Builder class.
062    */
063   public static class Builder extends ReaderParser.Builder {
064
065      private static final Cache<HashKey,PlainTextParser> CACHE = Cache.of(HashKey.class, PlainTextParser.class).build();
066
067      /**
068       * Constructor, default settings.
069       */
070      protected Builder() {
071         consumes("text/plain");
072      }
073
074      /**
075       * Copy constructor.
076       *
077       * @param copyFrom The builder to copy from.
078       *    <br>Cannot be <jk>null</jk>.
079       */
080      protected Builder(Builder copyFrom) {
081         super(assertArgNotNull("copyFrom", copyFrom));
082      }
083
084      /**
085       * Copy constructor.
086       *
087       * @param copyFrom The bean to copy from.
088       *    <br>Cannot be <jk>null</jk>.
089       */
090      protected Builder(PlainTextParser copyFrom) {
091         super(assertArgNotNull("copyFrom", copyFrom));
092      }
093
094      @Override /* Overridden from Builder */
095      public Builder annotations(Annotation...values) {
096         super.annotations(values);
097         return this;
098      }
099
100      @Override /* Overridden from Builder */
101      public Builder apply(AnnotationWorkList work) {
102         super.apply(work);
103         return this;
104      }
105
106      @Override /* Overridden from Builder */
107      public Builder applyAnnotations(Class<?>...from) {
108         super.applyAnnotations(from);
109         return this;
110      }
111
112      @Override /* Overridden from Builder */
113      public Builder applyAnnotations(Object...from) {
114         super.applyAnnotations(from);
115         return this;
116      }
117
118      @Override /* Overridden from Builder */
119      public Builder autoCloseStreams() {
120         super.autoCloseStreams();
121         return this;
122      }
123
124      @Override /* Overridden from Builder */
125      public Builder autoCloseStreams(boolean value) {
126         super.autoCloseStreams(value);
127         return this;
128      }
129
130      @Override /* Overridden from Builder */
131      public Builder beanClassVisibility(Visibility value) {
132         super.beanClassVisibility(value);
133         return this;
134      }
135
136      @Override /* Overridden from Builder */
137      public Builder beanConstructorVisibility(Visibility value) {
138         super.beanConstructorVisibility(value);
139         return this;
140      }
141
142      @Override /* Overridden from Builder */
143      public Builder beanContext(BeanContext value) {
144         super.beanContext(value);
145         return this;
146      }
147
148      @Override /* Overridden from Builder */
149      public Builder beanContext(BeanContext.Builder value) {
150         super.beanContext(value);
151         return this;
152      }
153
154      @Override /* Overridden from Builder */
155      public Builder beanDictionary(java.lang.Class<?>...values) {
156         super.beanDictionary(values);
157         return this;
158      }
159
160      @Override /* Overridden from Builder */
161      public Builder beanFieldVisibility(Visibility value) {
162         super.beanFieldVisibility(value);
163         return this;
164      }
165
166      @Override /* Overridden from Builder */
167      public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) {
168         super.beanInterceptor(on, value);
169         return this;
170      }
171
172      @Override /* Overridden from Builder */
173      public Builder beanMapPutReturnsOldValue() {
174         super.beanMapPutReturnsOldValue();
175         return this;
176      }
177
178      @Override /* Overridden from Builder */
179      public Builder beanMethodVisibility(Visibility value) {
180         super.beanMethodVisibility(value);
181         return this;
182      }
183
184      @Override /* Overridden from Builder */
185      public Builder beanProperties(Class<?> beanClass, String properties) {
186         super.beanProperties(beanClass, properties);
187         return this;
188      }
189
190      @Override /* Overridden from Builder */
191      public Builder beanProperties(Map<String,Object> values) {
192         super.beanProperties(values);
193         return this;
194      }
195
196      @Override /* Overridden from Builder */
197      public Builder beanProperties(String beanClassName, String properties) {
198         super.beanProperties(beanClassName, properties);
199         return this;
200      }
201
202      @Override /* Overridden from Builder */
203      public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) {
204         super.beanPropertiesExcludes(beanClass, properties);
205         return this;
206      }
207
208      @Override /* Overridden from Builder */
209      public Builder beanPropertiesExcludes(Map<String,Object> values) {
210         super.beanPropertiesExcludes(values);
211         return this;
212      }
213
214      @Override /* Overridden from Builder */
215      public Builder beanPropertiesExcludes(String beanClassName, String properties) {
216         super.beanPropertiesExcludes(beanClassName, properties);
217         return this;
218      }
219
220      @Override /* Overridden from Builder */
221      public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) {
222         super.beanPropertiesReadOnly(beanClass, properties);
223         return this;
224      }
225
226      @Override /* Overridden from Builder */
227      public Builder beanPropertiesReadOnly(Map<String,Object> values) {
228         super.beanPropertiesReadOnly(values);
229         return this;
230      }
231
232      @Override /* Overridden from Builder */
233      public Builder beanPropertiesReadOnly(String beanClassName, String properties) {
234         super.beanPropertiesReadOnly(beanClassName, properties);
235         return this;
236      }
237
238      @Override /* Overridden from Builder */
239      public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) {
240         super.beanPropertiesWriteOnly(beanClass, properties);
241         return this;
242      }
243
244      @Override /* Overridden from Builder */
245      public Builder beanPropertiesWriteOnly(Map<String,Object> values) {
246         super.beanPropertiesWriteOnly(values);
247         return this;
248      }
249
250      @Override /* Overridden from Builder */
251      public Builder beanPropertiesWriteOnly(String beanClassName, String properties) {
252         super.beanPropertiesWriteOnly(beanClassName, properties);
253         return this;
254      }
255
256      @Override /* Overridden from Builder */
257      public Builder beansRequireDefaultConstructor() {
258         super.beansRequireDefaultConstructor();
259         return this;
260      }
261
262      @Override /* Overridden from Builder */
263      public Builder beansRequireSerializable() {
264         super.beansRequireSerializable();
265         return this;
266      }
267
268      @Override /* Overridden from Builder */
269      public Builder beansRequireSettersForGetters() {
270         super.beansRequireSettersForGetters();
271         return this;
272      }
273
274      @Override /* Overridden from Context.Builder */
275      public PlainTextParser build() {
276         return cache(CACHE).build(PlainTextParser.class);
277      }
278
279      @Override /* Overridden from Builder */
280      public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) {
281         super.cache(value);
282         return this;
283      }
284
285      @Override /* Overridden from Builder */
286      public Builder consumes(String value) {
287         super.consumes(value);
288         return this;
289      }
290
291      @Override /* Overridden from Context.Builder */
292      public Builder copy() {
293         return new Builder(this);
294      }
295
296      @Override /* Overridden from Builder */
297      public Builder debug() {
298         super.debug();
299         return this;
300      }
301
302      @Override /* Overridden from Builder */
303      public Builder debug(boolean value) {
304         super.debug(value);
305         return this;
306      }
307
308      @Override /* Overridden from Builder */
309      public Builder debugOutputLines(int value) {
310         super.debugOutputLines(value);
311         return this;
312      }
313
314      @Override /* Overridden from Builder */
315      public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) {
316         super.dictionaryOn(on, values);
317         return this;
318      }
319
320      @Override /* Overridden from Builder */
321      public Builder disableBeansRequireSomeProperties() {
322         super.disableBeansRequireSomeProperties();
323         return this;
324      }
325
326      @Override /* Overridden from Builder */
327      public Builder disableIgnoreMissingSetters() {
328         super.disableIgnoreMissingSetters();
329         return this;
330      }
331
332      @Override /* Overridden from Builder */
333      public Builder disableIgnoreTransientFields() {
334         super.disableIgnoreTransientFields();
335         return this;
336      }
337
338      @Override /* Overridden from Builder */
339      public Builder disableIgnoreUnknownNullBeanProperties() {
340         super.disableIgnoreUnknownNullBeanProperties();
341         return this;
342      }
343
344      @Override /* Overridden from Builder */
345      public Builder disableInterfaceProxies() {
346         super.disableInterfaceProxies();
347         return this;
348      }
349
350      @Override /* Overridden from Builder */
351      public <T> Builder example(Class<T> pojoClass, String json) {
352         super.example(pojoClass, json);
353         return this;
354      }
355
356      @Override /* Overridden from Builder */
357      public <T> Builder example(Class<T> pojoClass, T o) {
358         super.example(pojoClass, o);
359         return this;
360      }
361
362      @Override /* Overridden from Builder */
363      public Builder fileCharset(Charset value) {
364         super.fileCharset(value);
365         return this;
366      }
367
368      @Override /* Overridden from Builder */
369      public Builder findFluentSetters() {
370         super.findFluentSetters();
371         return this;
372      }
373
374      @Override /* Overridden from Builder */
375      public Builder findFluentSetters(Class<?> on) {
376         super.findFluentSetters(on);
377         return this;
378      }
379
380      @Override /* Overridden from Context.Builder */
381      public HashKey hashKey() {
382         return super.hashKey();
383      }
384
385      @Override /* Overridden from Builder */
386      public Builder ignoreInvocationExceptionsOnGetters() {
387         super.ignoreInvocationExceptionsOnGetters();
388         return this;
389      }
390
391      @Override /* Overridden from Builder */
392      public Builder ignoreInvocationExceptionsOnSetters() {
393         super.ignoreInvocationExceptionsOnSetters();
394         return this;
395      }
396
397      @Override /* Overridden from Builder */
398      public Builder ignoreUnknownBeanProperties() {
399         super.ignoreUnknownBeanProperties();
400         return this;
401      }
402
403      @Override /* Overridden from Builder */
404      public Builder ignoreUnknownEnumValues() {
405         super.ignoreUnknownEnumValues();
406         return this;
407      }
408
409      @Override /* Overridden from Builder */
410      public Builder impl(Context value) {
411         super.impl(value);
412         return this;
413      }
414
415      @Override /* Overridden from Builder */
416      public Builder implClass(Class<?> interfaceClass, Class<?> implClass) {
417         super.implClass(interfaceClass, implClass);
418         return this;
419      }
420
421      @Override /* Overridden from Builder */
422      public Builder implClasses(Map<Class<?>,Class<?>> values) {
423         super.implClasses(values);
424         return this;
425      }
426
427      @Override /* Overridden from Builder */
428      public Builder interfaceClass(Class<?> on, Class<?> value) {
429         super.interfaceClass(on, value);
430         return this;
431      }
432
433      @Override /* Overridden from Builder */
434      public Builder interfaces(java.lang.Class<?>...value) {
435         super.interfaces(value);
436         return this;
437      }
438
439      @Override /* Overridden from Builder */
440      public Builder listener(Class<? extends org.apache.juneau.parser.ParserListener> value) {
441         super.listener(value);
442         return this;
443      }
444
445      @Override /* Overridden from Builder */
446      public Builder locale(Locale value) {
447         super.locale(value);
448         return this;
449      }
450
451      @Override /* Overridden from Builder */
452      public Builder mediaType(MediaType value) {
453         super.mediaType(value);
454         return this;
455      }
456
457      @Override /* Overridden from Builder */
458      public Builder notBeanClasses(java.lang.Class<?>...values) {
459         super.notBeanClasses(values);
460         return this;
461      }
462
463      @Override /* Overridden from Builder */
464      public Builder notBeanPackages(String...values) {
465         super.notBeanPackages(values);
466         return this;
467      }
468
469      @Override /* Overridden from Builder */
470      public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) {
471         super.propertyNamer(on, value);
472         return this;
473      }
474
475      @Override /* Overridden from Builder */
476      public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) {
477         super.propertyNamer(value);
478         return this;
479      }
480
481      @Override /* Overridden from Builder */
482      public Builder sortProperties() {
483         super.sortProperties();
484         return this;
485      }
486
487      @Override /* Overridden from Builder */
488      public Builder sortProperties(java.lang.Class<?>...on) {
489         super.sortProperties(on);
490         return this;
491      }
492
493      @Override /* Overridden from Builder */
494      public Builder stopClass(Class<?> on, Class<?> value) {
495         super.stopClass(on, value);
496         return this;
497      }
498
499      @Override /* Overridden from Builder */
500      public Builder streamCharset(Charset value) {
501         super.streamCharset(value);
502         return this;
503      }
504
505      @Override /* Overridden from Builder */
506      public Builder strict() {
507         super.strict();
508         return this;
509      }
510
511      @Override /* Overridden from Builder */
512      public Builder strict(boolean value) {
513         super.strict(value);
514         return this;
515      }
516
517      @Override /* Overridden from Builder */
518      public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) {
519         super.swap(normalClass, swappedClass, swapFunction);
520         return this;
521      }
522
523      @Override /* Overridden from Builder */
524      public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) {
525         super.swap(normalClass, swappedClass, swapFunction, unswapFunction);
526         return this;
527      }
528
529      @Override /* Overridden from Builder */
530      public Builder swaps(Class<?>...values) {
531         super.swaps(values);
532         return this;
533      }
534
535      @Override /* Overridden from Builder */
536      public Builder swaps(Object...values) {
537         super.swaps(values);
538         return this;
539      }
540
541      @Override /* Overridden from Builder */
542      public Builder timeZone(TimeZone value) {
543         super.timeZone(value);
544         return this;
545      }
546
547      @Override /* Overridden from Builder */
548      public Builder trimStrings() {
549         super.trimStrings();
550         return this;
551      }
552
553      @Override /* Overridden from Builder */
554      public Builder trimStrings(boolean value) {
555         super.trimStrings(value);
556         return this;
557      }
558
559      @Override /* Overridden from Builder */
560      public Builder type(Class<? extends org.apache.juneau.Context> value) {
561         super.type(value);
562         return this;
563      }
564
565      @Override /* Overridden from Builder */
566      public Builder typeName(Class<?> on, String value) {
567         super.typeName(on, value);
568         return this;
569      }
570
571      @Override /* Overridden from Builder */
572      public Builder typePropertyName(Class<?> on, String value) {
573         super.typePropertyName(on, value);
574         return this;
575      }
576
577      @Override /* Overridden from Builder */
578      public Builder typePropertyName(String value) {
579         super.typePropertyName(value);
580         return this;
581      }
582
583      @Override /* Overridden from Builder */
584      public Builder unbuffered() {
585         super.unbuffered();
586         return this;
587      }
588
589      @Override /* Overridden from Builder */
590      public Builder unbuffered(boolean value) {
591         super.unbuffered(value);
592         return this;
593      }
594
595      @Override /* Overridden from Builder */
596      public Builder useEnumNames() {
597         super.useEnumNames();
598         return this;
599      }
600
601      @Override /* Overridden from Builder */
602      public Builder useJavaBeanIntrospector() {
603         super.useJavaBeanIntrospector();
604         return this;
605      }
606   }
607
608   /** Default parser, all default settings.*/
609   public static final PlainTextParser DEFAULT = new PlainTextParser(create());
610
611   /**
612    * Creates a new builder for this object.
613    *
614    * @return A new builder.
615    */
616   public static Builder create() {
617      return new Builder();
618   }
619
620   private final Map<ClassMeta<?>,PlainTextClassMeta> plainTextClassMetas = new ConcurrentHashMap<>();
621   private final Map<BeanPropertyMeta,PlainTextBeanPropertyMeta> plainTextBeanPropertyMetas = new ConcurrentHashMap<>();
622
623   /**
624    * Constructor.
625    *
626    * @param builder The builder for this object.
627    */
628   public PlainTextParser(Builder builder) {
629      super(builder);
630   }
631
632   @Override /* Overridden from Context */
633   public Builder copy() {
634      return new Builder(this);
635   }
636
637   @Override /* Overridden from Context */
638   public PlainTextParserSession.Builder createSession() {
639      return PlainTextParserSession.create(this);
640   }
641
642   @Override /* Overridden from PlainTextMetaProvider */
643   public PlainTextBeanPropertyMeta getPlainTextBeanPropertyMeta(BeanPropertyMeta bpm) {
644      if (bpm == null)
645         return PlainTextBeanPropertyMeta.DEFAULT;
646      var m = plainTextBeanPropertyMetas.get(bpm);
647      if (m == null) {
648         m = new PlainTextBeanPropertyMeta(bpm.getDelegateFor(), this);
649         plainTextBeanPropertyMetas.put(bpm, m);
650      }
651      return m;
652   }
653
654   @Override /* Overridden from PlainTextMetaProvider */
655   public PlainTextClassMeta getPlainTextClassMeta(ClassMeta<?> cm) {
656      var m = plainTextClassMetas.get(cm);
657      if (m == null) {
658         m = new PlainTextClassMeta(cm, this);
659         plainTextClassMetas.put(cm, m);
660      }
661      return m;
662   }
663
664   @Override /* Overridden from Context */
665   public PlainTextParserSession getSession() { return createSession().build(); }
666}