/*******************************************************************************
* This file is protected by Copyright.
* Please refer to the COPYRIGHT file distributed with this source distribution.
*
* This file is part of REDHAWK IDE.
*
* 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
*******************************************************************************/
package gov.redhawk.ide.spd.internal.ui;
import gov.redhawk.ide.spd.ui.ComponentUiPlugin;
import gov.redhawk.spd.internal.validation.EventPortConstraint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import mil.jpeojtrs.sca.scd.ComponentFeatures;
import mil.jpeojtrs.sca.scd.Interface;
import mil.jpeojtrs.sca.scd.Interfaces;
import mil.jpeojtrs.sca.scd.PortType;
import mil.jpeojtrs.sca.scd.PortTypeContainer;
import mil.jpeojtrs.sca.scd.Ports;
import mil.jpeojtrs.sca.scd.ScdFactory;
import mil.jpeojtrs.sca.scd.SoftwareComponent;
import mil.jpeojtrs.sca.scd.Uses;
import mil.jpeojtrs.sca.spd.Descriptor;
import mil.jpeojtrs.sca.spd.SoftPkg;
import mil.jpeojtrs.sca.spd.SpdPackage;
import mil.jpeojtrs.sca.util.ScaResourceFactoryUtil;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EValidator;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.workspace.util.WorkspaceSynchronizer;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.ui.views.markers.WorkbenchMarkerResolution;
import org.omg.CosEventChannelAdmin.EventChannelHelper;
/**
*
*/
public class SpdMarkerResolution extends WorkbenchMarkerResolution {
private final IMarker rootMarker;
public SpdMarkerResolution(final IMarker marker) {
this.rootMarker = marker;
}
public static boolean canHandle(final IMarker marker) {
final int code = marker.getAttribute(IMarker.PROBLEM, 0);
final String sourceId = marker.getAttribute(IMarker.SOURCE_ID, "");
if (marker.getResource().getName().endsWith(SpdPackage.FILE_EXTENSION) && code == EventPortConstraint.STATUS_CODE
&& sourceId.equals(EventPortConstraint.SOURCE_ID)) {
return true;
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
public IMarker[] findOtherMarkers(final IMarker[] markers) {
final List<IMarker> retVal = new ArrayList<IMarker>();
for (final IMarker marker : markers) {
if (this.rootMarker == marker) {
continue;
}
if (SpdMarkerResolution.canHandle(marker)) {
retVal.add(marker);
}
}
return retVal.toArray(new IMarker[retVal.size()]);
}
/**
* {@inheritDoc}
*/
@Override
public String getDescription() {
return "Missing event port for property events.";
}
/**
* {@inheritDoc}
*/
@Override
public Image getImage() {
// TODO Auto-generated method stub
return null;
}
/**
* {@inheritDoc}
*/
@Override
public String getLabel() {
return "Add event port";
}
/**
* {@inheritDoc}
*/
@Override
public void run(final IMarker marker) {
final String uri = marker.getAttribute(EValidator.URI_ATTRIBUTE, null);
if (uri != null) {
final ResourceSet set = ScaResourceFactoryUtil.createResourceSet();
final EObject obj = set.getEObject(URI.createURI(uri), true);
if (obj instanceof SoftPkg) {
final SoftPkg spd = (SoftPkg) obj;
final List<Resource> editedResources = Collections.emptyList();
try {
addEventPort(spd);
} catch (final CoreException e) {
StatusManager.getManager().handle(new Status(e.getStatus().getSeverity(), ComponentUiPlugin.PLUGIN_ID, e.getLocalizedMessage(), e),
StatusManager.SHOW | StatusManager.LOG);
return;
}
save(editedResources, null);
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void run(final IMarker[] markers, final IProgressMonitor monitor) {
if (markers == null) {
return;
}
final ResourceSet set = ScaResourceFactoryUtil.createResourceSet();
final Collection<Resource> editedResources = new HashSet<Resource>();
final SubMonitor subMonitor = SubMonitor.convert(monitor, "Adding event port.", 100);
try {
final SubMonitor markerLoopMonitor = subMonitor.newChild(70).setWorkRemaining(markers.length); // SUPPRESS
// CHECKSTYLE
// MagicNumber
for (final IMarker marker : markers) {
final String uri = marker.getAttribute(EValidator.URI_ATTRIBUTE, null);
if (uri != null) {
final EObject obj = set.getEObject(URI.createURI(uri), true);
if (obj instanceof SoftPkg) {
final SoftPkg spd = (SoftPkg) obj;
try {
editedResources.addAll(addEventPort(spd));
} catch (final CoreException e) {
StatusManager.getManager().handle(new Status(e.getStatus().getSeverity(), ComponentUiPlugin.PLUGIN_ID, e.getLocalizedMessage(), e),
StatusManager.SHOW | StatusManager.LOG);
return;
}
}
}
markerLoopMonitor.worked(1);
}
save(editedResources, subMonitor.newChild(30));
} finally {
subMonitor.done();
}
}
private void save(final Collection<Resource> resources, final IProgressMonitor monitor) {
final SubMonitor resourceLoopMonitor = SubMonitor.convert(monitor, "Saving resources", resources.size()); // SUPPRESS
// CHECKSTYLE
// MagicNumber
for (final Resource resource : resources) {
try {
final IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
@Override
public void run(final IProgressMonitor monitor) throws CoreException {
try {
resource.save(null);
} catch (final IOException e) {
throw new CoreException(new Status(IStatus.ERROR, ComponentUiPlugin.PLUGIN_ID, "Failed to save Quick Fix for " + resource.getURI(),
e));
}
}
};
ResourcesPlugin.getWorkspace().run(runnable, WorkspaceSynchronizer.getFile(resource), 0, resourceLoopMonitor.newChild(1));
} catch (final CoreException e) {
StatusManager.getManager().handle(new Status(e.getStatus().getSeverity(), ComponentUiPlugin.PLUGIN_ID, e.getLocalizedMessage(), e),
StatusManager.SHOW | StatusManager.LOG);
}
}
}
private List<Resource> addEventPort(final SoftPkg spd) throws CoreException {
final Descriptor desc = spd.getDescriptor();
if (desc != null) {
final SoftwareComponent scd = desc.getComponent();
ComponentFeatures features = scd.getComponentFeatures();
if (features == null) {
features = ScdFactory.eINSTANCE.createComponentFeatures();
scd.setComponentFeatures(features);
}
Ports ports = features.getPorts();
if (ports == null) {
ports = ScdFactory.eINSTANCE.createPorts();
features.setPorts(ports);
}
Interfaces interfaces = scd.getInterfaces();
boolean found = false;
if (interfaces != null) {
for (final Interface i : interfaces.getInterface()) {
if (EventChannelHelper.id().equals(i.getRepid())) {
found = true;
break;
}
}
} else {
interfaces = ScdFactory.eINSTANCE.createInterfaces();
scd.setInterfaces(interfaces);
}
if (!found) {
final Interface i = ScdFactory.eINSTANCE.createInterface();
i.setName("EventChannel");
i.setRepid(EventChannelHelper.id());
interfaces.getInterface().add(i);
}
final Uses uses = ScdFactory.eINSTANCE.createUses();
ports.getUses().add(uses);
uses.setName(Uses.PORT_NAME_PROP_EVENTS);
uses.setRepID(EventChannelHelper.id());
final PortTypeContainer ptc = ScdFactory.eINSTANCE.createPortTypeContainer();
ptc.setType(PortType.RESPONSES);
uses.getPortType().add(ptc);
return Collections.singletonList(scd.eResource());
} else {
throw new CoreException(new Status(IStatus.ERROR, ComponentUiPlugin.PLUGIN_ID, "No descriptor, quick fix failed for "
+ spd.eResource().getURI().path(), null));
}
}
}