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