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.annotation.*;
017import org.apache.juneau.jsonschema.*;
018import org.apache.juneau.serializer.*;
019
020/**
021 * Serializes POJO metamodels to HTML.
022 *
023 * <h5 class='topic'>Media types</h5>
024 *
025 * Handles <c>Accept</c> types:  <bc>text/html+schema</bc>
026 * <p>
027 * Produces <c>Content-Type</c> types:  <bc>text/html</bc>
028 *
029 * <h5 class='topic'>Description</h5>
030 *
031 * Essentially the same as {@link HtmlSerializer}, except serializes the POJO metamodel instead of the model itself.
032 *
033 * <p>
034 * Produces output that describes the POJO metamodel similar to an XML schema document.
035 *
036 * <p>
037 * The easiest way to create instances of this class is through the {@link HtmlSerializer#getSchemaSerializer()},
038 * which will create a schema serializer with the same settings as the originating serializer.
039 */
040@ConfigurableContext
041public class HtmlSchemaSerializer extends HtmlSerializer {
042
043   //-------------------------------------------------------------------------------------------------------------------
044   // Configurable properties
045   //-------------------------------------------------------------------------------------------------------------------
046
047   static final String PREFIX = "HtmlSchemaSerializer";
048
049   //-------------------------------------------------------------------------------------------------------------------
050   // Predefined instances
051   //-------------------------------------------------------------------------------------------------------------------
052
053   /** Default serializer, all default settings.*/
054   public static final HtmlSchemaSerializer DEFAULT = new HtmlSchemaSerializer(PropertyStore.DEFAULT);
055
056   /** Default serializer, all default settings.*/
057   public static final HtmlSchemaSerializer DEFAULT_READABLE = new Readable(PropertyStore.DEFAULT);
058
059   /** Default serializer, single quotes, simple mode. */
060   public static final HtmlSchemaSerializer DEFAULT_SIMPLE = new Simple(PropertyStore.DEFAULT);
061
062   /** Default serializer, single quotes, simple mode, with whitespace. */
063   public static final HtmlSchemaSerializer DEFAULT_SIMPLE_READABLE = new SimpleReadable(PropertyStore.DEFAULT);
064
065   //-------------------------------------------------------------------------------------------------------------------
066   // Predefined subclasses
067   //-------------------------------------------------------------------------------------------------------------------
068
069   /** Default serializer, with whitespace. */
070   public static class Readable extends HtmlSchemaSerializer {
071
072      /**
073       * Constructor.
074       *
075       * @param ps The property store containing all the settings for this object.
076       */
077      public Readable(PropertyStore ps) {
078         super(
079            ps.builder().set(WSERIALIZER_useWhitespace, true).build()
080         );
081      }
082   }
083
084   /** Default serializer, single quotes, simple mode. */
085   public static class Simple extends HtmlSchemaSerializer {
086
087      /**
088       * Constructor.
089       *
090       * @param ps The property store containing all the settings for this object.
091       */
092      public Simple(PropertyStore ps) {
093         super(
094            ps.builder()
095               .set(WSERIALIZER_quoteChar, '\'')
096               .build()
097            );
098      }
099   }
100
101   /** Default serializer, single quotes, simple mode, with whitespace. */
102   public static class SimpleReadable extends HtmlSchemaSerializer {
103
104      /**
105       * Constructor.
106       *
107       * @param ps The property store containing all the settings for this object.
108       */
109      public SimpleReadable(PropertyStore ps) {
110         super(
111            ps.builder()
112               .set(WSERIALIZER_quoteChar, '\'')
113               .set(WSERIALIZER_useWhitespace, true)
114               .build()
115         );
116      }
117   }
118
119   //-------------------------------------------------------------------------------------------------------------------
120   // Instance
121   //-------------------------------------------------------------------------------------------------------------------
122
123   private final JsonSchemaGenerator generator;
124
125   /**
126    * Constructor.
127    *
128    * @param ps
129    *    The property store to use for creating the context for this serializer.
130    */
131   public HtmlSchemaSerializer(PropertyStore ps) {
132      super(
133         ps.builder()
134            .set(BEANTRAVERSE_detectRecursions, true)
135            .set(BEANTRAVERSE_ignoreRecursions, true)
136            .build(),
137         "text/html", "text/html+schema"
138      );
139
140      generator = JsonSchemaGenerator.create().apply(getPropertyStore()).build();
141   }
142
143   @Override /* Context */
144   public HtmlSchemaSerializerBuilder builder() {
145      return new HtmlSchemaSerializerBuilder(getPropertyStore());
146   }
147
148   @Override /* Context */
149   public HtmlSchemaSerializerSession createSession() {
150      return createSession(createDefaultSessionArgs());
151   }
152
153   @Override /* Serializer */
154   public HtmlSchemaSerializerSession createSession(SerializerSessionArgs args) {
155      return new HtmlSchemaSerializerSession(this, args);
156   }
157
158   JsonSchemaGenerator getGenerator() {
159      return generator;
160   }
161
162   //-----------------------------------------------------------------------------------------------------------------
163   // Other methods
164   //-----------------------------------------------------------------------------------------------------------------
165
166   @Override /* Context */
167   public ObjectMap toMap() {
168      return super.toMap()
169         .append("HtmlSchemaSerializer", new DefaultFilteringObjectMap()
170            .append("generator", generator)
171         );
172   }
173}