/******************************************************************************* * Copyright (c) 2006-2013 The RCP Company 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: * The RCP Company - initial API and implementation *******************************************************************************/ package com.rcpcompany.uibindings.internal.decorators; import java.util.HashMap; import java.util.Map; import org.eclipse.core.databinding.observable.IObserving; import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.databinding.observable.list.WritableList; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.core.databinding.observable.value.IValueChangeListener; import org.eclipse.core.databinding.observable.value.ValueChangeEvent; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; import com.rcpcompany.uibindings.Constants; import com.rcpcompany.uibindings.IManager; import com.rcpcompany.uibindings.IUIBindingDecorator; import com.rcpcompany.uibindings.IValueBinding; import com.rcpcompany.uibindings.decorators.SimpleUIBindingDecorator; import com.rcpcompany.utils.basic.ToStringUtils; import com.rcpcompany.utils.logging.LogUtils; /** * {@link IUIBindingDecorator} for EObject creation. * * @author Tonny Madsen, The RCP Company */ public class EObjectCreatorDecorator extends SimpleUIBindingDecorator implements IUIBindingDecorator { private EClass myEClass; private IObservableList myList; /** * The string used for <code>null</code> in the binding. */ private String myNullLabel; /** * Mapping UI to model with all the defined mappings. */ protected final Map<String, EClass> uiToModelClassMappings = new HashMap<String, EClass>(); /** * Mapping UI name to model objects. */ protected final Map<String, EObject> uiToModelObjectMappings = new HashMap<String, EObject>(); /** * Mapping model to UI with all the defined mappings. * <p> * Matching is based on an exact match */ protected final Map<EClass, String> modelToUIClassMappings = new HashMap<EClass, String>(); private IValueChangeListener myModelObjectChangeListener = null; @Override public void init(IValueBinding binding) { super.init(binding); final EClassifier attributeType = binding.getDataType().getEType(); if (!(attributeType instanceof EClass)) { getBinding().addErrorCondition("Attribute is not an EClass"); return; } myEClass = (EClass) attributeType; /* * Get the label used for the null value */ myNullLabel = getBinding().getArgument(Constants.ARG_NULL_LABEL, String.class, ""); myList = getBinding().getArgument(Constants.ARG_VALID_VALUES, IObservableList.class, null); if (myList == null) { getBinding().addErrorCondition("No class list given"); return; } // TODO: make this dynamic myValidUIList = WritableList.withElementType(String.class); for (final Object e : myList) { if (!(e instanceof EClass)) { getBinding().addErrorCondition("List element is not an EClass: " + e); return; } final EClass ec = (EClass) e; if (modelToUIClassMappings.get(ec) != null) { getBinding().addErrorCondition("List element is duplicated: " + ec); } final String name = ToStringUtils.formatHumanReadable(ec.getName()); // TODO: get label if present if (uiToModelClassMappings.get(name) != null) { getBinding().addErrorCondition( "List element name is duplicated: '" + ec + "' and '" + uiToModelClassMappings.get(name) + "'"); } modelToUIClassMappings.put(ec, name); uiToModelClassMappings.put(name, ec); myValidUIList.add(name); } if (!getBinding().getDataType().isRequired()) { myValidUIList.add(myNullLabel); } final IObservableValue ov = getBinding().getModelObservableValue(); if (ov instanceof IObserving) { final IObserving observing = (IObserving) ov; myModelObjectChangeListener = new IValueChangeListener() { Object currentObserved = observing.getObserved(); @Override public void handleValueChange(ValueChangeEvent event) { final Object newObserved = observing.getObserved(); if (currentObserved == newObserved) return; currentObserved = newObserved; uiToModelObjectMappings.clear(); } }; ov.addValueChangeListener(myModelObjectChangeListener); } } @Override public void dispose() { if (myModelObjectChangeListener != null) { getBinding().getModelObservableValue().removeValueChangeListener(myModelObjectChangeListener); } super.dispose(); } @Override protected Object convertModelToUI(Object fromObject) { if (fromObject == null) return myNullLabel; if (!(fromObject instanceof EObject)) { LogUtils.error(this, "Object not an EObject: " + fromObject, getBinding().getCreationPoint()); return ""; } final EObject e = (EObject) fromObject; final EClass ec = e.eClass(); final String name = modelToUIClassMappings.get(ec); if (name == null) { LogUtils.error(this, "Object type not mapped: " + fromObject, getBinding().getCreationPoint()); return ""; } if (uiToModelObjectMappings.get(name) == null) { uiToModelObjectMappings.put(name, e); } return name; } @Override protected Object convertUIToModel(Object fromObject) { if (fromObject == null || fromObject.equals("") || fromObject.equals(myNullLabel)) return null; if (!(fromObject instanceof String)) { LogUtils.error(this, "Object not an String: " + fromObject, getBinding().getCreationPoint()); return null; } final String name = (String) fromObject; // Look for an existing object if (uiToModelObjectMappings.get(name) != null) return uiToModelObjectMappings.get(name); // Create a new object final EClass ec = uiToModelClassMappings.get(name); if (ec == null) { LogUtils.error(this, "Name not mapped: " + name); return null; } /* * Create and initialize the object */ final EObject e = EcoreUtil.create(ec); IManager.Factory.getManager().initializeObject(getBinding().getEditingDomain(), null, null, e, false); uiToModelObjectMappings.put(name, e); return e; } @Override public IObservableList getValidUIList() { return myValidUIList; } }