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.html;
014
015import org.apache.juneau.*;
016import org.apache.juneau.cp.*;
017import org.apache.juneau.html.annotation.*;
018
019/**
020 * Metadata on bean properties specific to the HTML serializers and parsers pulled from the {@link Html @Html}
021 * annotation on the bean property.
022 *
023 * <h5 class='section'>See Also:</h5><ul>
024 *    <li class='link'><a class="doclink" href="../../../../index.html#jm.HtmlDetails">HTML Details</a>
025
026 * </ul>
027 */
028@SuppressWarnings("rawtypes")
029public final class HtmlBeanPropertyMeta extends ExtendedBeanPropertyMeta {
030
031   /**
032    * Default instance.
033    */
034   public static final HtmlBeanPropertyMeta DEFAULT = new HtmlBeanPropertyMeta();
035
036   private final boolean noTables, noTableHeaders;
037   private final HtmlFormat format;
038   private final HtmlRender render;
039   private final String link, anchorText;
040
041   /**
042    * Constructor.
043    *
044    * @param bpm The metadata of the bean property of this additional metadata.
045    * @param mp HTML metadata provider (for finding information about other artifacts).
046    */
047   public HtmlBeanPropertyMeta(BeanPropertyMeta bpm, HtmlMetaProvider mp) {
048      super(bpm);
049
050      Builder b = new Builder();
051      if (bpm.getInnerField() != null)
052         mp.forEachAnnotation(Html.class, bpm.getInnerField(), x-> true, x -> b.findHtmlInfo(x));
053      if (bpm.getGetter() != null)
054         mp.forEachAnnotation(Html.class, bpm.getGetter(), x-> true, x -> b.findHtmlInfo(x));
055      if (bpm.getSetter() != null)
056         mp.forEachAnnotation(Html.class, bpm.getSetter(), x-> true, x -> b.findHtmlInfo(x));
057
058      this.format = b.format;
059      this.noTables = b.noTables;
060      this.noTableHeaders = b.noTableHeaders;
061      this.render = b.render.orElse(null);
062      this.link = b.link;
063      this.anchorText = b.anchorText;
064   }
065
066   private HtmlBeanPropertyMeta() {
067      super(null);
068      this.format = HtmlFormat.HTML;
069      this.noTables = false;
070      this.noTableHeaders = false;
071      this.render = null;
072      this.link = null;
073      this.anchorText = null;
074   }
075
076   static final class Builder {
077      boolean noTables, noTableHeaders;
078      HtmlFormat format = HtmlFormat.HTML;
079      BeanCreator<HtmlRender> render = BeanCreator.of(HtmlRender.class);
080      String link, anchorText;
081
082      void findHtmlInfo(Html html) {
083         if (html == null)
084            return;
085         format = html.format();
086         if (html.noTables())
087            noTables = html.noTables();
088         if (html.noTableHeaders())
089            noTableHeaders = html.noTableHeaders();
090         if (html.render() != HtmlRender.class)
091            render.type(html.render());
092         if (! html.link().isEmpty())
093            link = html.link();
094         if (! html.anchorText().isEmpty())
095            anchorText = html.anchorText();
096      }
097   }
098
099   /**
100    * Returns the format of this bean property
101    *
102    * @return The value of the {@link Html#format()} annotation.
103    */
104   protected HtmlFormat getFormat() {
105      return format;
106   }
107
108   /**
109    * Returns <jk>true</jk> if {@link #getFormat()} returns {@link HtmlFormat#XML}.
110    *
111    * @return <jk>true</jk> if {@link #getFormat()} returns {@link HtmlFormat#XML}.
112    */
113   protected boolean isXml() {
114      return format == HtmlFormat.XML;
115   }
116
117   /**
118    * Returns <jk>true</jk> if {@link #getFormat()} returns {@link HtmlFormat#PLAIN_TEXT}.
119    *
120    * @return <jk>true</jk> if {@link #getFormat()} returns {@link HtmlFormat#PLAIN_TEXT}.
121    */
122   protected boolean isPlainText() {
123      return format == HtmlFormat.PLAIN_TEXT;
124   }
125
126   /**
127    * Returns <jk>true</jk> if {@link #getFormat()} returns {@link HtmlFormat#HTML}.
128    *
129    * @return <jk>true</jk> if {@link #getFormat()} returns {@link HtmlFormat#HTML}.
130    */
131   protected boolean isHtml() {
132      return format == HtmlFormat.HTML;
133   }
134
135   /**
136    * Returns <jk>true</jk> if {@link #getFormat()} returns {@link HtmlFormat#HTML_CDC}.
137    *
138    * @return <jk>true</jk> if {@link #getFormat()} returns {@link HtmlFormat#HTML_CDC}.
139    */
140   protected boolean isHtmlCdc() {
141      return format == HtmlFormat.HTML_CDC;
142   }
143
144   /**
145    * Returns <jk>true</jk> if {@link #getFormat()} returns {@link HtmlFormat#HTML_SDC}.
146    *
147    * @return <jk>true</jk> if {@link #getFormat()} returns {@link HtmlFormat#HTML_SDC}.
148    */
149   protected boolean isHtmlSdc() {
150      return format == HtmlFormat.HTML_SDC;
151   }
152
153   /**
154    * Returns whether this bean property should not be serialized as an HTML table.
155    *
156    * @return
157    *    <jk>true</jk> if the the {@link Html @Html} annotation is specified, and {@link Html#noTables() @Html(noTables)} is
158    *    <jk>true</jk>.
159    */
160   protected boolean isNoTables() {
161      return noTables;
162   }
163
164   /**
165    * Returns whether this bean property should not include table headers when serialized as an HTML table.
166    *
167    * @return
168    *    <jk>true</jk> if the the {@link Html @Html} annotation is specified, and {@link Html#noTableHeaders() @Html(noTableHeaders)} is
169    *    <jk>true</jk>.
170    */
171   public boolean isNoTableHeaders() {
172      return noTableHeaders;
173   }
174
175   /**
176    * Returns the render class for rendering the style and contents of this property value in HTML.
177    *
178    * <p>
179    * This value is specified via the {@link Html#render() @Html(render)} annotation.
180    *
181    * @return The render class, never <jk>null</jk>.
182    */
183   public HtmlRender getRender() {
184      return render;
185   }
186
187   /**
188    * Adds a hyperlink to this value in HTML.
189    *
190    * <p>
191    * This value is specified via the {@link Html#link() @Html(link)} annotation.
192    *
193    * @return The link string, or <jk>null</jk> if not specified.
194    */
195   public String getLink() {
196      return link;
197   }
198
199   /**
200    * Specifies the anchor text for this property.
201    *
202    * <p>
203    * This value is specified via the {@link Html#anchorText() @Html(anchorText)} annotation.
204    *
205    * @return The link string, or <jk>null</jk> if not specified.
206    */
207   public String getAnchorText() {
208      return anchorText;
209   }
210}