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