blob: 15602362808c51ba02129e5e7ccd19b20150844b [file] [log] [blame]
/*******************************************************************************
* 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.tools.ui.designer.model;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
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.internal.xml.ElementManager;
import org.eclipse.xwt.tools.ui.xaml.XamlAttribute;
import org.eclipse.xwt.tools.ui.xaml.XamlDocument;
import org.eclipse.xwt.tools.ui.xaml.XamlElement;
import org.eclipse.xwt.tools.ui.xaml.XamlFactory;
import org.eclipse.xwt.tools.ui.xaml.XamlNode;
/**
* @author Jin Liu(jin.liu@soyatec.com)
*/
public class XamlDocumentProvider {
private IFile file;
private XamlDocument document;
private boolean needReload = false;
private XamlDocumentProvider(IFile file) {
Assert.isTrue(file != null && file.exists());
this.file = file;
ResourcesPlugin.getWorkspace().addResourceChangeListener(
new IResourceChangeListener() {
public void resourceChanged(IResourceChangeEvent event) {
performResourceChanged(event);
}
});
}
private void performResourceChanged(IResourceChangeEvent event) {
if (file == null || !file.exists()) {
return;
}
IResourceDelta delta = event.getDelta();
try {
delta.accept(new IResourceDeltaVisitor() {
public boolean visit(IResourceDelta delta) throws CoreException {
IResource resource = delta.getResource();
if (resource != null
&& file.getFullPath()
.equals(resource.getFullPath())) {
needReload = true;
return false;// break
}
return true;
}
});
} catch (CoreException e) {
}
}
public XamlDocument getDocument() {
if (document == null) {
document = XamlFactory.eINSTANCE.createXamlDocument();
}
boolean reload = needReload || document.getRootElement() == null;
if (reload) {
reload();
needReload = false;
}
return document;
}
public boolean reload() {
if (document == null) {
return false;
}
try {
URL url = file.getLocationURI().toURL();
if (url == null) {
return false;
}
ElementManager manager = new ElementManager();
Element element = manager.load(file.getContents(), url);
XamlElement rootElement = document.getRootElement();
if (rootElement == null) {
rootElement = XamlFactory.eINSTANCE.createXamlElement();
}
updateNode(rootElement, element);
if (rootElement.eContainer() == null) {
document.setRootElement(rootElement);
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
private void updateNode(XamlNode node, DocumentObject obj) {
if (node == null || obj == null) {
throw new NullPointerException();
}
String namespace = obj.getNamespace();
// 1. basic settings
node.setId(obj.getId());
node.setName(obj.getName());
node.setNamespace(namespace);
node.setValue(obj.getContent());
// 2. Attributes
if (obj instanceof Element) {
Element element = (Element) obj;
List<XamlAttribute> oldAttributes = new ArrayList<XamlAttribute>(
node.getAttributes());
oldAttributes.removeAll(updateAttributes(node, element, null));
String[] attributeNamespaces = element.attributeNamespaces();
for (String ns : attributeNamespaces) {
oldAttributes.removeAll(updateAttributes(node, element, ns));
}
for (XamlAttribute forRemove : oldAttributes) {
node.getAttributes().remove(forRemove);
}
}
// 3. Children
List<XamlElement> oldChildren = new ArrayList<XamlElement>(node
.getChildNodes());
oldChildren.removeAll(updateChildNodes(node, obj));
for (XamlElement forRemove : oldChildren) {
node.getChildNodes().remove(forRemove);
}
}
private List<XamlElement> updateChildNodes(XamlNode node, DocumentObject obj) {
List<XamlElement> updates = new ArrayList<XamlElement>();
DocumentObject[] children = obj.getChildren();
for (int index = 0; index < children.length; index++) {
DocumentObject documentObject = children[index];
XamlElement child = node.getChild(index);
if (child == null) {
child = XamlFactory.eINSTANCE.createXamlElement();
}
updateNode(child, documentObject);
if (child.eContainer() == null) {
node.getChildNodes().add(child);
}
updates.add(child);
}
return updates;
}
private List<XamlAttribute> updateAttributes(XamlNode node,
Element element, String namespace) {
if (node == null || element == null) {
throw new NullPointerException();
}
List<XamlAttribute> attrs = new ArrayList<XamlAttribute>();
String[] attributeNames = namespace == null ? element.attributeNames()
: element.attributeNames(namespace);
for (String attrName : attributeNames) {
Attribute attribute = namespace == null ? element
.getAttribute(attrName) : element.getAttribute(namespace,
attrName);
if (attribute == null) {
continue;
}
XamlAttribute xa = node.getAttribute(attrName, namespace);
if (xa == null) {
xa = XamlFactory.eINSTANCE.createAttribute(attrName, namespace);
}
updateNode(xa, attribute);
if (xa.eContainer() == null) {
node.getAttributes().add(xa);
}
attrs.add(xa);
}
return attrs;
}
public static XamlDocument getDocument(IFile file) {
return getProvider(file).getDocument();
}
public static XamlDocumentProvider getProvider(IFile file) {
XamlDocumentProvider p = providers.get(file);
if (p == null) {
providers.put(file, p = new XamlDocumentProvider(file));
}
return p;
}
private static final Map<IFile, XamlDocumentProvider> providers = new HashMap<IFile, XamlDocumentProvider>(
1);
}