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.Iterator; 23 import java.util.Map; 24 25 /** 26 * Class that wraps a Data object and exports the same interface. Useful for extending the 27 * capabilities of an existing implementation. 28 */ 29 public class DelegatedData implements Data { 30 31 private final Data delegate; 32 DelegatedData(Data delegate)33 public DelegatedData(Data delegate) { 34 if (delegate == null) { 35 throw new NullPointerException("Delegate Data must not be null."); 36 } 37 this.delegate = delegate; 38 } 39 40 /** 41 * Subclasses will want to override this method to return a Data object of their specific type. 42 * 43 * @param newDelegate the Data object to wrap with a new delegator 44 * @return a DelegateData type or subclass. 45 */ newInstance(Data newDelegate)46 protected DelegatedData newInstance(Data newDelegate) { 47 return newDelegate == null ? null : new DelegatedData(newDelegate); 48 } 49 getDelegate()50 protected Data getDelegate() { 51 return delegate; 52 } 53 unwrap(Data data)54 protected static Data unwrap(Data data) { 55 if (data instanceof DelegatedData) { 56 data = ((DelegatedData) data).getDelegate(); 57 } 58 return data; 59 } 60 61 @Override getName()62 public String getName() { 63 return getDelegate().getName(); 64 } 65 66 @Override getValue()67 public String getValue() { 68 return getDelegate().getValue(); 69 } 70 71 @Override getIntValue()72 public int getIntValue() { 73 return getDelegate().getIntValue(); 74 } 75 76 @Override getBooleanValue()77 public boolean getBooleanValue() { 78 return getDelegate().getBooleanValue(); 79 } 80 81 @Override setValue(String value)82 public void setValue(String value) { 83 getDelegate().setValue(value); 84 } 85 86 @Override getFullPath()87 public String getFullPath() { 88 return getDelegate().getFullPath(); 89 } 90 91 @Override setAttribute(String key, String value)92 public void setAttribute(String key, String value) { 93 getDelegate().setAttribute(key, value); 94 } 95 96 @Override getAttribute(String key)97 public String getAttribute(String key) { 98 return getDelegate().getAttribute(key); 99 } 100 101 @Override hasAttribute(String key)102 public boolean hasAttribute(String key) { 103 return getDelegate().hasAttribute(key); 104 } 105 106 @Override getAttributeCount()107 public int getAttributeCount() { 108 return getDelegate().getAttributeCount(); 109 } 110 111 @Override getAttributes()112 public Iterable<Map.Entry<String, String>> getAttributes() { 113 return getDelegate().getAttributes(); 114 } 115 116 @Override getRoot()117 public Data getRoot() { 118 return newInstance(getDelegate().getRoot()); 119 } 120 121 @Override getParent()122 public Data getParent() { 123 return newInstance(getDelegate().getParent()); 124 } 125 126 @Override isFirstSibling()127 public boolean isFirstSibling() { 128 return getDelegate().isFirstSibling(); 129 } 130 131 @Override isLastSibling()132 public boolean isLastSibling() { 133 return getDelegate().isLastSibling(); 134 } 135 136 @Override getNextSibling()137 public Data getNextSibling() { 138 return newInstance(getDelegate().getNextSibling()); 139 } 140 141 @Override getChildCount()142 public int getChildCount() { 143 return getDelegate().getChildCount(); 144 } 145 146 /** 147 * Wrapping implementation of iterator that makes sure any Data object returned by the underlying 148 * iterator is wrapped with the right DelegatedData type. 149 */ 150 protected class DelegatedIterator implements Iterator<DelegatedData> { 151 private final Iterator<? extends Data> iterator; 152 DelegatedIterator(Iterator<? extends Data> iterator)153 DelegatedIterator(Iterator<? extends Data> iterator) { 154 this.iterator = iterator; 155 } 156 hasNext()157 public boolean hasNext() { 158 return iterator.hasNext(); 159 } 160 next()161 public DelegatedData next() { 162 return newInstance(iterator.next()); 163 } 164 remove()165 public void remove() { 166 iterator.remove(); 167 } 168 } 169 170 /** 171 * Subclasses can override this method to return specialized child iterators. For example, if they 172 * don't want to support the remove() operation. 173 * 174 * @return Iterator of children of delegate Data object that returns wrapped Data nodes. 175 */ newChildIterator()176 protected Iterator<DelegatedData> newChildIterator() { 177 return new DelegatedIterator(getDelegate().getChildren().iterator()); 178 } 179 180 /** 181 * Single Iterable object for each node. All it does is return a DelegatedIterator when asked for 182 * iterator. 183 */ 184 private final Iterable<DelegatedData> delegatedIterable = new Iterable<DelegatedData>() { 185 public Iterator<DelegatedData> iterator() { 186 return newChildIterator(); 187 } 188 }; 189 190 @Override getChildren()191 public Iterable<? extends Data> getChildren() { 192 return delegatedIterable; 193 } 194 195 @Override getChild(String path)196 public Data getChild(String path) { 197 return newInstance(getDelegate().getChild(path)); 198 } 199 200 @Override createChild(String path)201 public Data createChild(String path) { 202 return newInstance(getDelegate().createChild(path)); 203 } 204 205 @Override removeTree(String path)206 public void removeTree(String path) { 207 getDelegate().removeTree(path); 208 } 209 210 @Override setSymlink(String sourcePath, String destinationPath)211 public void setSymlink(String sourcePath, String destinationPath) { 212 getDelegate().setSymlink(sourcePath, destinationPath); 213 } 214 215 @Override setSymlink(String sourcePath, Data destination)216 public void setSymlink(String sourcePath, Data destination) { 217 destination = unwrap(destination); 218 getDelegate().setSymlink(sourcePath, destination); 219 } 220 221 @Override setSymlink(Data symLink)222 public void setSymlink(Data symLink) { 223 symLink = unwrap(symLink); 224 getDelegate().setSymlink(symLink); 225 } 226 227 @Override getSymlink()228 public Data getSymlink() { 229 return newInstance(getDelegate().getSymlink()); 230 } 231 232 @Override copy(String toPath, Data from)233 public void copy(String toPath, Data from) { 234 from = unwrap(from); 235 getDelegate().copy(toPath, from); 236 } 237 238 @Override copy(Data from)239 public void copy(Data from) { 240 from = unwrap(from); 241 getDelegate().copy(from); 242 } 243 244 @Override getValue(String path, String defaultValue)245 public String getValue(String path, String defaultValue) { 246 return getDelegate().getValue(path, defaultValue); 247 } 248 249 @Override getIntValue(String path, int defaultValue)250 public int getIntValue(String path, int defaultValue) { 251 return getDelegate().getIntValue(path, defaultValue); 252 } 253 254 @Override getValue(String path)255 public String getValue(String path) { 256 return getDelegate().getValue(path); 257 } 258 259 @Override getIntValue(String path)260 public int getIntValue(String path) { 261 return getDelegate().getIntValue(path); 262 } 263 264 @Override getBooleanValue(String path)265 public boolean getBooleanValue(String path) { 266 return getDelegate().getBooleanValue(path); 267 } 268 269 @Override setValue(String path, String value)270 public void setValue(String path, String value) { 271 getDelegate().setValue(path, value); 272 } 273 274 @Override toString()275 public String toString() { 276 return getDelegate().toString(); 277 } 278 279 @Override toString(StringBuilder out, int indent)280 public void toString(StringBuilder out, int indent) { 281 getDelegate().toString(out, indent); 282 } 283 284 @Override write(Appendable out, int indent)285 public void write(Appendable out, int indent) throws IOException { 286 getDelegate().write(out, indent); 287 } 288 289 @Override optimize()290 public void optimize() { 291 getDelegate().optimize(); 292 } 293 294 @Override setEscapeMode(EscapeMode mode)295 public void setEscapeMode(EscapeMode mode) { 296 getDelegate().setEscapeMode(mode); 297 } 298 299 @Override getEscapeMode()300 public EscapeMode getEscapeMode() { 301 return getDelegate().getEscapeMode(); 302 } 303 } 304