/* * Copyright 2011 cruxframework.org. * * 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 org.cruxframework.crux.core.rebind.screen.widget; import java.util.Map; import java.util.Set; import org.cruxframework.crux.core.client.permission.Permissions; import org.cruxframework.crux.core.client.screen.DeviceAdaptive.Device; import org.cruxframework.crux.core.client.screen.binding.DataObjectBinder.UpdatedStateBindingContext; import org.cruxframework.crux.core.client.utils.EscapeUtils; import org.cruxframework.crux.core.client.utils.StringUtils; import org.cruxframework.crux.core.client.utils.StyleUtils; import org.cruxframework.crux.core.rebind.AbstractProxyCreator.SourcePrinter; import org.cruxframework.crux.core.rebind.CruxGeneratorException; import org.cruxframework.crux.core.rebind.context.RebindContext; import org.cruxframework.crux.core.rebind.screen.View; import org.cruxframework.crux.core.rebind.screen.ViewFactory; import org.cruxframework.crux.core.rebind.screen.widget.ViewFactoryCreator.DataBindingProcessor; import org.cruxframework.crux.core.rebind.screen.widget.ViewFactoryCreator.WidgetConsumer; import org.cruxframework.crux.core.rebind.screen.widget.creator.HasDataProviderDataBindingProcessor; import org.cruxframework.crux.core.rebind.screen.widget.creator.event.AttachEvtBind; import org.cruxframework.crux.core.rebind.screen.widget.creator.event.DettachEvtBind; import org.cruxframework.crux.core.rebind.screen.widget.creator.event.LoadWidgetEvtProcessor; import org.cruxframework.crux.core.rebind.screen.widget.declarative.DeclarativeFactory; import org.cruxframework.crux.core.rebind.screen.widget.declarative.TagAttribute; import org.cruxframework.crux.core.rebind.screen.widget.declarative.TagAttributeDeclaration; import org.cruxframework.crux.core.rebind.screen.widget.declarative.TagAttributes; import org.cruxframework.crux.core.rebind.screen.widget.declarative.TagAttributesDeclaration; import org.cruxframework.crux.core.rebind.screen.widget.declarative.TagConstraints; import org.cruxframework.crux.core.rebind.screen.widget.declarative.TagEvent; import org.cruxframework.crux.core.rebind.screen.widget.declarative.TagEvents; import org.cruxframework.crux.core.utils.ClassUtils; import org.json.JSONArray; import org.json.JSONObject; import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.JType; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.PartialSupport; /** * Generate code for gwt widgets creation. Generates code based on a JSON meta data array * containing the information declared on crux pages. * * @author Thiago da Rosa de Bustamante */ @TagAttributesDeclaration({ @TagAttributeDeclaration(value="id", required=true, supportsDataBinding=false, description="Sets the identifier used to reference this widget on the crux view. ") }) @TagAttributes({ @TagAttribute(value="width", description="Sets the object's width, in CSS units (e.g. \"10px\", \"1em\"). This width does not include decorations such as border, margin, and padding."), @TagAttribute(value="height", description="Sets the object's height, in CSS units (e.g. \"10px\", \"1em\"). This height does not include decorations such as border, margin, and padding."), @TagAttribute(value="styleName", processor=WidgetCreator.StyleNameProcessor.class, supportsResources=true, description="Clears all of the element's style names and sets it to the given style."), @TagAttribute(value="visible", type=Boolean.class, description="Sets whether this object is visible. true to show the object, false to hide it"), @TagAttribute(value="tooltip", supportsI18N=true, property="title", description="Sets the HTML title property associated with this object. The title is the 'tool-tip' displayed to users when they hover over the object."), @TagAttribute(value="style", processor=WidgetCreator.StyleProcessor.class, description="Sets the HTML style property of the widget's element"), @TagAttribute(value="viewPermission", type=String.class, processor=WidgetCreator.ViewPermissionAttributeProcessor.class, description="A role that must be checked to verify if user can see this widget on the Screen. You must define a RoleManager to handle these permission validations.") }) @TagEvents({ @TagEvent(value=LoadWidgetEvtProcessor.class, description="Inform the handler for onLoadWidget event. This event is fired when the widget is loaded into its parent view."), @TagEvent(value=AttachEvtBind.class, description="Inform the handler for onLoadWidget event. This event is fired every time the widget is attached to the DOM in the browser."), @TagEvent(value=DettachEvtBind.class, description="Inform the handler for onLoadWidget event. This event is fired every time the widget is removed from the DOM in the browser.") }) public abstract class WidgetCreator <C extends WidgetCreatorContext> { private WidgetCreatorAnnotationsProcessor annotationProcessor; private ViewFactoryCreator viewFactory = null; private Class<?> widgetClass = getWidgetTypeFromClass(); /** * Used by widgets that need to create new widgets as children. * * @param out * @param metaElem * @param widgetId * @param widgetType * @param consumer * @param dataBindingProcessor * @param context * @return * @throws CruxGeneratorException */ public String createChildWidget(SourcePrinter out, JSONObject metaElem, String widgetId, String widgetType, WidgetConsumer consumer, DataBindingProcessor dataBindingProcessor, WidgetCreatorContext context) throws CruxGeneratorException { WidgetConsumer widgetConsumer = consumer != null ? consumer : context.getWidgetConsumer(); DataBindingProcessor bindingProcessor = dataBindingProcessor != null ? dataBindingProcessor : context.getDataBindingProcessor(); return viewFactory.newWidget(out, metaElem, widgetId, widgetType, widgetConsumer, bindingProcessor); } /** * Used by widgets that need to create new widgets as children. * * @param out * @param metaElem * @param consumer * @param dataBindingProcessor * @param context * @return * @throws CruxGeneratorException */ public String createChildWidget(SourcePrinter out, JSONObject metaElem, WidgetConsumer consumer, DataBindingProcessor dataBindingProcessor, WidgetCreatorContext context) throws CruxGeneratorException { if (!metaElem.has("id")) { throw new CruxGeneratorException("The id attribute is required for CRUX Widgets. " + "On page ["+getView().getId()+"], there is an widget of type ["+viewFactory.getMetaElementType(metaElem)+"] without id."); } String widgetId = metaElem.optString("id"); return createChildWidget(out, metaElem, widgetId, viewFactory.getMetaElementType(metaElem), consumer, dataBindingProcessor, context); } /** * Used by widgets that need to create new widgets as children. * * @param out * @param metaElem * @param context * @return * @throws CruxGeneratorException */ public String createChildWidget(SourcePrinter out, JSONObject metaElem, WidgetCreatorContext context) throws CruxGeneratorException { return createChildWidget(out, metaElem, null, null, context); } /** * @param varName * @return */ public String createVariableName(String varName) { return ViewFactoryCreator.createVariableName(varName); } /** * Generates the code for the given widget creation. * * @param out * @param metaElem * @param widgetId * @param consumer * @param dataBindingProcessor * @return * @throws CruxGeneratorException */ public String createWidget(SourcePrinter out, JSONObject metaElem, String widgetId, WidgetConsumer consumer, DataBindingProcessor dataBindingProcessor) throws CruxGeneratorException { boolean partialSupport = hasPartialSupport(); C context = createContext(out, metaElem, widgetId, consumer, dataBindingProcessor); if (partialSupport) { out.println("if ("+getWidgetClassName()+".isSupported()){"); } if (context != null) { processAttributes(out, context); annotationProcessor.processAttributes(out, context); processEvents(out, context); annotationProcessor.processEvents(out, context); processChildren(out, context); annotationProcessor.processChildren(out, context); context.setChildElement(context.getWidgetElement()); if (dataBindingProcessor != null) { dataBindingProcessor.processBindings(out, context); } postProcess(out, context); if (partialSupport) { out.println("}"); } return context.getWidget(); } else { if (partialSupport) { out.println("}"); out.println("else {"); out.println("Crux.getErrorHandler().handleError(Crux.getMessages().viewContainerUnsupportedWidget());"); out.println("}"); } return null; } } /** * @param metaElem * @param acceptsNoChild * @return * @throws CruxGeneratorException */ public JSONArray ensureChildren(JSONObject metaElem, boolean acceptsNoChild, String parentWidgetId) throws CruxGeneratorException { if (!acceptsNoChild && !metaElem.has("_children")) { throw new CruxGeneratorException("The widget ["+parentWidgetId+"], declared on View ["+getView().getId()+"], must contain at least one child."); } JSONArray children = metaElem.optJSONArray("_children"); if (acceptsNoChild && children == null) { return null; } if (!acceptsNoChild && (children == null || children.length() == 0 || children.opt(0)==null)) { throw new CruxGeneratorException("The widget ["+parentWidgetId+"], declared on View ["+getView().getId()+"], must contain at least one child."); } return children; } /** * @param metaElem * @param acceptsNoChild * @return */ public JSONObject ensureFirstChild(JSONObject metaElem, boolean acceptsNoChild, String parentWidgetId) throws CruxGeneratorException { if (!acceptsNoChild && !metaElem.has("_children")) { throw new CruxGeneratorException("The widget ["+parentWidgetId+"], declared on View ["+getView().getId()+"], must contain at least one child."); } JSONArray children = metaElem.optJSONArray("_children"); if (acceptsNoChild && children == null) { return null; } if (!acceptsNoChild && (children == null || children.length() == 0)) { throw new CruxGeneratorException("The widget ["+parentWidgetId+"], declared on view ["+getView().getId()+"], must contain at least one child."); } JSONObject firstChild = children.optJSONObject(0); if (!acceptsNoChild && firstChild == null) { throw new CruxGeneratorException("The widget ["+parentWidgetId+"], declared on View ["+getView().getId()+"], must contain at least one child."); } return firstChild; } /** * * @param metaElem * @param acceptsNoChild * @return * @throws CruxGeneratorException */ public String ensureHtmlChild(JSONObject metaElem, boolean acceptsNoChild, String parentWidgetId, WidgetCreatorContext context) throws CruxGeneratorException { String result = metaElem.optString("_html"); if (!acceptsNoChild && (result == null || result.length() == 0)) { throw new CruxGeneratorException("The widget ["+parentWidgetId+"], declared on View ["+getView().getId()+"], must contain an inner HTML."); } if (result != null) { result = viewFactory.getViewHTML(result); processNativeDataBindings(metaElem, context); } return result; } public void processNativeDataBindings(JSONObject metaElem, WidgetCreatorContext context) throws CruxGeneratorException { JSONArray nativeBindings = metaElem.optJSONArray("nativeBindings"); for (int i = 0; i < nativeBindings.length(); i++) { try { JSONObject nativeDataBinding = nativeBindings.getJSONObject(i); String elementId = nativeDataBinding.getString("elementId"); String dataBinding = nativeDataBinding.getString("dataBinding"); String attributeName = nativeDataBinding.getString("attributeName"); String getUiObjectExpression = context.getDataBindingProcessor().getNativeUiObjectExpression(elementId); PropertyBindInfo binding = getObjectDataBinding(dataBinding, getWidgetClassName(), attributeName, !attributeName.equals("value"), Element.class.getCanonicalName(), getUiObjectExpression, context.getDataBindingProcessor()); if (binding != null) { context.registerObjectDataBinding(binding); } else { ExpressionDataBinding expressionBinding = getExpressionDataBinding(dataBinding, getWidgetClassName(), attributeName, Element.class.getCanonicalName(), getUiObjectExpression, context.getDataBindingProcessor(), null, DataBindingNativeTypeResolver.resolveTypeForProperty(attributeName).getType()); if (expressionBinding != null) { context.registerExpressionDataBinding(expressionBinding); } } } catch(Exception e) { throw new CruxGeneratorException("Error processing native databinding declaration on widget [" + context.getWidgetId() + "] declared on view [" + getView().getId() + "]", e); } } } /** * * @param metaElem * @param acceptsNoChild * @param parentWidgetId * @param nullWhenEmpty * @return * @throws CruxGeneratorException */ public String ensureTextChild(JSONObject metaElem, boolean acceptsNoChild, String parentWidgetId, boolean nullWhenEmpty) throws CruxGeneratorException { String result = metaElem.optString("_text"); if (!acceptsNoChild && (result == null || result.length() == 0)) { throw new CruxGeneratorException("The widget ["+parentWidgetId+"], declared on View ["+getView().getId()+"], must contain a text node child."); } if (nullWhenEmpty && result != null && result.length() == 0) { result = null; } if (result != null) { result = resolveI18NString(result); } return result; } /** * * @param element * @return */ public JSONObject ensureWidget(JSONObject metaElem, String parentWidgetId) { if (!isWidget(metaElem)) { throw new CruxGeneratorException("The widget ["+parentWidgetId+"], declared on View ["+getView().getId()+"], must contain a valid widget as child."); } return metaElem; } /** * * @param out * @param bindingContextVariable * @param bindableContainerVariable */ public void generateBindingContextDeclaration(SourcePrinter out, String bindingContextVariable, String bindableContainerVariable) { String bindingContextClassName = UpdatedStateBindingContext.class.getCanonicalName(); out.println(bindingContextClassName + " " + bindingContextVariable + " = new " + bindingContextClassName + "("+ bindableContainerVariable + ", 0);"); } /** * * @param metaElem * @return */ public Class<?> getChildWidgetClass(JSONObject metaElem) { return viewFactory.getWidgetCreator(viewFactory.getMetaElementType(metaElem)).getWidgetClass(); } /** * @param metaElem * @return */ public String getChildWidgetClassName(JSONObject metaElem) { return viewFactory.getWidgetCreator(viewFactory.getMetaElementType(metaElem)).getWidgetClassName(); } /** * @return */ public RebindContext getContext() { return viewFactory.getContext(); } public JType getDataBindingReadExpression(String resultVariable, String dataObjectAlias, String bindingContextVariable, String propertyValue, Set<String> converterDeclarations, String widgetClassName, String widgetPropertyPath, HasDataProviderDataBindingProcessor dataBindingProcessor, StringBuilder expression) { return getDataBindingReadExpression(resultVariable, dataObjectAlias, bindingContextVariable, propertyValue, converterDeclarations, widgetClassName, widgetPropertyPath, dataBindingProcessor, expression, true); } public JType getDataBindingReadExpression(String resultVariable, String dataObjectAlias, String bindingContextVariable, String propertyValue, Set<String> converterDeclarations, String widgetClassName, String widgetPropertyPath, HasDataProviderDataBindingProcessor dataBindingProcessor, StringBuilder expression, boolean acceptExpressions) { JType result = null; PropertyBindInfo binding = getObjectDataBinding(propertyValue, widgetClassName, widgetPropertyPath, true, dataBindingProcessor); String dataObjectVariable = dataBindingProcessor.getCollectionDataObjectVariable(); String collectionItemVariable = dataBindingProcessor.getCollectionItemVariable(); if (binding != null) { expression.append(binding.getDataObjectReadExpression(bindingContextVariable, resultVariable, dataObjectVariable, collectionItemVariable)); String converterDeclaration = binding.getConverterDeclaration(); if (converterDeclaration != null) { converterDeclarations.add(converterDeclaration); } result = binding.getType(); } else if (acceptExpressions) { ExpressionDataBinding expressionBinding = getExpressionDataBinding(propertyValue, widgetClassName, widgetPropertyPath, dataBindingProcessor); if (expressionBinding != null) { expression.append(expressionBinding.getExpression(resultVariable, bindingContextVariable, dataObjectVariable, collectionItemVariable)); converterDeclarations.addAll(expressionBinding.getConverterDeclarations()); result = expressionBinding.getType(); } else { expression.append(resolveI18NString(propertyValue)); result = getContext().getGeneratorContext().getTypeOracle().findType(String.class.getCanonicalName()); } } return result; } public JClassType getDataObjectFromProvider(String dataProviderId) { return viewFactory.getDataObjectFromProvider(dataProviderId); } /** * @return */ public Device getDevice() { return (viewFactory.getDevice() == null?null:Device.valueOf(viewFactory.getDevice())); } /** * * @param propertyValue * @param widgetPropertyPath * @return */ public ExpressionDataBinding getExpressionDataBinding(String propertyValue, String widgetPropertyPath, DataBindingProcessor dataBindingProcessor) { return getExpressionDataBinding(propertyValue, getWidgetClassName(), widgetPropertyPath, dataBindingProcessor); } /** * * @param propertyValue * @param widgetClassName * @param widgetPropertyPath * @return */ public ExpressionDataBinding getExpressionDataBinding(String propertyValue, String widgetClassName, String widgetPropertyPath, DataBindingProcessor dataBindingProcessor) { return getExpressionDataBinding(propertyValue, widgetClassName, widgetPropertyPath, null, null, dataBindingProcessor, null, null); } /** * * @param propertyValue * @param widgetClassName * @param widgetPropertyPath * @param uiObjectClassName * @param getUiObjectExpression * @param dataBindingProcessor * @param setterMethod * @param propertyTypeName * @return */ public ExpressionDataBinding getExpressionDataBinding(String propertyValue, String widgetClassName, String widgetPropertyPath, String uiObjectClassName, String getUiObjectExpression, DataBindingProcessor dataBindingProcessor, String setterMethod, String propertyTypeName) { return viewFactory.getExpressionDataBinding(propertyValue, widgetClassName, widgetPropertyPath, uiObjectClassName, getUiObjectExpression, dataBindingProcessor, setterMethod, propertyTypeName); } /** * @return */ public TreeLogger getLogger() { return viewFactory.getLogger(); } /** * * @param propertyValue * @param widgetPropertyPath * @param boundToAttribute * @return */ public PropertyBindInfo getObjectDataBinding(String propertyValue, String widgetPropertyPath, boolean boundToAttribute, DataBindingProcessor dataBindingProcessor) { return getObjectDataBinding(propertyValue, getWidgetClassName(), widgetPropertyPath, boundToAttribute, dataBindingProcessor); } /** * * @param propertyValue * @param widgetClassName * @param widgetPropertyPath * @param boundToAttribute * @return */ public PropertyBindInfo getObjectDataBinding(String propertyValue, String widgetClassName, String widgetPropertyPath, boolean boundToAttribute, DataBindingProcessor dataBindingProcessor) { return getObjectDataBinding(propertyValue, widgetClassName, widgetPropertyPath, boundToAttribute, null, null, dataBindingProcessor); } public PropertyBindInfo getObjectDataBinding(String propertyValue, String widgetClassName, String widgetPropertyPath, boolean boundToAttribute, String uiObjectClassName, String getUiObjectExpression, DataBindingProcessor dataBindingProcessor) { return viewFactory.getObjectDataBinding(propertyValue, widgetClassName, widgetPropertyPath, boundToAttribute, uiObjectClassName, getUiObjectExpression, dataBindingProcessor); } /** * * @param property * @return */ public String getResourceAccessExpression(String property) { return viewFactory.getResourceAccessExpression(property); } /** * Create a new printer for a subType. That subType will be declared on the package name informed in the first parameter * * @param packageName * @param subType * @param superClass * @param interfaces * @param imports * @param isInterface * @return */ public SourcePrinter getSubTypeWriter(String packageName,String subType, String superClass, String[] interfaces, String[] imports, boolean isInterface) { return viewFactory.getSubTypeWriter(packageName,subType, superClass, interfaces, imports, isInterface); } /** * @param subType * @param superClass * @param interfaces * @param imports * @return */ public SourcePrinter getSubTypeWriter(String subType, String superClass, String[] interfaces, String[] imports) { return viewFactory.getSubTypeWriter(subType, superClass, interfaces, imports); } /** * Create a new printer for a subType. That subType will be declared on the same package of the * {@code ViewFactory}. * * @param subType * @param superClass * @param interfaces * @param imports * @param isInterface * @return */ public SourcePrinter getSubTypeWriter(String subType, String superClass, String[] interfaces, String[] imports, boolean isInterface) { return viewFactory.getSubTypeWriter(subType, superClass, interfaces, imports, isInterface); } /** * @return */ public View getView() { return viewFactory.getView(); } public Class<?> getWidgetClass() { return widgetClass; } /** * @return */ public Class<?> getWidgetClass(String widgetDeclaration) { WidgetCreator<?> widgetCreator = viewFactory.getWidgetCreator(widgetDeclaration); if (widgetCreator == null) { throw new CruxGeneratorException("No widget registered for declaration ["+widgetDeclaration+"]."); } return widgetCreator.getWidgetClass(); } /** * @return */ public String getWidgetClassName() { return getWidgetClass().getCanonicalName(); } /** * * @return */ public JClassType getWidgetClassType() { return getViewFactory().getContext().getGeneratorContext().getTypeOracle().findType(getWidgetClassName()); } /** * @return */ public String getWidgetFactoryDeclaration() { DeclarativeFactory declarativeFactory = getClass().getAnnotation(DeclarativeFactory.class); if (declarativeFactory != null) { return declarativeFactory.library()+"_"+declarativeFactory.id(); } throw new CruxGeneratorException("Error reading viewFactory declaration."); } /** * @param metaElem * @return */ public boolean hasChildPartialSupport(JSONObject metaElem) { return viewFactory.getWidgetCreator(viewFactory.getMetaElementType(metaElem)).hasPartialSupport(); } /** * @return */ public boolean hasPartialSupport() { JClassType widgetClassType = getWidgetClassType(); return widgetClassType != null && widgetClassType.getAnnotation(PartialSupport.class) != null && ClassUtils.hasMethod(getWidgetClass(), "isSupported"); } /** * @return */ public abstract C instantiateContext(); /** * @param out * @param context * @return * @throws CruxGeneratorException */ public void instantiateWidget(SourcePrinter out, C context) throws CruxGeneratorException { String className = getWidgetClassName(); if (hasPartialSupport() && ClassUtils.hasMethod(getWidgetClass(), "createIfSupported")) { out.println("final "+className + " " + context.getWidget()+" = "+className+".createIfSupported();"); } else { out.println("final "+className + " " + context.getWidget()+" = GWT.create("+className+".class);"); } } /** * * @param property * @return */ public boolean isResourceReference(String property) { return viewFactory.isResourceReference(property); } /** * * @param metaElem * @return */ public boolean isWidget(JSONObject metaElem) { return ViewFactory.isValidWidget(metaElem); } /** * Process element children * @param out * @param context * @throws CruxGeneratorException */ public void postProcess(SourcePrinter out, C context) throws CruxGeneratorException { } /** * Process widget attributes * @param out * @param element page DOM element representing the widget (Its <span> tag) * @throws CruxGeneratorException */ public void processAttributes(SourcePrinter out, C context) throws CruxGeneratorException { } /** * Process element children * @param out * @param context * @throws CruxGeneratorException */ public void processChildren(SourcePrinter out, C context) throws CruxGeneratorException { } /** * Process widget events * @param out * @param context * @throws CruxGeneratorException */ public void processEvents(SourcePrinter out, C context) throws CruxGeneratorException { } /** * * @param text * @return */ public String resolveI18NString(String text) { return viewFactory.resolveI18NString(text); } /** * Close the current postProcessing scope and schedule the execution of all scope commands. * @param printer */ protected void commitPostProcessing(SourcePrinter printer) { viewFactory.commitPostProcessing(printer); } /** * * @param out * @param metaElem * @param widgetId * @param consumer * @param dataBindingProcessor * @return * @throws CruxGeneratorException */ protected C createContext(SourcePrinter out, JSONObject metaElem, String widgetId, WidgetConsumer consumer, DataBindingProcessor dataBindingProcessor) throws CruxGeneratorException { C context = instantiateContext(); context.setWidgetElement(metaElem); context.setWidgetId(widgetId); context.setChildElement(metaElem); context.setWidgetConsumer(consumer); context.setDataBindingProcessor(dataBindingProcessor); String widgetVariableName = createVariableName("widget"); context.setWidget(widgetVariableName); context.pushWidgetComponent(getWidgetClassName(), widgetVariableName); instantiateWidget(out, context); if(consumer != null) { consumer.consume(out, widgetId, widgetVariableName, getWidgetFactoryDeclaration(), metaElem); } return context; } /** * Create a new post-processing scope */ protected void createPostProcessingScope() { viewFactory.createPostProcessingScope(); } /** * Retrieve the object responsible for print controller access expressions on client JS * @return */ protected ControllerAccessHandler getControllerAccessorHandler() { return viewFactory.getControllerAccessHandler(); } protected Map<String, String> getDeclaredMessages() { return viewFactory.getDeclaredMessages(); } protected String getLoggerVariable() { return viewFactory.getLoggerVariable(); } /** * Retrieve the current PostProcessingPrinter * @return */ protected SourcePrinter getPostProcessingPrinter() { return viewFactory.getPostProcessingPrinter(); } protected String getViewVariable() { return ViewFactoryCreator.getViewVariable(); } /** * * @param supported * @return */ protected boolean isCurrentDeviceSupported(Device[] supported) { for (Device device : supported) { if (device.equals(Device.all)) { return true; } if (viewFactory.getDevice().equals(device.toString())) { return true; } } return false; } protected boolean isCurrentDeviceSupported(String size, String input) { Device current = Device.valueOf(viewFactory.getDevice()); if (current.equals(Device.all)) { return true; } if (size != null && size.length() > 0) { if (!current.getSize().toString().equals(size)) { return false; } } if (input != null && input.length() > 0) { if (!current.getInput().toString().equals(input)) { return false; } } return true; } protected boolean isWidgetRegisteredForPostProcessing(String widgetId) { return viewFactory.isWidgetRegisteredForPostProcessing(widgetId); } /** * Print code that will be executed after the viewFactory completes the widgets construction * @param s code string */ protected void printlnPostProcessing(String s) { viewFactory.printlnPostProcessing(s); } protected void registerWidgetForPostProcessing(String widgetId) { viewFactory.registerWidgetForPostProcessing(widgetId); } protected boolean targetsDevice(JSONObject child) { return viewFactory.targetsDevice(child); } /** * * @param processorClass * @return */ TagConstraints getTagConstraints(Class<?> processorClass) { TagConstraints attributes = processorClass.getAnnotation(TagConstraints.class); if (attributes == null) { Class<?> superClass = processorClass.getSuperclass(); if (superClass != null && superClass.getSuperclass() != null) { attributes = getTagConstraints(superClass); } } return attributes; } /** * @return */ ViewFactoryCreator getViewFactory() { return this.viewFactory; } /** * @param viewFactory */ void setViewFactory(ViewFactoryCreator factory) { this.viewFactory = factory; if (annotationProcessor == null) { this.annotationProcessor = new WidgetCreatorAnnotationsProcessor(this); } } /** * * @return */ private Class<?> getWidgetTypeFromClass() { DeclarativeFactory declarativeFactory = getClass().getAnnotation(DeclarativeFactory.class); if (declarativeFactory != null) { return declarativeFactory.targetWidget(); } else { return null; } } /** * Retrieve the widget child element name * @param childElement element representing the child * @return child name */ public static String getChildName(JSONObject childElement) { return childElement.optString("_childTag"); } /** * * @param metaElem * @return */ public static boolean hasHeight(JSONObject metaElem) { if (!metaElem.has("height")) { return false; } String width = metaElem.optString("height"); return width != null && (width.length() > 0); } /** * * @param metaElem * @return */ public static boolean hasWidth(JSONObject metaElem) { if (!metaElem.has("width")) { return false; } String width = metaElem.optString("width"); return width != null && (width.length() > 0); } /** * @param metaElem * @return * @throws CruxGeneratorException */ public static boolean isHtmlChild(JSONObject metaElem) throws CruxGeneratorException { String result = metaElem.optString("_html"); return (!StringUtils.isEmpty(result)); } /** * @param metaElem * @return * @throws CruxGeneratorException */ public static boolean isTextChild(JSONObject metaElem) throws CruxGeneratorException { String result = metaElem.optString("_text"); return (!StringUtils.isEmpty(result)); } public static class StyleNameProcessor extends AttributeProcessor<WidgetCreatorContext> { public StyleNameProcessor(WidgetCreator<?> widgetCreator) { super(widgetCreator); } public void processAttribute(SourcePrinter out, String widget, String styleName) { if(!StringUtils.isEmpty(styleName)) { String[] classAttributes = styleName.split(" "); if (classAttributes.length > 1) { for (int i=0; i<classAttributes.length; i++) { styleName = classAttributes[i]; if (getWidgetCreator().isResourceReference(styleName)) { styleName = widgetCreator.getResourceAccessExpression(styleName); addStyleName(out, widget, styleName, i > 0); } else { addStyleName(out, widget, EscapeUtils.quote(styleName), i > 0); } } } else { if (getWidgetCreator().isResourceReference(styleName)) { styleName = widgetCreator.getResourceAccessExpression(styleName); addStyleName(out, widget, styleName, false); } else { addStyleName(out, widget, EscapeUtils.quote(styleName), false); } } } } public void processAttribute(SourcePrinter out, WidgetCreatorContext context, String styleName) { processAttribute(out, context.getWidget(), styleName); } private void addStyleName(SourcePrinter out, String widgetName, String valueExpr, boolean add) { if (add) { out.println(widgetName+".setStyleName("+valueExpr+", true);"); } else { out.println(widgetName+".setStyleName("+valueExpr+");"); } } } /** * @author Thiago da Rosa de Bustamante * */ public static class StyleProcessor extends AttributeProcessor<WidgetCreatorContext> { public StyleProcessor(WidgetCreator<?> widgetCreator) { super(widgetCreator); } public void processAttribute(SourcePrinter out, String widget, String style) { String[] styleAttributes = style.split(";"); if (styleAttributes.length > 0) { String element = ViewFactoryCreator.createVariableName("elem"); out.println(Element.class.getCanonicalName() +" "+element+" = "+widget+".getElement();"); for (int i=0; i<styleAttributes.length; i++) { String[] attr = styleAttributes[i].split(":"); if (attr != null && attr.length == 2) { out.println(StyleUtils.class.getCanonicalName()+".addStyleProperty("+element+", "+EscapeUtils.quote(getStylePropertyName(attr[0]))+ ", "+EscapeUtils.quote(attr[1])+");"); } } } } public void processAttribute(SourcePrinter out, WidgetCreatorContext context, String style) { processAttribute(out, context.getWidget(), style); } private String getStylePropertyName(String property) { int index = -1; while ((index = property.indexOf('-')) >0) { if (index < property.length()-1) { property = property.substring(0, index) + Character.toUpperCase(property.charAt(index+1)) + property.substring(index+2); } } return property; } } /** * Process viewPermission attribute * @author Thiago da Rosa de Bustamante * */ public static class ViewPermissionAttributeProcessor extends AttributeProcessor<WidgetCreatorContext> { public ViewPermissionAttributeProcessor(WidgetCreator<?> widgetCreator) { super(widgetCreator); } @Override public void processAttribute(SourcePrinter out, WidgetCreatorContext context, String attributeValue) { out.println("if (!"+Permissions.class.getCanonicalName()+".hasRole("+EscapeUtils.quote(attributeValue)+")){"); out.println(Permissions.class.getCanonicalName()+".markAsUnauthorizedForViewing("+context.getWidget()+");"); out.println("}"); } } }