| 1 | package de.uka.ipd.sdq.reliability.solver.pcm2markov; |
| 2 | |
| 3 | import java.io.BufferedWriter; |
| 4 | import java.io.File; |
| 5 | import java.io.FileWriter; |
| 6 | import java.io.IOException; |
| 7 | import java.net.URL; |
| 8 | import java.util.List; |
| 9 | |
| 10 | import org.eclipse.core.runtime.FileLocator; |
| 11 | import org.eclipse.swt.widgets.Display; |
| 12 | import org.eclipse.ui.IWorkbenchPage; |
| 13 | import org.eclipse.ui.PartInitException; |
| 14 | import org.eclipse.ui.PlatformUI; |
| 15 | |
| 16 | import de.uka.ipd.sdq.pcmsolver.models.PCMInstance; |
| 17 | import de.uka.ipd.sdq.pcmsolver.runconfig.PCMSolverWorkflowRunConfiguration; |
| 18 | import de.uka.ipd.sdq.pcmsolver.transformations.EMFHelper; |
| 19 | import de.uka.ipd.sdq.pcmsolver.transformations.SolverStrategy; |
| 20 | import de.uka.ipd.sdq.reliability.solver.reporting.MarkovReporting; |
| 21 | import de.uka.ipd.sdq.reliability.solver.sensitivity.MarkovSensitivity; |
| 22 | import de.uka.ipd.sdq.reliability.solver.sensitivity.MarkovSensitivityBuilder; |
| 23 | import de.uka.ipd.sdq.reliability.solver.visualisation.MarkovHtmlGenerator; |
| 24 | import de.uka.ipd.sdq.reliability.solver.visualisation.MarkovResultEditorInput; |
| 25 | |
| 26 | /** |
| 27 | * This class performs a transformation from a PCM instance to a Markov Chain |
| 28 | * instance, and solves the resulting Markov Chain instance. |
| 29 | * |
| 30 | * @author brosch |
| 31 | * |
| 32 | */ |
| 33 | public class Pcm2MarkovStrategy implements SolverStrategy { |
| 34 | |
| 35 | /** |
| 36 | * Configuration properties for the reliability solver workflow. |
| 37 | */ |
| 38 | private PCMSolverWorkflowRunConfiguration configuration; |
| 39 | |
| 40 | /** |
| 41 | * The Markov transformation results (one result object for each PCM |
| 42 | * UsageScenario). |
| 43 | */ |
| 44 | private List<MarkovTransformationResult> markovResults; |
| 45 | |
| 46 | /** |
| 47 | * Captures a configuration for sensitivity analysis (temporary). |
| 48 | */ |
| 49 | private MarkovSensitivity markovSensitivity; |
| 50 | |
| 51 | /** |
| 52 | * The constructor. |
| 53 | * |
| 54 | * @param configuration |
| 55 | * launch configuration parameters |
| 56 | */ |
| 57 | public Pcm2MarkovStrategy( |
| 58 | final PCMSolverWorkflowRunConfiguration configuration) { |
| 59 | this.configuration = configuration; |
| 60 | this.markovSensitivity = initSensitivityAnalysis(); |
| 61 | } |
| 62 | |
| 63 | /** |
| 64 | * Retrieves the Markov transformation results. |
| 65 | * |
| 66 | * If the PCM instance has multiple usage scenarios, only the results for |
| 67 | * the first usage scenario are returned. |
| 68 | * |
| 69 | * @return the Markov transformation results |
| 70 | */ |
| 71 | public MarkovTransformationResult getSolvedValue() { |
| 72 | return (markovResults.size() > 0) ? markovResults.get(0) : null; |
| 73 | } |
| 74 | |
| 75 | /** |
| 76 | * Initializes sensitivity analysis parameters. |
| 77 | * |
| 78 | * @return the sensitivity configuration; NULL if no sensitivity analysis |
| 79 | * shall be performed |
| 80 | */ |
| 81 | private MarkovSensitivity initSensitivityAnalysis() { |
| 82 | if (configuration.isSensitivityModelEnabled()) { |
| 83 | MarkovSensitivityBuilder builder = new MarkovSensitivityBuilder(); |
| 84 | return builder.buildSensitivity(resolveFile(configuration |
| 85 | .getSensitivityModelFileName()), resolveFile(configuration |
| 86 | .getSensitivityLogFileName())); |
| 87 | } |
| 88 | return null; |
| 89 | } |
| 90 | |
| 91 | /** |
| 92 | * Loads an already existing Markov Chain from a given XMI file. Not yet |
| 93 | * implemented. |
| 94 | * |
| 95 | * @param fileName |
| 96 | * the name of the XMI file |
| 97 | */ |
| 98 | public void loadTransformedModel(final String fileName) { |
| 99 | throw new UnsupportedOperationException(); |
| 100 | } |
| 101 | |
| 102 | /** |
| 103 | * Resolves a file's path in case it starts with "platform:/" and returns |
| 104 | * the entire absolute path to the file, including the file's name. |
| 105 | * |
| 106 | * @param fileURL |
| 107 | * the path to a file, including the file's name (and its |
| 108 | * extension) |
| 109 | * @return the absolute path to the file, including the file's name |
| 110 | */ |
| 111 | private String resolveFile(String fileURL) { |
| 112 | // if this is a platform URL, first resolve it to an absolute path |
| 113 | if (fileURL.startsWith("platform:")) { |
| 114 | try { |
| 115 | URL solvedURL = FileLocator.resolve(new URL(fileURL)); |
| 116 | fileURL = solvedURL.getPath(); |
| 117 | } catch (Exception e) { |
| 118 | e.printStackTrace(); |
| 119 | return ""; |
| 120 | } |
| 121 | } |
| 122 | return fileURL; |
| 123 | } |
| 124 | |
| 125 | /** |
| 126 | * Saves the given String (HTML code) to a file specified in the |
| 127 | * configuration. |
| 128 | * |
| 129 | * @param htmlCode |
| 130 | * the (HTML code) string to save |
| 131 | */ |
| 132 | private void saveResultsToFile(String htmlCode) { |
| 133 | BufferedWriter out = null; |
| 134 | String filePath = resolveFile(configuration.getSaveFile()); |
| 135 | try { |
| 136 | File f = new File(filePath); |
| 137 | // if the file exists, we will delete it and create a new, |
| 138 | // empty one (i.e., overwrite the existing file) once, and then |
| 139 | // repeatedly append to this file |
| 140 | if (f.exists()) { |
| 141 | f.delete(); // delete current (old) file |
| 142 | f.createNewFile(); // create a new, empty file |
| 143 | } |
| 144 | out = new BufferedWriter(new FileWriter(filePath, true)); |
| 145 | out.append(htmlCode.toString()); |
| 146 | } catch (IOException e) { |
| 147 | e.printStackTrace(); |
| 148 | } finally { |
| 149 | try { |
| 150 | if (out != null) { |
| 151 | out.flush(); |
| 152 | out.close(); |
| 153 | } |
| 154 | } catch (IOException e) { |
| 155 | e.printStackTrace(); |
| 156 | } |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | /** |
| 161 | * Shows the Markov transformation results in the workbench editor of the |
| 162 | * target instance, given HTML code, represented as string. |
| 163 | * |
| 164 | * @param htmlCode |
| 165 | * the HTML code as string |
| 166 | */ |
| 167 | private void showResults(final String htmlCode) { |
| 168 | if (markovResults != null) { |
| 169 | Display.getDefault().asyncExec(new Runnable() { |
| 170 | public void run() { |
| 171 | IWorkbenchPage page = PlatformUI.getWorkbench() |
| 172 | .getActiveWorkbenchWindow().getActivePage(); |
| 173 | if (page != null) { |
| 174 | try { |
| 175 | page |
| 176 | .openEditor(new MarkovResultEditorInput( |
| 177 | htmlCode), |
| 178 | "de.uka.ipd.sdq.reliability.solver.pcm2markov.MarkovResultEditor"); |
| 179 | } catch (PartInitException e) { |
| 180 | e.printStackTrace(); |
| 181 | } |
| 182 | } |
| 183 | } |
| 184 | }); |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | /** |
| 189 | * Solves the Markov Chain which has been created as a result of the |
| 190 | * transformation or has been loaded from an XMI file. |
| 191 | */ |
| 192 | public void solve() { |
| 193 | |
| 194 | // Solving of Markov Chain has already taken place during the |
| 195 | // transformation. |
| 196 | |
| 197 | } |
| 198 | |
| 199 | /** |
| 200 | * Saves the Markov Chain resulting from the transformation into an XMI |
| 201 | * file. |
| 202 | * |
| 203 | * If the PCM instance has multiple usage scenarios, only the results for |
| 204 | * the first usage scenario are written into the file. |
| 205 | * |
| 206 | * @param fileName |
| 207 | * the name of the XMI file to create |
| 208 | */ |
| 209 | public void storeTransformedModel(final String fileName) { |
| 210 | MarkovTransformationResult result = (markovResults.size() > 0) ? markovResults |
| 211 | .get(0) |
| 212 | : null; |
| 213 | if (result != null) { |
| 214 | EMFHelper.saveToXMIFile(result.getResultChain(), |
| 215 | resolveFile(fileName)); |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | /** |
| 220 | * Transforms a PCM instance into a Markov Chain instance. |
| 221 | * |
| 222 | * The transformation is performed either as a single transformation, or as |
| 223 | * a repeated transformation to perform sensitivity analysis. |
| 224 | * |
| 225 | * @param model |
| 226 | * the input PCM instance |
| 227 | */ |
| 228 | public void transform(final PCMInstance model) { |
| 229 | markovResults = new MarkovTransformation().runTransform(model, |
| 230 | configuration, markovSensitivity); |
| 231 | if (configuration.isMarkovModelStorageEnabled()) { |
| 232 | storeTransformedModel(configuration.getMarkovModelFile()); |
| 233 | } |
| 234 | |
| 235 | // embed results in HTML page |
| 236 | String htmlCode = new MarkovHtmlGenerator(new MarkovReporting( |
| 237 | markovResults, configuration)).getHtml(); |
| 238 | // check whether the HTML page containing the results shall be saved to |
| 239 | // a file |
| 240 | if (configuration.isSaveResultsToFileEnabled()) { |
| 241 | saveResultsToFile(htmlCode); |
| 242 | } // else do nothing |
| 243 | |
| 244 | // show the HTML page containing the results |
| 245 | if (configuration.isShowHtmlResults()){ |
| 246 | showResults(htmlCode); |
| 247 | } |
| 248 | } |
| 249 | } |