/******************************************************************************* * 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; } } }