ErrorBehaviorModel.java
/**
* Copyright (c) 2004-2025 Carnegie Mellon University and others. (see Contributors file).
* All Rights Reserved.
*
* NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
* KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE
* OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT
* MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
*
* This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
* SPDX-License-Identifier: EPL-2.0
*
* Created, in part, with funding and support from the United States Government. (see Acknowledgments file).
*
* This program includes and/or can make use of certain third party source code, object code, documentation and other
* files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system
* configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and
* conditions contained in any such Third Party Software or separate license file distributed with such Third Party
* Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici-
* aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li-
* censes only apply to the Third Party Software and not any other portion of this program or this program as a whole.
*/
package org.osate.ge.errormodel.ui.viewmodels;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.osate.aadl2.Classifier;
import org.osate.ge.BusinessObjectSelection;
import org.osate.ge.aadl2.ui.AadlModelAccessUtil;
import org.osate.ge.errormodel.util.ErrorModelGeUtil;
import org.osate.ge.swt.BaseObservableModel;
import org.osate.ge.swt.selectors.SingleSelectorModel;
import org.osate.xtext.aadl2.errormodel.errorModel.ErrorBehaviorStateMachine;
import org.osate.xtext.aadl2.errormodel.errorModel.ErrorModelPackage;
import org.osate.xtext.aadl2.errormodel.errorModel.ErrorModelSubclause;
/**
* View model which sets the use behavior for {@link Classifier} objects included in a {@link BusinessObjectSelection}.
* Creates an error model subclause if needed. Only a single {@link Classifier} is supported.
*
*/
public class ErrorBehaviorModel extends BaseObservableModel
implements SingleSelectorModel<ErrorBehaviorStateMachine> {
private static class Option {
public Option(final IEObjectDescription desc) {
this.stateMachine = (ErrorBehaviorStateMachine) desc.getEObjectOrProxy();
this.qualifiedName = ErrorModelViewModelUtil.getQualifiedName(desc);
}
public final ErrorBehaviorStateMachine stateMachine;
public final String qualifiedName;
}
private BusinessObjectSelection bos;
private Map<URI, Option> uriToOptionMap;
private String error;
/**
* Creates a new instance
* @param bos the initial business object selection
*/
public ErrorBehaviorModel(final BusinessObjectSelection bos) {
setBusinessObjectSelection(bos);
}
/**
* Refreshes the state of the model based on the specified business object selection
* @param value the business object selection
*/
public void setBusinessObjectSelection(final BusinessObjectSelection value) {
this.bos = Objects.requireNonNull(value, "value must not be null");
uriToOptionMap = Collections.emptyMap();
error = null;
final List<Classifier> selectedClassifiers = value.boStream(Classifier.class).collect(Collectors.toList());
if (selectedClassifiers.size() > 1) {
error = "<Multiple Classifiers Selected>";
} else if (selectedClassifiers.size() == 0) {
error = "<No Classifiers Selected>";
} else {
final Classifier selectedClassifier = selectedClassifiers.get(0);
if (selectedClassifier.eResource() == null) {
error = "<No Resource Available>";
} else {
final Collection<IEObjectDescription> descriptions = AadlModelAccessUtil.getAllEObjectsByType(
selectedClassifier.eResource(), ErrorModelPackage.eINSTANCE.getErrorBehaviorStateMachine());
uriToOptionMap = descriptions.stream()
.collect(Collectors.toMap(IEObjectDescription::getEObjectURI, Option::new));
}
}
triggerChangeEvent();
}
@Override
public Stream<ErrorBehaviorStateMachine> getElements() {
return Stream.concat(Stream.of((ErrorBehaviorStateMachine) null),
uriToOptionMap.values().stream().map(v -> v.stateMachine));
}
@Override
public ErrorBehaviorStateMachine getSelectedElement() {
final Optional<ErrorBehaviorStateMachine> optStateMachine = bos.boStream(Classifier.class)
.flatMap(ErrorModelGeUtil::getAllInheritedErrorModelSubclauses).map(ErrorModelSubclause::getUseBehavior)
.filter(Objects::nonNull).findFirst();
if (!optStateMachine.isPresent()) {
return null;
}
final ErrorBehaviorStateMachine sm = optStateMachine.get();
// Return the element from the options list.
final URI behaviorUri = EcoreUtil.getURI(sm);
final Option option = uriToOptionMap.get(behaviorUri);
if (option == null) {
// Return the actual state machine if an option wasn't available.
return sm;
}
return option.stateMachine;
}
@Override
public void setSelectedElement(final ErrorBehaviorStateMachine value) {
bos.modify("Set Error Behavior",
boc -> boc.getBusinessObject(Classifier.class).isPresent(), boc -> {
final Classifier c = boc.getBusinessObject(Classifier.class).get();
final Optional<ErrorModelSubclause> subclause = ErrorModelGeUtil.getFirstErrorModelSubclause(c);
return subclause.map(EObject.class::cast).orElse(c);
}, (boToModify, boc) -> {
// Get or create the error model subclause as needed
final ErrorModelSubclause subclause;
if (boToModify instanceof Classifier) {
subclause = ErrorModelGeUtil.getOrCreateErrorModelSubclause((Classifier) boToModify);
} else {
subclause = (ErrorModelSubclause) boToModify;
}
subclause.setUseBehavior(value);
});
}
@Override
public String getLabel(final ErrorBehaviorStateMachine element) {
if (error != null) {
return error;
}
if (element == null) {
return "<None>";
}
final Option option = uriToOptionMap.get(EcoreUtil.getURI(element));
if (option == null) {
return "<Unknown State Machine>";
}
return option.qualifiedName;
}
}