/** * Copyright 2014 SAP AG * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.spotter.eclipse.ui.navigator; import java.io.File; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.part.FileEditorInput; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.spotter.eclipse.ui.Activator; import org.spotter.eclipse.ui.handlers.DeleteHandler; import org.spotter.eclipse.ui.handlers.OpenHandler; import org.spotter.eclipse.ui.jobs.JobsContainer; import org.spotter.eclipse.ui.menu.IDeletable; import org.spotter.eclipse.ui.menu.IOpenable; import org.spotter.eclipse.ui.util.DialogUtils; import org.spotter.eclipse.ui.util.SpotterUtils; import org.spotter.eclipse.ui.view.ResultsView; import org.spotter.shared.result.ResultsLocationConstants; import org.spotter.shared.result.model.ResultsContainer; /** * An element that represents a run result node. * * @author Denis Knoepfle * */ public class SpotterProjectRunResult extends AbstractProjectElement { public static final String IMAGE_PATH = "icons/results.gif"; //$NON-NLS-1$ public static final String ERROR_IMAGE_PATH = "icons/exclamation.png"; //$NON-NLS-1$ private static final Logger LOGGER = LoggerFactory.getLogger(SpotterProjectRunResult.class); private static final String ELEMENT_TYPE_NAME = "Result Item"; private static final String OPEN_ID = ResultsView.VIEW_ID; private static final String TXT_OPEN_ID = EditorsUI.DEFAULT_TEXT_EDITOR_ID; private static final String MSG_SINGLE = "Are you sure you want to delete the result '%s'?"; private static final String MSG_MULTI = "Are you sure you want to delete these %d elements?"; private final ISpotterProjectElement parent; private final IFolder resultFolder; private boolean isErroneous; private final long jobId; private final long timestamp; private final String elementName; private String elementLabel; /** * Creates a new instance of this element. * * @param parent * the parent element * @param jobId * the corresponding job id of this run result * @param timestamp * the corresponding timestamp of this run result * @param resultFolder * the result folder that is represented by this node */ public SpotterProjectRunResult(ISpotterProjectElement parent, long jobId, long timestamp, IFolder resultFolder) { super(); this.parent = parent; this.jobId = jobId; this.timestamp = timestamp; this.resultFolder = resultFolder; String errorFilePath = resultFolder.getFile(ResultsLocationConstants.TXT_DIAGNOSIS_ERROR_FILE_NAME) .getLocation().toString(); this.isErroneous = new File(errorFilePath).exists(); if (isErroneous) { setImagePath(ERROR_IMAGE_PATH); } else { setImagePath(IMAGE_PATH); } SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd (HH:mm:ss)"); this.elementName = dateFormat.format(new Date(timestamp)); readElementLabel(); addOpenHandler(); addDeleteHandler(); } /** * @return <code>true</code> if erroneous diagnosis, otherwise * <code>false</code> */ public boolean isErroneous() { return isErroneous; } private void addOpenHandler() { addHandler(OpenHandler.OPEN_COMMAND_ID, new IOpenable() { @Override public void open() { SpotterProjectRunResult.this.open(); } @Override public String getOpenId() { return SpotterProjectRunResult.this.getOpenId(); } @Override public String getElementName() { return SpotterProjectRunResult.this.elementName; } }); } private void addDeleteHandler() { addHandler(DeleteHandler.DELETE_COMMAND_ID, new IDeletable() { @Override public String getElementTypeName() { return ELEMENT_TYPE_NAME; } @Override public void delete() { SpotterProjectRunResult.this.delete(); } @Override public void delete(Object[] elements) throws CoreException { SpotterProjectRunResult.this.delete(elements); } @Override public boolean showConfirmationDialog(Object[] elements) { return SpotterProjectRunResult.this.showConfirmationDialog(elements); } }); } @Override public String getText() { if (elementLabel != null && !elementLabel.isEmpty()) { return elementName + " " + elementLabel; } else { return elementName; } } /** * @return the corresponding timestamp of this run result */ public long getTimestamp() { return timestamp; } /** * @return the result folder this element is linked to */ public IFolder getResultFolder() { return resultFolder; } @Override public Object getParent() { return parent; } @Override public IProject getProject() { return parent.getProject(); } /** * Updates the label. This also updates the corresponding results container. * * @param label * the new label */ public synchronized void updateElementLabel(String label) { ResultsContainer container = SpotterUtils.readResultsContainer(resultFolder); if (container != null) { String oldLabel = container.getLabel(); container.setLabel(label); if (SpotterUtils.writeResultsContainer(resultFolder, container)) { this.elementLabel = label; } else { container.setLabel(oldLabel); } } } /** * @return the label of this element if any */ public String getElementLabel() { return elementLabel; } /** * Reads the corresponding container and updates the label. */ private void readElementLabel() { ResultsContainer container = SpotterUtils.readResultsContainer(resultFolder); String label = null; if (container != null) { label = container.getLabel(); } this.elementLabel = label; } private String getOpenId() { return isErroneous ? TXT_OPEN_ID : OPEN_ID; } private void open() { IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); try { if (isErroneous) { if (!resultFolder.isSynchronized(IResource.DEPTH_INFINITE)) { resultFolder.refreshLocal(IResource.DEPTH_INFINITE, null); } IFile file = resultFolder.getFile(ResultsLocationConstants.TXT_DIAGNOSIS_ERROR_FILE_NAME); page.openEditor(new FileEditorInput(file), getOpenId()); } else { ResultsView view = (ResultsView) page.showView(getOpenId()); view.setResult(this); } } catch (CoreException e) { String message = "Could not open view part " + getOpenId(); LOGGER.error(message, e); throw new RuntimeException(message, e); } } @Override public boolean equals(Object obj) { if (!(obj instanceof SpotterProjectRunResult)) { return false; } SpotterProjectRunResult other = (SpotterProjectRunResult) obj; boolean equalProject = getProject().equals(other.getProject()); boolean equalName = elementName.equals(other.elementName); return equalProject && equalName; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + getProject().hashCode(); result = prime * result + ((elementName == null) ? 0 : elementName.hashCode()); return result; } private boolean showConfirmationDialog(Object[] elements) { String prompt; if (elements.length > 1) { prompt = createMultiMessage(elements.length); } else { prompt = createSingleMessage(); } boolean confirm = DialogUtils.openConfirm(IDeletable.DELETE_DLG_TITLE, prompt); return confirm; } private void delete() { try { if (!resultFolder.isSynchronized(IResource.DEPTH_INFINITE)) { resultFolder.refreshLocal(IResource.DEPTH_INFINITE, null); } ResultsView.reset(resultFolder); resultFolder.delete(true, null); // clear job id if (!JobsContainer.removeJobId(getProject(), jobId)) { DialogUtils .openError("There was an error while updating the project's job ids. The results of the corresponding id will be fetched again."); } updateNavigatorViewer(); } catch (CoreException e) { String message = "Error while deleting result folder '" + resultFolder.getName() + "'!"; LOGGER.error(message, e); DialogUtils.handleError(message, e); } } private void singleDelete(SpotterProjectRunResult runResult, List<Long> jobIds) { IFolder resultFolder = runResult.getResultFolder(); try { if (!resultFolder.isSynchronized(IResource.DEPTH_INFINITE)) { resultFolder.refreshLocal(IResource.DEPTH_INFINITE, null); } ResultsView.reset(resultFolder); resultFolder.delete(true, null); jobIds.add(runResult.jobId); } catch (CoreException e) { String message = "Error while deleting result folder '" + resultFolder.getName() + "'!"; LOGGER.error(message, e); DialogUtils.handleError(message, e); } } private void delete(Object[] elements) { List<Long> jobIds = new ArrayList<>(); for (Object element : elements) { SpotterProjectRunResult runResult = (SpotterProjectRunResult) element; singleDelete(runResult, jobIds); } if (!JobsContainer.removeJobIds(getProject(), jobIds)) { DialogUtils .openError("There was an error while updating the project's job ids. The results of the corresponding ids will be fetched again."); } updateNavigatorViewer(); } private void updateNavigatorViewer() { SpotterProjectResults parent = (SpotterProjectResults) getParent(); parent.refreshChildren(); Activator.getDefault().getNavigatorViewer().refresh(parent); } private String createSingleMessage() { return String.format(MSG_SINGLE, getText()); } private String createMultiMessage(int count) { return String.format(MSG_MULTI, count); } }