Office-Support: allows viewing details of items from Excel and Word documents and selecting the Excel sheet to work on

Change-Id: Ifa0c0099e1e4e3d36c98e2ce1f2db47235115ff0
Signed-off-by: Dusan Kalanj <kalanj@chalmers.se>
diff --git a/org.eclipse.capra.ui.office/plugin.properties b/org.eclipse.capra.ui.office/plugin.properties
new file mode 100644
index 0000000..d34f04c
--- /dev/null
+++ b/org.eclipse.capra.ui.office/plugin.properties
@@ -0,0 +1,12 @@
+###############################################################################
+# Copyright (c) 2016 Chalmers | University of Gothenburg, rt-labs and others.
+# 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:
+#      Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
+###############################################################################
+
+req_fieldName=REQ
\ No newline at end of file
diff --git a/org.eclipse.capra.ui.office/plugin.xml b/org.eclipse.capra.ui.office/plugin.xml
index b07b22f..bae6627 100644
--- a/org.eclipse.capra.ui.office/plugin.xml
+++ b/org.eclipse.capra.ui.office/plugin.xml
@@ -18,12 +18,12 @@
             id="org.eclipse.capra.ui.views"
 			name="Capra Views">
       </category>
-      <view
-		category="org.eclipse.capra.ui.views"
-		class="org.eclipse.capra.ui.office.views.OfficeView"
-		icon="icons/selectionView.png"
-		id="org.eclipse.capra.ui.views.OfficeView"
-		name="Office Selection View">
+	  <view
+			category="org.eclipse.capra.ui.views"
+			class="org.eclipse.capra.ui.office.views.OfficeView"
+			icon="icons/selectionView.png"
+			id="org.eclipse.capra.ui.views.OfficeView"
+			name="Office Selection View">
       </view>
    </extension>
    <extension
@@ -40,41 +40,49 @@
             id="org.eclipse.capra.ui.office.openfile"
             name="Open File">
       </command>
+      <command
+            id="org.eclipse.capra.ui.office.selectsheet"
+            name="Select Sheet">
+      </command>
+      <command
+            id="org.eclipse.capra.ui.office.setcharactercount"
+            name="Character Count">
+      </command>
    </extension>
    <extension
          point="org.eclipse.ui.handlers">
       <handler
-	          class="org.eclipse.capra.ui.office.handlers.ClearSelectionHandler"
-	          commandId="org.eclipse.capra.ui.office.clearselection">
+            class="org.eclipse.capra.ui.office.handlers.ClearSelectionHandler"
+            commandId="org.eclipse.capra.ui.office.clearselection">
       </handler>
       <handler
-	          class="org.eclipse.capra.ui.office.handlers.ShowObjectDetailsHandler"
-	          commandId="org.eclipse.capra.ui.office.showdetails">
+            class="org.eclipse.capra.ui.office.handlers.ShowObjectDetailsHandler"
+            commandId="org.eclipse.capra.ui.office.showdetails">
       </handler>
       <handler
-	          class="org.eclipse.capra.ui.office.handlers.OpenFileHandler"
-	          commandId="org.eclipse.capra.ui.office.openfile">
+            class="org.eclipse.capra.ui.office.handlers.OpenFileHandler"
+            commandId="org.eclipse.capra.ui.office.openfile">
+      </handler>
+      <handler
+            class="org.eclipse.capra.ui.office.handlers.SelectSheetHandler"
+            commandId="org.eclipse.capra.ui.office.selectsheet">
       </handler>
    </extension>
    <extension
          point="org.eclipse.ui.menus">
       <menuContribution
-            locationURI="popup:org.eclipse.capra.ui.views.OfficeView?after=additions">
+            locationURI="menu:org.eclipse.capra.ui.views.OfficeView?after=additions"> 
          <command
                commandId="org.eclipse.capra.ui.office.openfile"
                label="Open File"
                style="push"
-               tooltip="Triggers the file selection dialog.">
+               tooltip="Triggers the file selection dialog">
          </command>
-         <separator
-               name="org.eclipse.capra.generic.tracecreation.separator1"
-               visible="true">
-         </separator>
          <command
-               commandId="org.eclipse.capra.ui.office.showdetails"
-               label="Show Details"
+         	   commandId="org.eclipse.capra.ui.office.selectsheet"
+               label="Select Sheet"
                style="push"
-               tooltip="Shows the details of the selected row">
+               tooltip="Select which sheet in the Excel workbook to display">
          </command>
          <command
                commandId="org.eclipse.capra.ui.office.clearselection"
@@ -82,10 +90,33 @@
                style="push"
                tooltip="Clears the current selection of elements">
          </command>
-         <separator
-               name="org.eclipse.capra.generic.tracecreation.separator1"
-               visible="true">
-         </separator>
+         <menu
+		       label="Options">
+            <command
+                  commandId="org.eclipse.capra.ui.office.setcharactercount"
+                  label="Character Count"
+                  style="push"
+                  tooltip="Set number of characters that are shown per line">
+            </command>
+         </menu>
+      </menuContribution>
+      <menuContribution
+            locationURI="popup:net.sourceforge.plantuml.eclipse.views.PlantUmlView?after=additions">
+         <menu
+		       label="Capra"
+		       id="org.eclipse.capra.ui.contextsubmenu">
+            <command
+                  commandId="org.eclipse.capra.ui.office.showdetails"
+                  label="Show Details"
+                  style="push"
+                  tooltip="Shows the details of the selected row">
+               <visibleWhen>
+     	          <iterate ifEmpty="false">
+                     <instanceof value="org.eclipse.capra.ui.office.objects.CapraOfficeObject"/>
+                  </iterate>
+               </visibleWhen> -->
+            </command>
+         </menu>     
       </menuContribution>
    </extension>
    <extension
diff --git a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/exceptions/CapraOfficeFileNotSupportedException.java b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/exceptions/CapraOfficeFileNotSupportedException.java
new file mode 100644
index 0000000..10c7e9c
--- /dev/null
+++ b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/exceptions/CapraOfficeFileNotSupportedException.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Chalmers | University of Gothenburg, rt-labs and others.
+ * 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:
+ * 	   Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.capra.ui.office.exceptions;
+
+/**
+ * An exception that is to be thrown when a non-supported file is dragged (or
+ * selected in the file dialog) into the Office view.
+ * 
+ * @author Dusan Kalanj
+ *
+ */
+public class CapraOfficeFileNotSupportedException extends Exception {
+
+	private static final long serialVersionUID = -7730053652692861930L;
+	private static String EXCEPTION_MESSAGE = "%s file type is not supported.";
+
+	/**
+	 * A default constructor.
+	 * 
+	 * @param fileType
+	 *            the type of the non-supported file that was dragged/put into
+	 *            the Office view
+	 */
+	public CapraOfficeFileNotSupportedException(String fileType) {
+		super(String.format(EXCEPTION_MESSAGE, fileType));
+	}
+
+}
diff --git a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/exceptions/CapraOfficeObjectNotFound.java b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/exceptions/CapraOfficeObjectNotFound.java
new file mode 100644
index 0000000..40b9f32
--- /dev/null
+++ b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/exceptions/CapraOfficeObjectNotFound.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Chalmers | University of Gothenburg, rt-labs and others.
+ * 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:
+ * 	   Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.capra.ui.office.exceptions;
+
+/**
+ * An exception that is to be thrown when an office object can't be tracked back
+ * to its native environment.
+ * 
+ * @author Dusan Kalanj
+ *
+ */
+public class CapraOfficeObjectNotFound extends Exception {
+
+	private static final long serialVersionUID = -3973348630832482778L;
+	private static String EXCEPTION_MESSAGE = "Could not find the object with ID %s in its document. Maybe the file has been edited or moved.";
+
+	/**
+	 * A default constructor.
+	 * 
+	 * @param id
+	 *            the id of the object that couldn't be found
+	 */
+	public CapraOfficeObjectNotFound(String id) {
+		super(String.format(EXCEPTION_MESSAGE, id));
+	}
+
+}
diff --git a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/handlers/SelectSheetHandler.java b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/handlers/SelectSheetHandler.java
new file mode 100644
index 0000000..8c17250
--- /dev/null
+++ b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/handlers/SelectSheetHandler.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Chalmers | University of Gothenburg, rt-labs and others.
+ * 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:
+ * 	    Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.capra.ui.office.handlers;
+
+import org.eclipse.capra.ui.office.views.OfficeView;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+
+/**
+ * A handler for displaying a dialog that prompts the user to select which Excel
+ * sheet to display.
+ *
+ * @author Dusan Kalanj
+ *
+ */
+public class SelectSheetHandler extends AbstractHandler {
+
+	@Override
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		OfficeView.getOpenedView().selectSheet();
+		return null;
+	}
+}
diff --git a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/objects/CapraExcelRow.java b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/objects/CapraExcelRow.java
index fa4ea8c..eacd6fe 100644
--- a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/objects/CapraExcelRow.java
+++ b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/objects/CapraExcelRow.java
@@ -1,68 +1,215 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Chalmers | University of Gothenburg, rt-labs and others.
+ * 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:
+ * 	   Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
 package org.eclipse.capra.ui.office.objects;
 
+import java.awt.Desktop;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.poi.hssf.usermodel.HSSFCell;
+import org.apache.poi.hssf.usermodel.HSSFRow;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.hssf.util.CellReference;
 import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.DataFormatter;
 import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.eclipse.capra.ui.office.exceptions.CapraOfficeObjectNotFound;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSelection;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetView;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetViews;
 
+import com.google.common.io.Files;
+
+/**
+ * This class extends the CapraOfficeObject and provides an object to describe a
+ * single MS Excel row.
+ *
+ * @author Dusan Kalanj
+ *
+ */
 public class CapraExcelRow extends CapraOfficeObject {
 
 	/**
+	 * RegEx of characters (tabs, newlines, carriage returns and invisible
+	 * control characters) to be replaced with white-spaces in the Office View.
+	 */
+	private static final String LINE_BREAKS_AND_CONTROL_REQE = "[\r\n\t\\p{C}]+";
+
+	private static final DataFormatter FORMATTER = new DataFormatter();
+
+	/**
 	 * Delimiter between excel cells as displayed in the Office View.
 	 */
-	private static final String cellDelimiter = " | ";
+	private static final String CELL_DELIMITER = " | ";
 
 	/**
-	 * Regex of characters to be replaced with white-spaces in the Office View.
+	 * Delimiter between sheetId and rowId as used in the uri.
 	 */
-	private static final String replaceRegex = "[\r\n\t\\p{C}]+";
+	private static final String ID_DELIMITER = "-";
 
-	public CapraExcelRow() {
-		super();
-	}
+	/**
+	 * A constant that is used if the row index isn't found when opening object
+	 * details.
+	 */
+	private static final int NO_ROW_INDEX = -1;
 
-	public CapraExcelRow(String data, String uri) {
-		super(data, uri);
-	}
+	/**
+	 * A constant that is used if the last cell in the row isn't found.
+	 */
+	private static final String NO_LAST_CELL_REFERENCE = "-1";
 
 	/**
 	 * A constructor that generates a new instance of CapraExcelRow where the
 	 * parent properties are extracted from the provided Excel row and File
 	 * object that contains the row.
+	 * 
+	 * @param officeFile
+	 *            a File object representing the Office document
+	 * @param row
+	 *            an Excel row, extracted from an Excel document
+	 * 
 	 */
-	public CapraExcelRow(Row row, File officeFile, DataFormatter formatter) {
-		int rowNum = row.getRowNum();
+	public CapraExcelRow(File officeFile, Row row) {
+		super();
 
+		String rowId = FORMATTER.formatCellValue(row.getCell(0));
 		StringBuilder rowBuilder = new StringBuilder();
-		rowBuilder.append("Row " + (rowNum + 1) + ": ");
+		rowBuilder.append("ID " + rowId + ": ");
 
 		boolean firstCellSet = false;
 
-		for (int j = 0; j < row.getLastCellNum(); j++) {
+		for (int j = 1; j < row.getLastCellNum(); j++) {
 			Cell cell = row.getCell(j);
-			String cellValue = formatter.formatCellValue(cell);
+			String cellValue = FORMATTER.formatCellValue(cell);
 			if (!cellValue.isEmpty()) {
 				if (!firstCellSet) {
 					rowBuilder.append(cellValue);
 					firstCellSet = true;
 				} else {
-					rowBuilder.append(cellDelimiter + cellValue);
+					rowBuilder.append(CELL_DELIMITER + cellValue);
 				}
 			}
 		}
 
 		if (firstCellSet) {
-			Pattern p = Pattern.compile(replaceRegex);
+			Pattern p = Pattern.compile(LINE_BREAKS_AND_CONTROL_REQE);
 			Matcher m = p.matcher(rowBuilder);
 
 			String rowContent = (m.replaceAll(" ")).trim();
-			String rowUri = CapraOfficeObject.createUri(officeFile, rowNum);
+			String rowUriEnd = row.getSheet().getSheetName() + ID_DELIMITER + rowId;
+			String rowUri = CapraOfficeObject.createUri(officeFile, rowUriEnd);
 
 			this.setData(rowContent);
 			this.setUri(rowUri);
 		}
 	}
+
+	@Override
+	public void showOfficeObjectInNativeEnvironment() throws CapraOfficeObjectNotFound {
+
+		String fileType = Files.getFileExtension(getFile().getAbsolutePath());
+		String rowId = getRowId();
+		String sheetName = getSheetName();
+
+		Sheet sheet;
+
+		try (FileInputStream in = new FileInputStream(getFile())) {
+			if (fileType.equals(CapraOfficeObject.XLSX)) {
+				sheet = new XSSFWorkbook(in).getSheet(sheetName);
+			} else {
+				sheet = new HSSFWorkbook(in).getSheet(sheetName);
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+			return;
+		}
+
+		DataFormatter formatter = new DataFormatter();
+		int rowIndex = NO_ROW_INDEX;
+		String lastCellReference = NO_LAST_CELL_REFERENCE;
+		for (int i = 0; i <= sheet.getLastRowNum(); i++) {
+			Row row = sheet.getRow(i);
+			if (row != null) {
+				String currRowID = formatter.formatCellValue(row.getCell(0));
+				if (currRowID.equals(rowId)) {
+					rowIndex = i;
+					lastCellReference = CellReference.convertNumToColString(row.getLastCellNum()) + (rowIndex + 1);
+					break;
+				}
+			}
+		}
+
+		if (rowIndex == NO_ROW_INDEX || lastCellReference == NO_LAST_CELL_REFERENCE)
+			throw new CapraOfficeObjectNotFound(getRowId());
+
+		int firstDisplayedRowIndex = (rowIndex - 2 > 0) ? rowIndex - 2 : 1;
+		if (fileType.equals(CapraOfficeObject.XLSX)) {
+			XSSFSheet xssfSheet = XSSFSheet.class.cast(sheet);
+			int sheetIndex = xssfSheet.getWorkbook().getSheetIndex(xssfSheet);
+			xssfSheet.getWorkbook().setActiveSheet(sheetIndex);
+
+			CTSheetViews ctSheetViews = xssfSheet.getCTWorksheet().getSheetViews();
+			CTSheetView ctSheetView = ctSheetViews.getSheetViewArray(ctSheetViews.sizeOfSheetViewArray() - 1);
+			ctSheetView.setTopLeftCell("A" + firstDisplayedRowIndex);
+
+			CTSelection ctSelection = ctSheetView.addNewSelection();
+			ctSelection.setActiveCell("A" + (rowIndex + 1));
+			ctSelection.setSqref(Arrays.asList("A" + (rowIndex + 1) + ":" + lastCellReference));
+
+		} else {
+			HSSFSheet hssfSheet = HSSFSheet.class.cast(sheet);
+			hssfSheet.setActive(true);
+			hssfSheet.showInPane((short) (rowIndex), (short) 0);
+
+			HSSFRow row = hssfSheet.getRow(rowIndex);
+			HSSFCell cell = row.getCell(0);
+			cell.setAsActiveCell(); // TODO doesn't work - bug (but xls doesn't
+									// necessarily even have to be supported)
+		}
+
+		try (FileOutputStream out = new FileOutputStream(getFile())) {
+			sheet.getWorkbook().write(out);
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+
+		// TODO If Excel is already open, then this doesn't trigger. Is there a
+		// way to refresh the application?
+		try {
+			Desktop.getDesktop().open(getFile());
+		} catch (IOException e) {
+			e.printStackTrace();
+			return;
+		}
+	}
+
+	public String getSheetName() {
+		String itemId = getId();
+		int lastIndexOfDelimiter = itemId.lastIndexOf(ID_DELIMITER);
+		return itemId.substring(0, lastIndexOfDelimiter);
+	}
+
+	public String getRowId() {
+		String itemId = getId();
+		int lastIndexOfDelimiter = itemId.lastIndexOf(ID_DELIMITER);
+		return itemId.substring(lastIndexOfDelimiter + 1);
+	}
 }
diff --git a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/objects/CapraOfficeObject.java b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/objects/CapraOfficeObject.java
index f595765..b7d223f 100644
--- a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/objects/CapraOfficeObject.java
+++ b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/objects/CapraOfficeObject.java
@@ -11,7 +11,11 @@
 
 package org.eclipse.capra.ui.office.objects;
 
+import java.awt.Desktop;
 import java.io.File;
+import java.io.IOException;
+
+import org.eclipse.capra.ui.office.exceptions.CapraOfficeObjectNotFound;
 
 /**
  * This class provides a custom object for describing the contents of MS Excel
@@ -23,6 +27,13 @@
 public class CapraOfficeObject {
 
 	/**
+	 * The MS Office file-types that are supported by the plugin.
+	 */
+	public static final String DOCX = "docx";
+	public static final String XLS = "xls";
+	public static final String XLSX = "xlsx";
+
+	/**
 	 * The description of the object (row in Excel, requirement in Word)
 	 */
 	private String data = "";
@@ -33,10 +44,6 @@
 	private String uri = "";
 
 	/**
-	 * The delimiter separating the filePath from the objectId in uri
-	 */
-
-	/**
 	 * A constructor that generates an empty instance of OfficeObject.
 	 */
 	public CapraOfficeObject() {
@@ -52,17 +59,6 @@
 	}
 
 	/**
-	 * A constructor that generates a new instance of OfficeObject with defined
-	 * data and uri properties, the latter being constructed from the file-path
-	 * and objectId.
-	 */
-	public CapraOfficeObject(String data, File officeFile, String objectId) {
-		// TODO here data can be extracted by reading the object in its file
-		this.data = data;
-		this.uri = createUri(officeFile, objectId);
-	}
-
-	/**
 	 * Returns the uri of the OfficeObject
 	 */
 	public String getUri() {
@@ -99,11 +95,11 @@
 	}
 
 	/**
-	 * Returns the file-path of the file that contains the OfficeObject
+	 * Returns the File reference of the file that contains the OfficeObject
 	 */
-	public String getFilePath() {
+	public File getFile() {
 		int lastDelimiterIndex = uri.lastIndexOf(File.separator);
-		return uri.substring(0, lastDelimiterIndex);
+		return new File(uri.substring(0, lastDelimiterIndex));
 	}
 
 	/**
@@ -131,6 +127,23 @@
 	}
 
 	/**
+	 * Opens the OfficeObject in its native environment. If object is of class
+	 * OfficeObject (parent object), then the method does nothing but return an
+	 * error string
+	 * 
+	 * @return an OK or ERROR message
+	 * @throws CapraOfficeObjectNotFound
+	 */
+	public void showOfficeObjectInNativeEnvironment() throws CapraOfficeObjectNotFound {
+		try {
+			Desktop.getDesktop().open(getFile());
+		} catch (IOException e) {
+			e.printStackTrace();
+			throw new CapraOfficeObjectNotFound(getId());
+		}
+	}
+
+	/**
 	 * Generates a uri given the file-path of the file that contains the object
 	 * and an objectID
 	 * 
diff --git a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/objects/CapraWordRequirement.java b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/objects/CapraWordRequirement.java
index 240f066..eab10a7 100644
--- a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/objects/CapraWordRequirement.java
+++ b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/objects/CapraWordRequirement.java
@@ -1,3 +1,14 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Chalmers | University of Gothenburg, rt-labs and others.
+ * 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:
+ * 	   Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
 package org.eclipse.capra.ui.office.objects;
 
 import java.io.File;
@@ -8,51 +19,52 @@
 import javax.xml.parsers.DocumentBuilderFactory;
 
 import org.apache.poi.xwpf.usermodel.XWPFParagraph;
+import org.eclipse.capra.ui.office.utils.OfficeProperties;
 import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
 import org.w3c.dom.Document;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
+/**
+ * This class extends the CapraOfficeObject and provides an object to describe a
+ * single MS Word requirement, which is defined with a specific field.
+ *
+ * @author Dusan Kalanj
+ *
+ */
 public class CapraWordRequirement extends CapraOfficeObject {
 
 	/**
-	 * Start and end XML tags of MS Word field commands
+	 * RegEx of characters (tabs, newlines, carriage returns and invisible
+	 * control characters) to be replaced with white-spaces in the Office View.
 	 */
-	private static final String wordFieldTag = "w:instrText";
-
-	/**
-	 * Regex of characters to be replaced with white-spaces in the Office View.
-	 */
-	private static final String replaceRegex = "[\r\n\t\\p{C}]+";
+	private static final String LINE_BREAKS_AND_CONTROL_REGEX = "[\r\n\t\\p{C}]+";
 
 	/**
 	 * Regex of characters to be used as delimiters when splitting the field
 	 * contents.
 	 */
-	private static final String splitFieldRegex = "(\")|(\\\\\\*)";
+	private static final String WORD_FIELD_SPLIT_DELIMITERS = "(\")|(\\\\\\*)";
+
+	/**
+	 * Start and end XML tags of MS Word field commands
+	 */
+	private static final String REQ_FIELD_TAG = "w:instrText";
 
 	/**
 	 * The name of the requirement field as defined in Word.
 	 */
-	// TODO define in properties?
-	private static final String fieldName = "REQ";
-
-	public CapraWordRequirement() {
-		super();
-	}
-
-	public CapraWordRequirement(String data, String uri) {
-		super(data, uri);
-	}
+	private static final String REQ_FIELD_NAME = OfficeProperties.getInstance().getProperty("req_fieldName");
 
 	/**
 	 * A constructor that generates a new instance of CapraWordRequirement where
 	 * the parent properties are extracted from the provided Word paragraph and
 	 * File object that contains containing the paragraph.
 	 */
-	public CapraWordRequirement(XWPFParagraph paragraph, File officeFile, int objectID) {
+	public CapraWordRequirement(XWPFParagraph paragraph, File officeFile) {
 		// TODO This solution assumes that there is only one requirement per
 		// paragraph. Should it be different?
+		super();
 
 		String rText = "";
 		String rId = "";
@@ -66,21 +78,22 @@
 			return;
 		}
 
-		NodeList nodeList = doc.getElementsByTagName(wordFieldTag);
+		NodeList nodeList = doc.getElementsByTagName(REQ_FIELD_TAG);
 		if (nodeList.getLength() > 0) {
 			// TODO Use a for loop if the solution needs to parse multiple
 			// requirements in a single paragraph. In that case,
 			// paragraph.getText() should be replaced with something from the
 			// org.w3c.dom.Document class.
-			String[] parts = nodeList.item(0).getTextContent().split(splitFieldRegex);
-			if (Arrays.asList(parts).contains(fieldName) && parts.length > 2) {
+			String[] parts = nodeList.item(0).getTextContent().split(WORD_FIELD_SPLIT_DELIMITERS);
+			if (Arrays.asList(parts).contains(REQ_FIELD_NAME) && parts.length > 2) {
 				rText = paragraph.getText();
 				rId = parts[2].trim();
 			}
 		}
 
-		rText = rText.replaceAll(replaceRegex, " ").trim();
+		rText = rText.replaceAll(LINE_BREAKS_AND_CONTROL_REGEX, " ").trim();
 		if (!rText.isEmpty()) {
+			rText = "ID " + rId + ": " + rText;
 			String pUri = CapraOfficeObject.createUri(officeFile, rId);
 
 			this.setData(rText);
diff --git a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/utils/OfficeProperties.java b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/utils/OfficeProperties.java
new file mode 100644
index 0000000..481977e
--- /dev/null
+++ b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/utils/OfficeProperties.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Chalmers | University of Gothenburg, rt-labs and others.
+ * 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:
+ * 	   Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.capra.ui.office.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * This singleton class provides access to the plugin.properties file.
+ *
+ * @author Dusan Kalanj
+ *
+ */
+public class OfficeProperties {
+
+	private static OfficeProperties officeProperties = new OfficeProperties();
+
+	private Properties properties;
+
+	private OfficeProperties() {
+		this.properties = new Properties();
+
+		try (InputStream is = this.getClass().getClassLoader().getResourceAsStream("plugin.properties")){
+			properties.load(is);
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * Provides an instance of OfficeProperties class.
+	 * 
+	 * @return instance of OfficeProperties
+	 */
+	public static OfficeProperties getInstance() {
+		return officeProperties;
+	}
+
+	/**
+	 * Returns the property String that corresponds to the provided key.
+	 * 
+	 * @param key
+	 *            key of the property to be accessed
+	 * @return value of the property that is defined by the provided key
+	 */
+	public String getProperty(String key) {
+		return properties.getProperty(key);
+	}
+}
diff --git a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/utils/OfficeTransferType.java b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/utils/OfficeTransferType.java
index 6b174c3..e87911c 100644
--- a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/utils/OfficeTransferType.java
+++ b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/utils/OfficeTransferType.java
@@ -93,9 +93,8 @@
 
 		ArrayList<CapraOfficeObject> officeObjects = (ArrayList<CapraOfficeObject>) object;
 
-		try {
-			ByteArrayOutputStream out = new ByteArrayOutputStream();
-			DataOutputStream writeOut = new DataOutputStream(out);
+		try (ByteArrayOutputStream out = new ByteArrayOutputStream();
+				DataOutputStream writeOut = new DataOutputStream(out)) {
 
 			for (int i = 0; i < officeObjects.size(); i++) {
 				CapraOfficeObject currOfficeObject = officeObjects.get(i);
@@ -110,11 +109,10 @@
 			}
 
 			byte[] bufferOut = out.toByteArray();
-			writeOut.close();
 
 			super.javaToNative(bufferOut, transferData);
 		} catch (IOException e) {
-
+			e.printStackTrace();
 		}
 	}
 
@@ -133,9 +131,8 @@
 
 			ArrayList<CapraOfficeObject> officeObjects = new ArrayList<CapraOfficeObject>();
 
-			try {
-				ByteArrayInputStream in = new ByteArrayInputStream(buffer);
-				DataInputStream readIn = new DataInputStream(in);
+			try (ByteArrayInputStream in = new ByteArrayInputStream(buffer);
+					DataInputStream readIn = new DataInputStream(in)) {
 
 				while (readIn.available() > 0) {
 
@@ -154,9 +151,9 @@
 
 					officeObjects.add(currOfficeObject);
 				}
-				readIn.close();
 
-			} catch (IOException ex) {
+			} catch (IOException e) {
+				e.printStackTrace();
 				return null;
 			}
 
diff --git a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/OfficeView.java b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/OfficeView.java
index e526eb2..fa062d9 100644
--- a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/OfficeView.java
+++ b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/OfficeView.java
@@ -19,14 +19,15 @@
 
 import org.apache.poi.hssf.OldExcelFormatException;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.ss.usermodel.DataFormatter;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.apache.poi.xwpf.usermodel.XWPFDocument;
 import org.apache.poi.xwpf.usermodel.XWPFParagraph;
 import org.apache.xmlbeans.SchemaTypeLoaderException;
+import org.eclipse.capra.ui.office.exceptions.CapraOfficeFileNotSupportedException;
+import org.eclipse.capra.ui.office.exceptions.CapraOfficeObjectNotFound;
 import org.eclipse.capra.ui.office.objects.CapraExcelRow;
 import org.eclipse.capra.ui.office.objects.CapraOfficeObject;
 import org.eclipse.capra.ui.office.objects.CapraWordRequirement;
@@ -82,23 +83,23 @@
 	public static final String ID = "org.eclipse.capra.ui.views.OfficeView";
 
 	/**
-	 * A constant that is used for checking whether the ID of the object is
-	 * provided or not
+	 * A constant that is used to specify that the user should be prompted to
+	 * select a sheet when opening an excel document.
 	 */
-	public static final String OBJECT_ID_NOT_SPECIFIED = "-1";
+	public static final boolean SHEET_SELECT_REQUIRED = true;
 
 	/**
-	 * The MS Office file-types that are supported by the plugin.
+	 * A constant that is used to specify that the user doesn't have to be
+	 * prompted to select a sheet and the currently active sheet will be
+	 * displayed.
 	 */
-	public static final String DOCX = "docx";
-	public static final String XLS = "xls";
-	public static final String XLSX = "xlsx";
+	public static final boolean SHEET_SELECT_NOT_REQUIRED = false;
 
 	/**
-	 * This file-type is not supported, but is needed to display the correct
-	 * error message.
+	 * The caption that is shown when a message dialog appears describing an
+	 * error.
 	 */
-	public static final String DOC = "doc";
+	private static final String ERROR_TITLE = "Error";
 
 	/**
 	 * The actual view that contains the contents of the documents.
@@ -165,7 +166,13 @@
 
 		@Override
 		public boolean performDrop(Object data) {
-			dropToSelection(data);
+			try {
+				dropToSelection(data);
+			} catch (CapraOfficeFileNotSupportedException e) {
+				e.printStackTrace();
+				showMessage(viewer.getControl().getShell(), SWT.ERROR, ERROR_TITLE, e.getMessage());
+				return false;
+			}
 			return true;
 		}
 
@@ -242,111 +249,92 @@
 	 *
 	 * @param data
 	 *            the object that was dragged into the view
+	 * @throws CapraOfficeFileNotSupportedException
 	 */
-	public void dropToSelection(Object data) {
+	private void dropToSelection(Object data) throws CapraOfficeFileNotSupportedException {
 
-		File officeFile = null;
+		File file = null;
 
 		if (data instanceof String[])
-			officeFile = new File(((String[]) data)[0]);
+			file = new File(((String[]) data)[0]);
 
-		if (officeFile != null)
-			parseFile(officeFile, OBJECT_ID_NOT_SPECIFIED);
+		if (file == null)
+			return;
+
+		String fileExtension = Files.getFileExtension(file.getName());
+
+		if (fileExtension.equals(CapraOfficeObject.XLSX) || fileExtension.equals(CapraOfficeObject.XLS))
+			parseExcelDocument(file, SHEET_SELECT_NOT_REQUIRED);
+		else if (fileExtension.equals(CapraOfficeObject.DOCX))
+			parseWordDocument(file);
 		else
-			showMessage(viewer.getControl().getShell(), SWT.ERROR, "Error", "Not an Excel or Word file.");
+			throw new CapraOfficeFileNotSupportedException(fileExtension);
 
 		viewer.refresh();
 	}
 
 	/**
-	 * Calls the appropriate parse method (according to the file extension),
-	 * which displays the data in the Office view.
-	 *
-	 * @param officeFile
-	 *            the File object that points to the file that is to be parsed
-	 * @param objectID
-	 *            if provided, only the object with this ID will be displayed
-	 */
-	private void parseFile(File officeFile, String objectID) {
-
-		String fileType = Files.getFileExtension(officeFile.getAbsolutePath());
-
-		if (fileType.equals(XLSX) || fileType.equals(XLS)) {
-			getOpenedView().clearSelection();
-			parseExcelDocument(officeFile, objectID);
-
-		} else if (fileType.equals(DOCX)) {
-			getOpenedView().clearSelection();
-			parseWordDocument(officeFile, objectID);
-
-		} else if (fileType.equals(DOC)) {
-			showMessage(viewer.getControl().getShell(), SWT.ERROR, "Error",
-					".doc file format not supported, use .docx");
-
-		} else {
-			showMessage(viewer.getControl().getShell(), SWT.ERROR, "Error", "Not an Excel or Word file.");
-		}
-	}
-
-	/**
 	 * Extracts the data from the Excel document and adds it to the view.
 	 *
 	 * @param officeFile
 	 *            the File object pointing to the Excel document that was
 	 *            dragged into the view.
-	 * @param objectID
-	 *            the row ID; if "-1" (the value of constant
-	 *            OBJECT_ID_NOT_SPECIFIED), the whole document will print out,
-	 *            otherwise only the selected row
+	 * @param sheetSelect
+	 *            true if the user has to be prompted to select a sheet, false
+	 *            otherwise
 	 */
-	private void parseExcelDocument(File officeFile, String objectID) {
+	private void parseExcelDocument(File officeFile, boolean sheetSelect) {
 
 		String fileType = Files.getFileExtension(officeFile.getAbsolutePath());
-		Sheet sheet;
+		Workbook workBook;
 
 		try {
-			if (fileType.equals(XLSX)) {
-				sheet = new XSSFWorkbook(OPCPackage.open(officeFile)).getSheetAt(0);
-			} else {
-				sheet = new HSSFWorkbook(new FileInputStream(officeFile)).getSheetAt(0);
-			}
+			if (fileType.equals(CapraOfficeObject.XLSX))
+				workBook = new XSSFWorkbook(new FileInputStream(officeFile));
+			else
+				workBook = new HSSFWorkbook(new FileInputStream(officeFile));
 		} catch (OldExcelFormatException e) {
-			showMessage(viewer.getControl().getShell(), SWT.ERROR, "Error", "This version of Excel is not supported.");
+			showMessage(viewer.getControl().getShell(), SWT.ERROR, ERROR_TITLE, e.getMessage());
 			return;
-		} catch (Exception e) {
+		} catch (IOException e) {
 			e.printStackTrace();
-			showMessage(viewer.getControl().getShell(), SWT.ERROR, "Error", "Couldn't open the file.");
 			return;
 		}
 
-		DataFormatter formatter = new DataFormatter();
+		String selectedSheetName;
+		if (!sheetSelect)
+			selectedSheetName = workBook.getSheetName(workBook.getActiveSheetIndex());
+		else if (selection.size() > 0) {
+			String activeSheetName = ((CapraExcelRow) selection.get(0)).getSheetName();
+			String[] sNames = new String[workBook.getNumberOfSheets()];
+
+			// Fill sNames with sheetNames, with the active sheet at index 0
+			int counter = 0;
+			sNames[counter++] = activeSheetName;
+			for (int i = 0; i < sNames.length; i++) {
+				String sName = workBook.getSheetName(i);
+				if (sName.equals(activeSheetName))
+					continue;
+				sNames[counter++] = workBook.getSheetName(i);
+			}
+
+			selectedSheetName = new SelectSheetDialog(viewer.getControl().getShell(),
+					SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL, sNames).open();
+		} else {
+			return;
+		}
+
+		Sheet sheet = workBook.getSheet(selectedSheetName);
 
 		getOpenedView().clearSelection();
 
-		// TODO Currently, the first block of code is only accessed
-		// if the method is triggered via OfficeHandler. Does this have to
-		// change if the handler is not allowed to have a dependency on UI?
-		// Also, the solution assumes that the location of the row is also the
-		// rowId, should that be different? Should the ID be defined, for
-		// example, in the first cell?
-		if (!objectID.equals(OBJECT_ID_NOT_SPECIFIED)) {
-			Row row = sheet.getRow(Integer.parseInt(objectID));
+		for (int i = 0; i <= sheet.getLastRowNum(); i++) {
+			Row row = sheet.getRow(i);
 			if (row != null) {
-				CapraExcelRow cRow = new CapraExcelRow(row, officeFile, formatter);
-
+				CapraExcelRow cRow = new CapraExcelRow(officeFile, row);
 				if (!cRow.getData().isEmpty())
 					selection.add(cRow);
 			}
-		} else {
-			for (int i = 0; i <= sheet.getLastRowNum(); i++) {
-				Row row = sheet.getRow(i);
-				if (row != null) {
-					CapraExcelRow cRow = new CapraExcelRow(row, officeFile, formatter);
-
-					if (!cRow.getData().isEmpty())
-						selection.add(cRow);
-				}
-			}
 		}
 	}
 
@@ -356,79 +344,40 @@
 	 * @param officeFile
 	 *            the File object pointing of the Word document that was dragged
 	 *            into the view.
-	 * @param objectID
-	 *            the paragraph/requirement ID; if "-1" (the value of constant
-	 *            OBJECT_ID_NOT_SPECIFIED), the whole document will print out,
-	 *            otherwise only the selected object
 	 */
-	private void parseWordDocument(File officeFile, String objectID) {
+	private void parseWordDocument(File officeFile) {
 		List<XWPFParagraph> paragraphs;
 
 		try {
 			FileInputStream fs = new FileInputStream(officeFile);
-			// TODO The following line always triggers an exception!
 			XWPFDocument xwpfDoc = new XWPFDocument(fs);
+			fs.close();
 			paragraphs = (xwpfDoc).getParagraphs();
-			// If poi 3.15 is used, it allows closing the XWPFDocument. If 3.9
-			// is used it is not possible.
-			// xwpfDoc.close();
 		} catch (IOException e) {
 			e.printStackTrace();
-			showMessage(viewer.getControl().getShell(), SWT.ERROR, "Error", "Couldn't open the file.");
+			showMessage(viewer.getControl().getShell(), SWT.ERROR, ERROR_TITLE, e.getMessage());
 			return;
 		} catch (SchemaTypeLoaderException e) {
-			// TODO This is the exception for the error!
 			e.printStackTrace();
-			showMessage(viewer.getControl().getShell(), SWT.ERROR, "Error", "Couldn't open the file.");
+			showMessage(viewer.getControl().getShell(), SWT.ERROR, ERROR_TITLE, e.getMessage());
 			return;
 		}
 
+		getOpenedView().clearSelection();
+
 		for (int i = 0; i < paragraphs.size(); i++) {
 			XWPFParagraph paragraph = paragraphs.get(i);
 			if (paragraph != null) {
-				CapraWordRequirement cRequirement = new CapraWordRequirement(paragraph, officeFile, i);
-
-				// TODO Currently, this condition is only true if the method
-				// is triggered via OfficeHandler. Does this have to change
-				// if the handler is not allowed to have a dependency on UI?
-				if (!objectID.equals(OBJECT_ID_NOT_SPECIFIED)) {
-					if (cRequirement.getId().equals(objectID)) {
-						selection.add(cRequirement);
-						break;
-					}
-				} else if (!cRequirement.getData().isEmpty())
+				CapraWordRequirement cRequirement = new CapraWordRequirement(paragraph, officeFile);
+				if (!cRequirement.getData().isEmpty())
 					selection.add(cRequirement);
 			}
 		}
 	}
 
 	/**
-	 * Shows only the selected OfficeObject in the Office Selection View.
-	 *
-	 * @param uri
-	 *            the uri of the row/word_requirement, containing the file path
-	 *            and the index of the row/word_requirement
-	 */
-	public void showSingleOfficeObjectInOfficeView(String uri) {
-
-		if (uri.isEmpty())
-			return;
-
-		File officeFile = new File(CapraOfficeObject.getFilePathFromUri(uri));
-		String objectID = CapraOfficeObject.getIdFromUri(uri);
-
-		// Check if the file (still) exists.
-		if (officeFile.exists())
-			parseFile(officeFile, objectID);
-		else
-			showMessage(viewer.getControl().getShell(), SWT.ERROR, "Error", "Resource not found.");
-
-		viewer.refresh();
-	}
-
-	/**
-	 * Shows the dialog with the information about the selected element in the
-	 * view.
+	 * Shows the details of the object in its native environment (MS Word or MS
+	 * Excel).
 	 * 
 	 * @param event
 	 *            Should be of type DoubleClickEvent or ExecutionEvent, hold the
@@ -437,7 +386,6 @@
 	 *            Shell which will be the parent of the dialog window.
 	 */
 	public void showObjectDetails(Object event, Shell parentShell) {
-
 		CapraOfficeObject officeObject;
 
 		if (event instanceof DoubleClickEvent) { // If called with double click
@@ -452,24 +400,19 @@
 				officeObject = (CapraOfficeObject) selection.getFirstElement();
 			} catch (ExecutionException e) {
 				e.printStackTrace();
-				officeObject = null;
+				return;
 			}
 		} else {
-			officeObject = null;
+			return;
 		}
 
-		String caption;
-		String message;
-
-		if (officeObject == null) {
-			caption = "Notification";
-			message = "No information to show.";
-		} else {
-			caption = "Row " + officeObject.getId();
-			message = officeObject.getData();
+		try {
+			officeObject.showOfficeObjectInNativeEnvironment();
+		} catch (CapraOfficeObjectNotFound e) {
+			e.printStackTrace();
+			showMessage(viewer.getControl().getShell(), SWT.ERROR, ERROR_TITLE, e.getMessage());
 		}
 
-		showMessage(parentShell, SWT.OK, caption, message);
 	}
 
 	/**
@@ -481,16 +424,55 @@
 	}
 
 	/**
-	 * Opens a file-chooser dialog and calls the parseFile method, which
+	 * Opens a file-chooser dialog and calls the parseOfficeFile method, which
 	 * displays the contents of the selected file in the TableViewer (if the
 	 * file is of type xlsx, xls or docx).
 	 */
 	public void openFile() {
 
 		FileDialog fd = new FileDialog(viewer.getControl().getShell(), SWT.OK);
-		File officeFile = new File(fd.open());
+		String filePath = fd.open();
 
-		parseFile(officeFile, OBJECT_ID_NOT_SPECIFIED);
+		if (filePath != null && !filePath.isEmpty()) {
+			File file = new File(filePath);
+			if (file != null) {
+				try {
+					dropToSelection(new String[] { file.getAbsolutePath() });
+				} catch (CapraOfficeFileNotSupportedException e) {
+					e.printStackTrace();
+					showMessage(viewer.getControl().getShell(), SWT.ERROR, ERROR_TITLE, e.getMessage());
+				}
+				viewer.refresh();
+			}
+		}
+	}
+
+	/**
+	 * Opens a pop-up window that allows the user to select which excel sheet
+	 * should be displayed.
+	 */
+	public void selectSheet() {
+
+		if (selection.isEmpty()) {
+			// TODO custom exception
+			return;
+		}
+
+		if (selection.get(0).getClass().equals(CapraWordRequirement.class)) {
+			// TODO custom exception - although this check won't be necessary
+			// since the select sheet option will be hidden (not yet
+			// implemented) when the selection is empty or when Word file is
+			// displayed. Therefore also the first check won't necessary.
+			return;
+		}
+
+		File currentFile = ((CapraExcelRow) selection.get(0)).getFile();
+
+		if (!Files.getFileExtension(currentFile.getAbsolutePath()).equals(CapraOfficeObject.XLSX)
+				&& !Files.getFileExtension(currentFile.getAbsolutePath()).equals(CapraOfficeObject.XLS))
+			return;
+
+		parseExcelDocument(currentFile, SHEET_SELECT_REQUIRED);
 
 		viewer.refresh();
 	}
diff --git a/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/SelectSheetDialog.java b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/SelectSheetDialog.java
new file mode 100644
index 0000000..902fd37
--- /dev/null
+++ b/org.eclipse.capra.ui.office/src/org/eclipse/capra/ui/office/views/SelectSheetDialog.java
@@ -0,0 +1,180 @@
+package org.eclipse.capra.ui.office.views;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Dialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+
+/**
+ * A class that extends Dialog in order to prompt the user for which excel sheet
+ * to display.
+ * 
+ * Code adapted from:
+ * http://www.java2s.com/Code/Java/SWT-JFace-Eclipse/Howtocreateyourowndialogclasses.htm
+ * 
+ * @author Dusan Kalanj
+ *
+ */
+public class SelectSheetDialog extends Dialog {
+
+	/**
+	 * Strings that are displayed in the Dialog.
+	 */
+	private static final String PROMPT_MESSAGE = "Please select the sheet to display.";
+	private static final String SELECT_TIP = "Click here to select the sheet.";
+	private static final String OK = "OK";
+	private static final String CANCEL = "Cancel";
+
+	/**
+	 * Top margin between elements in the dialog.
+	 */
+	private static final int VERTICAL_INDENT = 10;
+
+	private String[] sheetNames;
+	private String selectedSheetName;
+
+	/**
+	 * SelectSheetDialog constructor.
+	 * 
+	 * @param parentShell
+	 *            the shell that will accommodate the dialog.
+	 * @param style
+	 *            the style used by the dialog
+	 * @param currentSheet
+	 *            the currently displayed sheet
+	 * @param totalNumOfSheets
+	 *            the sheet that was selected in the dialog.
+	 */
+	public SelectSheetDialog(Shell parentShell, int style, String[] sheetNames) {
+		super(parentShell, style);
+		this.sheetNames = sheetNames;
+		this.selectedSheetName = sheetNames[0];
+	}
+
+	/**
+	 * Opens the dialog and returns the index of the selected sheet.
+	 * 
+	 * @return the number of the sheet to display
+	 */
+	public String open() {
+		Shell shell = new Shell(getParent(), getStyle());
+		createContents(shell);
+
+		Rectangle shellBounds = getParent().getBounds();
+
+		shell.setLocation(shellBounds.x + shellBounds.width / 2, shellBounds.y + shellBounds.height / 2);
+		shell.pack();
+		shell.open();
+
+		Display display = getParent().getDisplay();
+		while (!shell.isDisposed()) {
+			if (!display.readAndDispatch()) {
+				display.sleep();
+			}
+		}
+
+		return selectedSheetName;
+	}
+
+	/**
+	 * Fills the dialog window with content.
+	 * 
+	 * @param shell
+	 *            the window of the dialog
+	 */
+	private void createContents(final Shell shell) {
+
+		GridLayout gridLayout = new GridLayout(2, true);
+		shell.setLayout(gridLayout);
+
+		Label label = new Label(shell, SWT.NONE);
+		label.setText(PROMPT_MESSAGE);
+		GridData data = new GridData(GridData.FILL_HORIZONTAL);
+		data.horizontalSpan = 2;
+		label.setLayoutData(data);
+
+		final ToolBar toolBar = new ToolBar(shell, SWT.NONE);
+		data = new GridData(SWT.CENTER, SWT.CENTER, true, true, 1, 1);
+		data.verticalIndent = VERTICAL_INDENT;
+		data.horizontalSpan = 2;
+		toolBar.setLayoutData(data);
+		final ToolItem itemDropDown = new ToolItem(toolBar, SWT.DROP_DOWN);
+		final Menu menu = new Menu(shell, SWT.POP_UP);
+
+		itemDropDown.setText(sheetNames[0]);
+		itemDropDown.setToolTipText(SELECT_TIP);
+
+		for (int i = 0; i < sheetNames.length; i++) {
+			MenuItem item = new MenuItem(menu, SWT.PUSH);
+			item.setText(sheetNames[i]);
+			item.addSelectionListener(new SelectionListener() {
+
+				@Override
+				public void widgetSelected(SelectionEvent e) {
+					selectedSheetName = item.getText();
+					itemDropDown.setText(selectedSheetName);
+
+					toolBar.pack();
+				}
+
+				@Override
+				public void widgetDefaultSelected(SelectionEvent e) {
+					selectedSheetName = item.getText();
+					itemDropDown.setText(selectedSheetName);
+					toolBar.pack();
+				}
+			});
+		}
+
+		itemDropDown.addListener(SWT.Selection, new Listener() {
+			public void handleEvent(Event event) {
+				Rectangle bounds = itemDropDown.getBounds();
+				Point point = toolBar.toDisplay(bounds.x, bounds.y + bounds.height);
+				menu.setLocation(point);
+				menu.setVisible(true);
+			}
+		});
+
+		Button ok = new Button(shell, SWT.PUSH);
+		ok.setText(OK);
+		data = new GridData(GridData.FILL_HORIZONTAL);
+		data.verticalIndent = VERTICAL_INDENT;
+		data.horizontalSpan = 1;
+		ok.setLayoutData(data);
+		ok.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				shell.close();
+			}
+		});
+
+		Button cancel = new Button(shell, SWT.PUSH);
+		cancel.setText(CANCEL);
+		data = new GridData(GridData.FILL_HORIZONTAL);
+		data.verticalIndent = VERTICAL_INDENT;
+		data.horizontalSpan = 1;
+		cancel.setLayoutData(data);
+		cancel.addSelectionListener(new SelectionAdapter() {
+			public void widgetSelected(SelectionEvent event) {
+				selectedSheetName = sheetNames[0];
+				shell.close();
+			}
+		});
+
+		shell.setDefaultButton(ok);
+	}
+}
diff --git a/org.eclipse.capra.ui/plugin.xml b/org.eclipse.capra.ui/plugin.xml
index 936fec3..97f24c7 100644
--- a/org.eclipse.capra.ui/plugin.xml
+++ b/org.eclipse.capra.ui/plugin.xml
@@ -91,7 +91,8 @@
                name="org.eclipse.capra.generic.separator2">
          </separator>
          <menu
-               label="Capra">
+               label="Capra"
+               id="org.eclipse.capra.ui.contextsubmenu">
             <command
                   commandId="org.eclipse.capra.generic.addtoselection"
                   label="Add to Selection"
diff --git a/org.eclipse.capra.ui/src/org/eclipse/capra/ui/views/SelectionView.java b/org.eclipse.capra.ui/src/org/eclipse/capra/ui/views/SelectionView.java
index b9a3e42..bcabd56 100644
--- a/org.eclipse.capra.ui/src/org/eclipse/capra/ui/views/SelectionView.java
+++ b/org.eclipse.capra.ui/src/org/eclipse/capra/ui/views/SelectionView.java
@@ -135,9 +135,9 @@
 	class SelectionDropAdapter extends ViewerDropAdapter {
 		TableViewer view;
 
-		public SelectionDropAdapter(TableViewer viewer) {
+		public SelectionDropAdapter(TableViewer view) {
 			super(viewer);
-			this.view = viewer;
+			this.view = view;
 		}
 
 		@Override