7 package com.google.appinventor.components.scripts;
12 import java.io.IOException;
13 import java.io.Writer;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.List;
20 import javax.tools.Diagnostic;
21 import javax.tools.FileObject;
83 private static final String OUTPUT_FILE_NAME =
"simple_components.json";
85 private void outputComponent(
ComponentInfo component, StringBuilder sb) {
86 sb.append(
"{ \"type\": \"");
87 sb.append(component.
type);
88 sb.append(
"\",\n \"name\": \"");
89 sb.append(component.name);
90 sb.append(
"\",\n \"external\": \"");
91 sb.append(Boolean.toString(component.
external));
92 sb.append(
"\",\n \"version\": \"");
94 if (component.getVersionName() !=
null && !component.getVersionName().equals(
"")) {
95 sb.append(
"\",\n \"versionName\": \"");
96 sb.append(component.getVersionName());
98 sb.append(
"\",\n \"dateBuilt\": \"");
99 sb.append(component.getDateBuilt());
100 sb.append(
"\",\n \"categoryString\": \"");
102 sb.append(
"\",\n \"helpString\": ");
104 sb.append(
",\n \"helpUrl\": ");
105 sb.append(formatDescription(component.
getHelpUrl()));
106 sb.append(
",\n \"showOnPalette\": \"");
108 sb.append(
"\",\n \"nonVisible\": \"");
109 sb.append(component.getNonVisible());
110 sb.append(
"\",\n \"iconName\": \"");
111 sb.append(component.getIconName());
112 sb.append(
"\",\n \"androidMinSdk\": ");
113 sb.append(component.getAndroidMinSdk());
114 outputConditionalAnnotations(component, sb);
115 sb.append(
",\n \"properties\": [");
116 String separator =
"";
117 Set<String> alwaysSendProperties =
new HashSet<String>();
118 Map<String, String> defaultValues =
new HashMap<String, String>();
120 String propertyName = entry.getKey();
122 sb.append(separator);
124 alwaysSendProperties.add(propertyName);
129 outputProperty(propertyName, dp, sb);
135 sb.append(
"],\n \"blockProperties\": [");
137 for (Property prop : component.
properties.values()) {
138 sb.append(separator);
143 outputBlockProperty(prop.name, prop, alwaysSendProperties.contains(prop.name), defaultValues.get(prop.name), sb);
146 sb.append(
"],\n \"events\": [");
149 sb.append(separator);
150 outputBlockEvent(event.name, event, sb, event.userVisible, event.deprecated);
153 sb.append(
"],\n \"methods\": [");
156 sb.append(separator);
157 outputBlockMethod(method.name, method, sb, method.userVisible, method.deprecated);
163 sb.append(
",\n \"assets\": [");
164 for (String asset : component.
assets) {
166 sb.append(asset.replaceAll(
"\\\\",
"\\\\").replaceAll(
"\"",
"\\\""));
169 sb.setLength(sb.length() - 1);
184 private static void outputMultimap(StringBuilder sb, String indent, Map<String, String[]> map) {
185 boolean first =
true;
187 for (Map.Entry<String, String[]> entry : map.entrySet()) {
188 if (!first) sb.append(
",");
192 sb.append(entry.getKey());
193 sb.append(
"\": [\n");
196 StringUtils.join(sb,
"\",\n" + indent +
" \"", entry.getValue());
214 private void outputConditionalAnnotations(
ComponentInfo component, StringBuilder sb) {
221 sb.append(
",\n \"conditionals\":{\n ");
222 boolean first =
true;
224 sb.append(
"\"permissions\": ");
229 if (!first) sb.append(
",\n ");
230 sb.append(
"\"broadcastReceivers\": ");
235 if (!first) sb.append(
",\n ");
236 sb.append(
"\"services\": ");
241 if (!first) sb.append(
",\n ");
242 sb.append(
"\"contentProviders\": ");
250 private void outputProperty(String propertyName,
DesignerProperty dp, StringBuilder sb) {
251 sb.append(
"{ \"name\": \"");
252 sb.append(propertyName);
253 sb.append(
"\", \"editorType\": \"");
255 sb.append(
"\", \"defaultValue\": \"");
258 sb.append(
"\", \"editorArgs\": ");
260 for (
int idx = 0; idx < editorArgs.length; idx += 1)
261 editorArgs[idx] =
"\"" + editorArgs[idx].replace(
"\"",
"\\\"") +
"\"";
263 StringBuilder listLiteralBuilder =
new StringBuilder();
264 listLiteralBuilder.append(
"[");
266 if (editorArgs.length > 0) {
267 listLiteralBuilder.append(editorArgs[0]);
269 for (
int ind = 1; ind < editorArgs.length; ind += 1) {
270 listLiteralBuilder.append(
", ");
271 listLiteralBuilder.append(editorArgs[ind]);
275 listLiteralBuilder.append(
"]");
277 sb.append(listLiteralBuilder.toString());
279 sb.append(
", \"alwaysSend\": true");
293 private void outputBlockProperty(String propertyName, Property prop,
boolean alwaysSend, String defaultValue, StringBuilder sb) {
294 sb.append(
"{ \"name\": \"");
295 sb.append(propertyName);
296 sb.append(
"\", \"description\": ");
297 sb.append(formatDescription(prop.getDescription()));
298 sb.append(
", \"type\": \"");
299 sb.append(javaTypeToYailType(prop.getType()));
300 sb.append(
"\", \"rw\": \"");
301 sb.append(prop.isUserVisible() ? prop.getRwString() :
"invisible");
305 sb.append(
"\", \"deprecated\": \"");
306 sb.append(prop.isDeprecated());
309 sb.append(
", \"alwaysSend\": true, \"defaultValue\": \"");
310 sb.append(defaultValue.replaceAll(
"\"",
"\\\""));
316 private void outputBlockEvent(String eventName,
Event event, StringBuilder sb,
317 boolean userVisible,
boolean deprecated) {
318 sb.append(
"{ \"name\": \"");
319 sb.append(eventName);
320 sb.append(
"\", \"description\": ");
321 sb.append(formatDescription(event.description));
327 sb.append(
", \"deprecated\": \"" + deprecated +
"\"");
328 sb.append(
", \"params\": ");
333 private void outputBlockMethod(String methodName,
Method method, StringBuilder sb,
334 boolean userVisible,
boolean deprecated) {
335 sb.append(
"{ \"name\": \"");
336 sb.append(methodName);
337 sb.append(
"\", \"description\": ");
338 sb.append(formatDescription(method.description));
344 sb.append(
", \"deprecated\": \"" + deprecated +
"\"");
345 sb.append(
", \"params\": ");
348 sb.append(
", \"returnType\": \"");
359 private void outputParameters(List<Parameter> params, StringBuilder sb) {
361 String separator =
"";
363 sb.append(separator);
364 sb.append(
"{ \"name\": \"");
366 sb.append(
"\", \"type\": \"");
367 sb.append(javaTypeToYailType(p.type));
376 StringBuilder sb =
new StringBuilder();
379 String separator =
"";
384 sb.append(separator);
385 outputComponent(component, sb);
391 FileObject src = createOutputFileObject(OUTPUT_FILE_NAME);
392 Writer writer = src.openWriter();
393 writer.write(sb.toString());
396 messager.printMessage(Diagnostic.Kind.NOTE,
"Wrote file " + src.toUri());
403 private static String formatDescription(String description) {
404 return StringUtils.toJson(description);