| /* |
| * Copyright 2010 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.gwt.uibinder.rebind; |
| |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| import java.beans.Beans; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| /** |
| * Design time implementation of {@link DesignTimeUtils}. |
| */ |
| public class DesignTimeUtilsImpl implements DesignTimeUtils { |
| /** |
| * Returns <code>true</code> if given "Binder" is under design now. We should |
| * not use "design time" globally, because while one widget in under design, |
| * it may use other widgets and we want to execute them as is, without design |
| * time tweaks. |
| */ |
| public static boolean isDesignTime(String fqInterfaceName) { |
| if (Beans.isDesignTime()) { |
| String key = "gwt.UiBinder.isDesignTime " + fqInterfaceName; |
| return System.getProperty(key) != null; |
| } |
| return false; |
| } |
| |
| private final Map<Element, String> elementPaths = new HashMap<Element, String>(); |
| private final Map<String, String> attributes = new HashMap<String, String>(); |
| |
| public void addDeclarations(IndentedWriter w) { |
| // handler |
| w.write("public static interface DTObjectHandler {"); |
| { |
| w.indent(); |
| w.write("void handle(String path, Object object);"); |
| w.write("Object provideFactory(Class rawType, String methodName, Object[] args);"); |
| w.write("Object provideField(Class rawType, String fieldName);"); |
| w.outdent(); |
| } |
| w.write("}"); |
| w.write("public DTObjectHandler dtObjectHandler;"); |
| // attributes |
| w.write("public final java.util.Map dtAttributes = new java.util.HashMap();"); |
| w.write("private void dtPutAttribute(String key, Object...values) {"); |
| { |
| w.indent(); |
| w.write("if (values.length == 1) {"); |
| { |
| w.indent(); |
| w.write("dtAttributes.put(key, values[0]);"); |
| w.outdent(); |
| } |
| w.write("} else {"); |
| { |
| w.indent(); |
| w.write("dtAttributes.put(key, java.util.Arrays.asList(values));"); |
| w.outdent(); |
| } |
| w.write("}"); |
| w.outdent(); |
| } |
| w.write("}"); |
| } |
| |
| public String getImplName(String implName) { |
| return implName + "_designTime" + System.currentTimeMillis(); |
| } |
| |
| public String getPath(Element element) { |
| return elementPaths.get(element); |
| } |
| |
| public String getProvidedFactory(String typeName, String methodName, |
| String args) { |
| return String.format( |
| "(%1$s) dtObjectHandler.provideFactory(%1$s.class, \"%2$s\", new Object[] {%3$s})", |
| typeName, methodName, args); |
| } |
| |
| public String getProvidedField(String typeName, String fieldName) { |
| return String.format( |
| "(%1$s) dtObjectHandler.provideField(%1s.class, \"%2$s\")", typeName, |
| fieldName); |
| } |
| |
| public String getTemplateContent(String path) { |
| return System.getProperty("gwt.UiBinder.designTime " + path); |
| } |
| |
| public void handleUIObject(Statements writer, XMLElement elem, |
| String fieldName) { |
| writer.addStatement( |
| "if (dtObjectHandler != null) dtObjectHandler.handle(\"%s\", %s);", |
| elem.getDesignTimePath(), fieldName); |
| } |
| |
| public boolean isDesignTime() { |
| return true; |
| } |
| |
| public void putAttribute(XMLElement elem, String name, String value) { |
| String path = elem.getDesignTimePath(); |
| String key = path + " " + name; |
| attributes.put(key, value); |
| } |
| |
| public void putAttribute(XMLElement elem, String name, String[] values) { |
| if (values.length == 0) { |
| return; |
| } |
| StringBuilder sb = new StringBuilder(); |
| for (String value : values) { |
| if (sb.length() != 0) { |
| sb.append(", "); |
| } |
| sb.append(value); |
| } |
| sb.insert(0, "new String[] {"); |
| sb.append("}"); |
| putAttribute(elem, name, sb.toString()); |
| } |
| |
| public void rememberPathForElements(Document doc) { |
| rememberPathForElements(doc.getDocumentElement(), "0"); |
| } |
| |
| public void writeAttributes(Statements writer) { |
| for (Map.Entry<String, String> entry : attributes.entrySet()) { |
| String key = entry.getKey(); |
| String value = entry.getValue(); |
| writer.addStatement("dtPutAttribute(\"%s\", %s);", key, value); |
| } |
| attributes.clear(); |
| } |
| |
| /** |
| * Returns remembered attributes, used during tests only. |
| */ |
| Map<String, String> getAttributes() { |
| return attributes; |
| } |
| |
| /** |
| * Recursive implementation of {@link #rememberPathForElements(Document)}. |
| */ |
| private void rememberPathForElements(Element element, String path) { |
| elementPaths.put(element, path); |
| NodeList childNodes = element.getChildNodes(); |
| int elementIndex = 0; |
| for (int i = 0; i < childNodes.getLength(); ++i) { |
| Node childNode = childNodes.item(i); |
| if (childNode.getNodeType() == Node.ELEMENT_NODE) { |
| Element childElement = (Element) childNode; |
| rememberPathForElements(childElement, path + "/" + elementIndex++); |
| } |
| } |
| } |
| } |