/******************************************************************************* * 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.model.impl; import java.text.MessageFormat; import java.util.*; import org.eclipse.swt.widgets.Display; import org.jboss.tools.common.model.*; import org.jboss.tools.common.meta.*; import org.jboss.tools.common.model.event.XModelTreeEvent; import org.jboss.tools.common.model.plugin.ModelPlugin; import org.jboss.tools.common.model.util.XModelObjectLoaderUtil; public class RegularObjectImpl extends XModelObjectImpl implements XOrderedObject { private static final long serialVersionUID = 7942041044569562286L; protected RegularChildren children = null; public RegularObjectImpl() {} protected RegularChildren createChildren() { return new RegularChildren(); } public void destroy() { if(children != null && !children.isEmpty()) { XModelObject[] h = children.getObjects(); for (XModelObject o: h) { ((XModelObjectImpl)o).destroy(); } //TODO provide safe work at setting children to null. children = createChildren(); } super.destroy(); } public boolean areChildrenOrdered() { return children != null && children.areChildrenOrdered(); } public String name() { return get(XModelObjectConstants.XML_ATTR_NAME); } protected void onSetEntity(String name) { super.onSetEntity(name); if(children == null) { children = createChildren(); } children.clear(); children.setComparator(createComparator()); } protected Comparator<XModelObject> createComparator() { return EntityComparator.getComparator(getModelEntity()); } public boolean hasChildren() { return !children.isEmpty(); } protected void loadChildren() {} public XModelObject[] getChildren() { loadChildren(); return children.getObjects(); } public XModelObject[] getLoadedChildren() { return children.getObjects(); } public boolean addChild_0(XModelObject o) { if(o == null) { return false; } String entity = o.getModelEntity().getName(); XChild c = getModelEntity().getChild(entity); if(c == null) return false; if(c.getMaxCount() < Integer.MAX_VALUE && children.getChildrenCount(entity) >= c.getMaxCount()) { return false; } ((XModelObjectImpl)o).setParent_0(this); boolean b = children.addObject(o); if(b) { if(o.getErrorState() == 2 || o.getErrorChildCount() > 0) { registerErrorChild(); } if(o.getErrorState() == 1 || o.getWarningChildCount() > 0) { registerWarningChild(); } } return b; } public void removeChild_0(XModelObject o) { if(children.removeObject(o)) { if(o.getErrorState() == 2 || o.getErrorChildCount() > 0) { unregisterErrorChild(); } if(o.getErrorState() == 1 || o.getWarningChildCount() > 0) { unregisterWarningChild(); } } } public void set(String name, String value) { if(!(getParent() instanceof RegularObjectImpl)) { super.set(name, value); return; } String ov = super.get(name); String opp = getPathPart(); super.set(name, value); String npp = getPathPart(); if(opp != null && opp.equals(npp)) { return; } RegularObjectImpl p = (RegularObjectImpl)getParent(); XModelObject c = p.children.change(this, opp, npp); if(c != null) { if(getModelEntity().getAttribute(XModelObjectLoaderUtil.ATTR_ID_NAME) != null) { int k = 1; while(c != null) { super.set(XModelObjectLoaderUtil.ATTR_ID_NAME, "" + k); //$NON-NLS-1$ npp = getPathPart(); c = p.children.change(this, opp, npp); k++; } return; } else if(hasIdAttr()) { int k = 1; while(c != null) { super.set(XModelObjectImpl.DUPLICATE, "" + k); //$NON-NLS-1$ npp = getPathPart(); if(k == 1 && npp.indexOf(XModelObjectImpl.DUPLICATE) < 0) { elementExists(c, name, value); return; } c = p.children.change(this, opp, npp); k++; } } else { if(ov == null) properties.remove(name); else super.set(name, ov); elementExists(c, name, value); } } } public XModelObject getChildByPathPart(String pathpart) { loadChildren(); return children.getObject(pathpart); } // diagnostic /** * This method may be called in two cases: * 1) User input is not appropriately validated. In this case proper validation * and notification should be implemented (e.g. error message in dialogs, * error markers in editors/error view) * 2) Internal model update is implemented with errors. * @param o * @param name * @param value */ protected void elementExists(XModelObject o, String name, String value) { if(getModel().getService() == null) return; String mes = MessageFormat.format( "Cannot set {0} = {1} for {2}\nbecause {3} exists in the {4}", getAttrNameByXMLName(name), value, title(this), title(o), title(getParent())); if(Display.getCurrent() != null) { getModel().getService().showDialog("Error", mes, new String[]{"OK"}, null, 1); } ModelPlugin.getDefault().logError(mes); } private static String title(XModelObject o) { return o.getAttributeValue(XModelObjectConstants.ATTR_ELEMENT_TYPE) + " " + //$NON-NLS-1$ o.getModelEntity().getRenderer().getTitle(o); } private String getAttrNameByXMLName(String name) { if(getModelEntity().getAttribute(name) != null) return name; XAttribute[] as = getModelEntity().getAttributes(); for (int i = 0; i < as.length; i++) if(name.equals(as[i].getXMLName())) return as[i].getName(); return name; } // implementation of interface XOrderedObject for ordered subclasses public int getIndexOfChild(XModelObject o) { return children.getIndex(o); } public boolean move(int from, int to, boolean firechange) { boolean b = children.move(from, to); if(b) { fireStructureChanged(XModelTreeEvent.STRUCTURE_CHANGED, this); if(firechange) setModified(true); } return b; } //TODO implement registering/unregistering error children public void replaceChildren(XModelObject[] objects) { for (int i = 0; i < objects.length; i++) { ((XModelObjectImpl)objects[i]).setParent_0(this); } children.replaceChildren(objects); changeTimeStamp(); } }