Skip to content
Closed
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ Require-Bundle: org.eclipse.ui,
de.dlr.sc.virsat.model.extension.cefx,
org.eclipse.ui.navigator,
de.dlr.sc.virsat.model.calculation.ui,
de.dlr.sc.virsat.cef.branding.ui
de.dlr.sc.virsat.cef.branding.ui,
org.eclipse.ui.ide,
de.dlr.sc.virsat.external.lib.comet.sdkj.servicedal
Bundle-RequiredExecutionEnvironment: JavaSE-11
Bundle-ActivationPolicy: lazy
Export-Package: de.dlr.sc.virsat.model.extension.cefx.ui.itemprovider,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions de.dlr.sc.virsat.model.extension.cefx.ui/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2697,6 +2697,23 @@
</with>
</activeWhen>
</handler>
</extension>
<extension
point="org.eclipse.ui.importWizards">
<wizard
category="de.dlr.virsat.global.category.import.virsat"
class="de.dlr.sc.virsat.model.extension.cefx.ui.importWizards.CometImportWizard"
icon="icons/sample.png"
id="de.dlr.sc.virsat.model.extension.cefx.ui.importWizards.CometImportWizard"
name="Comet Import Wizards">
<description>
Import a file from the local file system into the workspace.
Copy link
Member

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?

Copy link
Contributor Author

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.

</description>
</wizard>
<category
id="de.dlr.virsat.global.category.import.virsat"
name="Virtual Satellite">
</category>
</extension>
<!-- Plugin.XML Protected Region End -->
</plugin>
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/*******************************************************************************
* 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;
Copy link
Member

Choose a reason for hiding this comment

The 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...

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.net.URI;
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 (Exception e) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it would be better to not catch the generic Exception but rather specific ones that can happen at this location?

You can check the Anti-Pattern Chapter at this page for more information:
https://www.baeldung.com/java-exceptions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for providing the link. I checked it and already fixed it :).

handleException(e, tree);
}
}).start();
}

/**
* Opens the session for communication with the COMET system.
*/
private void openSession() {
session.open().join();
}

/**
* Populates the provided Tree with data from the current iteration
* of the engineering model.
*
* @param tree The SWT Tree widget to populate.
*/
private void populateTreeWithIteration(Tree tree) {
var siteDirectory = session.getAssembler().retrieveSiteDirectory();
var engineeringModelIid = siteDirectory.getModel().get(0).getEngineeringModelIid();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if there are more than one model in COMET ? :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a good point. I've updated the code to handle multiple models by checking for their presence and implementing a selection mechanism to choose the appropriate model before proceeding.

var iterationIid = siteDirectory.getModel().get(0).getIterationSetup().get(0).getIterationIid();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And we do actually have multiple iterations in our COMET example...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated the code to handle multiple iterations by checking if more than one iteration exists and implemented a mechanism to select the appropriate iteration before proceeding.

var domainOfExpertiseIid = siteDirectory.getModel().get(0).getActiveDomain().get(0).getIid();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we use the first DomainOfExperties here? The domains are System, Power, AOCS and so on, aren't they? What happens if we want to access data of another domain?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the existing code, we use the first DomainOfExpertise as a default selection to retrieve data like the example of comet. This is a simplification assuming that the first domain is sufficient for the intended operation. If we need to access data from a different domain, the code would need to be extended to allow selection or iteration over the available domains rather than defaulting to the first one.


EngineeringModel model = new EngineeringModel(engineeringModelIid, session.getAssembler().getCache(), uri);
Iteration iteration = new Iteration(iterationIid, session.getAssembler().getCache(), uri);
iteration.setContainer(model);

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(element -> "Space Segment".equals(element.getName()))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we focused on the "Space Segement" here? What happens if there is now Space Segement in the COMET model? Maybe filter for the element that has TopLevelElement=true? (In our example that should be the CEFO Mission)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've implemented a custom method to identify the top-level element by checking if it is not referenced by any other element, ensuring that the correct element is selected even if 'Space Segment' is not present.

.findFirst()
.ifPresent(element -> {
TreeItem spaceSegmentItem = new TreeItem(tree, SWT.NONE);
spaceSegmentItem.setText(element.getName());
addChildren(spaceSegmentItem, element);
spaceSegmentItem.setExpanded(true);
});
} else {
showErrorMessage(tree, "No open iteration found.");
}
}

/**
* Recursively adds child elements of a parent ElementDefinition to a TreeItem.
*/
private void addChildren(TreeItem parentItem, ElementDefinition parentElement) {
Copy link
Member

Choose a reason for hiding this comment

The 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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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,61 @@
/*******************************************************************************
* 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.Wizard;
import org.eclipse.ui.IImportWizard;
import org.eclipse.ui.IWorkbench;
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;

/**
* Constructor for CometImportWizard.
* Sets the window title and specifies that a progress monitor is needed.
*/
public CometImportWizard() {
super();
setWindowTitle("Comet Import Wizard");
setNeedsProgressMonitor(true);
}

/**
* Initializes the wizard with the workbench and current selection.
* This method is called when the wizard is initialized and is responsible
* for adding the pages to the wizard.
*
* @param workbench The current workbench.
* @param selection The current object selection.
*/
@Override
public void init(IWorkbench workbench, IStructuredSelection selection) {
mainPage = new CometImportWizardPage("Configure Comet Server");
addPage(mainPage);
}

/**
* Called when the user clicks the Finish button on the wizard.
* This method should contain the logic to process the data collected through the wizard pages.
*
* @return true if the data processing is successful and the wizard can be closed; false otherwise.
*/
@Override
public boolean performFinish() {
// This method delegates the finish operation to the mainPage
return mainPage.performFinish();
}
}

Loading