/***************************************************************************** * Copyright (c) 2011 CEA LIST. * * 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: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation *****************************************************************************/ package org.eclipse.papyrus.uml.properties.expression; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import org.eclipse.core.databinding.observable.ChangeEvent; import org.eclipse.core.databinding.observable.IChangeListener; import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.databinding.observable.list.WritableList; import org.eclipse.papyrus.infra.widgets.editors.AbstractEditor; import org.eclipse.papyrus.infra.widgets.editors.ICommitListener; /** * An IObservableList for handling Expressions * * An Expression has a Language and a Body * * The UML low-level implementation maintains two lists of Strings (One for the * languages, and another one for the bodies), which should be synchronized * (1-1 mapping, with a few specific cases when the mapping is not strict) * * This class simplifies this mapping by maintaining a single list of * Expressions, each of which containing a Body and a Language. * * @author Camille Letavernier */ public class ExpressionList extends WritableList implements IChangeListener, ICommitListener { private List<Expression> expressions; private IObservableList languages; private IObservableList bodies; private boolean ignoreChanges = false; /** * * Constructor. * * @param languages * The IObservableList containing Languages * @param bodies * The IObservableList containing Bodies */ public ExpressionList(IObservableList languages, IObservableList bodies) { super(new LinkedList<Expression>(), Expression.class); expressions = wrappedList; this.languages = languages; this.bodies = bodies; languages.addChangeListener(this); bodies.addChangeListener(this); UMLToExpression(); } private void UMLToExpression() { expressions.clear(); int maxSize = Math.max(languages.size(), bodies.size()); Iterator<?> languageIterator = languages.iterator(); Iterator<?> bodyIterator = bodies.iterator(); for(int i = 0; i < maxSize; i++) { Expression expression = new Expression(); if(languageIterator.hasNext()) { expression.language = (String)languageIterator.next(); } if(bodyIterator.hasNext()) { expression.body = (String)bodyIterator.next(); } expressions.add(expression); } } public void handleChange(ChangeEvent event) { //A change occurs on languages or bodies if(!ignoreChanges) { UMLToExpression(); } } public void commit(AbstractEditor editor) { ignoreChanges = true; expressionToUML(); if(languages instanceof ICommitListener) { ((ICommitListener)languages).commit(editor); } if(bodies instanceof ICommitListener) { ((ICommitListener)bodies).commit(editor); } ignoreChanges = false; } void expressionToUML() { //Executes two commands, one on languages, and another one on bodies int fillLanguage = 0, fillBody = 0; languages.clear(); bodies.clear(); Iterator<Expression> iterator = expressions.iterator(); while(iterator.hasNext()) { Expression expression = iterator.next(); if(expression == null) { iterator.remove(); continue; } String language = expression.getLanguage(); String body = expression.getBody(); if(language == null && body == null) { iterator.remove(); continue; } if(language != null && body != null) { addLanguage(language, fillLanguage); addBody(body, fillBody); fillBody = fillLanguage = 0; } if(language == null) { fillLanguage++; addBody(body, fillBody); fillBody = 0; } else if(body == null) { fillBody++; addLanguage(language, fillLanguage); fillLanguage = 0; } } } private void addBody(String body, int fillBody) { for(int i = 0; i < fillBody; i++) { bodies.add(""); //$NON-NLS-1$ } bodies.add(body); } private void addLanguage(String language, int fillLanguage) { for(int i = 0; i < fillLanguage; i++) { languages.add(""); //$NON-NLS-1$ } languages.add(language); } /** * A helper class to aggregate the expression body and language in a single * object * * @author Camille Letavernier */ public static class Expression { String language; String body; /** * @return this Expression's language */ public String getLanguage() { return language; } /** * @return this Expression's body */ public String getBody() { return body; } /** * Sets this Expression's language * * @param language */ public void setLanguage(String language) { this.language = language; } /** * Sets this Expression's body * * @param body */ public void setBody(String body) { this.body = body; } @Override public String toString() { return language; } @Override public int hashCode() { return language == null ? 0 : language.hashCode(); } @Override public boolean equals(Object other) { if(!(other instanceof Expression)) { return false; } Expression otherExpression = (Expression)other; if(otherExpression.getLanguage() == null) { return getLanguage() == null; } return otherExpression.getLanguage().equals(getLanguage()); } } }