1/*
2 * Copyright (C) 2010 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.clearsilver.jsilver.data;
18
19import com.google.clearsilver.jsilver.autoescape.EscapeMode;
20
21import java.io.IOException;
22import java.util.Map;
23
24/**
25 * Represents a hierarchical data set of primitives.
26 *
27 * This is the JSilver equivalent to ClearSilver's HDF object.
28 */
29public interface Data {
30
31  // ******************* Node data *******************
32
33  /**
34   * Returns the name of this HDF node. The root node has no name, so calling this on the root node
35   * will return null.
36   */
37  String getName();
38
39  /**
40   * Returns the value of this HDF node, or null if this node has no value. Every node in the tree
41   * can have a value, a child, and a next peer.
42   */
43  String getValue();
44
45  /**
46   * Returns the integer value of this HDF node, or 0 if this node has no value.
47   *
48   * Note: The fact that this method returns a primitive type, rather than an Integer means that its
49   * value cannot be used to determine whether the data node exists or not. Note also that, when
50   * implementing a Data object that caches these values, care must be taken to ensure that a node
51   * with an integer value of '0' is not mistaken for a non-existent node.
52   */
53  int getIntValue();
54
55  /**
56   * Returns the boolean value of this HDF node, or false if this node has no value.
57   *
58   * Note: The fact that this method returns a primitive type, rather than a Boolean means that its
59   * value cannot be used to determine whether the data node exists or not. Note also that, when
60   * implementing a Data object that caches these values, care must be taken to ensure that a node
61   * with a boolean value of 'false' is not mistaken for a non-existent node.
62   */
63  boolean getBooleanValue();
64
65  /**
66   * Set the value of this node. Any symlink that may have been set for this node will be replaced.
67   */
68  void setValue(String value);
69
70  /**
71   * Returns the full path to this node via its parent links.
72   */
73  String getFullPath();
74
75  // ******************* Attributes *******************
76
77  /**
78   * Sets an attribute key and value on the current node, replacing any existing value.
79   *
80   * @param key the name of the attribute to add/modify.
81   * @param value the value to assign it. Value of {@code null} will clear the attribute.
82   */
83  void setAttribute(String key, String value);
84
85  /**
86   * Returns the value of the node attribute with the given name, or {@code null} if there is no
87   * value.
88   */
89  String getAttribute(String key);
90
91  /**
92   * Returns {@code true} if the node contains an attribute with the given name, {@code false}
93   * otherwise.
94   */
95  boolean hasAttribute(String key);
96
97  /**
98   * Returns the number of attributes on this node.
99   */
100  int getAttributeCount();
101
102  /**
103   * Returns an iterable collection of attribute name/value pairs.
104   *
105   * @return an object that can be iterated over to get all the attribute name/value pairs. Should
106   *         return empty iterator if there are no attributes.
107   */
108  Iterable<Map.Entry<String, String>> getAttributes();
109
110  // ******************* Children *******************
111
112  /**
113   * Return the root of the tree where the current node lies. If the current node is the root,
114   * return this.
115   */
116  Data getRoot();
117
118  /**
119   * Get the parent node.
120   */
121  Data getParent();
122
123  /**
124   * Is this the first of its siblings?
125   */
126  boolean isFirstSibling();
127
128  /**
129   * Is this the last of its siblings?
130   */
131  boolean isLastSibling();
132
133  /**
134   * Retrieves the node representing the next sibling of this Data node, if any.
135   *
136   * @return the next sibling Data object or {@code null} if this is the last sibling.
137   */
138  Data getNextSibling();
139
140  /**
141   * Returns number of child nodes.
142   */
143  int getChildCount();
144
145  /**
146   * Returns children of this node.
147   */
148  Iterable<? extends Data> getChildren();
149
150  /**
151   * Retrieves the object that is the root of the subtree at hdfpath, returning null if the subtree
152   * doesn't exist
153   */
154  Data getChild(String path);
155
156  /**
157   * Retrieves the HDF object that is the root of the subtree at hdfpath, create the subtree if it
158   * doesn't exist
159   */
160  Data createChild(String path);
161
162  /**
163   * Remove the specified subtree.
164   */
165  void removeTree(String path);
166
167  // ******************* Symbolic links *******************
168
169  /**
170   * Set the source node to be a symbolic link to the destination.
171   */
172  void setSymlink(String sourcePath, String destinationPath);
173
174  /**
175   * Set the source node to be a symbolic link to the destination.
176   */
177  void setSymlink(String sourcePath, Data destination);
178
179  /**
180   * Set this node to be a symbolic link to another node.
181   */
182  void setSymlink(Data symLink);
183
184  /**
185   * Retrieve the symbolic link this node points to. Will return reference to self if not a symlink.
186   */
187  Data getSymlink();
188
189  // **************************** Copy **************************
190
191  /**
192   * Does a deep copy of the attributes and values from one node to another.
193   *
194   * @param toPath destination path for the deep copy.
195   * @param from Data object that should be copied over.
196   */
197  void copy(String toPath, Data from);
198
199  /**
200   * Does a deep copy the attributes and values from one node to another
201   *
202   * @param from Data object whose value should be copied over.
203   */
204  void copy(Data from);
205
206  // ******************* Convenience methods *******************
207
208  /**
209   * Retrieves the value at the specified path in this HDF node's subtree.
210   */
211  String getValue(String path, String defaultValue);
212
213  /**
214   * Retrieves the integer value at the specified path in this HDF node's subtree. If the value does
215   * not exist, or cannot be converted to an integer, default_value will be returned.
216   */
217  int getIntValue(String path, int defaultValue);
218
219  /**
220   * Retrieves the value at the specified path in this HDF node's subtree. If not found, returns
221   * null.
222   */
223  String getValue(String path);
224
225  /**
226   * Retrieves the value at the specified path in this HDF node's subtree. If not found or invalid,
227   * returns 0.
228   */
229  int getIntValue(String path);
230
231  /**
232   * Retrieves the value at the specified path in this HDF node's subtree. If not found or invalid,
233   * returns false.
234   */
235  boolean getBooleanValue(String path);
236
237  /**
238   * Sets the value at the specified path in this HDF node's subtree.
239   */
240  void setValue(String path, String value);
241
242  // ******************* String representation *******************
243
244  String toString();
245
246  void toString(StringBuilder out, int indent);
247
248  /**
249   * Write out the String representation of this HDF node.
250   */
251  void write(Appendable out, int indent) throws IOException;
252
253  /**
254   * Optimizes the Data structure for performance. This is a somewhat expensive operation that
255   * should improve CPU and/or memory usage for long-lived Data objects. For example, it may
256   * internalize all Strings to reduce redundant copies.
257   */
258  void optimize();
259
260  /**
261   * Indicates the escaping, if any that was applied to this HDF node.
262   *
263   * @return EscapeMode that was applied to this node's value. {@code EscapeMode.ESCAPE_NONE} if the
264   *         value is not escaped. {@code EscapeMode.ESCAPE_IS_CONSTANT} if value is a string or
265   *         numeric literal.
266   *
267   * @see #setEscapeMode
268   * @see EscapeMode
269   */
270  EscapeMode getEscapeMode();
271
272  /**
273   * Set the escaping that was applied to this HDF node. This method may be called by the template
274   * renderer, for instance, when a "set" command sets the node to a constant string. It may also be
275   * explicitly called if populating the HDF with pre-escaped or trusted values.
276   *
277   * @see #getEscapeMode
278   */
279  void setEscapeMode(EscapeMode mode);
280}
281