/*******************************************************************************
 * 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.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.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;
import org.eclipse.xwt.ICLRFactory;
import org.eclipse.xwt.IConstants;
import org.eclipse.xwt.IDataProvider;
import org.eclipse.xwt.IEventHandler;
import org.eclipse.xwt.IEventInvoker;
import org.eclipse.xwt.IIndexedElement;
import org.eclipse.xwt.ILoadingContext;
import org.eclipse.xwt.INamespaceHandler;
import org.eclipse.xwt.IStyle;
import org.eclipse.xwt.IXWTLoader;
import org.eclipse.xwt.ResourceDictionary;
import org.eclipse.xwt.Tracking;
import org.eclipse.xwt.XWT;
import org.eclipse.xwt.XWTException;
import org.eclipse.xwt.XWTLoader;
import org.eclipse.xwt.XWTMaps;
import org.eclipse.xwt.annotation.UI;
import org.eclipse.xwt.callback.ICreatedCallback;
import org.eclipse.xwt.callback.ILoadedCallback;
import org.eclipse.xwt.core.IBinding;
import org.eclipse.xwt.core.IDynamicBinding;
import org.eclipse.xwt.core.IDynamicValueBinding;
import org.eclipse.xwt.core.IRenderingContext;
import org.eclipse.xwt.core.IVisualElementLoader;
import org.eclipse.xwt.core.Setter;
import org.eclipse.xwt.core.Style;
import org.eclipse.xwt.core.ValidationStatus;
import org.eclipse.xwt.input.ICommand;
import org.eclipse.xwt.internal.core.Binding;
import org.eclipse.xwt.internal.core.Core;
import org.eclipse.xwt.internal.core.DataBindingTrack;
import org.eclipse.xwt.internal.core.IEventController;
import org.eclipse.xwt.internal.core.ScopeKeeper;
import org.eclipse.xwt.internal.utils.ClassLoaderUtil;
import org.eclipse.xwt.internal.utils.DocumentObjectSorter;
import org.eclipse.xwt.internal.utils.LoggerManager;
import org.eclipse.xwt.internal.utils.NamespaceHelper;
import org.eclipse.xwt.internal.utils.ObjectUtil;
import org.eclipse.xwt.internal.utils.TableEditorHelper;
import org.eclipse.xwt.internal.utils.UserData;
import org.eclipse.xwt.internal.xml.Attribute;
import org.eclipse.xwt.internal.xml.DocumentObject;
import org.eclipse.xwt.internal.xml.Element;
import org.eclipse.xwt.javabean.metadata.properties.PropertiesConstants;
import org.eclipse.xwt.javabean.metadata.properties.TableItemProperty;
import org.eclipse.xwt.jface.JFacesHelper;
import org.eclipse.xwt.metadata.IEvent;
import org.eclipse.xwt.metadata.IMetaclass;
import org.eclipse.xwt.metadata.IProperty;
import org.eclipse.xwt.metadata.IValueLoading;
import org.eclipse.xwt.utils.PathHelper;

/**
 * @author jliu (jin.liu@soyatec.com)
 */
public class ResourceLoader implements IVisualElementLoader {
	static Map<String, Object> EMPTY_MAP = Collections.EMPTY_MAP;

	static private String VALIDATION_STATUS_CONSTANT = "status";

	static final String RESOURCE_LOADER_PROPERTY = "XWT.ResourceLoader";

	private static final String COLUMN = "Column";

	private Map<String, Object> options;

	private Collection<Binding> bindings;
	
	private Collection<ValidationStatus> status;

	public Collection<Binding> getBindings() {
		return bindings;
	}

	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.EMPTY_LIST;
		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) {
						method = ObjectUtil.findMethod(clazz, handler);
					}
					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.xwt.IVisualElementLoader#createUIElement(org.eclipse.
	 * e4.xwt.Element, org.eclipse.xwt.ILoadData,
	 * org.eclipse.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.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((Widget) parent)), widget);
			UserData.bindNameContext((Widget) 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.EMPTY_MAP);
				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.EMPTY_MAP);
				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.EMPTY_MAP);
			}
		}

		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) {

		if (targetObject instanceof IDynamicBinding) {
			if (bindings == null)
				bindings = new ArrayList<Binding>();
			bindings.add((Binding) 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) {

		// after create a binding with validationstatus tag, the datasource of
		// the binding should be updated to the corresponding bindingcontext
		Collection<ValidationStatus> removedStatus = new ArrayList<ValidationStatus>();
		if (status != null && !status.isEmpty()) {
			for (ValidationStatus validationStatus : status) {
				if (bindings != null && !bindings.isEmpty()) {
					for (Binding binding : bindings) {
						if (binding.getName() != null
								&& validationStatus.getSourceName() != null
								&& validationStatus.getSourceName().equals(
										binding.getName())) {
							removedStatus.add(validationStatus);
							Control control = (Control) validationStatus
									.getControl();
							if (binding.getControl().equals(control))
								if (binding != null) {
									Binding targetBinding = (Binding) validationStatus
											.getParent();
									targetBinding.setSource(binding
											.getBindingContext());
									targetBinding
											.setPath(VALIDATION_STATUS_CONSTANT);
								}
						}
					}
				}
			}
			if (removedStatus != null) {
				status.removeAll(removedStatus);
				removedStatus.clear();
			}
		}

	}

	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 = (Widget) 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 = (Widget) 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 = (Widget) 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 = (Widget) 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 = (Widget) 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 (property == null) {
				IMetaclass mc = XWT.getMetaclass(targetObject);
				property = mc.findProperty(attrName);

				if (property != null) {
					metaclass = mc;
				}
			}

			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.EMPTY_MAP);
			}
			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((Widget) 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((Widget) instance, instance);
				}
				return instance;
			} else {
				Object instance = type.newInstance();
				loadData.setClr(instance);
				if (instance instanceof Widget) {
					UserData.setCLR((Widget) 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);
					}
					// deal with validation staus
					if ((value instanceof ValidationStatus)
							&& (property.getName().equals("source"))
							&& (target instanceof Binding)) {
						ValidationStatus validationStatus = (ValidationStatus) value;
						validationStatus.setParent(target);
						if (status == null)
							status = new ArrayList<ValidationStatus>();
						status.add(validationStatus);
					} else {
						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();
	}
}
