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.Iterator; 23import 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 */ 29public class DelegatedData implements Data { 30 31 private final Data delegate; 32 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 */ 46 protected DelegatedData newInstance(Data newDelegate) { 47 return newDelegate == null ? null : new DelegatedData(newDelegate); 48 } 49 50 protected Data getDelegate() { 51 return delegate; 52 } 53 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 62 public String getName() { 63 return getDelegate().getName(); 64 } 65 66 @Override 67 public String getValue() { 68 return getDelegate().getValue(); 69 } 70 71 @Override 72 public int getIntValue() { 73 return getDelegate().getIntValue(); 74 } 75 76 @Override 77 public boolean getBooleanValue() { 78 return getDelegate().getBooleanValue(); 79 } 80 81 @Override 82 public void setValue(String value) { 83 getDelegate().setValue(value); 84 } 85 86 @Override 87 public String getFullPath() { 88 return getDelegate().getFullPath(); 89 } 90 91 @Override 92 public void setAttribute(String key, String value) { 93 getDelegate().setAttribute(key, value); 94 } 95 96 @Override 97 public String getAttribute(String key) { 98 return getDelegate().getAttribute(key); 99 } 100 101 @Override 102 public boolean hasAttribute(String key) { 103 return getDelegate().hasAttribute(key); 104 } 105 106 @Override 107 public int getAttributeCount() { 108 return getDelegate().getAttributeCount(); 109 } 110 111 @Override 112 public Iterable<Map.Entry<String, String>> getAttributes() { 113 return getDelegate().getAttributes(); 114 } 115 116 @Override 117 public Data getRoot() { 118 return newInstance(getDelegate().getRoot()); 119 } 120 121 @Override 122 public Data getParent() { 123 return newInstance(getDelegate().getParent()); 124 } 125 126 @Override 127 public boolean isFirstSibling() { 128 return getDelegate().isFirstSibling(); 129 } 130 131 @Override 132 public boolean isLastSibling() { 133 return getDelegate().isLastSibling(); 134 } 135 136 @Override 137 public Data getNextSibling() { 138 return newInstance(getDelegate().getNextSibling()); 139 } 140 141 @Override 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 153 DelegatedIterator(Iterator<? extends Data> iterator) { 154 this.iterator = iterator; 155 } 156 157 public boolean hasNext() { 158 return iterator.hasNext(); 159 } 160 161 public DelegatedData next() { 162 return newInstance(iterator.next()); 163 } 164 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 */ 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 191 public Iterable<? extends Data> getChildren() { 192 return delegatedIterable; 193 } 194 195 @Override 196 public Data getChild(String path) { 197 return newInstance(getDelegate().getChild(path)); 198 } 199 200 @Override 201 public Data createChild(String path) { 202 return newInstance(getDelegate().createChild(path)); 203 } 204 205 @Override 206 public void removeTree(String path) { 207 getDelegate().removeTree(path); 208 } 209 210 @Override 211 public void setSymlink(String sourcePath, String destinationPath) { 212 getDelegate().setSymlink(sourcePath, destinationPath); 213 } 214 215 @Override 216 public void setSymlink(String sourcePath, Data destination) { 217 destination = unwrap(destination); 218 getDelegate().setSymlink(sourcePath, destination); 219 } 220 221 @Override 222 public void setSymlink(Data symLink) { 223 symLink = unwrap(symLink); 224 getDelegate().setSymlink(symLink); 225 } 226 227 @Override 228 public Data getSymlink() { 229 return newInstance(getDelegate().getSymlink()); 230 } 231 232 @Override 233 public void copy(String toPath, Data from) { 234 from = unwrap(from); 235 getDelegate().copy(toPath, from); 236 } 237 238 @Override 239 public void copy(Data from) { 240 from = unwrap(from); 241 getDelegate().copy(from); 242 } 243 244 @Override 245 public String getValue(String path, String defaultValue) { 246 return getDelegate().getValue(path, defaultValue); 247 } 248 249 @Override 250 public int getIntValue(String path, int defaultValue) { 251 return getDelegate().getIntValue(path, defaultValue); 252 } 253 254 @Override 255 public String getValue(String path) { 256 return getDelegate().getValue(path); 257 } 258 259 @Override 260 public int getIntValue(String path) { 261 return getDelegate().getIntValue(path); 262 } 263 264 @Override 265 public boolean getBooleanValue(String path) { 266 return getDelegate().getBooleanValue(path); 267 } 268 269 @Override 270 public void setValue(String path, String value) { 271 getDelegate().setValue(path, value); 272 } 273 274 @Override 275 public String toString() { 276 return getDelegate().toString(); 277 } 278 279 @Override 280 public void toString(StringBuilder out, int indent) { 281 getDelegate().toString(out, indent); 282 } 283 284 @Override 285 public void write(Appendable out, int indent) throws IOException { 286 getDelegate().write(out, indent); 287 } 288 289 @Override 290 public void optimize() { 291 getDelegate().optimize(); 292 } 293 294 @Override 295 public void setEscapeMode(EscapeMode mode) { 296 getDelegate().setEscapeMode(mode); 297 } 298 299 @Override 300 public EscapeMode getEscapeMode() { 301 return getDelegate().getEscapeMode(); 302 } 303} 304