View Javadoc

1   /*
2    * Copyright 2008 Google Inc.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5    * use this file except in compliance with the License. You may obtain a copy of
6    * 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, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations under
14   * the License.
15   */
16  package org.vectomatic.dev.svg.impl.gen;
17  
18  import java.net.URL;
19  import java.util.HashMap;
20  import java.util.Map;
21  
22  import org.vectomatic.dom.svg.impl.ExternalSVGResourcePrototype;
23  import org.vectomatic.dom.svg.ui.SVGResource;
24  import org.vectomatic.dom.svg.ui.ExternalSVGResource.Validated;
25  
26  import com.google.gwt.core.ext.Generator;
27  import com.google.gwt.core.ext.TreeLogger;
28  import com.google.gwt.core.ext.UnableToCompleteException;
29  import com.google.gwt.core.ext.typeinfo.JClassType;
30  import com.google.gwt.core.ext.typeinfo.JMethod;
31  import com.google.gwt.core.ext.typeinfo.JType;
32  import com.google.gwt.core.ext.typeinfo.TypeOracle;
33  import com.google.gwt.dev.util.Util;
34  import com.google.gwt.resources.ext.AbstractResourceGenerator;
35  import com.google.gwt.resources.ext.ClientBundleFields;
36  import com.google.gwt.resources.ext.ClientBundleRequirements;
37  import com.google.gwt.resources.ext.ResourceContext;
38  import com.google.gwt.resources.ext.ResourceGeneratorUtil;
39  import com.google.gwt.user.rebind.SourceWriter;
40  import com.google.gwt.user.rebind.StringSourceWriter;
41  
42  /**
43   * Implementation of ExternalSVGResource derived from Google's original
44   * ExternalTextResourceGenerator implementation
45   * @author laaglu
46   */
47  public class ExternalSVGResourceGenerator extends AbstractResourceGenerator {
48  	private StringBuffer data;
49  	private boolean first;
50  	private String urlExpression;
51  	private Map<String, Integer> hashes;
52  	private Map<String, Integer> offsets;
53  	private int currentIndex;
54  
55  	private String externalSVGUrlIdent;
56  
57  	private String externalSVGCacheIdent;
58  
59  	@Override
60  	public String createAssignment(TreeLogger logger, ResourceContext context,
61  			JMethod method) throws UnableToCompleteException {
62  		String name = method.getName();
63  
64  		SourceWriter sw = new StringSourceWriter();
65  		sw
66  				.println("new " + ExternalSVGResourcePrototype.class.getName()
67  						+ "(");
68  		sw.indent();
69  		sw.println('"' + name + "\",");
70  		// These are field names
71  		sw.println(externalSVGUrlIdent + ", " + externalSVGCacheIdent + ", ");
72  		sw.println(offsets.get(method.getName()).toString());
73  		sw.outdent();
74  		sw.print(")");
75  
76  		return sw.toString();
77  	}
78  
79  	@Override
80  	public void createFields(TreeLogger logger, ResourceContext context,
81  			ClientBundleFields fields) throws UnableToCompleteException {
82  		data.append(']');
83  
84  		urlExpression = context.deploy(context.getClientBundleType()
85  				.getQualifiedSourceName().replace('.', '_')
86  				+ "_jsonbundle.txt", "text/plain", data.toString().getBytes(),
87  				true);
88  
89  		TypeOracle typeOracle = context.getGeneratorContext().getTypeOracle();
90  		JClassType stringType = typeOracle.findType(String.class.getName());
91  		assert stringType != null;
92  
93  		externalSVGUrlIdent = fields.define(stringType, "externalSVGUrl",
94  				urlExpression, true, true);
95  
96  		JClassType textResourceType = typeOracle.findType(SVGResource.class
97  				.getName());
98  		assert textResourceType != null;
99  		JType textResourceArrayType = typeOracle.getArrayType(textResourceType);
100 
101 		externalSVGCacheIdent = fields.define(textResourceArrayType,
102 				"externalSVGCache", "new " + SVGResource.class.getName()
103 						+ "[" + currentIndex + "]", true, true);
104 	}
105 
106 	@Override
107 	public void init(TreeLogger logger, ResourceContext context)
108 			throws UnableToCompleteException {
109 		data = new StringBuffer("[\n");
110 		first = true;
111 		urlExpression = null;
112 		hashes = new HashMap<String, Integer>();
113 		offsets = new HashMap<String, Integer>();
114 		currentIndex = 0;
115 	}
116 
117 	@Override
118 	public void prepare(TreeLogger logger, ResourceContext context,
119 			ClientBundleRequirements requirements, JMethod method)
120 			throws UnableToCompleteException {
121 
122 		URL[] urls = ResourceGeneratorUtil.findResources(logger, context,
123 				method);
124 
125 		if (urls.length != 1) {
126 			logger.log(TreeLogger.ERROR,
127 					"Exactly one resource must be specified", null);
128 			throw new UnableToCompleteException();
129 		}
130 
131 		URL resource = urls[0];
132 
133 		String toWrite = Util.readURLAsString(resource);
134 		if (getValidated(method)) {
135 			SVGValidator.validate(toWrite, resource.toExternalForm(), logger, null);
136 		}
137 
138 		// This de-duplicates strings in the bundle.
139 		if (!hashes.containsKey(toWrite)) {
140 			hashes.put(toWrite, currentIndex++);
141 
142 			if (!first) {
143 				data.append(",\n");
144 			} else {
145 				first = false;
146 			}
147 
148 			data.append('"');
149 			data.append(Generator.escape(toWrite));
150 			data.append('"');
151 		}
152 
153 		// Store the (possibly n:1) mapping of resource function to bundle
154 		// index.
155 		offsets.put(method.getName(), hashes.get(toWrite));
156 	}
157 
158 	private boolean getValidated(JMethod method) {
159 		Validated validated = method.getAnnotation(Validated.class);
160 		if (validated == null) {
161 			return true;
162 		} else {
163 			return validated.validated();
164 		}
165 	}
166 }