/*******************************************************************************
* Copyright (c) 2015 Inria
* 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:
* - Philippe Merle <philippe.merle@inria.fr>
*******************************************************************************/
package org.occiware.clouddesigner.occi.connector.jocci.services;
import cz.cesnet.cloud.occi.Model;
import cz.cesnet.cloud.occi.api.Client;
import cz.cesnet.cloud.occi.api.EntityBuilder;
import cz.cesnet.cloud.occi.api.exception.CommunicationException;
import cz.cesnet.cloud.occi.api.exception.EntityBuildingException;
import cz.cesnet.cloud.occi.core.ActionInstance;
import cz.cesnet.cloud.occi.exception.InvalidAttributeValueException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.occiware.clouddesigner.occi.Action;
import org.occiware.clouddesigner.occi.Configuration;
import org.occiware.clouddesigner.occi.Entity;
import org.occiware.clouddesigner.occi.connector.jocci.Activator;
import org.occiware.clouddesigner.occi.connector.jocci.dialogs.OcciActionDialog;
import org.occiware.clouddesigner.occi.connector.jocci.dialogs.OcciServerDialog;
import org.occiware.clouddesigner.occi.util.OcciHelper;
public class DesignServices {
// TODO: add a location attribute to the Configuration class.
private Client jocciClient;
/**
* Report an exception.
* @param throwable the exception to report.
*/
private static void reportException(Throwable throwable)
{
Shell shell = Display.getCurrent().getActiveShell();
Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, null, throwable);
ErrorDialog.openError(shell, null, throwable.getMessage(), status);
throwable.printStackTrace(System.err);
}
/**
* Get the jOCCI client.
* It is created the first time.
* @return the jOCCI client.
*/
private Client getJocciClient()
{
if(jocciClient == null) {
Shell shell = Display.getCurrent().getActiveShell();
OcciServerDialog occiServerDialog = new OcciServerDialog(shell);
occiServerDialog.create();
if (occiServerDialog.open() == Window.OK) {
String occiServerUrl = occiServerDialog.getOcciServerUrl();
if(occiServerUrl == null || occiServerUrl.isEmpty()) {
return null;
}
try {
// Create a jOCCI client.
jocciClient = Importer.newJocciClient(occiServerUrl);
} catch(CommunicationException ce) {
reportException(ce);
jocciClient = null;
}
}
}
return jocciClient;
}
/**
* Get the jOCCI client.
* It is created the first time.
* @param entity
* @return the jOCCI client.
*/
private Client getJocciClient(Entity entity)
{
if(jocciClient == null) {
try {
// Create a jOCCI client.
jocciClient = Importer.newJocciClient(OcciHelper.getConfiguration(entity).getLocation());
} catch(CommunicationException ce) {
reportException(ce);
jocciClient = null;
}
}
return jocciClient;
}
/**
* Get the identifier for a given category.
* @param category the given category.
* @return its identifier, aka scheme + term.
*/
private static String getIdentifier(org.occiware.clouddesigner.occi.Category category)
{
return category.getScheme() + category.getTerm();
}
/**
* Create an URI for a given category.
* @param category the given category.
* @return the created URI.
*/
private static URI createURI(org.occiware.clouddesigner.occi.Category category)
{
return URI.create(getIdentifier(category));
}
/**
* Get the location of a given entity.
* @param entity the given entity.
* @return its location inside the OCCI server.
*/
private String getLocation(Entity entity)
{
org.occiware.clouddesigner.occi.Kind entityKind = entity.getKind();
cz.cesnet.cloud.occi.core.Kind jocciKind = jocciClient.getModel().findKind(createURI(entityKind));
if(jocciKind == null) {
reportException(new Error("Kind " + entityKind.getScheme() + entityKind.getTerm() + " not found!"));
return null;
}
return jocciKind.getLocation().toString() + entity.getId();
}
/**
* Create a jOCCI entity from an OCCIware entity.
* @param entity the OCCIware entity.
* @return the jOCCI entity.
*/
private cz.cesnet.cloud.occi.core.Entity newJocciEntity(org.occiware.clouddesigner.occi.Entity entity)
{
// Get the jOCCI model.
Model jocciModel = jocciClient.getModel();
// Get an jOCCI entity builder.
EntityBuilder eb = new EntityBuilder(jocciModel);
// The jOCCI entity to create.
cz.cesnet.cloud.occi.core.Entity jocciEntity = null;
if(entity instanceof org.occiware.clouddesigner.occi.Resource) {
try {
// Create an jOCCI resource.
jocciEntity = eb.getResource(createURI(entity.getKind()));
} catch (EntityBuildingException ebe) {
reportException(ebe);
return null;
}
} else if(entity instanceof org.occiware.clouddesigner.occi.Link) {
org.occiware.clouddesigner.occi.Link link = (org.occiware.clouddesigner.occi.Link)entity;
cz.cesnet.cloud.occi.core.Link jocciLink = null;
try {
// Create an jOCCI link.
jocciLink = eb.getLink(createURI(entity.getKind()));
jocciEntity = jocciLink;
} catch (EntityBuildingException ebe) {
reportException(ebe);
return null;
}
try {
jocciLink.setSource(getLocation(link.getSource()));
} catch (InvalidAttributeValueException iave) {
reportException(iave);
return null;
}
try {
jocciLink.setTarget(getLocation(link.getTarget()));
} catch (InvalidAttributeValueException iave) {
reportException(iave);
return null;
}
} else {
// Should never happen!
reportException(new Error("Must be a Resource or a Link"));
return null;
}
// Iterate over all entity's mixins.
for(org.occiware.clouddesigner.occi.Mixin mixin : entity.getMixins()) {
cz.cesnet.cloud.occi.core.Mixin jocciMixin = jocciModel.findMixin(createURI(mixin));
jocciEntity.addMixin(jocciMixin);
}
// Iterate over all entity's attributes.
for(org.occiware.clouddesigner.occi.AttributeState as : entity.getAttributes()) {
try {
jocciEntity.addAttribute(as.getName(), as.getValue());
} catch (InvalidAttributeValueException iave) {
reportException(iave);
}
}
return jocciEntity;
}
private void convertJocciEntity2Entity(
cz.cesnet.cloud.occi.core.Entity source,
org.occiware.clouddesigner.occi.Entity target)
{
// Set the target entity's id.
target.setId(source.getId());
// Set the target entity's kind.
String sourceKindIdentifier = source.getKind().getIdentifier();
if(sourceKindIdentifier.equals(getIdentifier(target.getKind()))) {
// Nothing to do as the kind has not been changed.
} else {
// TODO: implement it
System.err.println("Entity's kind has been changed to " + sourceKindIdentifier);
// org.occiware.clouddesigner.occi.Kind targetKind = searchKind(configuration, source.getKind());
// if(targetKind != null) {
// target.setKind(targetKind);
// } else {
// TODO: Use Eclipse error report.
// System.err.println("Kind " + sourceKindIdentifier + " unknown!");
// }
}
// TODO: implement it
// Set target entity's mixins.
// List<org.occiware.clouddesigner.occi.Mixin> targetMixins = target.getMixins();
// for(cz.cesnet.cloud.occi.core.Mixin mixin : source.getMixins()) {
// String mixinIdentifier = mixin.getIdentifier();
// org.occiware.clouddesigner.occi.Mixin targetMixin = searchMixin(configuration, mixin);
// if(targetMixin != null) {
// targetMixins.add(targetMixin);
// } else {
// TODO: Use Eclipse error report.
// System.err.println("Mixin " + mixinIdentifier + " unknown!");
// }
// }
// Create all target entity's attributes.
List<org.occiware.clouddesigner.occi.AttributeState> targetAttributes = target.getAttributes();
targetAttributes.clear();
for(Map.Entry<cz.cesnet.cloud.occi.core.Attribute, String> sourceAttribute : source.getAttributes().entrySet()) {
String attributeName = sourceAttribute.getKey().getName();
if(!Importer.attributesToOmit.contains(attributeName)) {
org.occiware.clouddesigner.occi.AttributeState targetAttribute = org.occiware.clouddesigner.occi.OCCIFactory.eINSTANCE.createAttributeState();
targetAttributes.add(targetAttribute);
targetAttribute.setName(sourceAttribute.getKey().getName());
targetAttribute.setValue(sourceAttribute.getValue());
}
}
if(source instanceof cz.cesnet.cloud.occi.core.Link) {
// TODO: deal with Link
System.err.println("TODO: Deal with a Link instance");
}
}
/**
* Import into a configuration.
* @param configuration
*/
public void importConfiguration(Configuration configuration) {
Client jocciClient = getJocciClient();
if(jocciClient != null) {
try {
Importer.importFromOcciServer(configuration, jocciClient);
} catch(Throwable throwable) {
reportException(throwable);
}
}
}
/**
* Create an OCCI entity.
* @param entity the entity to create.
*/
public void createEntity(Entity entity)
{
// Get the jOCCI client to interact with an OCCI server.
Client jocciClient = getJocciClient(entity);
if(jocciClient == null) {
return;
}
// Create the jOCCI entity.
cz.cesnet.cloud.occi.core.Entity jocciEntity = newJocciEntity(entity);
if(jocciEntity == null) {
return;
}
URI location = null;
try {
// Create the OCCI resource.
location = jocciClient.create(jocciEntity);
} catch (CommunicationException ce) {
reportException(ce);
return;
}
// Update the ID of the entity.
String path = location.getPath();
String id = path.substring(path.lastIndexOf('/') + 1);
entity.setId(id);
MessageDialog.openInformation(Display.getCurrent().getActiveShell(), "Create OCCI Entity", "Entity " + location.toString() + " created");
}
/**
* Retrieve an OCCI entity.
* @param entity the entity to retrieve.
*/
public void retrieveEntity(Entity entity)
{
Client jocciClient = getJocciClient(entity);
if(jocciClient == null) {
return;
}
// Retrieve the jOCCI entity.
cz.cesnet.cloud.occi.core.Entity jocciEntity = null;
try {
jocciEntity = jocciClient.describe(URI.create(getLocation(entity))).get(0);
} catch (CommunicationException ce) {
reportException(ce);
return;
}
convertJocciEntity2Entity(jocciEntity, entity);
MessageDialog.openInformation(Display.getCurrent().getActiveShell(), "Retrieve OCCI Entity", "Entity " + getLocation(entity) + " retrieved");
}
/**
* Update an OCCI entity.
* @param entity the entity to update.
*/
public void updateEntity(Entity entity)
{
Client jocciClient = getJocciClient(entity);
if(jocciClient == null) {
return;
}
// Create the jOCCI entity.
cz.cesnet.cloud.occi.core.Entity jocciEntity = newJocciEntity(entity);
if(jocciEntity == null) {
return;
}
try {
jocciEntity.setId(entity.getId());
} catch (InvalidAttributeValueException iave) {
reportException(iave);
return;
}
try {
// Update the OCCI resource.
boolean updated = jocciClient.update(jocciEntity);
if(updated) {
MessageDialog.openInformation(Display.getCurrent().getActiveShell(), "Update OCCI Entity", "Entity " + getLocation(entity) + " updated");
} else {
MessageDialog.openWarning(Display.getCurrent().getActiveShell(), "Update OCCI Entity", "Entity " + getLocation(entity) + " not updated");
}
} catch (CommunicationException ce) {
reportException(ce);
return;
}
}
/**
* Execute an OCCI action on an OCCI entity.
* @param entity the entity on which an OCCI action will be executed.
*/
public void executeAction(Entity entity)
{
Client jocciClient = getJocciClient(entity);
if(jocciClient == null) {
return;
}
// Get all actions of the entity.
List<Action> actions = new ArrayList<Action>();
addActions(entity, actions);
// Display the OCCI action dialog.
Shell shell = Display.getCurrent().getActiveShell();
OcciActionDialog occiActionDialog = new OcciActionDialog(shell, actions.toArray(new Action[actions.size()]));
occiActionDialog.create();
if (occiActionDialog.open() != Window.OK) {
return;
}
String selectedAction = occiActionDialog.getSelectedAction();
if(selectedAction == null || selectedAction.isEmpty()) {
return;
}
// Get an jOCCI entity builder.
EntityBuilder eb = new EntityBuilder(jocciClient.getModel());
// Create a jOCCI action instance.
ActionInstance actionInstance;
try {
actionInstance = eb.getActionInstance(URI.create(selectedAction));
} catch (EntityBuildingException ebe) {
reportException(ebe);
return;
}
// TODO: add action's parameters.
// Execute the OCCI action.
try {
boolean status = jocciClient.trigger(URI.create(getLocation(entity)), actionInstance);
if(status) {
MessageDialog.openInformation(Display.getCurrent().getActiveShell(), "Execute OCCI Action", "Action " + selectedAction + " on " + getLocation(entity) + " executed");
} else {
MessageDialog.openWarning(Display.getCurrent().getActiveShell(), "Execute OCCI Action", "Action " + selectedAction + " on " + getLocation(entity) + " failed");
}
} catch (CommunicationException ce) {
reportException(ce);
return;
}
}
private static void addActions(org.occiware.clouddesigner.occi.Entity entity, List<Action> actions)
{
addActions(entity.getKind(), actions);
for(org.occiware.clouddesigner.occi.Mixin mixin : entity.getMixins()) {
addActions(mixin, actions);
}
}
private static void addActions(org.occiware.clouddesigner.occi.Kind kind, List<Action> actions)
{
if(kind == null) { return; }
addActions(kind.getParent(), actions);
actions.addAll(kind.getActions());
}
private static void addActions(org.occiware.clouddesigner.occi.Mixin mixin, List<Action> actions)
{
for(org.occiware.clouddesigner.occi.Mixin depend : mixin.getDepends()) {
addActions(depend, actions);
}
actions.addAll(mixin.getActions());
}
/**
* Delete an OCCI entity.
* @param entity the entity to delete.
*/
public void deleteEntity(Entity entity)
{
Client jocciClient = getJocciClient(entity);
if(jocciClient == null) {
return;
}
boolean deleted = false;
try {
deleted = jocciClient.delete(URI.create(getLocation(entity)));
} catch (CommunicationException ce) {
reportException(ce);
return;
}
if(deleted) {
MessageDialog.openInformation(Display.getCurrent().getActiveShell(), "Delete OCCI Entity", "Entity " + getLocation(entity) + " deleted");
} else {
MessageDialog.openWarning(Display.getCurrent().getActiveShell(), "Delete OCCI Entity", "Entity " + getLocation(entity) + " not deleted");
return;
}
if(entity instanceof org.occiware.clouddesigner.occi.Resource) {
Configuration configuration = (Configuration)entity.eContainer();
configuration.getResources().remove(entity);
} else if(entity instanceof org.occiware.clouddesigner.occi.Link) {
org.occiware.clouddesigner.occi.Link link = (org.occiware.clouddesigner.occi.Link)entity;
link.getSource().getLinks().remove(link);
} else {
// Should never happen!
reportException(new Error("Must be a Resource or a Link"));
return;
}
}
}