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.commons.template;
018
019import java.util.*;
020
021/**
022 * Describes the names a template may read, for {@link TemplateResolver#check(String, TemplateCatalog)}.
023 *
024 * <p>
025 * A <em>field</em> is a top-level name.  A <em>list</em> is a top-level name holding rows; it may carry a
026 * {@link FieldCatalog} naming the row fields, and without one any row field is accepted.
027 */
028public final class TemplateCatalog {
029
030   private final Set<String> fields;
031   private final Map<String,FieldCatalog> lists;
032   private final boolean allowUnknownFunctions;
033
034   private TemplateCatalog(Builder b) {
035      fields = Collections.unmodifiableSet(new LinkedHashSet<>(b.fields));
036      lists = Collections.unmodifiableMap(new LinkedHashMap<>(b.lists));
037      allowUnknownFunctions = b.allowUnknownFunctions;
038   }
039
040   /**
041    * Creates a builder.
042    *
043    * @return A new builder.
044    */
045   public static Builder create() { return new Builder(); }
046
047   /** Builder for {@link TemplateCatalog}. */
048   public static final class Builder {
049      private final Set<String> fields = new LinkedHashSet<>();
050      private final Map<String,FieldCatalog> lists = new LinkedHashMap<>();
051      private boolean allowUnknownFunctions;
052
053      private Builder() {}
054
055      /**
056       * Declares top-level fields.
057       *
058       * @param names The names.
059       * @return This object.
060       */
061      public Builder fields(String...names) {
062         for (var n : names)
063            fields.add(new FieldDef(n).name());
064         return this;
065      }
066
067      /**
068       * Declares a list whose row fields are not checked.
069       *
070       * @param name The list name.
071       * @return This object.
072       */
073      public Builder list(String name) {
074         lists.put(new FieldDef(name).name(), null);
075         return this;
076      }
077
078      /**
079       * Declares a list with its row fields.
080       *
081       * @param name The list name.
082       * @param rowFields The row fields.  Must not be <jk>null</jk>.
083       * @return This object.
084       */
085      public Builder list(String name, FieldCatalog rowFields) {
086         lists.put(new FieldDef(name).name(), Objects.requireNonNull(rowFields, "rowFields must not be null"));
087         return this;
088      }
089
090      /**
091       * Accepts function names the resolver does not know or permit.
092       *
093       * @param value Whether to accept them.  Default <jk>false</jk>.
094       * @return This object.
095       */
096      public Builder allowUnknownFunctions(boolean value) {
097         allowUnknownFunctions = value;
098         return this;
099      }
100
101      /**
102       * Builds the catalog.
103       *
104       * @return A new catalog.
105       */
106      public TemplateCatalog build() { return new TemplateCatalog(this); }
107   }
108
109   boolean hasName(String name) { return fields.contains(name) || lists.containsKey(name); }
110
111   boolean isList(String name) { return lists.containsKey(name); }
112
113   /** @return The row catalog, or <jk>null</jk> if the list is undeclared or has none. */
114   FieldCatalog rowFields(String list) { return lists.get(list); }
115
116   boolean allowUnknownFunctions() { return allowUnknownFunctions; }
117}