/*******************************************************************************
* Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Exadel, Inc. and Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.common.meta.impl;
import java.util.*;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.jboss.tools.common.meta.*;
import org.jboss.tools.common.meta.action.*;
import org.jboss.tools.common.meta.action.impl.*;
import org.jboss.tools.common.model.*;
import org.jboss.tools.common.model.loaders.XObjectLoader;
import org.jboss.tools.common.model.plugin.ModelPlugin;
import org.jboss.tools.common.model.util.*;
public class XModelEntityImpl extends XMetaElementImpl implements XModelEntity {
public static boolean hideHelp = true;
protected String module;
protected XChildrenImpl children = new XChildrenImpl();
protected XAttribute[] m_Attributes;
protected XActionListImpl actions = new XActionListImpl();
protected XEntityRenderer m_Renderer = null;
protected String implementationClassName = null;
protected String resolvedImplementationClassName = null;
protected String m_GeneratorClassName = null;
protected String loaderClassName = null;
protected String resolvedLoaderClassName = null;
protected String m_EditorClassName = null;
protected XDependencies dependencies = new DefaultDependencies();
protected XAdoptManager adopt = null;
protected String xmlSubPath = null;
protected Element element = null;
protected XModelEntityImpl() {}
public void setModule(String s) {
module = s;
}
public String getModule() {
return module;
}
void setElement(Element element) {
this.element = element;
setName(element.getAttribute(NAME));
}
void validate() {
if(element == null) return;
synchronized(this) {
if(element == null) return;
load(element);
element = null;
XModelMetaDataImpl meta = (XModelMetaDataImpl)getMetaModel();
ArrayList<XModelEntityExtensionImpl> es = meta.getExtensions().getExtensions(getName());
if(es != null) {
for (int i = 0; i < es.size(); i++)
merge((XModelEntityExtensionImpl)es.get(i));
if(!hideHelp) addHelpAction();
}
}
}
private void addHelpAction() {
XActionListImpl list = actions;
XActionItem item = actions.getItem("Properties"); //$NON-NLS-1$
if(item instanceof XActionListImpl) list = (XActionListImpl)item;
list.addActionItem(XActionImpl.getHelpAction());
}
public XAttribute[] getAttributes(){
return m_Attributes;
}
public XAttribute getAttribute(String name) {
for (int i = 0; i < m_Attributes.length; i++)
if(m_Attributes[i].getName().equals(name)) return m_Attributes[i];
return null;
}
public void setAttributes(XAttribute[] attrs){
m_Attributes=attrs;
if(attrs != null) for (int i = 0; i < attrs.length; i++) {
XAttributeImpl ai = (XAttributeImpl)attrs[i];
ai.setModelEntity(this);
}
}
public Class getImplementingClass() {
if(resolvedImplementationClassName == UNRESOLVED) {
resolvedImplementationClassName = expand(implementationClassName, "Implementations"); //$NON-NLS-1$
}
if(resolvedImplementationClassName == null) return null;
Class cls = ModelFeatureFactory.getInstance().getFeatureClass(resolvedImplementationClassName);
if(cls == null) {
resolvedImplementationClassName = null;
}
return cls;
}
public boolean hasObjectImplementation() {
return implementationClassName != null && implementationClassName.length() > 0;
}
public XModelObject getObjectImplementation() {
if(resolvedImplementationClassName == UNRESOLVED) {
resolvedImplementationClassName = expand(implementationClassName, "Implementations"); //$NON-NLS-1$
}
if(resolvedImplementationClassName == null) return null;
XModelObject o = ModelFeatureFactory.getInstance().createXModelObjectInstance(resolvedImplementationClassName);
if(o == null) {
resolvedImplementationClassName = null;
}
return o;
}
public void setImplementingClassName(String className){
if(className != null && className.length() == 0) className = null;
implementationClassName = className;
if(className != null) {
resolvedImplementationClassName = UNRESOLVED;
}
}
public boolean hasObjectLoader() {
return loaderClassName != null && loaderClassName.length() > 0;
}
public XObjectLoader getObjectLoader() {
if(resolvedLoaderClassName == UNRESOLVED) {
resolvedLoaderClassName = expand(loaderClassName, "Loaders"); //$NON-NLS-1$
}
if(resolvedLoaderClassName == null) return null;
Object o = ModelFeatureFactory.getInstance().createFeatureInstance(resolvedLoaderClassName);
if(o == null) {
return null;
}
if(!(o instanceof XObjectLoader)) {
ModelPlugin.getPluginLog().logError("Model object loader" + resolvedLoaderClassName + " must implement " + XObjectLoader.class.getName()); //$NON-NLS-1$ //$NON-NLS-2$
resolvedLoaderClassName = null;
return null;
}
return (XObjectLoader)o;
}
static String UNRESOLVED = "UNRESOLVED"; //$NON-NLS-1$
public void setLoaderClassName(String className) {
if(className != null && className.length() > 0) {
loaderClassName = className;
resolvedLoaderClassName = UNRESOLVED;
}
}
public String getEditorClassName() {
return (m_EditorClassName = expand(m_EditorClassName, "ObjectEditor")); //$NON-NLS-1$
}
public void setEditorClassName(String className){
m_EditorClassName = className;
}
public String getGeneratorClassName() {
return m_GeneratorClassName;
}
public void setGeneratorClassName(String className) {
m_GeneratorClassName = className;
}
public XActionList getActionList() {
if(!actions.isLoaded()) {
actions.validate();
if(!hideHelp) addHelpAction();
}
return actions;
}
public XChild getChild(String entityName) {
return children.getChild(entityName);
}
public XChild[] getChildren() {
return children.getChildren();
}
public XEntityRenderer getRenderer() {
return m_Renderer;
}
public void setRenderer(XEntityRenderer renderer) {
m_Renderer = renderer;
}
public String getXMLSubPath() {
return xmlSubPath;
}
public void load(Element element) {
setName(element.getAttribute(NAME));
setImplementingClassName(element.getAttribute(IMPLEMENTING_CLASS));
setLoaderClassName(element.getAttribute(IMPLEMENTATION_LOADING_CLASS));
if(XMetaDataLoader.hasAttribute(element, OBJECT_EDITOR_CLASSNAME)) {
setEditorClassName(element.getAttribute(OBJECT_EDITOR_CLASSNAME));
}
if(XMetaDataLoader.hasAttribute(element, IMPLEMENTATION_GENERATOR_CLASS)) {
setGeneratorClassName(element.getAttribute(IMPLEMENTATION_GENERATOR_CLASS));
}
// setAttributes((XAttribute[])XMetaDataLoader.loadElementGroup(element,XMODEL_ATTRIBUTES, XMODEL_ATTRIBUTE, XAttributeImpl.class));
loadAttributes(element);
children.load(element);
setRenderer((XEntityRenderer)XMetaDataLoader.loadMetaElement(element,RENDERER, XEntityRendererImpl.class, true));
if(XMetaDataLoader.hasAttribute(element, ADOPT_MANAGER_CLASS)) {
setAdoptManager(element.getAttribute(ADOPT_MANAGER_CLASS));
}
loadDependencies(element);
xmlSubPath = element.getAttribute("XMLSUBPATH"); //$NON-NLS-1$
Element ei = XMetaDataLoader.getUniqueChild(element, "XActionItem"); //$NON-NLS-1$
actions.setElement(ei);
loadProperties(element);
}
private void loadAttributes(Element element) {
Element att = XMetaDataLoader.getUniqueChild(element, XMODEL_ATTRIBUTES);
NodeList nl = att.getChildNodes();
List<XAttributeImpl> list = new ArrayList<XAttributeImpl>();
for (int i = 0; i < nl.getLength(); i++) {
Node n = nl.item(i);
if(n.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element)n;
String name = e.getNodeName();
if(XMODEL_ATTRIBUTE.equals(name)) {
XAttributeImpl attr = (XAttributeImpl)XMetaDataLoader.loadMetaElement(e, XAttributeImpl.class, false);
if(attr != null) list.add(attr);
} else if(XMODEL_ATTRIBUTE_REF.equals(name)) {
String entityName = e.getAttribute(XMetaDataConstants.ENTITY);
String attrName = e.getAttribute(NAME);
String attributes = e.getAttribute("attributes"); //$NON-NLS-1$
String[] atributeNames = new String[]{attrName};
if(atributeNames != null && attributes.length() > 0) {
atributeNames = XModelObjectUtil.asStringArray(attributes);
}
XModelEntity entity = getMetaModel().getEntity(entityName);
if(entity != null) {
for (int k = 0; k < atributeNames.length; k++) {
XAttributeImpl attr = (XAttributeImpl)entity.getAttribute(atributeNames[k]);
if(attr != null) {
list.add(attr.copy());
} else if(ModelPlugin.isDebugEnabled()) {
ModelPlugin.getPluginLog().logInfo("Cannot find reference to attribute " + attrName + " of entity " + entityName); //$NON-NLS-1$ //$NON-NLS-2$
}
}
} else if(ModelPlugin.isDebugEnabled()) {
ModelPlugin.getPluginLog().logInfo("Cannot find reference to entity " + entityName); //$NON-NLS-1$
}
}
}
}
setAttributes(list.toArray(new XAttributeImpl[0]));
}
private void loadDependencies(Element el) {
Element c = XMetaDataLoader.getUniqueChild(el, "XDependencies"); //$NON-NLS-1$
XDependencies d = (c == null) ? null : (XDependencies)XMetaDataLoader.loadMetaElement(c, null, false);
if(d != null) dependencies = d;
}
public String toString(){
StringBuffer sb = new StringBuffer(100);
sb.append(getName());
sb.append('\n');
for(int i = 0; i < m_Attributes.length;++i)
sb.append(" " + m_Attributes[i] + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
return sb.toString();
}
///////// dependencies
public boolean isVisible(XModelObject object, String attribute) {
return dependencies.isVisible(object, attribute);
}
public boolean isEditable(XModelObject object, String attribute) {
return dependencies.isEditable(object, attribute);
}
public void setDependentValues(XModelObject object, String attribute) {
dependencies.setDependentValues(object, attribute);
}
//// adopt
public XAdoptManager getAdoptManager() {
return adopt;
}
public void setAdoptManager(String adoptclass) {
if(adoptclass != null && adoptclass.length() > 0) {
adopt = new XAdoptWrapper(adoptclass, this);
}
}
void validateChildren() {
children.validate(getMetaModel());
}
//// merge
private void merge(XModelEntityExtensionImpl ext) {
children.merge(ext.getChildren());
actions.merge((XActionListImpl)ext.getActionList());
}
//optimization
private HashMap<String,Integer> registered = new HashMap<String,Integer>();
public int getPropertyIndex(String name, boolean register) {
Integer io = registered.get(name);
if(io == null) {
if(!register) return -1;
synchronized (registered) {
io = registered.get(name);
if(io == null) {
io = Integer.valueOf(registered.size());
registered.put(name, io);
}
}
}
return io.intValue();
}
public int getPropertyCount() {
return registered.size();
}
private Properties xmlmap = null;
static Set<String> unfoundEntities = null;
public String getChildByXML(String xmlname) {
if(xmlmap == null) {
xmlmap = new Properties();
XChild[] cs = children.getChildren();
for (int i = 0; i < cs.length; i++) {
String n = cs[i].getName();
XModelEntity e = getMetaModel().getEntity(n);
if(e == null) {
if(unfoundEntities == null) unfoundEntities = new HashSet<String>();
if(!unfoundEntities.contains(n)) {
unfoundEntities.add(n);
ModelPlugin.getPluginLog().logInfo("getChildByXML: cannot find child entity " + n); //$NON-NLS-1$
}
continue;
}
String x = e.getXMLSubPath();
if(x == null || x.length() == 0) continue;
xmlmap.setProperty(x, n);
}
}
return xmlmap.getProperty(xmlname);
}
public Set<String> getRequiredChildren() {
return children.getRequiredChildren();
}
/**
* FIXME Move to ModelTest plugin
*/
public String testImplementation() {
if(implementationClassName == null || implementationClassName.length() == 0) {
return null;
}
String cn = expand(implementationClassName, "Implementations"); //$NON-NLS-1$
if(cn == null) {
return "cannot expand implementation " + implementationClassName; //$NON-NLS-1$
}
Class cls = ModelFeatureFactory.getInstance().getFeatureClass(cn);
if(cls == null) {
return "cannot load implementation class " + cn; //$NON-NLS-1$
}
try {
Object h = cls.newInstance();
if(!(h instanceof XModelObject)) {
return "cannot reduce implementation to XModelObject"; //$NON-NLS-1$
}
} catch (InstantiationException e) {
return "cannot create implementation object"; //$NON-NLS-1$
} catch (IllegalAccessException e) {
return "cannot create implementation object"; //$NON-NLS-1$
}
return null;
}
/**
* FIXME Move to ModelTest plugin
*/
public String testLoader() {
if(loaderClassName == null || loaderClassName.length() == 0) {
return null;
}
String cn = expand(loaderClassName, "Loaders"); //$NON-NLS-1$
if(cn == null) {
return "cannot expand loader " + loaderClassName; //$NON-NLS-1$
}
Class cls = ModelFeatureFactory.getInstance().getFeatureClass(cn);
if(cls == null) {
return "cannot load loader class " + cn; //$NON-NLS-1$
}
try {
Object h = cls.newInstance();
if(!(h instanceof XObjectLoader)) {
return "cannot reduce loader to XObjectLoader"; //$NON-NLS-1$
}
} catch (InstantiationException e) {
return "cannot create loader object"; //$NON-NLS-1$
} catch (IllegalAccessException e) {
return "cannot create loader object"; //$NON-NLS-1$
}
return null;
}
}
class XAdoptWrapper implements XAdoptManager {
String adoptclass;
XModelEntityImpl entity;
public XAdoptWrapper(String adoptclass, XModelEntityImpl entity) {
this.adoptclass = adoptclass;
this.entity = entity;
}
public void adopt(XModelObject target, XModelObject object, Properties p) throws XModelException {
validate();
if(entity.adopt != null) {
entity.adopt.adopt(target, object, p);
}
}
public boolean isAdoptable(XModelObject target, XModelObject object) {
validate();
return entity.adopt != null && entity.adopt.isAdoptable(target, object);
}
void validate() {
try {
if(adoptclass != null && adoptclass.length() > 0) {
entity.adopt = (XAdoptManager)ModelFeatureFactory.getInstance().createFeatureInstance(adoptclass);
}
} catch (ClassCastException e) {
ModelPlugin.getPluginLog().logError("XModelEntityImpl:setAdoptManager:" + e.getMessage()); //$NON-NLS-1$
entity.adopt = null;
}
}
}