blob: eeb9826250a2c653b858c7a3a6fc7e44f0095a6c [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2013, 2021 CEA LIST.
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Ansgar Radermacher (CEA LIST) Ansgar.Radermacher@cea.fr - Initial API and implementation
* Ansgar Radermacher - Bug 573920, avoid NPE possibility
*
*****************************************************************************/
package org.eclipse.papyrus.designer.languages.cpp.cdt.texteditor.listener;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.UniqueEList;
import org.eclipse.papyrus.designer.languages.cpp.cdt.texteditor.Activator;
import org.eclipse.papyrus.infra.core.listenerservice.IPapyrusListener;
import org.eclipse.papyrus.uml.tools.listeners.PapyrusStereotypeListener;
import org.eclipse.uml2.uml.Behavior;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.DirectedRelationship;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Feature;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Parameter;
/**
* Main listener for model changes (registered via plugin.xml). It will delegate
* to the sub-listeners for specific sub-elements (type, operation, port, ...) that
* can be found in this package
*/
@SuppressWarnings("deprecation") // TODO: replace with StereotypeElementListener
public class ModelListener implements IPapyrusListener {
/**
* set to true, if a synchronization from an CDT editor to the model is active
*/
public static boolean syncFromEditor;
@Override
public void notifyChanged(Notification notification) {
Object notifier = notification.getNotifier();
int eventType = notification.getEventType();
if (syncFromEditor) {
return;
}
if ((eventType == Notification.REMOVING_ADAPTER) ||
(eventType == Notification.RESOLVE)) {
// does not indicate a modification of the element
return;
}
OperationHistoryListener.init();
try {
if (notifier instanceof Classifier) {
Classifier classifier = (Classifier) notifier;
if ((eventType == Notification.REMOVE) ||
(eventType == PapyrusStereotypeListener.MODIFIED_STEREOTYPE)) {
addtoList(getNearestClassifier(classifier));
}
// don't treat addition here, since operations/properties do not have their final names yet
// IStorage storage = new TextStorage(string);
}
if (notifier instanceof Behavior) {
Behavior behavior = (Behavior) notifier;
if (eventType == Notification.SET) {
// name modification
if (behavior.getSpecification() == null) {
}
} else if (eventType == Notification.ADD) {
// modification of an opaque behavior in Papyrus implied remove&add operations
Classifier nearestCl = getNearestClassifier(behavior);
addtoList(nearestCl);
}
}
else if (notifier instanceof Feature) {
// if a feature is added, it is first generated with a dummy name, then the name is corrected.
Feature feature = (Feature) notifier;
Element owner = feature.getOwner();
if (owner instanceof Classifier) {
addtoList(getNearestClassifier(owner));
}
} else if (notifier instanceof Parameter) {
Parameter parameter = (Parameter) notifier;
addtoList(getNearestClassifier(parameter));
} else if (notifier instanceof DirectedRelationship) {
// if a feature is added, it is first generated with a dummy name, then the name is corrected.
DirectedRelationship dr = (DirectedRelationship) notifier;
for (Element client : dr.getSources()) {
if (client instanceof Classifier) {
addtoList(getNearestClassifier(client));
}
}
} else if (notifier instanceof Package) {
}
} catch (Exception e) {
Activator.log.error(e);
}
}
/**
* Navigate to the nearest classifier. This function is useful, as behaviors are also
* classifiers and we want to avoid regenerating code for owned behaviors
*
* @param element
* a UML element
* @return the nearest element (in the containment hierarchy) that is a classifier but not a behavior
*/
public static Classifier getNearestClassifier(Element element) {
while (element != null) {
if (!(element instanceof Behavior) && (element instanceof Classifier)) {
return (Classifier) element;
}
element = element.getOwner();
}
return null;
}
/**
* Add a classifier to the re-generation list
* @param cl a classifier. If null, the element is ignored.
*/
static void addtoList(Classifier cl) {
if (cl != null) {
regenList.add(cl);
}
}
static EList<Classifier> regenList = new UniqueEList<Classifier>();
}