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.html;
018
019import java.lang.annotation.*;
020import java.nio.charset.*;
021import java.util.*;
022import java.util.concurrent.*;
023
024import org.apache.juneau.*;
025import org.apache.juneau.internal.*;
026import org.apache.juneau.utils.*;
027import org.apache.juneau.xml.*;
028
029/**
030 * Parses text generated by the {@link HtmlSerializer} class back into a POJO model.
031 *
032 * <h5 class='topic'>Media types</h5>
033 *
034 * Handles <c>Content-Type</c> types:  <bc>text/html</bc>
035 *
036 * <h5 class='topic'>Description</h5>
037 *
038 * See the {@link HtmlSerializer} class for a description of the HTML generated.
039 * <p>
040 * This class is used primarily for automated testing of the {@link HtmlSerializer} class.
041 *
042 * <h5 class='section'>Notes:</h5><ul>
043 *    <li class='note'>This class is thread safe and reusable.
044 * </ul>
045 *
046 * <h5 class='section'>See Also:</h5><ul>
047 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/HtmlBasics">HTML Basics</a>
048
049 * </ul>
050 */
051public class HtmlParser extends XmlParser implements HtmlMetaProvider {
052
053   //-------------------------------------------------------------------------------------------------------------------
054   // Static
055   //-------------------------------------------------------------------------------------------------------------------
056
057   /** Default parser, all default settings.*/
058   public static final HtmlParser DEFAULT = new HtmlParser(create());
059
060   /**
061    * Creates a new builder for this object.
062    *
063    * @return A new builder.
064    */
065   public static Builder create() {
066      return new Builder();
067   }
068
069   //-------------------------------------------------------------------------------------------------------------------
070   // Builder
071   //-------------------------------------------------------------------------------------------------------------------
072
073   /**
074    * Builder class.
075    */
076   public static class Builder extends XmlParser.Builder {
077
078      private static final Cache<HashKey,HtmlParser> CACHE = Cache.of(HashKey.class, HtmlParser.class).build();
079
080      /**
081       * Constructor, default settings.
082       */
083      protected Builder() {
084         consumes("text/html,text/html+stripped");
085      }
086
087      /**
088       * Copy constructor.
089       *
090       * @param copyFrom The bean to copy from.
091       */
092      protected Builder(HtmlParser copyFrom) {
093         super(copyFrom);
094      }
095
096      /**
097       * Copy constructor.
098       *
099       * @param copyFrom The builder to copy from.
100       */
101      protected Builder(Builder copyFrom) {
102         super(copyFrom);
103      }
104
105      @Override /* Context.Builder */
106      public Builder copy() {
107         return new Builder(this);
108      }
109
110      @Override /* Context.Builder */
111      public HtmlParser build() {
112         return cache(CACHE).build(HtmlParser.class);
113      }
114
115      @Override /* Context.Builder */
116      public HashKey hashKey() {
117         return super.hashKey();
118      }
119
120      //-----------------------------------------------------------------------------------------------------------------
121      // Properties
122      //-----------------------------------------------------------------------------------------------------------------
123      @Override /* Overridden from Builder */
124      public Builder annotations(Annotation...values) {
125         super.annotations(values);
126         return this;
127      }
128
129      @Override /* Overridden from Builder */
130      public Builder apply(AnnotationWorkList work) {
131         super.apply(work);
132         return this;
133      }
134
135      @Override /* Overridden from Builder */
136      public Builder applyAnnotations(Object...from) {
137         super.applyAnnotations(from);
138         return this;
139      }
140
141      @Override /* Overridden from Builder */
142      public Builder applyAnnotations(Class<?>...from) {
143         super.applyAnnotations(from);
144         return this;
145      }
146
147      @Override /* Overridden from Builder */
148      public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) {
149         super.cache(value);
150         return this;
151      }
152
153      @Override /* Overridden from Builder */
154      public Builder debug() {
155         super.debug();
156         return this;
157      }
158
159      @Override /* Overridden from Builder */
160      public Builder debug(boolean value) {
161         super.debug(value);
162         return this;
163      }
164
165      @Override /* Overridden from Builder */
166      public Builder impl(Context value) {
167         super.impl(value);
168         return this;
169      }
170
171      @Override /* Overridden from Builder */
172      public Builder type(Class<? extends org.apache.juneau.Context> value) {
173         super.type(value);
174         return this;
175      }
176
177      @Override /* Overridden from Builder */
178      public Builder beanClassVisibility(Visibility value) {
179         super.beanClassVisibility(value);
180         return this;
181      }
182
183      @Override /* Overridden from Builder */
184      public Builder beanConstructorVisibility(Visibility value) {
185         super.beanConstructorVisibility(value);
186         return this;
187      }
188
189      @Override /* Overridden from Builder */
190      public Builder beanContext(BeanContext value) {
191         super.beanContext(value);
192         return this;
193      }
194
195      @Override /* Overridden from Builder */
196      public Builder beanContext(BeanContext.Builder value) {
197         super.beanContext(value);
198         return this;
199      }
200
201      @Override /* Overridden from Builder */
202      public Builder beanDictionary(java.lang.Class<?>...values) {
203         super.beanDictionary(values);
204         return this;
205      }
206
207      @Override /* Overridden from Builder */
208      public Builder beanFieldVisibility(Visibility value) {
209         super.beanFieldVisibility(value);
210         return this;
211      }
212
213      @Override /* Overridden from Builder */
214      public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) {
215         super.beanInterceptor(on, value);
216         return this;
217      }
218
219      @Override /* Overridden from Builder */
220      public Builder beanMapPutReturnsOldValue() {
221         super.beanMapPutReturnsOldValue();
222         return this;
223      }
224
225      @Override /* Overridden from Builder */
226      public Builder beanMethodVisibility(Visibility value) {
227         super.beanMethodVisibility(value);
228         return this;
229      }
230
231      @Override /* Overridden from Builder */
232      public Builder beanProperties(Map<String,Object> values) {
233         super.beanProperties(values);
234         return this;
235      }
236
237      @Override /* Overridden from Builder */
238      public Builder beanProperties(Class<?> beanClass, String properties) {
239         super.beanProperties(beanClass, properties);
240         return this;
241      }
242
243      @Override /* Overridden from Builder */
244      public Builder beanProperties(String beanClassName, String properties) {
245         super.beanProperties(beanClassName, properties);
246         return this;
247      }
248
249      @Override /* Overridden from Builder */
250      public Builder beanPropertiesExcludes(Map<String,Object> values) {
251         super.beanPropertiesExcludes(values);
252         return this;
253      }
254
255      @Override /* Overridden from Builder */
256      public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) {
257         super.beanPropertiesExcludes(beanClass, properties);
258         return this;
259      }
260
261      @Override /* Overridden from Builder */
262      public Builder beanPropertiesExcludes(String beanClassName, String properties) {
263         super.beanPropertiesExcludes(beanClassName, properties);
264         return this;
265      }
266
267      @Override /* Overridden from Builder */
268      public Builder beanPropertiesReadOnly(Map<String,Object> values) {
269         super.beanPropertiesReadOnly(values);
270         return this;
271      }
272
273      @Override /* Overridden from Builder */
274      public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) {
275         super.beanPropertiesReadOnly(beanClass, properties);
276         return this;
277      }
278
279      @Override /* Overridden from Builder */
280      public Builder beanPropertiesReadOnly(String beanClassName, String properties) {
281         super.beanPropertiesReadOnly(beanClassName, properties);
282         return this;
283      }
284
285      @Override /* Overridden from Builder */
286      public Builder beanPropertiesWriteOnly(Map<String,Object> values) {
287         super.beanPropertiesWriteOnly(values);
288         return this;
289      }
290
291      @Override /* Overridden from Builder */
292      public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) {
293         super.beanPropertiesWriteOnly(beanClass, properties);
294         return this;
295      }
296
297      @Override /* Overridden from Builder */
298      public Builder beanPropertiesWriteOnly(String beanClassName, String properties) {
299         super.beanPropertiesWriteOnly(beanClassName, properties);
300         return this;
301      }
302
303      @Override /* Overridden from Builder */
304      public Builder beansRequireDefaultConstructor() {
305         super.beansRequireDefaultConstructor();
306         return this;
307      }
308
309      @Override /* Overridden from Builder */
310      public Builder beansRequireSerializable() {
311         super.beansRequireSerializable();
312         return this;
313      }
314
315      @Override /* Overridden from Builder */
316      public Builder beansRequireSettersForGetters() {
317         super.beansRequireSettersForGetters();
318         return this;
319      }
320
321      @Override /* Overridden from Builder */
322      public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) {
323         super.dictionaryOn(on, values);
324         return this;
325      }
326
327      @Override /* Overridden from Builder */
328      public Builder disableBeansRequireSomeProperties() {
329         super.disableBeansRequireSomeProperties();
330         return this;
331      }
332
333      @Override /* Overridden from Builder */
334      public Builder disableIgnoreMissingSetters() {
335         super.disableIgnoreMissingSetters();
336         return this;
337      }
338
339      @Override /* Overridden from Builder */
340      public Builder disableIgnoreTransientFields() {
341         super.disableIgnoreTransientFields();
342         return this;
343      }
344
345      @Override /* Overridden from Builder */
346      public Builder disableIgnoreUnknownNullBeanProperties() {
347         super.disableIgnoreUnknownNullBeanProperties();
348         return this;
349      }
350
351      @Override /* Overridden from Builder */
352      public Builder disableInterfaceProxies() {
353         super.disableInterfaceProxies();
354         return this;
355      }
356
357      @Override /* Overridden from Builder */
358      public <T> Builder example(Class<T> pojoClass, T o) {
359         super.example(pojoClass, o);
360         return this;
361      }
362
363      @Override /* Overridden from Builder */
364      public <T> Builder example(Class<T> pojoClass, String json) {
365         super.example(pojoClass, json);
366         return this;
367      }
368
369      @Override /* Overridden from Builder */
370      public Builder findFluentSetters() {
371         super.findFluentSetters();
372         return this;
373      }
374
375      @Override /* Overridden from Builder */
376      public Builder findFluentSetters(Class<?> on) {
377         super.findFluentSetters(on);
378         return this;
379      }
380
381      @Override /* Overridden from Builder */
382      public Builder ignoreInvocationExceptionsOnGetters() {
383         super.ignoreInvocationExceptionsOnGetters();
384         return this;
385      }
386
387      @Override /* Overridden from Builder */
388      public Builder ignoreInvocationExceptionsOnSetters() {
389         super.ignoreInvocationExceptionsOnSetters();
390         return this;
391      }
392
393      @Override /* Overridden from Builder */
394      public Builder ignoreUnknownBeanProperties() {
395         super.ignoreUnknownBeanProperties();
396         return this;
397      }
398
399      @Override /* Overridden from Builder */
400      public Builder ignoreUnknownEnumValues() {
401         super.ignoreUnknownEnumValues();
402         return this;
403      }
404
405      @Override /* Overridden from Builder */
406      public Builder implClass(Class<?> interfaceClass, Class<?> implClass) {
407         super.implClass(interfaceClass, implClass);
408         return this;
409      }
410
411      @Override /* Overridden from Builder */
412      public Builder implClasses(Map<Class<?>,Class<?>> values) {
413         super.implClasses(values);
414         return this;
415      }
416
417      @Override /* Overridden from Builder */
418      public Builder interfaceClass(Class<?> on, Class<?> value) {
419         super.interfaceClass(on, value);
420         return this;
421      }
422
423      @Override /* Overridden from Builder */
424      public Builder interfaces(java.lang.Class<?>...value) {
425         super.interfaces(value);
426         return this;
427      }
428
429      @Override /* Overridden from Builder */
430      public Builder locale(Locale value) {
431         super.locale(value);
432         return this;
433      }
434
435      @Override /* Overridden from Builder */
436      public Builder mediaType(MediaType value) {
437         super.mediaType(value);
438         return this;
439      }
440
441      @Override /* Overridden from Builder */
442      public Builder notBeanClasses(java.lang.Class<?>...values) {
443         super.notBeanClasses(values);
444         return this;
445      }
446
447      @Override /* Overridden from Builder */
448      public Builder notBeanPackages(String...values) {
449         super.notBeanPackages(values);
450         return this;
451      }
452
453      @Override /* Overridden from Builder */
454      public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) {
455         super.propertyNamer(value);
456         return this;
457      }
458
459      @Override /* Overridden from Builder */
460      public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) {
461         super.propertyNamer(on, value);
462         return this;
463      }
464
465      @Override /* Overridden from Builder */
466      public Builder sortProperties() {
467         super.sortProperties();
468         return this;
469      }
470
471      @Override /* Overridden from Builder */
472      public Builder sortProperties(java.lang.Class<?>...on) {
473         super.sortProperties(on);
474         return this;
475      }
476
477      @Override /* Overridden from Builder */
478      public Builder stopClass(Class<?> on, Class<?> value) {
479         super.stopClass(on, value);
480         return this;
481      }
482
483      @Override /* Overridden from Builder */
484      public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) {
485         super.swap(normalClass, swappedClass, swapFunction);
486         return this;
487      }
488
489      @Override /* Overridden from Builder */
490      public <T, S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) {
491         super.swap(normalClass, swappedClass, swapFunction, unswapFunction);
492         return this;
493      }
494
495      @Override /* Overridden from Builder */
496      public Builder swaps(Object...values) {
497         super.swaps(values);
498         return this;
499      }
500
501      @Override /* Overridden from Builder */
502      public Builder swaps(Class<?>...values) {
503         super.swaps(values);
504         return this;
505      }
506
507      @Override /* Overridden from Builder */
508      public Builder timeZone(TimeZone value) {
509         super.timeZone(value);
510         return this;
511      }
512
513      @Override /* Overridden from Builder */
514      public Builder typeName(Class<?> on, String value) {
515         super.typeName(on, value);
516         return this;
517      }
518
519      @Override /* Overridden from Builder */
520      public Builder typePropertyName(String value) {
521         super.typePropertyName(value);
522         return this;
523      }
524
525      @Override /* Overridden from Builder */
526      public Builder typePropertyName(Class<?> on, String value) {
527         super.typePropertyName(on, value);
528         return this;
529      }
530
531      @Override /* Overridden from Builder */
532      public Builder useEnumNames() {
533         super.useEnumNames();
534         return this;
535      }
536
537      @Override /* Overridden from Builder */
538      public Builder useJavaBeanIntrospector() {
539         super.useJavaBeanIntrospector();
540         return this;
541      }
542
543      @Override /* Overridden from Builder */
544      public Builder autoCloseStreams() {
545         super.autoCloseStreams();
546         return this;
547      }
548
549      @Override /* Overridden from Builder */
550      public Builder autoCloseStreams(boolean value) {
551         super.autoCloseStreams(value);
552         return this;
553      }
554
555      @Override /* Overridden from Builder */
556      public Builder consumes(String value) {
557         super.consumes(value);
558         return this;
559      }
560
561      @Override /* Overridden from Builder */
562      public Builder debugOutputLines(int value) {
563         super.debugOutputLines(value);
564         return this;
565      }
566
567      @Override /* Overridden from Builder */
568      public Builder listener(Class<? extends org.apache.juneau.parser.ParserListener> value) {
569         super.listener(value);
570         return this;
571      }
572
573      @Override /* Overridden from Builder */
574      public Builder strict() {
575         super.strict();
576         return this;
577      }
578
579      @Override /* Overridden from Builder */
580      public Builder strict(boolean value) {
581         super.strict(value);
582         return this;
583      }
584
585      @Override /* Overridden from Builder */
586      public Builder trimStrings() {
587         super.trimStrings();
588         return this;
589      }
590
591      @Override /* Overridden from Builder */
592      public Builder trimStrings(boolean value) {
593         super.trimStrings(value);
594         return this;
595      }
596
597      @Override /* Overridden from Builder */
598      public Builder unbuffered() {
599         super.unbuffered();
600         return this;
601      }
602
603      @Override /* Overridden from Builder */
604      public Builder unbuffered(boolean value) {
605         super.unbuffered(value);
606         return this;
607      }
608
609      @Override /* Overridden from Builder */
610      public Builder fileCharset(Charset value) {
611         super.fileCharset(value);
612         return this;
613      }
614
615      @Override /* Overridden from Builder */
616      public Builder streamCharset(Charset value) {
617         super.streamCharset(value);
618         return this;
619      }
620
621      @Override /* Overridden from Builder */
622      public Builder eventAllocator(Class<? extends javax.xml.stream.util.XMLEventAllocator> value) {
623         super.eventAllocator(value);
624         return this;
625      }
626
627      @Override /* Overridden from Builder */
628      public Builder preserveRootElement() {
629         super.preserveRootElement();
630         return this;
631      }
632
633      @Override /* Overridden from Builder */
634      public Builder preserveRootElement(boolean value) {
635         super.preserveRootElement(value);
636         return this;
637      }
638
639      @Override /* Overridden from Builder */
640      public Builder reporter(Class<? extends javax.xml.stream.XMLReporter> value) {
641         super.reporter(value);
642         return this;
643      }
644
645      @Override /* Overridden from Builder */
646      public Builder resolver(Class<? extends javax.xml.stream.XMLResolver> value) {
647         super.resolver(value);
648         return this;
649      }
650
651      @Override /* Overridden from Builder */
652      public Builder validating() {
653         super.validating();
654         return this;
655      }
656
657      @Override /* Overridden from Builder */
658      public Builder validating(boolean value) {
659         super.validating(value);
660         return this;
661      }
662   }
663
664   //-------------------------------------------------------------------------------------------------------------------
665   // Instance
666   //-------------------------------------------------------------------------------------------------------------------
667
668   private final Map<ClassMeta<?>,HtmlClassMeta> htmlClassMetas = new ConcurrentHashMap<>();
669   private final Map<BeanPropertyMeta,HtmlBeanPropertyMeta> htmlBeanPropertyMetas = new ConcurrentHashMap<>();
670
671   /**
672    * Constructor.
673    *
674    * @param builder The builder for this object.
675    */
676   public HtmlParser(Builder builder) {
677      super(builder);
678   }
679
680   @Override /* Context */
681   public Builder copy() {
682      return new Builder(this);
683   }
684
685   @Override /* Context */
686   public HtmlParserSession.Builder createSession() {
687      return HtmlParserSession.create(this);
688   }
689
690   @Override /* Context */
691   public HtmlParserSession getSession() {
692      return createSession().build();
693   }
694
695   //-----------------------------------------------------------------------------------------------------------------
696   // Extended metadata
697   //-----------------------------------------------------------------------------------------------------------------
698
699   @Override /* HtmlMetaProvider */
700   public HtmlClassMeta getHtmlClassMeta(ClassMeta<?> cm) {
701      HtmlClassMeta m = htmlClassMetas.get(cm);
702      if (m == null) {
703         m = new HtmlClassMeta(cm, this);
704         htmlClassMetas.put(cm, m);
705      }
706      return m;
707   }
708
709   @Override /* HtmlMetaProvider */
710   public HtmlBeanPropertyMeta getHtmlBeanPropertyMeta(BeanPropertyMeta bpm) {
711      if (bpm == null)
712         return HtmlBeanPropertyMeta.DEFAULT;
713      HtmlBeanPropertyMeta m = htmlBeanPropertyMetas.get(bpm);
714      if (m == null) {
715         m = new HtmlBeanPropertyMeta(bpm.getDelegateFor(), this);
716         htmlBeanPropertyMetas.put(bpm, m);
717      }
718      return m;
719   }
720}