Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/operation/ExportChangeReportOperation.java45
-rw-r--r--plugins/org.eclipse.osee.framework.core.test/src/org/eclipse/osee/framework/core/test/FrameworkCoreTestSuite.java4
-rw-r--r--plugins/org.eclipse.osee.framework.core.test/src/org/eclipse/osee/framework/core/test/ops/OpsTestSuite.java23
-rw-r--r--plugins/org.eclipse.osee.framework.core.test/src/org/eclipse/osee/framework/core/test/ops/RenameFilesOperationTest.java65
-rw-r--r--plugins/org.eclipse.osee.framework.core/META-INF/MANIFEST.MF4
-rw-r--r--plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/internal/Activator.java2
-rw-r--r--plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/ops/RenameFilesOperation.java80
-rw-r--r--plugins/org.eclipse.osee.framework.ui.skynet/META-INF/MANIFEST.MF1
-rw-r--r--plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/RenameFiles.java41
-rw-r--r--plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/RendererManager.java9
10 files changed, 222 insertions, 52 deletions
diff --git a/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/operation/ExportChangeReportOperation.java b/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/operation/ExportChangeReportOperation.java
index eb32696339c..7104f2531c1 100644
--- a/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/operation/ExportChangeReportOperation.java
+++ b/plugins/org.eclipse.osee.ats/src/org/eclipse/osee/ats/operation/ExportChangeReportOperation.java
@@ -13,6 +13,7 @@ package org.eclipse.osee.ats.operation;
import static org.eclipse.osee.framework.ui.skynet.render.IRenderer.NO_DISPLAY;
import static org.eclipse.osee.framework.ui.skynet.render.IRenderer.SKIP_DIALOGS;
import java.io.File;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -25,6 +26,7 @@ import org.eclipse.osee.ats.artifact.TeamWorkFlowArtifact;
import org.eclipse.osee.ats.internal.AtsPlugin;
import org.eclipse.osee.ats.util.AtsBranchManager;
import org.eclipse.osee.framework.core.exception.OseeCoreException;
+import org.eclipse.osee.framework.core.exception.OseeExceptions;
import org.eclipse.osee.framework.core.exception.OseeStateException;
import org.eclipse.osee.framework.core.model.Branch;
import org.eclipse.osee.framework.core.model.TransactionRecord;
@@ -38,19 +40,26 @@ import org.eclipse.osee.framework.skynet.core.revision.ChangeManager;
import org.eclipse.osee.framework.skynet.core.transaction.TransactionManager;
import org.eclipse.osee.framework.skynet.core.types.IArtifact;
import org.eclipse.osee.framework.ui.skynet.render.RendererManager;
+import org.eclipse.osee.framework.ui.skynet.render.compare.CompareData;
+import org.eclipse.osee.framework.ui.skynet.render.compare.CompareDataCollector;
/**
* @author Ryan D. Brooks
*/
-public class ExportChangeReportOperation extends AbstractOperation {
+public final class ExportChangeReportOperation extends AbstractOperation {
private final List<TeamWorkFlowArtifact> workflows;
- private String resultFolder;
+ private final Appendable resultFolder;
private final boolean reverse;
- public ExportChangeReportOperation(List<TeamWorkFlowArtifact> workflows, boolean reverse) {
+ public ExportChangeReportOperation(List<TeamWorkFlowArtifact> workflows, boolean reverse, Appendable resultFolder) {
super("Exporting Change Report(s)", AtsPlugin.PLUGIN_ID);
this.workflows = workflows;
this.reverse = reverse;
+ this.resultFolder = resultFolder;
+ }
+
+ public ExportChangeReportOperation(List<TeamWorkFlowArtifact> workflows, boolean reverse) {
+ this(workflows, reverse, new StringBuilder());
}
@Override
@@ -59,11 +68,30 @@ public class ExportChangeReportOperation extends AbstractOperation {
sortWorkflows();
+ CompareDataCollector collector = new CompareDataCollector() {
+
+ @Override
+ public void onCompare(CompareData data) throws OseeCoreException {
+ String filePath = data.getOutputPath();
+ String modifiedPath = filePath.substring(0, filePath.lastIndexOf(File.separator));
+ try {
+ if (resultFolder.toString().isEmpty()) {
+ resultFolder.append(modifiedPath);
+ }
+ } catch (IOException ex) {
+ OseeExceptions.wrapAndThrow(ex);
+ }
+ }
+ };
+
for (Artifact workflow : workflows) {
Collection<Change> changes = computeChanges(workflow, monitor);
if (!changes.isEmpty() && changes.size() < 4000) {
String legacyPcrId = workflow.getSoleAttributeValueAsString(AtsAttributeTypes.LegacyPcrId, null);
- resultFolder = generateDiffReport(changes, legacyPcrId, monitor);
+
+ Collection<ArtifactDelta> artifactDeltas = ChangeManager.getCompareArtifacts(changes);
+ String prefix = "/" + legacyPcrId;
+ RendererManager.diff(collector, artifactDeltas, prefix, NO_DISPLAY, true, SKIP_DIALOGS, true);
}
monitor.worked(calculateWork(0.50));
}
@@ -127,13 +155,4 @@ public class ExportChangeReportOperation extends AbstractOperation {
return TransactionManager.getTransactionId(minTransactionId);
}
- private String generateDiffReport(Collection<Change> changes, String legacyPcrId, IProgressMonitor monitor) {
- Collection<ArtifactDelta> artifactDeltas = ChangeManager.getCompareArtifacts(changes);
- String filePath = RendererManager.diff(artifactDeltas, "/" + legacyPcrId, NO_DISPLAY, true, SKIP_DIALOGS, true);
- return filePath.substring(0, filePath.lastIndexOf(File.separator));
- }
-
- public String getResultFolder() {
- return resultFolder;
- }
} \ No newline at end of file
diff --git a/plugins/org.eclipse.osee.framework.core.test/src/org/eclipse/osee/framework/core/test/FrameworkCoreTestSuite.java b/plugins/org.eclipse.osee.framework.core.test/src/org/eclipse/osee/framework/core/test/FrameworkCoreTestSuite.java
index 1f88c493df3..222026e65d7 100644
--- a/plugins/org.eclipse.osee.framework.core.test/src/org/eclipse/osee/framework/core/test/FrameworkCoreTestSuite.java
+++ b/plugins/org.eclipse.osee.framework.core.test/src/org/eclipse/osee/framework/core/test/FrameworkCoreTestSuite.java
@@ -13,6 +13,7 @@ package org.eclipse.osee.framework.core.test;
import org.eclipse.osee.framework.core.test.enums.EnumsTestSuite;
import org.eclipse.osee.framework.core.test.exception.ExceptionTestSuite;
import org.eclipse.osee.framework.core.test.internal.InternalCoreTestSuite;
+import org.eclipse.osee.framework.core.test.ops.OpsTestSuite;
import org.eclipse.osee.framework.core.test.util.UtilCoreTestSuite;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@@ -22,7 +23,8 @@ import org.junit.runners.Suite;
EnumsTestSuite.class,
ExceptionTestSuite.class,
InternalCoreTestSuite.class,
- UtilCoreTestSuite.class})
+ UtilCoreTestSuite.class,
+ OpsTestSuite.class})
/**
* @author Roberto E. Escobar
*/
diff --git a/plugins/org.eclipse.osee.framework.core.test/src/org/eclipse/osee/framework/core/test/ops/OpsTestSuite.java b/plugins/org.eclipse.osee.framework.core.test/src/org/eclipse/osee/framework/core/test/ops/OpsTestSuite.java
new file mode 100644
index 00000000000..6a4c7dc3297
--- /dev/null
+++ b/plugins/org.eclipse.osee.framework.core.test/src/org/eclipse/osee/framework/core/test/ops/OpsTestSuite.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Boeing.
+ * 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:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.framework.core.test.ops;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({RenameFilesOperationTest.class})
+/**
+ * @author Ryan D. Brooks
+ */
+public class OpsTestSuite {
+ // Test Suite Class
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.osee.framework.core.test/src/org/eclipse/osee/framework/core/test/ops/RenameFilesOperationTest.java b/plugins/org.eclipse.osee.framework.core.test/src/org/eclipse/osee/framework/core/test/ops/RenameFilesOperationTest.java
new file mode 100644
index 00000000000..a5dd448d6db
--- /dev/null
+++ b/plugins/org.eclipse.osee.framework.core.test/src/org/eclipse/osee/framework/core/test/ops/RenameFilesOperationTest.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Boeing.
+ * 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:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.framework.core.test.ops;
+
+import java.io.File;
+import java.io.IOException;
+import junit.framework.Assert;
+import org.eclipse.osee.framework.core.exception.OseeCoreException;
+import org.eclipse.osee.framework.core.operation.NullOperationLogger;
+import org.eclipse.osee.framework.core.operation.Operations;
+import org.eclipse.osee.framework.core.ops.RenameFilesOperation;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+/**
+ * Test Case for {@link RenameFilesOperation}
+ *
+ * @author Ryan D. Brooks
+ */
+public class RenameFilesOperationTest {
+ @Rule
+ public final TemporaryFolder tempFolder = new TemporaryFolder();
+
+ @Test
+ public void testDelayedParameterValues() throws IOException, OseeCoreException {
+ tempFolder.newFile("abcde1");
+
+ StringBuilder parentFolder = new StringBuilder();
+ StringBuffer pathPattern = new StringBuffer();
+ RenameFilesOperation renameOperation =
+ new RenameFilesOperation(NullOperationLogger.getSingleton(), parentFolder, pathPattern, "");
+
+ parentFolder.append(tempFolder.getRoot().getCanonicalPath());
+ pathPattern.append(".+ab(cde)\\d");
+
+ Operations.executeWorkAndCheckStatus(renameOperation);
+ Assert.assertTrue(new File(parentFolder.toString(), "ab1").exists());
+ }
+
+ @Test
+ public void testMultipleFileMatches() throws IOException, OseeCoreException {
+ tempFolder.newFile("abcde12");
+ tempFolder.newFile("abcde13");
+ tempFolder.newFile("abcde21");
+
+ String parentFolder = tempFolder.getRoot().getCanonicalPath();
+
+ RenameFilesOperation renameOperation =
+ new RenameFilesOperation(NullOperationLogger.getSingleton(), parentFolder, ".+ab(cde)1\\d", "_");
+
+ Operations.executeWorkAndCheckStatus(renameOperation);
+ Assert.assertTrue(new File(parentFolder, "ab_12").exists());
+ Assert.assertTrue(new File(parentFolder, "ab_13").exists());
+ Assert.assertTrue(new File(parentFolder, "abcde21").exists());
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.osee.framework.core/META-INF/MANIFEST.MF b/plugins/org.eclipse.osee.framework.core/META-INF/MANIFEST.MF
index 90e6bc70759..c9917f2d0d2 100644
--- a/plugins/org.eclipse.osee.framework.core/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.osee.framework.core/META-INF/MANIFEST.MF
@@ -16,6 +16,9 @@ Import-Package: com.lowagie.text;version="2.1.7",
org.eclipse.core.net.proxy,
org.eclipse.core.runtime,
org.eclipse.core.runtime.jobs,
+ org.eclipse.osee.framework.jdk.core.text,
+ org.eclipse.osee.framework.jdk.core.text.change,
+ org.eclipse.osee.framework.jdk.core.text.rules,
org.eclipse.osee.framework.jdk.core.type,
org.eclipse.osee.framework.jdk.core.util,
org.eclipse.osee.framework.jdk.core.util.time,
@@ -28,6 +31,7 @@ Export-Package: org.eclipse.osee.framework.core.data,
org.eclipse.osee.framework.core.enums,
org.eclipse.osee.framework.core.exception,
org.eclipse.osee.framework.core.operation,
+ org.eclipse.osee.framework.core.ops,
org.eclipse.osee.framework.core.translation,
org.eclipse.osee.framework.core.util
Bundle-ActivationPolicy: lazy
diff --git a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/internal/Activator.java b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/internal/Activator.java
index 54e7ea178ce..a0f31ec6550 100644
--- a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/internal/Activator.java
+++ b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/internal/Activator.java
@@ -14,7 +14,7 @@ import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Activator implements BundleActivator {
-
+ public static final String PLUGIN_ID = "org.eclipse.osee.framework.core";
private static BundleContext bundleContext;
@Override
diff --git a/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/ops/RenameFilesOperation.java b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/ops/RenameFilesOperation.java
new file mode 100644
index 00000000000..34d95983d2d
--- /dev/null
+++ b/plugins/org.eclipse.osee.framework.core/src/org/eclipse/osee/framework/core/ops/RenameFilesOperation.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Boeing.
+ * 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:
+ * Boeing - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osee.framework.core.ops;
+
+import java.io.File;
+import java.util.List;
+import java.util.regex.Pattern;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.osee.framework.core.internal.Activator;
+import org.eclipse.osee.framework.core.operation.AbstractOperation;
+import org.eclipse.osee.framework.core.operation.OperationLogger;
+import org.eclipse.osee.framework.jdk.core.text.Rule;
+import org.eclipse.osee.framework.jdk.core.text.change.ChangeSet;
+import org.eclipse.osee.framework.jdk.core.text.rules.ReplaceAll;
+import org.eclipse.osee.framework.jdk.core.util.Lib;
+
+/**
+ * Operation that renames files matching a regex.
+ *
+ * @author Ryan D. Brooks
+ */
+public class RenameFilesOperation extends AbstractOperation {
+ private final CharSequence parentFolderPath;
+ private final CharSequence pathPattern;
+ private final CharSequence replacement;
+
+ /**
+ * All parameters of this operation are not used until the operation is run. This enables the operation to be
+ * constructed prior to its execution with parameters whose values are not yet set. This is needed for constructing
+ * composite operations where results of prior sub-operations are used in subsequent sub-operations
+ *
+ * @param logger passed along the the super class and used by this class by calling one of AbstractOperation's log
+ * methods
+ * @param parentFolderPath parent folder that will be searched using the pathPattern
+ * @param pathPattern java regex that must match the entire path of any files to be renamed
+ * @param replacement the replacement value used in renaming (may be the empty string)
+ */
+ public RenameFilesOperation(OperationLogger logger, CharSequence parentFolderPath, CharSequence pathPattern, CharSequence replacement) {
+ super("Rename Files", Activator.PLUGIN_ID, logger);
+ this.parentFolderPath = parentFolderPath;
+ this.pathPattern = pathPattern;
+ this.replacement = replacement;
+ }
+
+ @Override
+ protected void doWork(IProgressMonitor monitor) throws Exception {
+ Rule rule = new ReplaceAll(Pattern.compile(pathPattern.toString()), replacement.toString());
+ File parentFolder = new File(parentFolderPath.toString()).getCanonicalFile();
+ List<File> files = Lib.recursivelyListFiles(parentFolder, null);
+ int size = files.size();
+ int renamedFileCount = 0;
+
+ for (int i = 0; i < size; i++) {
+ if (monitor.isCanceled()) {
+ return;
+ }
+ File file = files.get(i);
+ rule.setRuleWasApplicable(false);
+ ChangeSet newName = rule.computeChanges(file.getPath());
+ if (rule.ruleWasApplicable()) {
+ File newFile = new File(newName.toString());
+ if (file.renameTo(newFile)) {
+ log(file.getPath() + " became " + newFile.getPath());
+ renamedFileCount++;
+ } else {
+ log(file.getPath() + " failed to become " + newFile.getPath());
+ }
+ }
+ }
+ log("Changed " + renamedFileCount + " files");
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.osee.framework.ui.skynet/META-INF/MANIFEST.MF b/plugins/org.eclipse.osee.framework.ui.skynet/META-INF/MANIFEST.MF
index 8fbad8d72f3..7a371d7538c 100644
--- a/plugins/org.eclipse.osee.framework.ui.skynet/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.osee.framework.ui.skynet/META-INF/MANIFEST.MF
@@ -57,6 +57,7 @@ Import-Package: com.lowagie.text;version="2.1.7",
org.eclipse.osee.framework.core.model.event,
org.eclipse.osee.framework.core.model.type,
org.eclipse.osee.framework.core.operation,
+ org.eclipse.osee.framework.core.ops,
org.eclipse.osee.framework.core.services,
org.eclipse.osee.framework.core.util,
org.eclipse.osee.framework.database,
diff --git a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/RenameFiles.java b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/RenameFiles.java
index c4747d34480..a6290aa6e3d 100644
--- a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/RenameFiles.java
+++ b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/RenameFiles.java
@@ -10,16 +10,11 @@
*******************************************************************************/
package org.eclipse.osee.framework.ui.skynet.blam.operation;
-import java.io.File;
import java.util.Arrays;
import java.util.Collection;
-import java.util.List;
-import java.util.regex.Pattern;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.osee.framework.jdk.core.text.Rule;
-import org.eclipse.osee.framework.jdk.core.text.change.ChangeSet;
-import org.eclipse.osee.framework.jdk.core.text.rules.ReplaceAll;
-import org.eclipse.osee.framework.jdk.core.util.Lib;
+import org.eclipse.osee.framework.core.operation.IOperation;
+import org.eclipse.osee.framework.core.operation.OperationLogger;
+import org.eclipse.osee.framework.core.ops.RenameFilesOperation;
import org.eclipse.osee.framework.ui.skynet.blam.AbstractBlam;
import org.eclipse.osee.framework.ui.skynet.blam.VariableMap;
@@ -27,36 +22,12 @@ import org.eclipse.osee.framework.ui.skynet.blam.VariableMap;
* @author Ryan D. Brooks
*/
public class RenameFiles extends AbstractBlam {
-
@Override
- public void runOperation(VariableMap variableMap, IProgressMonitor monitor) throws Exception {
- File parentFolder = new File(variableMap.getString("Parent Folder"));
+ public IOperation createOperation(VariableMap variableMap, OperationLogger logger) throws Exception {
+ String parentFolder = variableMap.getString("Parent Folder");
String pathPattern = variableMap.getString("Full Path Pattern");
String replacement = variableMap.getString("Replacement");
-
- Rule rule = new ReplaceAll(Pattern.compile(pathPattern), replacement);
- List<File> files = Lib.recursivelyListFiles(parentFolder.getCanonicalFile(), null);
- int size = files.size();
- int renamedFileCount = 0;
-
- for (int i = 0; i < size; i++) {
- if (monitor.isCanceled()) {
- return;
- }
- File file = files.get(i);
- rule.setRuleWasApplicable(false);
- ChangeSet newName = rule.computeChanges(file.getPath());
- if (rule.ruleWasApplicable()) {
- File newFile = new File(newName.toString());
- if (file.renameTo(newFile)) {
- report(file.getPath() + " became " + newFile.getPath());
- renamedFileCount++;
- } else {
- report(file.getPath() + " failed to become " + newFile.getPath());
- }
- }
- }
- report("Changed " + renamedFileCount + " files");
+ return new RenameFilesOperation(logger, parentFolder, pathPattern, replacement);
}
@Override
diff --git a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/RendererManager.java b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/RendererManager.java
index be98d6a51b3..80e9bc738ea 100644
--- a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/RendererManager.java
+++ b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/render/RendererManager.java
@@ -214,6 +214,11 @@ public final class RendererManager {
Operations.executeAsJob(new DiffUsingRenderer(collector, artifactDelta, pathPrefix, options), true);
}
+ public static void diff(CompareDataCollector collector, Collection<ArtifactDelta> artifactDelta, String pathPrefix, Object... options) {
+ DiffUsingRenderer operation = new DiffUsingRenderer(collector, artifactDelta, pathPrefix, options);
+ Operations.executeWork(operation);
+ }
+
public static void diff(CompareDataCollector collector, ArtifactDelta artifactDelta, String pathPrefix, Object... options) {
DiffUsingRenderer operation = new DiffUsingRenderer(collector, artifactDelta, pathPrefix, options);
Operations.executeWork(operation);
@@ -225,9 +230,9 @@ public final class RendererManager {
Operations.executeAsJob(operation, true);
}
- public static void diff(Collection<ArtifactDelta> artifactDeltas, String diffPrefix, Object... options) {
+ public static void diff(Collection<ArtifactDelta> artifactDeltas, String pathPrefix, Object... options) {
CompareDataCollector collector = new NoOpCompareDataCollector();
- IOperation operation = new DiffUsingRenderer(collector, artifactDeltas, diffPrefix, options);
+ IOperation operation = new DiffUsingRenderer(collector, artifactDeltas, pathPrefix, options);
Operations.executeWork(operation);
}
} \ No newline at end of file

Back to the top