blob: ae24474ff73c783066cf4347e4740c9d0c20d8c5 [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.internal.xml;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.eclipse.xwt.IConstants;
import org.eclipse.xwt.internal.core.Core;
/**
* @since 1.0
* @author yyang
*/
public class Element extends DocumentObject {
private static final String[] EMPTY_STRING_ARRAY = new String[0];
private String path;
private Map<String, Attribute> originalAttributes;
private Map<String, Map<String, Attribute>> externalAttributes;
private String[] xmlnsMapping;
/**
* @return the path of this element, i.e. indexes of this element and its parents in XML.
*/
public String getPath() {
return path;
}
public String getXmlns(String prefix) {
if (prefix == null) {
prefix = "";
}
if (xmlnsMapping != null) {
for (int i = 0; i < xmlnsMapping.length; i++) {
if (prefix.equals(xmlnsMapping[i++])) {
return xmlnsMapping[i];
}
}
}
return null;
}
/**
* Default constructor
*
* @param context
* bundle context
* @param namespace
* element namespace
* @param name
* element name
* @param originalAttributes
* element arributes
*/
public Element(String namespace, String name, Map<String, String> xmlnsMapping) {
this(namespace, name, null, null, xmlnsMapping);
}
public Element(String namespace, String name, String path, Collection<Attribute> attributes, Map<String, String> xmlnsMapping) {
super(namespace, name);
this.path = path;
if (xmlnsMapping != null) {
this.xmlnsMapping = new String[xmlnsMapping.size() * 2];
int i = 0;
for (Map.Entry<String, String> entry : xmlnsMapping.entrySet()) {
String key = entry.getKey();
if (key == null) {
key = "";
}
this.xmlnsMapping[i++] = key;
this.xmlnsMapping[i++] = entry.getValue();
}
}
this.originalAttributes = Collections.EMPTY_MAP;
this.externalAttributes = Collections.EMPTY_MAP;
if (attributes != null) {
for (Attribute attribute : attributes) {
setInternalAttribute(attribute);
}
}
}
/*
* (non-Javadoc)
*
* @see com.soyatec.eface.core.IElement#attributeNames()
*/
public String[] attributeNames() {
return originalAttributes.keySet().toArray(EMPTY_STRING_ARRAY);
}
/*
* (non-Javadoc)
*
* @see com.soyatec.eface.core.IElement#attributeNamespaces()
*/
public String[] attributeNamespaces() {
return externalAttributes.keySet().toArray(EMPTY_STRING_ARRAY);
}
/*
* (non-Javadoc)
*
* @seecom.soyatec.eface.core.IElement#setAttribute(com.soyatec.eface.core. IAttribute)
*/
public void setAttribute(Attribute attribute) {
setInternalAttribute(attribute);
firePropertyChanged(attribute);
}
/*
* (non-Javadoc)
*
* @see com.soyatec.eface.IElement#attributeNames(java.lang.String)
*/
public String[] attributeNames(String namespace) {
if (getNamespace().equals(namespace)) {
return attributeNames();
}
Map<String, Attribute> externalAttribute = externalAttributes.get(namespace);
if (externalAttribute != null) {
return externalAttribute.keySet().toArray(EMPTY_STRING_ARRAY);
} else {
return Core.EMPTY_STRING_ARRAY;
}
}
/*
* (non-Javadoc)
*
* @see com.soyatec.eface.core.IElement#getAttribute(java.lang.String)
*/
public Attribute getAttribute(String name) {
assert name != null;
return originalAttributes.get(name);
}
/*
* (non-Javadoc)
*
* @see com.soyatec.eface.core.IElement#getAttribute(java.lang.String, java.lang.String)
*/
public Attribute getAttribute(String namespace, String name) {
Map<String, Attribute> externalAttribute = externalAttributes.get(namespace);
if (externalAttribute != null) {
return externalAttribute.get(name);
} else {
return null;
}
}
@Override
public Object clone() throws CloneNotSupportedException {
Element element = (Element) super.clone();
element.parent = null;
if (originalAttributes.isEmpty()) {
originalAttributes = Collections.EMPTY_MAP;
} else {
element.originalAttributes = new LinkedHashMap<String, Attribute>(originalAttributes.size());
for (String attrName : originalAttributes.keySet()) {
Attribute attrValue = (Attribute) originalAttributes.get(attrName).clone();
element.originalAttributes.put(attrName, attrValue);
}
}
if (externalAttributes.isEmpty()) {
element.originalAttributes = Collections.EMPTY_MAP;
} else {
element.externalAttributes = new LinkedHashMap<String, Map<String, Attribute>>(externalAttributes.size());
for (String ns : externalAttributes.keySet()) {
Map<String, Attribute> oAttributes = externalAttributes.get(ns);
Map<String, Attribute> nAttributes = new LinkedHashMap<String, Attribute>(oAttributes.size());
for (Map.Entry<String, Attribute> entry : oAttributes.entrySet()) {
String attrName = entry.getKey();
Attribute attrValue = (Attribute) entry.getValue().clone();
nAttributes.put(attrName, attrValue);
}
element.externalAttributes.put(ns, nAttributes);
}
}
return element;
}
protected void setAttributes(Collection<Attribute> attributes) {
for (Attribute attribute : attributes) {
setInternalAttribute(attribute);
}
firePropertyChanged(attributes);
}
private void firePropertyChanged(Attribute attribute) {
notifyObservers(attribute);
}
private void firePropertyChanged(Collection<Attribute> attributes) {
notifyObservers(attributes);
}
private boolean isXWTNamespace(String namespace) {
String scopeNamespace = getNamespace();
if (namespace == null || "".equals(namespace)) {
return true;
}
if (scopeNamespace.startsWith(IConstants.XAML_CLR_NAMESPACE_PROTO) || scopeNamespace.equals(IConstants.XWT_NAMESPACE)) {
return namespace.equalsIgnoreCase(scopeNamespace) || namespace.equals(IConstants.XWT_NAMESPACE);
}
return false;
}
/**
* Set attribute without notifying event.
*
* @param attribute
* the modified attribute.
*/
private void setInternalAttribute(Attribute attribute) {
assert attribute != null;
String namespace = attribute.getNamespace();
String name = attribute.getName();
if (isXWTNamespace(namespace)) {
if (originalAttributes == Collections.EMPTY_MAP) {
originalAttributes = new LinkedHashMap<String, Attribute>();
}
originalAttributes.put(name, attribute);
} else {
Map<String, Attribute> externalAttribute = externalAttributes.get(namespace);
if (externalAttribute == null) {
externalAttribute = new HashMap<String, Attribute>();
}
if (externalAttributes == Collections.EMPTY_MAP) {
externalAttributes = new LinkedHashMap<String, Map<String, Attribute>>();
}
externalAttribute.put(name, attribute);
externalAttributes.put(namespace, externalAttribute);
}
((DocumentObject) attribute).setParent(this);
}
}