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 17 package com.google.clearsilver.jsilver.data; 18 19 import com.google.clearsilver.jsilver.autoescape.EscapeMode; 20 21 import java.io.IOException; 22 import 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 */ 29 public 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 */ getName()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 */ getValue()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 */ getIntValue()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 */ getBooleanValue()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 */ setValue(String value)68 void setValue(String value); 69 70 /** 71 * Returns the full path to this node via its parent links. 72 */ getFullPath()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 */ setAttribute(String key, String value)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 */ getAttribute(String key)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 */ hasAttribute(String key)95 boolean hasAttribute(String key); 96 97 /** 98 * Returns the number of attributes on this node. 99 */ getAttributeCount()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 */ getAttributes()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 */ getRoot()116 Data getRoot(); 117 118 /** 119 * Get the parent node. 120 */ getParent()121 Data getParent(); 122 123 /** 124 * Is this the first of its siblings? 125 */ isFirstSibling()126 boolean isFirstSibling(); 127 128 /** 129 * Is this the last of its siblings? 130 */ isLastSibling()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 */ getNextSibling()138 Data getNextSibling(); 139 140 /** 141 * Returns number of child nodes. 142 */ getChildCount()143 int getChildCount(); 144 145 /** 146 * Returns children of this node. 147 */ getChildren()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 */ getChild(String path)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 */ createChild(String path)160 Data createChild(String path); 161 162 /** 163 * Remove the specified subtree. 164 */ removeTree(String path)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 */ setSymlink(String sourcePath, String destinationPath)172 void setSymlink(String sourcePath, String destinationPath); 173 174 /** 175 * Set the source node to be a symbolic link to the destination. 176 */ setSymlink(String sourcePath, Data destination)177 void setSymlink(String sourcePath, Data destination); 178 179 /** 180 * Set this node to be a symbolic link to another node. 181 */ setSymlink(Data symLink)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 */ getSymlink()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 */ copy(String toPath, Data from)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 */ copy(Data from)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 */ getValue(String path, String defaultValue)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 */ getIntValue(String path, int defaultValue)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 */ getValue(String path)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 */ getIntValue(String path)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 */ getBooleanValue(String path)235 boolean getBooleanValue(String path); 236 237 /** 238 * Sets the value at the specified path in this HDF node's subtree. 239 */ setValue(String path, String value)240 void setValue(String path, String value); 241 242 // ******************* String representation ******************* 243 toString()244 String toString(); 245 toString(StringBuilder out, int indent)246 void toString(StringBuilder out, int indent); 247 248 /** 249 * Write out the String representation of this HDF node. 250 */ write(Appendable out, int indent)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 */ optimize()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 */ getEscapeMode()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 */ setEscapeMode(EscapeMode mode)279 void setEscapeMode(EscapeMode mode); 280 } 281