-
Notifications
You must be signed in to change notification settings - Fork 3
226 implement data exchange with comet #227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
69f87b3
0d290d3
af1e883
8a7d210
7b92e22
17f37a1
383655d
55d8c79
dbb9cde
db78b2b
6dd2be4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,197 @@ | ||
| /******************************************************************************* | ||
| * Copyright (c) 2008-2019 German Aerospace Center (DLR), Simulation and Software Technology, Germany. | ||
| * | ||
| * This program and the accompanying materials are made available under the | ||
| * terms of the Eclipse Public License 2.0 which is available at | ||
| * http://www.eclipse.org/legal/epl-2.0. | ||
| * | ||
| * SPDX-License-Identifier: EPL-2.0 | ||
| *******************************************************************************/ | ||
|
|
||
|
|
||
| package de.dlr.sc.virsat.model.extension.cefx.ui.importWizards; | ||
|
|
||
| import cdp4common.engineeringmodeldata.ElementDefinition; | ||
| import cdp4common.engineeringmodeldata.ElementUsage; | ||
| import cdp4common.engineeringmodeldata.EngineeringModel; | ||
| import cdp4common.engineeringmodeldata.Iteration; | ||
| import cdp4common.engineeringmodeldata.Parameter; | ||
| import cdp4common.engineeringmodeldata.ParameterSwitchKind; | ||
| import cdp4common.engineeringmodeldata.ParameterValueSet; | ||
| import cdp4common.sitedirectorydata.DomainOfExpertise; | ||
| import cdp4dal.Session; | ||
| import cdp4dal.SessionImpl; | ||
| import cdp4dal.dal.Credentials; | ||
| import cdp4servicesdal.CdpServicesDal; | ||
| import org.eclipse.swt.SWT; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it makes sense to separate data fetching and UI? So that we do not have UI classes (SWT) in this one? Then we could move this class to the non-ui part of the plugin and test it? :) Probably we could do that by replacing the SWT tree class with some UI independent class? Such as either a EMF object / Maybe directly a VirSat model class? Or maybe a plain java object that just accepts children objects? What do you think? The error handling would then work with Exceptions: If there is an error (Login wrong, no Iteration or whatever) you throw a corresponding exception and catch this exception in the Wizard... Then e.g. showing a warning...
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've separated the data fetching logic from the UI by creating a non-UI CometDataFetcher class that uses a TreeNode model to represent the data. The UI components now handle displaying this data and catching exceptions to show appropriate warnings, making the code more modular and testable. |
||
| import org.eclipse.swt.widgets.Display; | ||
| import org.eclipse.swt.widgets.MessageBox; | ||
| import org.eclipse.swt.widgets.Tree; | ||
| import org.eclipse.swt.widgets.TreeItem; | ||
|
|
||
| import java.io.IOException; | ||
| import java.net.URI; | ||
| import java.security.GeneralSecurityException; | ||
| import java.util.Optional; | ||
|
|
||
| /** | ||
| * The CometDataFetcher class is responsible for fetching and populating | ||
| * data from a COMET system into a SWT Tree widget. | ||
| */ | ||
| public class CometDataFetcher { | ||
|
|
||
| private final Credentials credentials; | ||
| private final Session session; | ||
| private final URI uri; | ||
|
|
||
| /** | ||
| * Constructs a new CometDataFetcher instance. | ||
| * | ||
| * @param url The URL of the COMET system. | ||
| * @param username The username for authentication. | ||
| * @param password The password for authentication. | ||
| */ | ||
| public CometDataFetcher(String url, String username, String password) { | ||
| this.uri = URI.create(url); | ||
| CdpServicesDal dal = new CdpServicesDal(); | ||
| this.credentials = new Credentials(username, password, this.uri, null); | ||
| this.session = new SessionImpl(dal, this.credentials); | ||
| } | ||
|
|
||
| /** | ||
| * Initiates the process to fetch data and populate the provided Tree. | ||
| */ | ||
| public void fetchData(Tree tree) { | ||
| new Thread(() -> { | ||
| try { | ||
| openSession(); | ||
| Display.getDefault().asyncExec(() -> populateTreeWithIteration(tree)); | ||
| } catch (IOException e) { | ||
| // Handle I/O exceptions, such as network issues | ||
| handleException(e, tree); | ||
| } catch (GeneralSecurityException e) { | ||
| // Handle security-related exceptions, such as authentication failures | ||
| handleException(e, tree); | ||
| } catch (RuntimeException e) { | ||
| // Handle any other runtime exceptions that might occur | ||
| handleException(e, tree); | ||
| } | ||
| }).start(); | ||
| } | ||
|
|
||
| /** | ||
| * Opens the session for communication with the COMET system. | ||
| */ | ||
| public void openSession() throws IOException, GeneralSecurityException { | ||
| session.open().join(); | ||
| } | ||
|
|
||
| /** | ||
| * Populates the provided Tree with data from the selected iteration | ||
| * of the engineering model. | ||
| * | ||
| * @param tree The SWT Tree widget to populate. | ||
| */ | ||
| private void populateTreeWithIteration(Tree tree) { | ||
| var siteDirectory = session.getAssembler().retrieveSiteDirectory(); | ||
| var model = siteDirectory.getModel().get(0); | ||
|
|
||
| var iterationIid = model.getIterationSetup().get(0).getIterationIid(); | ||
| var domainOfExpertiseIid = model.getActiveDomain().get(0).getIid(); | ||
|
|
||
| EngineeringModel engineeringModel = new EngineeringModel(model.getEngineeringModelIid(), session.getAssembler().getCache(), uri); | ||
| Iteration iteration = new Iteration(iterationIid, session.getAssembler().getCache(), uri); | ||
| iteration.setContainer(engineeringModel); | ||
|
|
||
| DomainOfExpertise domainOfExpertise = new DomainOfExpertise(domainOfExpertiseIid, session.getAssembler().getCache(), uri); | ||
|
|
||
| session.read(iteration, domainOfExpertise).join(); | ||
|
|
||
| Optional<Iteration> openIteration = session.getOpenIterations().keySet().stream().findFirst(); | ||
|
|
||
| if (openIteration.isPresent()) { | ||
| openIteration.get().getElement().stream() | ||
| .filter(this::isTopLevelElement) // Filter for the top-level element | ||
| .findFirst() | ||
| .ifPresent(element -> { | ||
| TreeItem topLevelItem = new TreeItem(tree, SWT.NONE); | ||
| topLevelItem.setText(element.getName()); | ||
| addChildren(topLevelItem, element); | ||
| topLevelItem.setExpanded(true); | ||
| }); | ||
| } else { | ||
| showErrorMessage(tree, "No open iteration found."); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Custom method to determine if an ElementDefinition is a top-level element. | ||
| * A top-level element is typically not referenced by any other elements. | ||
| */ | ||
| private boolean isTopLevelElement(ElementDefinition element) { | ||
| return element.referencingElementUsages().isEmpty(); | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
| /** | ||
| * Recursively adds child elements of a parent ElementDefinition to a TreeItem. | ||
| */ | ||
| private void addChildren(TreeItem parentItem, ElementDefinition parentElement) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we create a option in the wizard for what kind of data we want to import? For CEF interessting values are probably mass, power and temperature?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will add later options in the wizard to allow users to select the specific parameters they want to import, such as mass, power, and temperature, and modified the data fetching process to include only the selected parameters. Now, the mass will be automatically imported during the import. |
||
| parentElement.getParameter().stream() | ||
| .filter(parameter -> "mass".equalsIgnoreCase(parameter.getParameterType().getName())) | ||
| .findFirst() | ||
| .ifPresent(parameter -> { | ||
| String massValue = fetchParameterValue(parameter); | ||
| TreeItem massItem = new TreeItem(parentItem, SWT.NONE); | ||
| massItem.setText("Mass: " + massValue + " kg"); | ||
| }); | ||
|
|
||
| for (ElementUsage usage : parentElement.getContainedElement()) { | ||
| TreeItem usageItem = new TreeItem(parentItem, SWT.NONE); | ||
| usageItem.setText(usage.getName()); | ||
| addChildren(usageItem, usage.getElementDefinition()); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Fetches the value of the specified Parameter. | ||
| * | ||
| */ | ||
| private String fetchParameterValue(Parameter parameter) { | ||
| try { | ||
| ParameterValueSet valueSet = parameter.getValueSet().get(0); | ||
|
|
||
| if (valueSet.getValueSwitch() == ParameterSwitchKind.COMPUTED) { | ||
| return valueSet.getComputed().get(0); | ||
| } else if (valueSet.getValueSwitch() == ParameterSwitchKind.MANUAL) { | ||
| return valueSet.getManual().get(0); | ||
| } else { | ||
| return "No valid mass found"; | ||
| } | ||
| } catch (Exception e) { | ||
| e.printStackTrace(); | ||
| return "N/A"; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Displays an error message in a MessageBox. | ||
| */ | ||
| private void showErrorMessage(Tree tree, String message) { | ||
| Display.getDefault().asyncExec(() -> { | ||
| MessageBox messageBox = new MessageBox(tree.getShell(), SWT.ICON_ERROR); | ||
| messageBox.setMessage(message); | ||
| messageBox.open(); | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * Handles exceptions by printing the stack trace and displaying an error message. | ||
| */ | ||
| private void handleException(Exception e, Tree tree) { | ||
| e.printStackTrace(); | ||
| showErrorMessage(tree, "An error occurred: " + e.getMessage()); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| /******************************************************************************* | ||
| * Copyright (c) 2008-2019 German Aerospace Center (DLR), Simulation and Software Technology, Germany. | ||
| * | ||
| * This program and the accompanying materials are made available under the | ||
| * terms of the Eclipse Public License 2.0 which is available at | ||
| * http://www.eclipse.org/legal/epl-2.0. | ||
| * | ||
| * SPDX-License-Identifier: EPL-2.0 | ||
| *******************************************************************************/ | ||
| package de.dlr.sc.virsat.model.extension.cefx.ui.importWizards; | ||
|
|
||
| import org.eclipse.jface.wizard.IWizardPage; | ||
| import org.eclipse.jface.wizard.Wizard; | ||
| import org.eclipse.swt.widgets.TreeItem; | ||
| import org.eclipse.ui.IImportWizard; | ||
| import org.eclipse.ui.IWorkbench; | ||
|
|
||
| import de.dlr.sc.virsat.model.dvlm.structural.StructuralElementInstance; | ||
| import de.dlr.sc.virsat.model.extension.ps.model.ConfigurationTree; | ||
| import de.dlr.sc.virsat.project.editingDomain.VirSatEditingDomainRegistry; | ||
| import de.dlr.sc.virsat.project.editingDomain.VirSatTransactionalEditingDomain; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import org.eclipse.core.resources.IResource; | ||
| import org.eclipse.core.resources.ResourcesPlugin; | ||
| import org.eclipse.core.runtime.CoreException; | ||
| import org.eclipse.emf.common.command.Command; | ||
| import org.eclipse.emf.edit.command.AddCommand; | ||
| import org.eclipse.jface.viewers.IStructuredSelection; | ||
|
|
||
| /** | ||
| * This wizard handles the import of data from a Comet server. | ||
| * It guides the user through server configuration and initiates the data import process. | ||
| */ | ||
| public class CometImportWizard extends Wizard implements IImportWizard { | ||
|
|
||
| private CometImportWizardPage mainPage; | ||
| private SelectedElementsPage selectedElementsPage; | ||
|
|
||
| public CometImportWizard() { | ||
| super(); | ||
| setWindowTitle("CometImportWizard"); | ||
| setNeedsProgressMonitor(true); | ||
| } | ||
|
|
||
| @Override | ||
| public void init(IWorkbench workbench, IStructuredSelection selection) { | ||
| mainPage = new CometImportWizardPage("Configure Comet Server"); | ||
| selectedElementsPage = new SelectedElementsPage("Selected Elements"); | ||
| addPage(mainPage); | ||
| addPage(selectedElementsPage); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean performFinish() { | ||
| TreeItem rootItem = selectedElementsPage.getTree().getItem(0); | ||
|
|
||
| if (rootItem != null) { | ||
| ConfigurationTree configurationTree = importElements(rootItem); | ||
|
|
||
| // Save the configuration tree | ||
| saveConfigurationTree(configurationTree); | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
|
|
||
| private ConfigurationTree importElements(TreeItem rootItem) { | ||
| ImportHandler importHandler = new ImportHandler(); | ||
| return importHandler.importElements(rootItem); | ||
| } | ||
|
|
||
| /** | ||
| * Saves the imported ConfigurationTree to the editing domain. | ||
| */ | ||
|
|
||
|
|
||
| public void saveConfigurationTree(ConfigurationTree configurationTree) { | ||
| if (configurationTree == null) { | ||
| throw new IllegalStateException("ConfigurationTree is null. Import failed or was not executed correctly."); | ||
| } | ||
|
|
||
| StructuralElementInstance rootInstance = configurationTree.getStructuralElementInstance(); | ||
| if (rootInstance == null) { | ||
| throw new IllegalStateException("StructuralElementInstance is null in the ConfigurationTree."); | ||
| } | ||
|
|
||
| // Ensure that the rootInstance is associated with a resource | ||
| if (rootInstance.eResource() == null) { | ||
| throw new IllegalStateException("StructuralElementInstance's resource is null."); | ||
| } | ||
|
|
||
| // Check if editing domain retrieval is successful | ||
| VirSatTransactionalEditingDomain editingDomain = VirSatEditingDomainRegistry.INSTANCE.getEd(rootInstance); | ||
| if (editingDomain == null) { | ||
| throw new IllegalStateException("Editing domain is null. Unable to get the editing domain for the StructuralElementInstance."); | ||
| } | ||
|
|
||
| try { | ||
| Command addCommand = AddCommand.create(editingDomain, rootInstance.eResource(), rootInstance.eResource().getContents(), rootInstance); | ||
| editingDomain.getCommandStack().execute(addCommand); | ||
| editingDomain.saveAll(); | ||
|
|
||
| ResourcesPlugin.getWorkspace().getRoot().refreshLocal(IResource.DEPTH_INFINITE, null); | ||
| } catch (CoreException e) { | ||
| e.printStackTrace(); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| @Override | ||
| public IWizardPage getNextPage(IWizardPage page) { | ||
| if (page == mainPage) { | ||
| // Get the selected TreeItems from the mainPage | ||
| List<TreeItem> checkedItems = mainPage.getCheckedItems(); | ||
|
|
||
| // Pass the selected items to the SelectedElementsPage | ||
| selectedElementsPage.setSelectedElements(checkedItems); | ||
| return selectedElementsPage; | ||
| } | ||
| return super.getNextPage(page); | ||
| } | ||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This description is outdated isn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it and wrote: CometImportWizard.