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.console;
018
019import java.util.*;
020import java.util.regex.*;
021
022/**
023 * A click-triggered action on an element: an icon button that calls a handler.
024 *
025 * <h2 class='section'>Example:</h2>
026 * <p class='bjava'>
027 *   ModelAction.<jsm>of</jsm>(<js>"archive"</js>).icon(<js>"archive"</js>).label(<js>"Archive"</js>).handler(<js>"orders.archive"</js>);
028 * </p>
029 *
030 * @since 10.0.0
031 */
032@SuppressWarnings({
033   "java:S1192", // Contract key names repeat as inline literals by design.
034   "java:S1845" // Instance field id and the ID pattern constant are distinct, conventionally named members.
035})
036public final class ModelAction {
037
038   private static final Pattern ID = Pattern.compile("^[A-Za-z0-9_.-]{1,128}$");
039
040   private final String id;
041   private String icon;
042   private String label;
043   private String tooltip;
044   private String tone;
045   private HandlerRef handler;
046   private Map<String,Object> payload;
047
048   private ModelAction(String id) {
049      if (id == null || ! ID.matcher(id).matches())
050         throw new IllegalArgumentException("Action id '" + id + "' must match " + ID.pattern());
051      this.id = id;
052   }
053
054   /**
055    * Starts an action.
056    *
057    * @param id The action id, unique per element.
058    * @return A new action.
059    * @throws IllegalArgumentException If the id is malformed.
060    */
061   public static ModelAction of(String id) {
062      return new ModelAction(id);
063   }
064
065   /**
066    * Returns the action id.
067    *
068    * @return The id.
069    */
070   public String id() {
071      return id;
072   }
073
074   /**
075    * Sets the icon (a sprite name).
076    *
077    * @param v The icon.
078    * @return This object.
079    */
080   public ModelAction icon(String v) {
081      icon = v;
082      return this;
083   }
084
085   /**
086    * Sets the visible label.
087    *
088    * @param v The label.
089    * @return This object.
090    */
091   public ModelAction label(String v) {
092      label = v;
093      return this;
094   }
095
096   /**
097    * Sets the tooltip.
098    *
099    * @param v The tooltip.
100    * @return This object.
101    */
102   public ModelAction tooltip(String v) {
103      tooltip = v;
104      return this;
105   }
106
107   /**
108    * Sets the tone.
109    *
110    * @param v The tone.
111    * @return This object.
112    */
113   public ModelAction tone(String v) {
114      tone = v;
115      return this;
116   }
117
118   /**
119    * Sets the handler by name.
120    *
121    * @param name A registered handler name or a listed built-in ({@code juneau.refresh}).
122    * @return This object.
123    * @throws IllegalArgumentException If the name is malformed.
124    */
125   public ModelAction handler(String name) {
126      return handler(HandlerRef.named(name));
127   }
128
129   /**
130    * Sets the handler.
131    *
132    * @param ref The handler reference.
133    * @return This object.
134    */
135   public ModelAction handler(HandlerRef ref) {
136      handler = Objects.requireNonNull(ref, "handler");
137      return this;
138   }
139
140   /**
141    * Sets the payload merged into the event payload.
142    *
143    * @param v The payload.
144    * @return This object.
145    */
146   public ModelAction payload(Map<String,Object> v) {
147      payload = v == null ? null : new LinkedHashMap<>(v);
148      return this;
149   }
150
151   /**
152    * Returns the handler.
153    *
154    * @return The handler, or <jk>null</jk> if not yet set.
155    */
156   HandlerRef handlerRef() {
157      return handler;
158   }
159
160   /**
161    * Serializes to the contract shape.
162    *
163    * @return The map, with {@code "type":"handler"}.
164    * @throws IllegalStateException If no handler was set.
165    */
166   public Map<String,Object> toMap() {
167      if (handler == null)
168         throw new IllegalStateException("Action '" + id + "' has no handler.");
169      var m = new LinkedHashMap<String,Object>();
170      m.put("type", "handler");
171      m.put("id", id);
172      if (icon != null)
173         m.put("icon", icon);
174      if (label != null)
175         m.put("label", label);
176      if (tooltip != null)
177         m.put("tooltip", tooltip);
178      if (tone != null)
179         m.put("tone", tone);
180      m.put("handler", handler.toJson());
181      if (payload != null)
182         m.put("payload", payload);
183      return m;
184   }
185}