1 52 53 package freemarker.core; 54 55 import java.util.*; 56 import java.io.IOException ; 57 import javax.swing.tree.TreeNode ; 58 import freemarker.template.*; 59 import freemarker.template.utility.Collections12; 60 61 66 abstract public class TemplateElement extends TemplateObject implements TreeNode { 67 68 TemplateElement parent; 69 70 72 TemplateElement nestedBlock; 73 74 List nestedElements; 75 76 82 abstract void accept(Environment env) throws TemplateException, IOException ; 83 84 abstract public String getDescription(); 85 86 88 public TemplateNodeModel getParentNode() { 89 return null; 91 } 92 93 public String getNodeNamespace() { 94 return null; 95 } 96 97 public String getNodeType() { 98 return "element"; 99 } 100 101 public TemplateSequenceModel getChildNodes() { 102 if (nestedElements != null) { 103 return new SimpleSequence(nestedElements); 104 } 105 SimpleSequence result = null; 106 if (nestedBlock != null) { 107 result.add(nestedBlock); 108 } 109 return result; 110 } 111 112 public String getNodeName() { 113 String classname = this.getClass().getName(); 114 int shortNameOffset = classname.lastIndexOf('.')+1; 115 return classname.substring(shortNameOffset); 116 } 117 118 120 public boolean isLeaf() { 121 return nestedBlock == null 122 && (nestedElements == null || nestedElements.isEmpty()); 123 } 124 125 public boolean getAllowsChildren() { 126 return !isLeaf(); 127 } 128 129 public int getIndex(TreeNode node) { 130 if (nestedBlock instanceof MixedContent) { 131 return nestedBlock.getIndex(node); 132 } 133 if (nestedBlock != null) { 134 if (node == nestedBlock) { 135 return 0; 136 } 137 } 138 else if (nestedElements != null) { 139 return nestedElements.indexOf(node); 140 } 141 return -1; 142 } 143 144 public int getChildCount() { 145 if (nestedBlock instanceof MixedContent) { 146 return nestedBlock.getChildCount(); 147 } 148 if (nestedBlock != null) { 149 return 1; 150 } 151 else if (nestedElements != null) { 152 return nestedElements.size(); 153 } 154 return 0; 155 } 156 157 public Enumeration children() { 158 if (nestedBlock instanceof MixedContent) { 159 return nestedBlock.children(); 160 } 161 if (nestedBlock != null) { 162 return Collections.enumeration(Collections12.singletonList(nestedBlock)); 163 } 164 else if (nestedElements != null) { 165 return Collections.enumeration(nestedElements); 166 } 167 return Collections.enumeration(Collections.EMPTY_LIST); 168 } 169 170 public TreeNode getChildAt(int index) { 171 if (nestedBlock instanceof MixedContent) { 172 return nestedBlock.getChildAt(index); 173 } 174 if (nestedBlock != null) { 175 if (index == 0) { 176 return nestedBlock; 177 } 178 throw new ArrayIndexOutOfBoundsException ("invalid index"); 179 } 180 else if (nestedElements != null) { 181 return(TreeNode ) nestedElements.get(index); 182 } 183 throw new ArrayIndexOutOfBoundsException ("element has no children"); 184 } 185 186 public void setChildAt(int index, TemplateElement element) { 187 if(nestedBlock instanceof MixedContent) { 188 nestedBlock.setChildAt(index, element); 189 } 190 else if(nestedBlock != null) { 191 if(index == 0) { 192 nestedBlock = element; 193 element.parent = this; 194 } 195 else { 196 throw new IndexOutOfBoundsException ("invalid index"); 197 } 198 } 199 else if(nestedElements != null) { 200 nestedElements.set(index, element); 201 element.parent = this; 202 } 203 else { 204 throw new IndexOutOfBoundsException ("element has no children"); 205 } 206 } 207 208 public TreeNode getParent() { 209 return parent; 210 } 211 212 214 void setParentRecursively(TemplateElement parent) { 215 this.parent = parent; 216 int nestedSize = nestedElements == null ? 0 : nestedElements.size(); 217 for (int i = 0; i < nestedSize; i++) { 218 ((TemplateElement) nestedElements.get(i)).setParentRecursively(this); 219 } 220 if (nestedBlock != null) { 221 nestedBlock.setParentRecursively(this); 222 } 223 } 224 225 229 TemplateElement postParseCleanup(boolean stripWhitespace) throws ParseException { 230 if (nestedElements != null) { 231 for (int i = 0; i < nestedElements.size(); i++) { 232 TemplateElement te = (TemplateElement) nestedElements.get(i); 233 te = te.postParseCleanup(stripWhitespace); 234 nestedElements.set(i, te); 235 te.parent = this; 236 } 237 if (stripWhitespace) { 238 for (Iterator it = nestedElements.iterator(); it.hasNext();) { 239 TemplateElement te = (TemplateElement) it.next(); 240 if (te.isIgnorable()) { 241 it.remove(); 242 } 243 } 244 } 245 if (nestedElements instanceof ArrayList) { 246 ((ArrayList) nestedElements).trimToSize(); 247 } 248 } 249 if (nestedBlock != null) { 250 nestedBlock = nestedBlock.postParseCleanup(stripWhitespace); 251 if (nestedBlock.isIgnorable()) { 252 nestedBlock = null; 253 } else { 254 nestedBlock.parent = this; 255 } 256 } 257 return this; 258 } 259 260 boolean isIgnorable() { 261 return false; 262 } 263 264 267 TemplateElement prevTerminalNode() { 268 TemplateElement prev = previousSibling(); 269 if (prev != null) { 270 return prev.getLastLeaf(); 271 } 272 else if (parent != null) { 273 return parent.prevTerminalNode(); 274 } 275 return null; 276 } 277 278 TemplateElement nextTerminalNode() { 279 TemplateElement next = nextSibling(); 280 if (next != null) { 281 return next.getFirstLeaf(); 282 } 283 else if (parent != null) { 284 return parent.nextTerminalNode(); 285 } 286 return null; 287 } 288 289 290 291 TemplateElement previousSibling() { 292 if (parent == null) { 293 return null; 294 } 295 List siblings = parent.nestedElements; 296 if (siblings == null) { 297 return null; 298 } 299 for (int i = siblings.size() - 1; i>=0; i--) { 300 if (siblings.get(i) == this) { 301 return(i >0) ? (TemplateElement) siblings.get(i-1) : null; 302 } 303 } 304 return null; 305 } 306 307 TemplateElement nextSibling() { 308 if (parent == null) { 309 return null; 310 } 311 List siblings = parent.nestedElements; 312 if (siblings == null) { 313 return null; 314 } 315 for (int i = 0; i < siblings.size(); i++) { 316 if (siblings.get(i) == this) { 317 return (i+1) < siblings.size() ? (TemplateElement) siblings.get(i+1) : null; 318 } 319 } 320 return null; 321 } 322 323 private TemplateElement getFirstChild() { 324 if (nestedBlock != null) { 325 return nestedBlock; 326 } 327 if (nestedElements != null && nestedElements.size() >0) { 328 return(TemplateElement) nestedElements.get(0); 329 } 330 return null; 331 } 332 333 private TemplateElement getLastChild() { 334 if (nestedBlock != null) { 335 return nestedBlock; 336 } 337 if (nestedElements != null && nestedElements.size() >0) { 338 return(TemplateElement) nestedElements.get(nestedElements.size() -1); 339 } 340 return null; 341 } 342 343 344 private TemplateElement getFirstLeaf() { 345 TemplateElement te = this; 346 while (!te.isLeaf() && !(te instanceof Macro) && !(te instanceof BlockAssignment)) { 347 te = te.getFirstChild(); 349 } 350 return te; 351 } 352 353 private TemplateElement getLastLeaf() { 354 TemplateElement te = this; 355 while (!te.isLeaf() && !(te instanceof Macro) && !(te instanceof BlockAssignment)) { 356 te = te.getLastChild(); 358 } 359 return te; 360 } 361 362 367 boolean heedsOpeningWhitespace() { 368 return false; 369 } 370 371 376 boolean heedsTrailingWhitespace() { 377 return false; 378 } 379 } 380 | Popular Tags |