/******************************************************************************* * 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.action.impl.handlers; import java.text.MessageFormat; import java.util.Properties; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Display; import org.jboss.tools.common.meta.XAttribute; import org.jboss.tools.common.meta.XChild; import org.jboss.tools.common.meta.action.XAttributeData; import org.jboss.tools.common.meta.action.XEntityData; import org.jboss.tools.common.meta.action.impl.AbstractHandler; import org.jboss.tools.common.meta.constraint.XAttributeConstraint; import org.jboss.tools.common.meta.impl.XMetaDataConstants; import org.jboss.tools.common.meta.key.WizardKeys; import org.jboss.tools.common.model.ServiceDialog; import org.jboss.tools.common.model.XModelException; import org.jboss.tools.common.model.XModelObjectConstants; import org.jboss.tools.common.model.XModelObject; import org.jboss.tools.common.model.event.ActionDeclinedException; import org.jboss.tools.common.model.impl.RegularObjectImpl; import org.jboss.tools.common.model.plugin.ModelMessages; import org.jboss.tools.common.model.undo.XCreateUndo; import org.jboss.tools.common.model.undo.XUndoManager; import org.jboss.tools.common.model.util.FindObjectHelper; import org.jboss.tools.common.model.util.XModelObjectLoaderUtil; public class DefaultCreateHandler extends AbstractHandler { public DefaultCreateHandler() {} public void executeHandler(XModelObject object, Properties prop) throws XModelException { if(!isEnabled(object) || data == null || data.length == 0) return; String entity = getEntityName(); Properties p = extractProperties(data[0]); setOtherProperties(object, p); XModelObject c = XModelObjectLoaderUtil.createValidObject(object.getModel(), entity, p); c = modifyCreatedObject(c); addCreatedObject(object, c, prop); checkPosition(object, c, prop); if(prop != null) prop.put("created", c); //$NON-NLS-1$ } private void checkPosition(XModelObject o, XModelObject c, Properties prop) { if(prop == null || !(prop.get("insertAfter") instanceof Integer)) return; //$NON-NLS-1$ int i = ((Integer)prop.get("insertAfter")).intValue(); //$NON-NLS-1$ if(i < 0) return; ++i; RegularObjectImpl impl = (RegularObjectImpl)o; impl.move(impl.getIndexOfChild(c), i, true); } protected String getEntityName() { String n = action.getProperty(XMetaDataConstants.ENTITY); return (n == null) ? data[0].getModelEntity().getName() : n; } protected XModelObject modifyCreatedObject(XModelObject o) { return o; } public static Properties extractProperties(XEntityData es) { Properties p = new Properties(); XAttributeData[] ads = es.getAttributeData(); for (int i = 0; i < ads.length; i++) { XAttribute a = ads[i].getAttribute(); String pn = a.getName(); String pv = extractProperty(ads[i]); p.setProperty(pn, pv); } return p; } //TODO throw XModelException public static String extractProperty(XAttributeData ad) { XAttribute a = ad.getAttribute(); String pn = a.getName(); String pv = ad.getValue(); if(a.isTrimmable()) pv = (pv == null) ? "" : pv.trim(); //$NON-NLS-1$ if((pv == null || pv.length() == 0) && ad.getMandatoryFlag()) throw new RuntimeException(getReguiredMessage(pn)); XAttributeConstraint c = ad.getAttribute().getConstraint(); validateValue(pn, pv, c); return pv; } public static String getReguiredMessage(String attributeName) { return NLS.bind(ModelMessages.ATTRIBUTE_REQUIRED, new Object[]{attributeName}); } public static Properties getProperties(XEntityData es) { Properties p = new Properties(); XAttributeData[] ads = es.getAttributeData(); for (int i = 0; i < ads.length; i++) { XAttribute a = ads[i].getAttribute(); String pn = a.getName(); String pv = ads[i].getValue(); if(a.isTrimmable()) pv = (pv == null) ? "" : pv.trim(); //$NON-NLS-1$ if(pv == null) pv = ""; //$NON-NLS-1$ p.setProperty(pn, pv); } return p; } public static String validateAttribute(XAttributeData ad, String pv) { XAttribute a = ad.getAttribute(); String vis = WizardKeys.getAttributeDisplayName(ad, true); if(a.isTrimmable()) pv = (pv == null) ? "" : pv.trim(); //$NON-NLS-1$ if((pv == null || pv.length() == 0) && ad.getMandatoryFlag()) { return NLS.bind(ModelMessages.ATTRIBUTE_REQUIRED, new Object[]{vis}); } XAttributeConstraint c = ad.getAttribute().getConstraint(); return getConstraintMessage(vis, pv, c); } public static String getConstraintMessage(String name, String value, XAttributeConstraint c) { if(c == null || c.getError(value) == null) return null; return NLS.bind(ModelMessages.SET_ATTRIBUTE_FAILURE, new Object[]{name, value, c.getError(value)}); } public static void validateValue(String name, String value, XAttributeConstraint c) { String mes = getConstraintMessage(name, value, c); if(mes != null) throw new RuntimeException(mes); } protected void setOtherProperties(XModelObject object, Properties p) {} public boolean isEnabled(XModelObject object) { return (object != null && object.isObjectEditable()); } public static void addCreatedObject(XModelObject parent, XModelObject child, Properties whereSelect) throws XModelException { addCreatedObject(parent, child, true, whereSelect); } public static String getContainsMessage(XModelObject parent, XModelObject child) { return getContainsMessage(parent, child, true); } private static String getContainsMessage(XModelObject parent, XModelObject child, boolean forceUnique) { String pathpart = child.getPathPart(); XModelObject e = parent.getChildByPath(pathpart); if(e != null && e != parent && e != parent.getParent()) { if(child.getModelEntity().getAttribute(XModelObjectLoaderUtil.ATTR_ID_NAME) != null) { if(!forceUnique || !XModelObjectConstants.TRUE.equals(child.getModelEntity().getProperty("unique"))) { //$NON-NLS-1$ return null; } } String tp = title(parent, true), tc = title(child, false), te = title(e, false); String mes = (tc.equals(te)) ? NLS.bind(ModelMessages.CONTAINS_OBJECT_1, new Object[]{tp, tc}) : NLS.bind(ModelMessages.CONTAINS_OBJECT_2, new Object[]{tp, te, "\n", tc}); //$NON-NLS-1$ return mes; } return null; } public static void addCreatedObject(XModelObject parent, XModelObject child, boolean registerundo, Properties whereSelect) throws XModelException { addCreatedObject(parent, child, registerundo, extractWhereSelect(whereSelect)); } public static void addCreatedObject(XModelObject parent, XModelObject child, int whereSelect) throws XModelException { addCreatedObject(parent, child, true, whereSelect); } public static void addCreatedObject(XModelObject parent, final XModelObject child, boolean registerundo, final int whereSelect) throws XModelException { if(child == null) throw new XModelException(ModelMessages.OBJECT_CREATION_FAILURE); String mes = getContainsMessage(parent, child, false); if(mes != null) throw new XModelException(mes); String ce = child.getModelEntity().getName(); XChild c = parent.getModelEntity().getChild(ce); if(c == null) throw new XModelException(ModelMessages.OBJECT_ADDING_FAILURE); int max = c.getMaxCount(); int cur = parent.getChildren(ce).length; if(cur >= max) { ServiceDialog d = parent.getModel().getService(); d.showDialog(ModelMessages.WARNING, MessageFormat.format("The limit of {0} children is achieved.", max), new String[]{"OK"}, null, ServiceDialog.MESSAGE); // i18n: assumes germanic plurals mes = MessageFormat.format("{0} can contain only {1}{2}with entity {3}.", title(parent, true), max, ((max == 1) ? " child " : " children "), ce); throw new ActionDeclinedException(mes); } boolean b = parent.addChild(child); if(!b && child.getModelEntity().getAttribute(XModelObjectLoaderUtil.ATTR_ID_NAME) != null) { int k = 1; String pp = child.getPathPart(); while(parent.getChildByPath(pp) != null) { child.setAttributeValue(XModelObjectLoaderUtil.ATTR_ID_NAME, "" + k); //$NON-NLS-1$ String ppn = child.getPathPart(); if(ppn.equals(pp)) throw new RuntimeException(ModelMessages.OBJECT_ADDING_FAILURE); pp = ppn; ++k; } b = parent.addChild(child); } if(!b) { throw new XModelException(ModelMessages.OBJECT_ADDING_FAILURE); } XUndoManager undo = getUndoManager(parent); if(registerundo && undo != null) { undo.addUndoable(new XCreateUndo(parent, child)); } child.setModified(true); if(whereSelect >= 0) { Display.getDefault().asyncExec(new Runnable() { public void run() { FindObjectHelper.findModelObject(child, whereSelect); } }); } } // now undo works only for ancestors of the model root! static XUndoManager getUndoManager(XModelObject o) { XModelObject root = o.getModel().getRoot(); while(o != null && o != root) o = o.getParent(); return (o == null) ? null : o.getModel().getUndoManager(); } public static String title(XModelObject o, boolean capitalize) { String elementType = o.getAttributeValue(XModelObjectConstants.ATTR_ELEMENT_TYPE); String objectTitle = o.getModelEntity().getRenderer().getTitle(o); String s = elementType + " " + objectTitle; //$NON-NLS-1$ if(objectTitle != null && objectTitle.equalsIgnoreCase(elementType)) { s = objectTitle; } return (!capitalize || s.length() < 1 || Character.isUpperCase(s.charAt(0))) ? s : s.substring(0, 1).toUpperCase() + s.substring(1); } public static int extractWhereSelect(Properties p) { if(p == null) return FindObjectHelper.EVERY_WHERE; String component = p.getProperty("actionSourceGUIComponentID"); //$NON-NLS-1$ if("navigator".equals(component)) return FindObjectHelper.IN_NAVIGATOR_AND_IN_EDITOR_IF_OPEN; //$NON-NLS-1$ if("editor".equals(component)) return FindObjectHelper.IN_EDITOR_ONLY; //$NON-NLS-1$ if("dialog".equals(component)) return FindObjectHelper.IN_NAVIGATOR_ONLY; //$NON-NLS-1$ return FindObjectHelper.EVERY_WHERE; } }