JHdf.java revision 56ed4167b942ec265f9cee70ac4d71d10b3835ce
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.adaptor;
18
19import com.google.clearsilver.jsilver.JSilverOptions;
20import com.google.clearsilver.jsilver.data.Data;
21import com.google.clearsilver.jsilver.data.DataFactory;
22import com.google.clearsilver.jsilver.data.Parser;
23import com.google.clearsilver.jsilver.exceptions.JSilverBadSyntaxException;
24
25import org.clearsilver.CSFileLoader;
26import org.clearsilver.HDF;
27
28import java.io.FileWriter;
29import java.io.IOException;
30import java.io.StringReader;
31import java.util.Date;
32import java.util.TimeZone;
33
34/**
35 * Adaptor that wraps a JSilver Data object so it can be used as an HDF object.
36 */
37public class JHdf implements HDF {
38
39  // Only changed to null on close()
40  private Data data;
41  private final DataFactory dataFactory;
42  private final JSilverOptions options;
43
44  private final LoadPathToFileCache loadPathCache;
45  private ResourceLoaderAdaptor resourceLoader;
46
47
48  JHdf(Data data, DataFactory dataFactory, LoadPathToFileCache loadPathCache, JSilverOptions options) {
49    this.data = data;
50    this.loadPathCache = loadPathCache;
51    this.dataFactory = dataFactory;
52    this.options = options;
53    this.resourceLoader = new ResourceLoaderAdaptor(this, loadPathCache, null);
54  }
55
56  static JHdf cast(HDF hdf) {
57    if (!(hdf instanceof JHdf)) {
58      throw new IllegalArgumentException("HDF object not of type JHdf.  "
59          + "Make sure you use the same ClearsilverFactory to construct all "
60          + "related HDF and CS objects.");
61    }
62    return (JHdf) hdf;
63  }
64
65  Data getData() {
66    return data;
67  }
68
69  ResourceLoaderAdaptor getResourceLoaderAdaptor() {
70    return resourceLoader;
71  }
72
73  @Override
74  public void close() {
75    // This looks pointless but it actually reduces the lifetime of the large
76    // Data object as far as the garbage collector is concerned and
77    // dramatically improves performance.
78    data = null;
79  }
80
81  @Override
82  public boolean readFile(String filename) throws IOException {
83    dataFactory.loadData(filename, resourceLoader, data);
84    return false;
85  }
86
87  @Override
88  public CSFileLoader getFileLoader() {
89    return resourceLoader.getCSFileLoader();
90  }
91
92  @Override
93  public void setFileLoader(CSFileLoader fileLoader) {
94    this.resourceLoader = new ResourceLoaderAdaptor(this, loadPathCache, fileLoader);
95  }
96
97  @Override
98  public boolean writeFile(String filename) throws IOException {
99    FileWriter writer = new FileWriter(filename);
100    try {
101      data.write(writer, 2);
102    } finally {
103      writer.close();
104    }
105    return true;
106  }
107
108  @Override
109  public boolean readString(String content) {
110    Parser hdfParser = dataFactory.getParser();
111    try {
112      hdfParser.parse(new StringReader(content), data, new Parser.ErrorHandler() {
113        public void error(int line, String lineContent, String fileName, String errorMessage) {
114          throw new JSilverBadSyntaxException("HDF parsing error : '" + errorMessage + "'",
115              lineContent, fileName, line, JSilverBadSyntaxException.UNKNOWN_POSITION, null);
116        }
117      }, resourceLoader, null, options.getIgnoreAttributes());
118      return true;
119    } catch (IOException e) {
120      return false;
121    }
122  }
123
124  @Override
125  public int getIntValue(String hdfName, int defaultValue) {
126    return data.getIntValue(hdfName, defaultValue);
127  }
128
129  @Override
130  public String getValue(String hdfName, String defaultValue) {
131    return data.getValue(hdfName, defaultValue);
132  }
133
134  @Override
135  public void setValue(String hdfName, String value) {
136    data.setValue(hdfName, value);
137  }
138
139  @Override
140  public void removeTree(String hdfName) {
141    data.removeTree(hdfName);
142  }
143
144  @Override
145  public void setSymLink(String hdfNameSrc, String hdfNameDest) {
146    data.setSymlink(hdfNameSrc, hdfNameDest);
147  }
148
149  @Override
150  public void exportDate(String hdfName, TimeZone timeZone, Date date) {
151    throw new UnsupportedOperationException("TBD");
152  }
153
154  @Override
155  public void exportDate(String hdfName, String tz, int tt) {
156    throw new UnsupportedOperationException("TBD");
157  }
158
159  @Override
160  public HDF getObj(String hdfpath) {
161    Data d = data.getChild(hdfpath);
162    return d == null ? null : new JHdf(d, dataFactory, loadPathCache, options);
163  }
164
165  @Override
166  public HDF getChild(String hdfpath) {
167    Data d = data.getChild(hdfpath);
168    if (d == null) {
169      return null;
170    }
171    for (Data child : d.getChildren()) {
172      if (child.isFirstSibling()) {
173        return new JHdf(child, dataFactory, loadPathCache, options);
174      } else {
175        // The first child returned should be the first sibling. Throw an error
176        // if not.
177        throw new IllegalStateException("First child was not first sibling.");
178      }
179    }
180    return null;
181  }
182
183  @Override
184  public HDF getRootObj() {
185    Data root = data.getRoot();
186    if (root == data) {
187      return this;
188    } else {
189      return new JHdf(root, dataFactory, loadPathCache, options);
190    }
191  }
192
193  @Override
194  public boolean belongsToSameRoot(HDF hdf) {
195    JHdf jHdf = cast(hdf);
196    return this.data.getRoot() == jHdf.data.getRoot();
197  }
198
199  @Override
200  public HDF getOrCreateObj(String hdfpath) {
201    return new JHdf(data.createChild(hdfpath), dataFactory, loadPathCache, options);
202  }
203
204  @Override
205  public String objName() {
206    return data.getName();
207  }
208
209  @Override
210  public String objValue() {
211    return data.getValue();
212  }
213
214  @Override
215  public HDF objChild() {
216    for (Data child : data.getChildren()) {
217      if (child.isFirstSibling()) {
218        return new JHdf(child, dataFactory, loadPathCache, options);
219      }
220    }
221    return null;
222  }
223
224  @Override
225  public HDF objNext() {
226    Data next = data.getNextSibling();
227    return next == null ? null : new JHdf(next, dataFactory, loadPathCache, options);
228  }
229
230  @Override
231  public void copy(String hdfpath, HDF src) {
232    JHdf srcJHdf = cast(src);
233    if (hdfpath.equals("")) {
234      data.copy(srcJHdf.data);
235    } else {
236      data.copy(hdfpath, srcJHdf.data);
237    }
238  }
239
240  @Override
241  public String dump() {
242    StringBuilder sb = new StringBuilder();
243    try {
244      data.write(sb, 0);
245      return sb.toString();
246    } catch (IOException e) {
247      return null;
248    }
249  }
250
251  @Override
252  public String writeString() {
253    return dump();
254  }
255
256  @Override
257  public String toString() {
258    return dump();
259  }
260
261  /**
262   * JSilver-specific method that optimizes the underlying data object. Should only be used on
263   * long-lived HDF objects (e.g. global HDF).
264   */
265  public void optimize() {
266    data.optimize();
267  }
268}
269