/*******************************************************************************
* Copyright (c) 2006, 2010 Soyatec (http://www.soyatec.com) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Soyatec - initial API and implementation
*******************************************************************************/
package org.eclipse.papyrus.xwt.javabean;
import java.io.File;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import org.eclipse.core.databinding.conversion.IConverter;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.papyrus.xwt.ICLRFactory;
import org.eclipse.papyrus.xwt.IConstants;
import org.eclipse.papyrus.xwt.IDataProvider;
import org.eclipse.papyrus.xwt.IEventHandler;
import org.eclipse.papyrus.xwt.IEventInvoker;
import org.eclipse.papyrus.xwt.IIndexedElement;
import org.eclipse.papyrus.xwt.ILoadingContext;
import org.eclipse.papyrus.xwt.INamespaceHandler;
import org.eclipse.papyrus.xwt.IStyle;
import org.eclipse.papyrus.xwt.IXWTLoader;
import org.eclipse.papyrus.xwt.ResourceDictionary;
import org.eclipse.papyrus.xwt.Tracking;
import org.eclipse.papyrus.xwt.XWT;
import org.eclipse.papyrus.xwt.XWTException;
import org.eclipse.papyrus.xwt.XWTLoader;
import org.eclipse.papyrus.xwt.XWTMaps;
import org.eclipse.papyrus.xwt.annotation.UI;
import org.eclipse.papyrus.xwt.callback.ICreatedCallback;
import org.eclipse.papyrus.xwt.callback.ILoadedCallback;
import org.eclipse.papyrus.xwt.core.IBinding;
import org.eclipse.papyrus.xwt.core.IDynamicBinding;
import org.eclipse.papyrus.xwt.core.IDynamicValueBinding;
import org.eclipse.papyrus.xwt.core.IRenderingContext;
import org.eclipse.papyrus.xwt.core.IVisualElementLoader;
import org.eclipse.papyrus.xwt.core.Setter;
import org.eclipse.papyrus.xwt.core.Style;
import org.eclipse.papyrus.xwt.input.ICommand;
import org.eclipse.papyrus.xwt.internal.core.Core;
import org.eclipse.papyrus.xwt.internal.core.DataBindingTrack;
import org.eclipse.papyrus.xwt.internal.core.IEventController;
import org.eclipse.papyrus.xwt.internal.core.ScopeKeeper;
import org.eclipse.papyrus.xwt.internal.utils.ClassLoaderUtil;
import org.eclipse.papyrus.xwt.internal.utils.DocumentObjectSorter;
import org.eclipse.papyrus.xwt.internal.utils.LoggerManager;
import org.eclipse.papyrus.xwt.internal.utils.NamespaceHelper;
import org.eclipse.papyrus.xwt.internal.utils.ObjectUtil;
import org.eclipse.papyrus.xwt.internal.utils.TableEditorHelper;
import org.eclipse.papyrus.xwt.internal.utils.UserData;
import org.eclipse.papyrus.xwt.internal.xml.Attribute;
import org.eclipse.papyrus.xwt.internal.xml.DocumentObject;
import org.eclipse.papyrus.xwt.internal.xml.Element;
import org.eclipse.papyrus.xwt.javabean.metadata.properties.PropertiesConstants;
import org.eclipse.papyrus.xwt.javabean.metadata.properties.TableItemProperty;
import org.eclipse.papyrus.xwt.jface.JFacesHelper;
import org.eclipse.papyrus.xwt.metadata.IEvent;
import org.eclipse.papyrus.xwt.metadata.IMetaclass;
import org.eclipse.papyrus.xwt.metadata.IProperty;
import org.eclipse.papyrus.xwt.metadata.IValueLoading;
import org.eclipse.papyrus.xwt.utils.PathHelper;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ControlEditor;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Widget;
/**
* @author jliu (jin.liu@soyatec.com)
*/
public class ResourceLoader implements IVisualElementLoader {
static Map<String, Object> EMPTY_MAP = Collections.emptyMap();
static final String RESOURCE_LOADER_PROPERTY = "XWT.ResourceLoader";
private static final String COLUMN = "Column";
private Map<String, Object> options;
protected ResourceLoader parentLoader;
protected IRenderingContext context;
protected IXWTLoader loader;
protected Object scopedObject;
protected ScopeKeeper nameScoped;
protected LoadingData loadData = new LoadingData();
protected Event loadedEvent = new Event();
class LoadingData {
protected LoadingData parent;
protected Object clr;
protected Collection<IStyle> styles = Collections.emptyList();
private Object currentWidget = null;
private Object host = null;
private Object dataContext = null;
public Object getDataContext() {
return dataContext;
}
public void setDataContext(Object dataContext) {
this.dataContext = dataContext;
}
public Object getHost() {
return host;
}
public Object getCurrentWidget() {
return currentWidget;
}
public Object findElement(Class<?> type) {
if(type.isInstance(currentWidget)) {
return currentWidget;
}
if(parent != null) {
return parent.findElement(type);
}
return null;
}
public void setCurrentWidget(Object currentWidget) {
this.currentWidget = currentWidget;
}
public LoadingData getParent() {
return parent;
}
public LoadingData() {
}
public LoadingData(LoadingData loadingData, Object host) {
this.parent = loadingData;
this.styles = loadingData.styles;
this.clr = loadingData.clr;
this.currentWidget = loadingData.currentWidget;
this.dataContext = loadingData.dataContext;
this.host = host;
}
public Collection<IStyle> getStyles() {
return styles;
}
public void setStyles(Collection<IStyle> styles) {
this.styles = styles;
}
public Object getClr() {
return clr;
}
public void setClr(Object clr) {
this.clr = clr;
}
public void inject(Object targetObject, String name) {
doInject(targetObject, name, null);
}
protected void doInject(Object targetObject, String name, Object previousClr) {
Class<?> filedType = targetObject.getClass();
if(clr != null && (previousClr != clr || previousClr == null)) {
for(Field field : clr.getClass().getDeclaredFields()) {
UI annotation = field.getAnnotation(UI.class);
if(annotation != null) {
if(!field.getType().isAssignableFrom(filedType)) {
continue;
}
String annotationValue = annotation.value();
if(annotationValue == null || annotationValue.length() == 0) {
if(field.getName().equals(name)) {
field.setAccessible(true);
try {
field.set(clr, targetObject);
return;
} catch (Exception e) {
}
}
} else if(annotationValue.equals(name)) {
field.setAccessible(true);
try {
field.set(clr, targetObject);
break;
} catch (Exception e) {
}
}
}
}
}
if(parent != null) {
parent.doInject(targetObject, name, clr);
}
}
public void updateEvent(IRenderingContext context, Widget control, IEvent event, String handler) {
IEventController eventController = UserData.updateEventController(control);
Method method = null;
Object clrObject = null;
LoadingData current = this;
ResourceLoader currentParentLoader = parentLoader;
while(current != null) {
Object receiver = current.getClr();
if(receiver instanceof IEventHandler) {
IEventHandler eventManager = (IEventHandler)receiver;
IEventInvoker eventInvoker = eventManager.getEventInvoker(handler, control.getClass(), Event.class);
if(eventInvoker != null) {
eventController.setEvent(event, control, control, eventInvoker);
}
} else if(receiver != null) {
Class<?> clazz = receiver.getClass();
method = ObjectUtil.findMethod(clazz, handler, control.getClass(), Event.class);
if(method == null) {
method = ObjectUtil.findMethod(clazz, handler, Event.class);
}
if(method == null) {
// Load again.
clazz = ClassLoaderUtil.loadClass(context.getLoadingContext(), clazz.getName());
method = ObjectUtil.findMethod(clazz, handler, Event.class);
}
if(method != null) {
clrObject = receiver;
eventController.setEvent(event, control, clrObject, control, method);
break;
}
}
current = current.getParent();
if(current == null && currentParentLoader != null) {
current = currentParentLoader.loadData;
currentParentLoader = currentParentLoader.parentLoader;
}
}
if(method == null) {
LoggerManager.log(new XWTException("Event handler \"" + handler + "\" is not found."));
}
}
public void end() {
if(parent == null || clr != parent.getClr()) {
Method method = ObjectUtil.findDeclaredMethod(clr.getClass(), "initializeComponent");
if(method == null) {
method = ObjectUtil.findDeclaredMethod(clr.getClass(), "InitializeComponent");
}
if(method != null) {
try {
method.setAccessible(true);
method.invoke(clr);
} catch (Exception e) {
LoggerManager.log(e);
}
}
}
}
public void addStyle(IStyle style) {
if(styles == Collections.EMPTY_LIST) {
styles = new ArrayList<IStyle>();
}
styles.add(style);
}
}
private DataBindingTrack dataBindingTrack;
/**
* @param context
*/
public ResourceLoader(IRenderingContext context, IXWTLoader loader) {
this.context = context;
this.loader = loader;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.papyrus.xwt.IVisualElementLoader#createUIElement(org.eclipse.
* e4.xwt.Element, org.eclipse.papyrus.xwt.ILoadData,
* org.eclipse.papyrus.xwt.IResourceDictionary)
*/
public Object createUIElement(Element element, Map<String, Object> options) {
try {
this.options = options;
Object container = options.get(IXWTLoader.CONTAINER_PROPERTY);
Widget parent = UserData.getWidget(container);
if(!loader.getTrackings().isEmpty()) {
dataBindingTrack = new DataBindingTrack();
}
parentLoader = (ResourceLoader)options.get(RESOURCE_LOADER_PROPERTY);
options.remove(RESOURCE_LOADER_PROPERTY);
ResourceDictionary resourceDictionary = (ResourceDictionary)options.get(IXWTLoader.RESOURCE_DICTIONARY_PROPERTY);
if(resourceDictionary != null) {
Object styles = resourceDictionary.get(Core.DEFAULT_STYLES_KEY);
if(styles != null) {
loadData.setStyles((Collection<IStyle>)styles);
resourceDictionary.remove(Core.DEFAULT_STYLES_KEY);
}
}
if(!options.containsKey(IXWTLoader.CLASS_FACTORY_PROPERTY)) {
try {
options.put(IXWTLoader.CLASS_FACTORY_PROPERTY, loader.getCLRFactory());
} catch (UnsupportedOperationException e) {
if(options.isEmpty()) {
options = new HashMap<String, Object>();
options.put(IXWTLoader.CLASS_FACTORY_PROPERTY, loader.getCLRFactory());
} else {
throw e;
}
}
}
Object control = doCreate(parent, element, null, options);
// get databinding messages and print into console view
if(dataBindingTrack != null) {
String dataBindingMessage = dataBindingTrack.getDataBindMessage();// getDataBindMessage();
org.eclipse.papyrus.xwt.ILogger log = loader.getLogger();
log.addMessage(dataBindingMessage, Tracking.DATABINDING);
log.printInfo(dataBindingMessage, Tracking.DATABINDING, loader.getTrackings());
}
if(control instanceof Composite) {
((Composite)control).layout();
}
ILoadedCallback loadedAction = (ILoadedCallback)options.get(IXWTLoader.LOADED_CALLBACK);
if(loadedAction != null) {
loadedAction.onLoaded(control);
}
return control;
} catch (Exception e) {
if(e instanceof RuntimeException) {
throw ((RuntimeException)e);
}
throw new XWTException(e);
}
}
protected Object doCreate(Object parent, Element element, Class<?> constraintType, Map<String, Object> options) throws Exception {
int styles = -1;
if(options.containsKey(IXWTLoader.INIT_STYLE_PROPERTY)) {
styles = (Integer)options.get(IXWTLoader.INIT_STYLE_PROPERTY);
}
ResourceDictionary dico = (ResourceDictionary)options.get(IXWTLoader.RESOURCE_DICTIONARY_PROPERTY);
Object dataContext = options.get(IXWTLoader.DATACONTEXT_PROPERTY);
Object bindingContext = options.get(IXWTLoader.BINDING_CONTEXT_PROPERTY);
String name = element.getName();
String namespace = element.getNamespace();
if(IConstants.XWT_X_NAMESPACE.equalsIgnoreCase(namespace)) {
if(IConstants.XAML_X_NULL.equalsIgnoreCase(name)) {
return null;
}
if(IConstants.XAML_X_TYPE.equalsIgnoreCase(name) && constraintType != null && constraintType instanceof Class<?>) {
DocumentObject[] children = element.getChildren();
if(children != null && children.length > 0) {
if(children[0] instanceof Element) {
Element type = (Element)children[0];
IMetaclass metaclass = loader.getMetaclass(type.getName(), type.getNamespace());
if(metaclass != null) {
return metaclass.getType();
}
}
} else {
String content = element.getContent();
return loader.convertFrom(Class.class, content);
}
}
return null;
}
IMetaclass metaclass = loader.getMetaclass(name, namespace);
if(constraintType != null && !(IBinding.class.isAssignableFrom(metaclass.getType())) && (!constraintType.isAssignableFrom(metaclass.getType()))) {
if(!constraintType.isArray() || !constraintType.getComponentType().isAssignableFrom(metaclass.getType())) {
IConverter converter = XWT.findConvertor(metaclass.getType(), constraintType);
if(converter == null) {
return null;
}
}
}
Object targetObject = null;
Integer styleValue = getStyleValue(element, styles);
if(parent == null || metaclass.getType() == Shell.class) {
if(dataBindingTrack != null) {
dataBindingTrack.addWidgetElement(element);
}
Shell shell = null;
if((parent == null && metaclass.getType() != Shell.class) || styleValue == null || styleValue == -1) {
styleValue = SWT.SHELL_TRIM;
}
Display display = Display.getCurrent();
shell = new Shell(display, styleValue);
targetObject = shell;
invokeCreatededAction(element, targetObject);
loadData.setCurrentWidget(shell);
if(metaclass.getType() != Shell.class) {
shell.setLayout(new FillLayout());
return doCreate(targetObject, element, constraintType, options);
} else {
if(bindingContext != null) {
setBindingContext(metaclass, targetObject, dico, bindingContext);
}
if(dataContext != null) {
setDataContext(metaclass, targetObject, dico, dataContext);
}
}
pushStack(parent);
// for Shell
Attribute classAttribute = element.getAttribute(IConstants.XWT_X_NAMESPACE, IConstants.XAML_X_CLASS);
if(classAttribute != null) {
String className = classAttribute.getContent();
loadShellCLR(className, shell);
} else {
Attribute classFactoryAttribute = element.getAttribute(IConstants.XWT_X_NAMESPACE, IConstants.XAML_X_CLASS_FACTORY);
ICLRFactory clrFactory = (ICLRFactory)options.get(XWTLoader.CLASS_FACTORY_PROPERTY);
if(classFactoryAttribute != null) {
String content = classFactoryAttribute.getContent();
Object clr = loadFactoryCLR(content, clrFactory);
loadData.setClr(clr);
UserData.setCLR(shell, clr);
} else {
if(clrFactory != null) {
Object clr = clrFactory.createCLR(null, options);
loadData.setClr(clr);
UserData.setCLR(shell, clr);
}
}
}
} else {
pushStack(parent);
//
// load the content in case of UserControl
//
Class<?> type = metaclass.getType();
URL file = type.getResource(type.getSimpleName() + IConstants.XWT_EXTENSION_SUFFIX);
if(file != null && nameScoped != null) {
if(parent instanceof Composite) {
Object childDataContext = getDataContext(element, (Widget)parent);
Object childBindingContext = getBindingContext(element, (Widget)parent);
if(dataContext != null) {
childDataContext = dataContext;
}
if(bindingContext != null) {
childBindingContext = bindingContext;
}
Map<String, Object> nestedOptions = new HashMap<String, Object>();
nestedOptions.put(IXWTLoader.CONTAINER_PROPERTY, parent);
if(styleValue != null) {
nestedOptions.put(IXWTLoader.INIT_STYLE_PROPERTY, styleValue);
}
nestedOptions.put(IXWTLoader.DATACONTEXT_PROPERTY, childDataContext);
nestedOptions.put(IXWTLoader.BINDING_CONTEXT_PROPERTY, childBindingContext);
nestedOptions.put(RESOURCE_LOADER_PROPERTY, this);
nestedOptions.put(IXWTLoader.CLASS_FACTORY_PROPERTY, null); // disable
// the
// global
// setting
targetObject = loader.loadWithOptions(file, nestedOptions);
if(targetObject == null) {
return null;
}
invokeCreatededAction(element, targetObject);
} else {
throw new XWTException("Cannot add user control: Parent is not a composite");
}
} else {
Object[] parameters = null;
if(TableViewerColumn.class.isAssignableFrom(type)) {
int columnIndex = getColumnIndex(element);
parameters = (styleValue != null ? new Object[]{ parent, styleValue, columnIndex } : new Object[]{ parent, SWT.NONE, columnIndex });
} else {
parameters = (styleValue != null ? new Object[]{ parent, styleValue } : new Object[]{ parent });
}
// x:Class
{
boolean hasClass = false;
Attribute classAttribute = element.getAttribute(IConstants.XWT_X_NAMESPACE, IConstants.XAML_X_CLASS);
if(classAttribute != null) {
String className = classAttribute.getContent();
targetObject = loadCLR(className, parameters, metaclass.getType(), options);
hasClass = true;
} else {
Object clr = options.get(XWTLoader.CLASS_PROPERTY);
if(clr != null) {
loadData.setClr(clr);
hasClass = true;
}
}
if(!hasClass) {
Attribute classFactoryAttribute = element.getAttribute(IConstants.XWT_X_NAMESPACE, IConstants.XAML_X_CLASS_FACTORY);
ICLRFactory clrFactory = (ICLRFactory)options.get(XWTLoader.CLASS_FACTORY_PROPERTY);
if(classFactoryAttribute != null) {
Object clr = loadFactoryCLR(classFactoryAttribute.getContent(), clrFactory);
if(clr != null) {
loadData.setClr(clr);
}
} else {
if(clrFactory != null) {
loadData.setClr(clrFactory.createCLR(null, options));
}
}
}
if(targetObject == null) {
targetObject = metaclass.newInstance(parameters);
invokeCreatededAction(element, targetObject);
Widget widget = UserData.getWidget(targetObject);
if(widget != null) {
Object clr = loadData.getClr();
if(clr != null) {
UserData.setCLR(widget, clr);
}
}
} else {
metaclass = loader.getMetaclass(targetObject);
}
}
if(targetObject == null) {
return null;
}
}
}
Widget widget = UserData.getWidget(targetObject);
if(widget != null) {
loadData.setCurrentWidget(targetObject);
}
if(scopedObject == null && widget != null) {
scopedObject = widget;
nameScoped = new ScopeKeeper((parent == null ? null : UserData.findScopeKeeper(parent)), widget);
UserData.bindNameContext(widget, nameScoped);
}
// set first data context and resource dictionary
setDataContext(metaclass, targetObject, dico, dataContext);
if(bindingContext != null) {
setBindingContext(metaclass, targetObject, dico, bindingContext);
}
if(dataBindingTrack != null) {
dataBindingTrack.tracking(targetObject, element, dataContext);
}
// set parent relationship and viewer
if(targetObject instanceof Widget) {
if(parent != null) {
UserData.setParent(targetObject, parent);
}
} else if(JFacesHelper.isViewer(targetObject)) {
UserData.setParent(targetObject, parent);
UserData.setViewer(targetObject, targetObject);
} else if(targetObject instanceof TableItemProperty.Cell) {
((TableItemProperty.Cell)targetObject).setParent((TableItem)parent);
}
applyStyles(element, targetObject);
for(Map.Entry<String, Object> entry : options.entrySet()) {
String key = entry.getKey();
if(IXWTLoader.Utilities.isPropertyName(key)) {
continue;
}
IProperty property = metaclass.findProperty(key);
if(property == null) {
throw new XWTException("Property " + key + " not found.");
}
property.setValue(targetObject, entry.getValue());
}
Map<String, IProperty> delayedAttributes = new HashMap<String, IProperty>();
init(metaclass, targetObject, element, delayedAttributes);
if(targetObject instanceof Style && element.getChildren().length > 0) {
Collection<Setter> setters = new ArrayList<Setter>();
for(DocumentObject doc : element.getChildren()) {
Object child = doCreate(targetObject, (Element)doc, null, Collections.<String, Object> emptyMap());
if(!(child instanceof Setter)) {
throw new XWTException("Setter is expected in Style.");
}
setters.add((Setter)child);
}
((Style)targetObject).setSetters(setters.toArray(new Setter[setters.size()]));
} else if(targetObject instanceof ControlEditor) {
for(DocumentObject doc : element.getChildren()) {
Object editor = doCreate(parent, (Element)doc, null, Collections.<String, Object> emptyMap());
if(editor != null && editor instanceof Control) {
((ControlEditor)targetObject).setEditor((Control)editor);
((Control)editor).setData(PropertiesConstants.DATA_CONTROLEDITOR_OF_CONTROL, targetObject);
}
}
} else if(targetObject instanceof IDataProvider) {
for(DocumentObject doc : element.getChildren()) {
if(IConstants.XWT_X_NAMESPACE.equals(doc.getNamespace())) {
String content = doc.getContent();
if(content != null) {
((IDataProvider)targetObject).setProperty(doc.getName(), content);
}
}
}
} else {
for(DocumentObject doc : element.getChildren()) {
doCreate(targetObject, (Element)doc, null, Collections.<String, Object> emptyMap());
}
}
iniDelayedAttribute(metaclass, targetObject, element, null, delayedAttributes);
postCreation(targetObject);
popStack();
return targetObject;
}
protected void iniDelayedAttribute(IMetaclass metaclass, Object targetObject, Element element, String namespace, Map<String, IProperty> delayedAttributes) throws Exception {
Set<String> keys = delayedAttributes.keySet();
while(!keys.isEmpty()) {
for(String delayed : keys.toArray(new String[keys.size()])) {
IProperty property = delayedAttributes.get(delayed);
boolean hasDependency = false;
IProperty[] dependencies = property.getLoadingType().getDependencies();
if(dependencies.length > 0) {
for(IProperty dependency : dependencies) {
if(delayedAttributes.containsValue(dependency)) {
hasDependency = true;
break;
}
}
}
if(!hasDependency) {
initAttribute(metaclass, targetObject, element, null, delayed);
keys.remove(delayed);
}
}
}
}
/**
* This method is invoked directly after creation of component instance, but
* before applying its attributes and creating children.
*
* @param element
* the source element in XML.
* @param targetObject
* the created visual object.
*/
protected void postCreation0(Element element, Object targetObject) {
}
private void invokeCreatededAction(Element element, Object targetObject) {
if(targetObject != null) {
postCreation0(element, targetObject);
}
if(options != null) {
ICreatedCallback createdAction = (ICreatedCallback)options.get(IXWTLoader.CREATED_CALLBACK);
if(createdAction != null) {
createdAction.onCreated(targetObject);
}
}
}
/**
* This method is invoked after full creation of component, i.e. after
* creating its instance, applying its attributes and creating children.
*/
protected void postCreation(Object target) {
}
protected void setDataContext(IMetaclass metaclass, Object targetObject, ResourceDictionary dico, Object dataContext) throws IllegalAccessException, InvocationTargetException, NoSuchFieldException {
Object control = null;
IMetaclass widgetMetaclass = metaclass;
if(JFacesHelper.isViewer(targetObject)) {
Widget widget = JFacesHelper.getControl(targetObject);
widgetMetaclass = loader.getMetaclass(widget.getClass());
control = targetObject;
} else if(targetObject instanceof Widget) {
control = targetObject;
} else {
control = loadData.getCurrentWidget();
}
if(control != null) {
if(targetObject instanceof IDynamicBinding) {
IDynamicBinding dynamicBinding = (IDynamicBinding)targetObject;
dynamicBinding.setControl(control);
dynamicBinding.setHost(loadData.getHost());
}
if(dico != null) {
UserData.setResources(control, dico);
}
if(dataContext != null) {
IProperty property = widgetMetaclass.findProperty(IConstants.XAML_DATA_CONTEXT);
if(property != null) {
property.setValue(UserData.getWidget(control), dataContext);
} else {
throw new XWTException("DataContext is missing in " + widgetMetaclass.getType().getName());
}
}
}
}
protected void setBindingContext(IMetaclass metaclass, Object targetObject, ResourceDictionary dico, Object bindingContext) throws IllegalAccessException, InvocationTargetException, NoSuchFieldException {
Object control = null;
IMetaclass widgetMetaclass = metaclass;
if(JFacesHelper.isViewer(targetObject)) {
Widget widget = JFacesHelper.getControl(targetObject);
widgetMetaclass = loader.getMetaclass(widget.getClass());
control = targetObject;
} else if(targetObject instanceof Widget) {
control = targetObject;
} else {
control = loadData.getCurrentWidget();
}
if(control != null) {
if(targetObject instanceof IDynamicBinding) {
IDynamicBinding dynamicBinding = (IDynamicBinding)targetObject;
dynamicBinding.setControl(control);
dynamicBinding.setHost(loadData.getHost());
}
if(dico != null) {
UserData.setResources(control, dico);
}
if(bindingContext != null) {
IProperty property = widgetMetaclass.findProperty(IConstants.XAML_BINDING_CONTEXT);
if(property != null) {
property.setValue(UserData.getWidget(control), bindingContext);
} else {
throw new XWTException("DataContext is missing in " + widgetMetaclass.getType().getName());
}
}
}
}
protected void applyStyles(Element element, Object targetObject) throws Exception {
if(targetObject instanceof Widget) {
Widget widget = (Widget)targetObject;
Map<String, Object> dico = UserData.getLocalResources(widget);
Attribute attribute = element.getAttribute(IConstants.XAML_RESOURCES);
if(attribute == null) {
attribute = element.getAttribute(IConstants.XWT_NAMESPACE, IConstants.XAML_RESOURCES);
}
if(attribute != null) {
if(attribute.getChildren().length > 0) {
if(dico == null) {
dico = new ResourceDictionary();
UserData.setResources(widget, dico);
}
for(DocumentObject doc : attribute.getChildren()) {
Element elem = (Element)doc;
Object doCreate = doCreate(widget, elem, null, EMPTY_MAP);
Attribute keyAttribute = elem.getAttribute(IConstants.XWT_X_NAMESPACE, IConstants.XAML_X_KEY);
if(keyAttribute == null) {
keyAttribute = elem.getAttribute(IConstants.XWT_X_NAMESPACE, IConstants.XAML_X_TYPE);
}
if(keyAttribute != null) {
dico.put(keyAttribute.getContent(), doCreate);
}
if(doCreate instanceof IStyle) {
IStyle style = (IStyle)doCreate;
loadData.addStyle(style);
}
}
}
}
// apply the styles defined in parent's resources via TargetType
Widget current = widget;
while(current != null) {
dico = UserData.getLocalResources(current);
if(dico != null) {
for(Object value : dico.values()) {
if(value instanceof Style) {
Style style = (Style)value;
Class<?> targetType = style.getTargetType();
if(targetType != null && targetType.isInstance(widget)) {
style.apply(targetObject);
}
}
}
}
current = UserData.getTreeParent(current);
}
}
for(IStyle style : loadData.getStyles()) {
style.applyStyle(targetObject);
}
}
protected int getColumnIndex(Element columnElement) {
String name = columnElement.getName();
String namespace = columnElement.getNamespace();
IMetaclass metaclass = loader.getMetaclass(name, namespace);
int index = -1;
Class<?> type = metaclass.getType();
if(TableViewerColumn.class.isAssignableFrom(type)) {
DocumentObject parent = columnElement.getParent();
List<DocumentObject> children = DocumentObjectSorter.sortWithAttr(parent.getChildren(), "Index");
index = children.indexOf(columnElement);
}
return index;
}
/**
* @param tableItem
*/
protected void installTableEditors(TableItem tableItem) {
Table table = tableItem.getParent();
TableColumn[] columns = table.getColumns();
if(columns == null || columns.length == 0) {
return;
}
for(TableColumn tableColumn : columns) {
Object data = tableColumn.getData(PropertiesConstants.DATA_DEFINED_EDITOR);
if(data == null || !(data instanceof Element)) {
continue;
}
int column = table.indexOf(tableColumn);
Element editor = (Element)data;
try {
TableEditor tableEditor = (TableEditor)doCreate(table, editor, null, EMPTY_MAP);
if(tableEditor != null) {
tableEditor.setColumn(column);
tableEditor.setItem(tableItem);
}
} catch (Exception e) {
continue;
}
}
}
protected Object getDataContext(Element element, Widget swtObject) {
// x:DataContext
try {
Object dataContext = loadData.getDataContext();
if(dataContext != null) {
return dataContext;
}
{
Attribute dataContextAttribute = element.getAttribute(IConstants.XAML_DATA_CONTEXT);
if(dataContextAttribute != null) {
Widget composite = swtObject;
DocumentObject documentObject = dataContextAttribute.getChildren()[0];
if(IConstants.XAML_STATICRESOURCES.equals(documentObject.getName()) || IConstants.XAML_DYNAMICRESOURCES.equals(documentObject.getName())) {
String key = documentObject.getContent();
dataContext = new StaticResourceBinding(composite, key);
loadData.setDataContext(dataContext);
return dataContext;
} else if(IConstants.XAML_BINDING.equals(documentObject.getName())) {
dataContext = doCreate(swtObject, (Element)documentObject, null, EMPTY_MAP);
loadData.setDataContext(dataContext);
return dataContext;
} else {
LoggerManager.log(new UnsupportedOperationException(documentObject.getName()));
}
}
}
} catch (Exception e) {
LoggerManager.log(e);
}
return null;
}
protected Object getBindingContext(Element element, Widget swtObject) {
// x:DataContext
try {
{
Attribute dataContextAttribute = element.getAttribute(IConstants.XAML_BINDING_CONTEXT);
if(dataContextAttribute != null) {
Widget composite = swtObject;
DocumentObject documentObject = dataContextAttribute.getChildren()[0];
if(IConstants.XAML_STATICRESOURCES.equals(documentObject.getName()) || IConstants.XAML_DYNAMICRESOURCES.equals(documentObject.getName())) {
String key = documentObject.getContent();
return new StaticResourceBinding(composite, key);
} else if(IConstants.XAML_BINDING.equals(documentObject.getName())) {
return doCreate(swtObject, (Element)documentObject, null, EMPTY_MAP);
} else {
LoggerManager.log(new UnsupportedOperationException(documentObject.getName()));
}
}
}
} catch (Exception e) {
LoggerManager.log(e);
}
return null;
}
protected void pushStack(Object host) {
loadData = new LoadingData(loadData, host);
}
protected void popStack() {
LoadingData previous = loadData;
loadData = previous.getParent();
previous.end();
}
protected Integer getStyleValue(Element element, int styles) {
Attribute attribute = element.getAttribute(IConstants.XWT_X_NAMESPACE, IConstants.XAML_STYLE);
if(attribute == null) {
if(styles != -1) {
return styles;
}
return null;
}
if(styles == -1) {
return (Integer)loader.findConvertor(String.class, Integer.class).convert(attribute.getContent());
}
return styles | (Integer)loader.findConvertor(String.class, Integer.class).convert(attribute.getContent());
}
protected void init(IMetaclass metaclass, Object targetObject, Element element, Map<String, IProperty> delayedAttributes) throws Exception {
// editors for TableItem,
if(targetObject instanceof TableItem) {
installTableEditors((TableItem)targetObject);
}
// x:DataContext
if(loadData.getDataContext() == null) {
Attribute dataContextAttribute = element.getAttribute(IConstants.XAML_DATA_CONTEXT);
if(dataContextAttribute != null) {
IProperty property = metaclass.findProperty(IConstants.XAML_DATA_CONTEXT);
Widget composite = UserData.getWidget(targetObject);
DocumentObject documentObject = dataContextAttribute.getChildren()[0];
if(IConstants.XAML_STATICRESOURCES.equals(documentObject.getName()) || IConstants.XAML_DYNAMICRESOURCES.equals(documentObject.getName())) {
String key = documentObject.getContent();
property.setValue(composite, new StaticResourceBinding(composite, key));
} else if(IConstants.XAML_BINDING.equals(documentObject.getName())) {
Object object = doCreate(targetObject, (Element)documentObject, null, EMPTY_MAP);
property.setValue(composite, object);
} else {
LoggerManager.log(new UnsupportedOperationException(documentObject.getName()));
}
}
}
HashSet<String> done = new HashSet<String>();
Attribute nameAttr = element.getAttribute(IConstants.XAML_X_NAME);
if(nameAttr == null) {
nameAttr = element.getAttribute(IConstants.XWT_X_NAMESPACE, IConstants.XAML_X_NAME);
}
if(nameAttr != null && UserData.getWidget(targetObject) != null) {
String value = nameAttr.getContent();
loadData.inject(targetObject, value);
nameScoped.addNamedObject(value, targetObject);
UserData.setElementName(targetObject, value, false);
done.add(IConstants.XAML_X_NAME);
}
for(String attrName : element.attributeNames()) {
IProperty property = metaclass.findProperty(attrName);
if(IConstants.XWT_X_NAMESPACE.equals(element.getAttribute(attrName).getNamespace())) {
continue;
} else if(delayedAttributes != null && property != null && property.getLoadingType().getValueLoading() != IValueLoading.Normal) {
delayedAttributes.put(attrName, property);
} else {
if(!done.contains(attrName)) {
initAttribute(metaclass, targetObject, element, null, attrName);
done.add(attrName);
}
}
}
for(String namespace : element.attributeNamespaces()) {
if(IConstants.XWT_X_NAMESPACE.equals(namespace)) {
for(String attrName : element.attributeNames(namespace)) {
if("class".equalsIgnoreCase(attrName) || IConstants.XAML_STYLE.equalsIgnoreCase(attrName)) {
continue; // done before
} else if(IConstants.XAML_X_NAME.equalsIgnoreCase(attrName)) {
nameScoped.addNamedObject(element.getAttribute(namespace, attrName).getContent(), targetObject);
done.add(attrName);
} else if(IConstants.XAML_DATA_CONTEXT.equalsIgnoreCase(attrName)) {
continue; // done before
} else if(IConstants.XAML_X_ARRAY.equalsIgnoreCase(attrName)) {
IProperty property = metaclass.findProperty(attrName);
Class<?> type = property.getType();
Object value = getArrayProperty(type, targetObject, element, attrName);
if(value != null) {
property.setValue(targetObject, value);
}
} else if(IConstants.XAML_RESOURCES.equalsIgnoreCase(attrName)) {
continue;
} else {
if(!done.contains(attrName)) {
initAttribute(metaclass, targetObject, element, namespace, attrName);
done.add(attrName);
}
}
}
continue;
}
for(String attrName : element.attributeNames(namespace)) {
if(IConstants.XAML_X_NAME.equalsIgnoreCase(attrName) && (targetObject instanceof Widget)) {
continue;
}
if(!done.contains(attrName)) {
initAttribute(metaclass, targetObject, element, namespace, attrName);
done.add(attrName);
}
}
}
for(String attrName : element.attributeNames()) {
if(IConstants.XAML_X_NAME.equalsIgnoreCase(attrName) && UserData.getWidget(targetObject) != null) {
continue;
}
if(!done.contains(attrName) && !delayedAttributes.containsKey(attrName)) {
initAttribute(metaclass, targetObject, element, null, attrName);
done.add(attrName);
}
}
//
// handle foreigner namespace
//
for(String namespace : element.attributeNamespaces()) {
if(XWT.isXWTNamespace(namespace)) {
continue;
}
INamespaceHandler namespaceHandler = loader.getNamespaceHandler(namespace);
if(namespaceHandler != null) {
for(String attrName : element.attributeNames(namespace)) {
Attribute attribute = element.getAttribute(namespace, attrName);
Widget widget = UserData.getWidget(loadData.getCurrentWidget());
namespaceHandler.handleAttribute(widget, targetObject, attrName, attribute.getContent());
}
}
}
}
protected Object getArrayProperty(Class<?> type, Object swtObject, DocumentObject docObject, String attrName) throws IllegalAccessException, InvocationTargetException, NoSuchFieldException {
Class<?> arrayType = null;
if(type == Object.class) {
if(docObject instanceof Element) {
Element element = (Element)docObject;
Attribute attribute = element.getAttribute(IConstants.XWT_NAMESPACE, IConstants.XAML_X_TYPE);
if(attribute == null) {
throw new XWTException("The type attribute is missing in the element x:Array.");
}
String value = attribute.getContent();
IMetaclass metaclass = XWT.getMetaclass(value, attribute.getNamespace());
if(metaclass == null) {
throw new XWTException("The type \"" + value + "\" is not found.");
}
arrayType = metaclass.getType();
}
} else {
if(!type.isArray()) {
throw new XWTException("Type mismatch: property " + attrName + " isn't an array.");
}
arrayType = type.getComponentType();
}
if(arrayType != null) {
List<Object> list = new ArrayList<Object>();
for(DocumentObject childModel : docObject.getChildren()) {
if(!(childModel instanceof Element)) {
continue;
}
Object child = createInstance(swtObject, (Element)childModel);
list.add(child);
}
Object[] array = (Object[])Array.newInstance(arrayType, list.size());
list.toArray(array);
for(int i = 0; i < array.length; i++) {
if(array[i] instanceof IIndexedElement) {
((IIndexedElement)array[i]).setIndex(swtObject, i);
}
}
return array;
}
return null;
}
@SuppressWarnings("unchecked")
protected Object getCollectionProperty(Class<?> type, Object swtObject, DocumentObject element, String attrName) throws IllegalAccessException, InvocationTargetException, NoSuchFieldException {
Collection<Object> collector = null;
if(type.isInterface()) {
collector = new ArrayList<Object>();
} else {
if(Modifier.isAbstract(type.getModifiers())) {
LoggerManager.log(new XWTException("Collection " + type.getSimpleName() + " is abstract type"));
}
try {
collector = (Collection)type.newInstance();
} catch (InstantiationException e) {
LoggerManager.log(new XWTException(e));
}
}
for(DocumentObject childModel : element.getChildren()) {
if(!(childModel instanceof Element)) {
continue;
}
Object child = createInstance(swtObject, (Element)childModel);
collector.add(child);
if(child instanceof IIndexedElement) {
((IIndexedElement)child).setIndex(swtObject, collector.size() - 1);
}
}
return collector;
}
protected String findNamespace(DocumentObject context, String prefix) {
while(context != null && !(context instanceof Element)) {
context = context.getParent();
}
if(context == null) {
return null;
}
Element element = (Element)context;
if(prefix != null) {
prefix = (prefix.length() == 0 ? null : prefix);
}
String namespace = element.getXmlns(prefix);
if(namespace != null) {
return namespace;
}
DocumentObject parent = element.getParent();
return findNamespace(parent, prefix);
}
protected Object createInstance(Object swtObject, Element element) {
String name = element.getName();
String namespace = element.getNamespace();
if(IConstants.XWT_X_NAMESPACE.equalsIgnoreCase(namespace) && IConstants.XAML_X_NULL.equalsIgnoreCase(name)) {
return null;
}
try {
Class<?> type = NamespaceHelper.loadCLRClass(context.getLoadingContext(), name, namespace);
IMetaclass metaclass = loader.getMetaclass(name, namespace);
if(type == null) {
if(metaclass != null) {
type = metaclass.getType();
}
}
if(metaclass == null) {
throw new XWTException("Class for " + name + " is not found.");
}
// type = expected type;
// Need to support the
String content = element.getContent();
Object instance = null;
if(content == null) {
instance = metaclass.newInstance(new Object[]{ swtObject });
invokeCreatededAction(element, instance);
if(instance instanceof TableEditor) {
// TODO should be moved into IMetaclass
TableEditor tableEditor = (TableEditor)instance;
if(swtObject instanceof TableItem) {
TableItem item = (TableItem)swtObject;
tableEditor.setItem(item);
for(DocumentObject doc : element.getChildren()) {
Control control = (Control)doCreate(((TableItem)swtObject).getParent(), (Element)doc, null, EMPTY_MAP);
tableEditor.setEditor(control);
int column = getColumnValue(element);
TableEditorHelper.initEditor(item, control, column);
}
}
}
} else {
Constructor<?> constructor = type.getConstructor(type);
if(constructor != null) {
instance = constructor.newInstance(loader.convertFrom(type, content));
invokeCreatededAction(element, instance);
} else {
LoggerManager.log(new XWTException("Constructor \"" + name + "(" + type.getSimpleName() + ")\" is not found"));
}
}
Map<String, IProperty> delayedAttributes = new HashMap<String, IProperty>();
init(metaclass, instance, element, delayedAttributes);
iniDelayedAttribute(metaclass, instance, element, null, delayedAttributes);
for(DocumentObject doc : element.getChildren()) {
doCreate(instance, (Element)doc, null, Collections.<String, Object> emptyMap());
}
return instance;
} catch (Exception e) {
LoggerManager.log(e);
}
return null;
}
static protected int getColumnValue(Element context) {
Attribute attribute = context.getAttribute(COLUMN);
if(attribute != null) {
String content = attribute.getContent();
if(content != null) {
return Integer.parseInt(content);
}
}
return 0;
}
protected void loadShellCLR(String className, Shell shell) {
Class<?> type = ClassLoaderUtil.loadClass(context.getLoadingContext(), className);
try {
Object instance = type.newInstance();
loadData.setClr(instance);
UserData.setCLR(shell, instance);
} catch (Exception e) {
LoggerManager.log(e);
}
}
protected Object loadFactoryCLR(String value, ICLRFactory factory) {
String token;
String arg;
if(value.startsWith("+")) {
if(factory == null) {
throw new XWTException("ICLRFactory option is missing.");
}
arg = value.substring(1).trim();
return factory.createCLR(arg, options);
} else {
StringTokenizer stringTokenizer = new StringTokenizer(value);
if(!stringTokenizer.hasMoreTokens()) {
throw new XWTException("x:ClassFactory is empty");
}
token = stringTokenizer.nextToken();
arg = value.substring(token.length()).trim();
}
int index = token.lastIndexOf('.');
if(index != -1) {
String memberName = token.substring(index + 1);
String typeName = token.substring(0, index);
Class<?> type = ClassLoaderUtil.loadClass(context.getLoadingContext(), typeName);
if(type != null) {
Object member = ClassLoaderUtil.loadMember(context.getLoadingContext(), type, memberName, false);
if(member instanceof ICLRFactory) {
factory = (ICLRFactory)member;
}
if(factory != null) {
return factory.createCLR(arg, options);
}
}
}
Class<?> type = ClassLoaderUtil.loadClass(context.getLoadingContext(), token);
if(type != null && ICLRFactory.class.isAssignableFrom(type)) {
try {
ICLRFactory localFactory = (ICLRFactory)type.newInstance();
return localFactory.createCLR(arg, options);
} catch (Exception e) {
throw new XWTException(e);
}
}
throw new XWTException(value + " ClassFactory not found.");
}
protected Object loadCLR(String className, Object[] parameters, Class<?> currentTagType, Map<String, Object> options) {
Class<?> type = ClassLoaderUtil.loadClass(context.getLoadingContext(), className);
if(type == null) {
return null;
}
try {
Object clr = options.get(XWTLoader.CLASS_PROPERTY);
if(clr != null && type.isInstance(clr)) {
loadData.setClr(clr);
if(clr instanceof Widget) {
UserData.setCLR(clr, clr);
}
} else if(currentTagType != null && currentTagType.isAssignableFrom(type)) {
IMetaclass metaclass = loader.getMetaclass(type);
Object instance = metaclass.newInstance(parameters);
loadData.setClr(instance);
// use x:Class's instance
if(instance instanceof Widget) {
UserData.setCLR(instance, instance);
}
return instance;
} else {
Object instance = type.newInstance();
loadData.setClr(instance);
if(instance instanceof Widget) {
UserData.setCLR(instance, instance);
}
}
} catch (Exception e) {
LoggerManager.log(e);
}
return null;
}
protected void initAttribute(IMetaclass metaclass, Object targetObject, Element element, String namespace, String attrName) throws Exception {
if(attrName.indexOf('.') != -1) {
String[] segments = attrName.split("\\.");
IMetaclass currentMetaclass = metaclass;
Object target = targetObject;
for(int i = 0; i < segments.length - 1; i++) {
IProperty property = currentMetaclass.findProperty(segments[i]);
if(property != null) {
target = property.getValue(target);
if(target == null) {
LoggerManager.log(new XWTException("Property \"" + segments[i] + "\" is null."));
}
currentMetaclass = loader.getMetaclass(target);
} else {
LoggerManager.log(new XWTException("Property \"" + segments[i] + "\" not found in " + element.getName() + "."));
}
}
initSegmentAttribute(currentMetaclass, segments[segments.length - 1], target, element, namespace, attrName);
return;
}
initSegmentAttribute(metaclass, attrName, targetObject, element, namespace, attrName);
}
protected void addCommandExecuteListener(String commandName, final Widget targetButton) {
final ICommand commandObj = loader.getCommand(commandName);
if(commandObj != null) {
targetButton.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
commandObj.execute(targetButton);
}
});
}
}
protected void initSegmentAttribute(IMetaclass metaclass, String propertyName, Object target, Element element, String namespace, String attrName) throws Exception {
Attribute attribute = namespace == null ? element.getAttribute(attrName) : element.getAttribute(namespace, attrName);
if(attribute == null) {
attribute = element.getAttribute(attrName);
}
IProperty property = null;
boolean isAttached = false;
{
String namePrefix = attribute.getNamePrefix();
if(namePrefix == null) {
property = metaclass.findProperty(propertyName);
} else {
//
IMetaclass metaclassAttached = loader.getMetaclass(namePrefix, attribute.getNamespace());
if(metaclassAttached != null) {
property = metaclassAttached.findProperty(propertyName);
isAttached = true;
} else {
LoggerManager.log(attribute.getNamespace() + " -> " + namePrefix + " is not found.");
return;
}
}
}
if(propertyName.equals(IConstants.XAML_DATA_CONTEXT)) {
property = null;
}
if(IConstants.XAML_COMMAND.equalsIgnoreCase(propertyName) && ICommand.class.isAssignableFrom(property.getType()) && (target instanceof Widget)) {
addCommandExecuteListener(attribute.getContent(), (Widget)target);
}
if(property == null) {
if(options.get(IXWTLoader.DESIGN_MODE_PROPERTY) == Boolean.TRUE) {
return;
}
// prepare event
IEvent event = metaclass.findEvent(attrName);
if(event == null) {
return;
}
// add events for controls and items.
if(!(target instanceof Widget)) {
return;
}
loadData.updateEvent(context, (Widget)target, event, attribute.getContent());
return;
}
String contentValue = attribute.getContent();
if("MenuItem".equalsIgnoreCase(element.getName()) && "Text".equalsIgnoreCase(attrName)) {
Attribute attributeAccelerator = element.getAttribute("Accelerator");
if(attributeAccelerator != null) {
contentValue = contentValue + '\t' + getContentValue(attributeAccelerator.getContent());
}
}
if(contentValue != null && "Accelerator".equalsIgnoreCase(attrName)) {
contentValue = XWTMaps.getCombAccelerator(contentValue);
if(contentValue.contains("'")) {
contentValue = removeSubString(contentValue, "'");
}
}
if(contentValue != null && loader.isFileResolveType(property.getType())) {
contentValue = getImagePath(contentValue);
}
// if (contentValue != null
// && (URL.class.isAssignableFrom(property.getType()))) {
// contentValue = getSourceURL(contentValue);
// }
Object value = null;
DocumentObject[] children = attribute.getChildren();
boolean usingExistingValue = false;
if(contentValue == null) {
Class<?> type = property.getType();
if(Collection.class.isAssignableFrom(type)) {
value = getCollectionProperty(type, target, attribute, attrName);
} else {
Object directTarget = null;
if(TableViewerColumn.class.isAssignableFrom(type) && attrName.equalsIgnoreCase("columns")) {
children = DocumentObjectSorter.sortWithAttr(children, "Index").toArray(new DocumentObject[children.length]);
} else {
try {
Object propertyValue = property.getValue(target);
if(UserData.getWidget(propertyValue) != null) {
directTarget = propertyValue;
// use the existing property value as parent,
// not need to add the constraint
if(!property.isValueAsParent()) {
if(isChildTypeCompatible(attribute, type)) {
directTarget = null;
} else {
type = null;
usingExistingValue = true;
}
}
}
} catch (Exception e) {
}
}
if(directTarget == null) {
directTarget = target;
}
for(DocumentObject child : children) {
String name = child.getName();
String ns = child.getNamespace();
if(name.equalsIgnoreCase(IConstants.XAML_X_STATIC) && ns.equals(IConstants.XWT_X_NAMESPACE)) {
value = getStaticValue(child);
} else if(name.equalsIgnoreCase(IConstants.XAML_STATICRESOURCES) && ns.equals(IConstants.XWT_NAMESPACE)) {
String key = child.getContent();
value = new StaticResourceBinding(loadData.getCurrentWidget(), key);
} else if((IConstants.XWT_X_NAMESPACE.equals(ns) && IConstants.XAML_X_ARRAY.equalsIgnoreCase(name))) {
value = getArrayProperty(property.getType(), directTarget, child, name);
} else if(property.getType().isArray()) {
value = getArrayProperty(property.getType(), directTarget, attribute, name);
break;
} else if(isAssignableFrom(element, TableColumn.class) && isAssignableFrom(child, TableEditor.class)) {
value = child;
} else if(TableViewerColumn.class.isAssignableFrom(property.getType()) && attribute.getContent() != null) {
value = attribute.getContent();
} else {
if("Null".equals(child.getName()) && IConstants.XWT_X_NAMESPACE.equals(child.getNamespace())) {
property.setValue(directTarget, null);
return;
} else {
value = doCreate(directTarget, (Element)child, type, EMPTY_MAP);
if(value == null && type != null && !(type == Table.class && "TableColumn".equals(child.getName()) && Table.class.isInstance(directTarget))) {
throw new XWTException(child.getName() + " cannot be a content of " + type.getName() + " " + target.getClass().getName() + "." + property.getName());
}
if(value instanceof IDynamicBinding) {
((IDynamicBinding)value).setType(attrName);
}
}
}
}
}
}
if(contentValue != null && value == null && !IConstants.XAML_COMMAND.equalsIgnoreCase(propertyName)) {
if(property.getType().isInstance(Class.class)) {
int index = contentValue.lastIndexOf(':');
if(index != -1) {
String prefix = contentValue.substring(0, index);
contentValue = findNamespace(attribute, prefix) + contentValue.substring(index);
}
}
value = loader.convertFrom(property.getType(), contentValue);
}
if(!usingExistingValue) {
if(value != null) {
Class<?> propertyType = property.getType();
if(!propertyType.isAssignableFrom(value.getClass()) || (value instanceof IBinding && !(IBinding.class.isAssignableFrom(propertyType)))) {
Object orginalValue = value;
IConverter converter = loader.findConvertor(value.getClass(), propertyType);
if(converter != null) {
value = converter.convert(value);
if(value != null && orginalValue instanceof IBinding && !propertyType.isAssignableFrom(value.getClass())) {
converter = loader.findConvertor(value.getClass(), propertyType);
if(converter != null) {
value = converter.convert(value);
} else {
LoggerManager.log(new XWTException("Convertor " + value.getClass().getSimpleName() + "->" + propertyType.getSimpleName() + " is not found"));
}
}
} else {
LoggerManager.log(new XWTException("Convertor " + value.getClass().getSimpleName() + "->" + propertyType.getSimpleName() + " is not found"));
}
}
if(isAttached) {
UserData.setLocalData(target, property, value);
} else {
if(value instanceof IDynamicValueBinding) {
IDynamicValueBinding dynamicValueBinding = (IDynamicValueBinding)value;
dynamicValueBinding.setControl(loadData.findElement(Widget.class));
dynamicValueBinding.setProperty(property);
dynamicValueBinding.setObject(target);
}
property.setValue(target, value);
}
} else {
if(value == null) {
value = property.getValue(target);
}
if(value != null) {
// create children.
for(DocumentObject child : children) {
String name = child.getName();
String ns = child.getNamespace();
if(!IConstants.XWT_X_NAMESPACE.equals(ns) || !IConstants.XAML_X_ARRAY.equalsIgnoreCase(name)) {
Class<?> type = property.getType();
if(!Collection.class.isAssignableFrom(type)) {
doCreate(value, (Element)child, null, EMPTY_MAP);
}
}
}
}
}
}
if(attribute.attributeNames(IConstants.XWT_NAMESPACE).length > 0) {
IMetaclass propertyMetaclass = loader.getMetaclass(property.getType());
if(value == null) {
value = property.getValue(target);
}
if(value != null) {
Map<String, IProperty> delayedAttributes = new HashMap<String, IProperty>();
init(propertyMetaclass, value, attribute, delayedAttributes);
iniDelayedAttribute(metaclass, target, element, namespace, delayedAttributes);
}
}
}
protected boolean isChildTypeCompatible(Attribute attribute, Class<?> type) {
DocumentObject[] children = attribute.getChildren();
if(children.length != 1) {
return false;
}
DocumentObject child = children[0];
if(!(child instanceof Element)) {
return false;
}
Element childElement = (Element)child;
String name = childElement.getName();
String namespace = childElement.getNamespace();
IMetaclass metaclass = loader.getMetaclass(name, namespace);
if(metaclass == null) {
return false;
}
return type.isAssignableFrom(metaclass.getType());
}
/**
* @param contentValue
* @return
*/
protected String getSourceURL(String contentValue) {
URL url = null;
try {
url = new URL(contentValue);
} catch (MalformedURLException e) {
if(!contentValue.startsWith("/")) {
contentValue = "/" + contentValue;
}
ILoadingContext loadingContext = context.getLoadingContext();
URL resource = loadingContext.getResource(contentValue);
if(resource == null) {
try {
resource = new URL(context.getResourcePath() + contentValue);
return resource.toString();
} catch (MalformedURLException e1) {
}
} else {
return resource.toString();
}
}
if(url != null) {
return url.toString();
}
return contentValue;
}
protected Class<?> getJavaType(DocumentObject element) {
String name = element.getName();
String namespace = element.getNamespace();
if(IConstants.XWT_X_NAMESPACE.equalsIgnoreCase(namespace) && IConstants.XAML_X_NULL.equalsIgnoreCase(name)) {
return null;
}
IMetaclass metaclass = loader.getMetaclass(name, namespace);
if(metaclass == null) {
return null;
}
return metaclass.getType();
}
protected boolean isAssignableFrom(DocumentObject element, Class<?> type) {
Class<?> targetType = getJavaType(element);
if(targetType == null) {
return false;
}
return targetType.isAssignableFrom(type);
}
protected Object getStaticValue(DocumentObject child) {
DocumentObject[] children = child.getChildren();
if(children.length == 1) {
Element element = (Element)children[0];
if(element != null) {
return ClassLoaderUtil.loadStaticMember(context.getLoadingContext(), element);
}
}
return null;
}
protected String getImagePath(String contentValue) {
String value = contentValue;
try {
File file = new File(contentValue);
if(file.exists()) {
return file.toURI().toURL().toString();
}
if(!contentValue.startsWith("/")) {
URL url = context.getResourcePath();
if(url != null) {
return url.toString() + "/" + contentValue;
}
contentValue = "/" + contentValue;
}
ILoadingContext loadingContext = context.getLoadingContext();
URL resource = loadingContext.getResource(contentValue);
if(resource == null) {
URL resourcePath = context.getResourcePath();
String fPath = resourcePath.toString();
String absolutePath = PathHelper.getAbsolutePath(fPath, contentValue);
if((file = new File(absolutePath)).exists()) {
return file.toURI().toURL().toString();
}
resource = new URL(absolutePath);
}
return resource.toString();
} catch (MalformedURLException e) {
return value;
}
}
protected String removeSubString(String str, String subString) {
StringBuffer stringBuffer = new StringBuffer();
int lenOfsource = str.length();
int i;
int posStart;
for(posStart = 0; (i = str.indexOf(subString, posStart)) >= 0; posStart = i + subString.length()) {
stringBuffer.append(str.substring(posStart, i));
}
if(posStart < lenOfsource) {
stringBuffer.append(str.substring(posStart));
}
return stringBuffer.toString();
}
protected String getContentValue(String text) {
StringBuffer stringBuffer = new StringBuffer();
String subString = "SWT.";
String str = XWTMaps.getCombAccelerator(text);
if(str.contains(subString)) {
str = removeSubString(str, subString);
}
if(str.contains("'")) {
str = removeSubString(str, "'");
}
if(str.contains(" ")) {
str = removeSubString(str, " ");
}
if(str.contains("|")) {
str = str.replace('|', '+');
}
stringBuffer.append(str);
return stringBuffer.toString();
}
}