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.marshall.html;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020
021import java.util.*;
022import java.util.concurrent.*;
023
024import org.apache.juneau.commons.bean.*;
025import org.apache.juneau.commons.collections.*;
026import org.apache.juneau.marshall.*;
027import org.apache.juneau.marshall.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/HtmlSupport">HTML</a>
048
049 * </ul>
050 */
051@SuppressWarnings({
052   "java:S110", // Inheritance depth acceptable for this class hierarchy
053   "java:S1192", // Duplicated literals (argument/property names) read more clearly inline than as constants
054   "java:S9149" // Per-format static factories intentionally shadow the parent's.
055})
056public class HtmlParser extends XmlParser implements HtmlMetaProvider {
057
058   /**
059    * Builder class.
060    */
061   public static class Builder extends XmlParser.Builder<Builder> {
062
063      private static final Cache<HashKey,HtmlParser> CACHE = Cache.of(HashKey.class, HtmlParser.class).build();
064
065      /**
066       * Constructor, default settings.
067       */
068      protected Builder() {
069         consumes("text/html,text/html+stripped");
070      }
071
072      /**
073       * Copy constructor.
074       *
075       * @param copyFrom The builder to copy from.
076       *    <br>Cannot be <jk>null</jk>.
077       */
078      protected Builder(Builder copyFrom) {
079         super(reqnn("copyFrom", copyFrom));
080      }
081
082      /**
083       * Copy constructor.
084       *
085       * @param copyFrom The bean to copy from.
086       *    <br>Cannot be <jk>null</jk>.
087       */
088      protected Builder(HtmlParser copyFrom) {
089         super(reqnn("copyFrom", copyFrom));
090      }
091
092      @Override /* Overridden from Context.Builder<?> */
093      public HtmlParser build() {
094         return cache(CACHE).build(HtmlParser.class);
095      }
096
097      @Override /* Overridden from Context.Builder<?> */
098      public Builder copy() {
099         return new Builder(this);
100      }
101
102
103   }
104
105   /** Default parser, all default settings.*/
106   public static final HtmlParser DEFAULT = new HtmlParser(create());
107
108   /**
109    * Creates a new builder for this object.
110    *
111    * @return A new builder.
112    */
113   public static Builder create() {
114      return new Builder();
115   }
116
117   private final Map<ClassMeta<?>,HtmlClassMeta> htmlClassMetas = new ConcurrentHashMap<>();
118   private final Map<BeanPropertyMeta,HtmlBeanPropertyMeta> htmlBeanPropertyMetas = new ConcurrentHashMap<>();
119
120   /**
121    * Constructor.
122    *
123    * @param builder The builder for this object.
124    */
125   public HtmlParser(Builder builder) {
126      super(builder);
127   }
128
129   @Override /* Overridden from Context */
130   public Builder copy() {
131      return new Builder(this);
132   }
133
134   @Override /* Overridden from Context */
135   public HtmlParserSession.Builder createSession() {
136      return HtmlParserSession.create(this);
137   }
138
139   @Override /* Overridden from HtmlMetaProvider */
140   public HtmlBeanPropertyMeta getHtmlBeanPropertyMeta(BeanPropertyMeta bpm) {
141      if (bpm == null)
142         return HtmlBeanPropertyMeta.DEFAULT;
143      return htmlBeanPropertyMetas.computeIfAbsent(bpm, k -> new HtmlBeanPropertyMeta(k.getDelegateFor(), this.getAnnotationProvider(), this));
144   }
145
146   @Override /* Overridden from HtmlMetaProvider */
147   public HtmlClassMeta getHtmlClassMeta(ClassMeta<?> cm) {
148      return htmlClassMetas.computeIfAbsent(cm, k -> new HtmlClassMeta(k, this));
149   }
150
151   @Override /* Overridden from Context */
152   public HtmlParserSession getSession() { return createSession().build(); }
153}