Commits

Anonymous committed 6d6168a Merge
  • Participants
  • Parent commits 24d790a, 2cc8d32

Comments (0)

Files changed (11)

+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>

.hgignore

File contents unchanged.

pom.xml

File contents unchanged.

src/main/java/org/nrg/dcm/DicomSessionVariable.java

 import java.util.Collections;
 import java.util.Set;
 
+import javax.swing.JOptionPane;
+
 import org.dcm4che2.data.DicomObject;
 import org.nrg.dcm.edit.MultipleInitializationException;
 import org.nrg.dcm.edit.ScriptEvaluationException;
 				try {
 					return iv.on(sample);
 				} catch (ScriptEvaluationException e) {
+					final StringBuilder errorMessage = new StringBuilder();
+					errorMessage.append("An serious error was encountered while preparing the DICOM.\n");
+					errorMessage.append("Please contact your site administrator with the following error\n");
+					errorMessage.append("message before uploading this data, as it could contain incorrect data.\n\n");
+					errorMessage.append(e.getMessage());
+					
+					//non-ideal, but somewhat protects against HTTP issues in GetURL
+					JOptionPane.showMessageDialog(null, errorMessage.toString(), "DICOM Script Error", JOptionPane.ERROR_MESSAGE);
+					
 					return null;
 				}
 			}

src/main/java/org/nrg/dcm/Series.java

 	private final Set<String> modalities = new TreeSet<String>();
 	private final Set<File> files = new LinkedHashSet<File>();
 	private DicomObject sampleObject = null;
+	private boolean uploadAllowed = true;
 	
 	Series(final Study study,
 			final String uid, final int number, final String modality) {
 	public boolean equals(final Object o) {
 		return o instanceof Series && getAttributes().equals(((Entity)o).getAttributes());
 	}
+
+	public void setUploadAllowed(final boolean uploadAllowed) {
+		this.uploadAllowed = uploadAllowed;
+	}
+
+	public boolean isUploadAllowed() {
+		return uploadAllowed;
+	}
 }

src/main/java/org/nrg/dcm/Study.java

 
 		final Collection<File> files = new ArrayList<File>();
 		for (final Series s : series) {
-			for (final File f : s) {
-				files.add(f);
+			if (s.isUploadAllowed()) {
+				for (final File f : s) {
+					files.add(f);
+				}
 			}
 		}
 

src/main/java/org/nrg/net/RestServer.java

 import org.json.JSONTokener;
 import org.netbeans.spi.wizard.ResultProgressHandle;
 import org.nrg.IOUtils;
-import org.nrg.util.Utils;
+import org.nrg.util.Base64;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 		unenc.append(auth.getPassword());
 
 		final StringBuilder enc = new StringBuilder("Basic ");
-		enc.append(Utils.base64encode(unenc.toString()));
+		enc.append(Base64.encode(unenc.toString()));
 		m.put(AUTHORIZATION_HEADER, enc.toString());
 	}
 

src/main/java/org/nrg/upload/ui/AssignSessionVariablesPage.java

 public final class AssignSessionVariablesPage extends WizardPage implements SessionVariableConsumer {
 	private static final long serialVersionUID = 1L;
 	
-	private static final String STEP_DESCRIPTION = "Assign session variables";
-	private static final String LONG_DESCRIPTION = "Review session information and assign session identifiers";
+	private static final String STEP_DESCRIPTION = "Enter session details";
+	private static final String LONG_DESCRIPTION = "Review session information and enter session details";
 	public static final String PRODUCT_NAME = "*session-variables*";
 	
 	private final Logger logger = LoggerFactory.getLogger(AssignSessionVariablesPage.class);

src/main/java/org/nrg/upload/ui/SelectSessionPage.java

 	private static final long serialVersionUID = 1L;
 	
 	public static final String PRODUCT_NAME = "*session*";
-	private static final String STEP_DESCRIPTION = "Select session";
+	private static final String STEP_DESCRIPTION = "Review session";
 	private static final String LONG_DESCRIPTION = "Review session information";
 	
 	public static String getDescription() {

src/main/java/org/nrg/upload/ui/SessionReviewPanel.java

  */
 package org.nrg.upload.ui;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Set;
 
+import javax.swing.BorderFactory;
 import javax.swing.BoxLayout;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import javax.swing.table.DefaultTableModel;
 
+import org.dcm4che2.data.Tag;
 import org.nrg.dcm.DicomUtils;
+import org.nrg.dcm.Series;
+import org.nrg.dcm.Study;
 import org.nrg.upload.data.Session;
 import org.nrg.util.Utils;
 
 	public SessionReviewPanel(final Session session) {
 		setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
 		this.session = session;
-		add(new JLabel(session.getFormat() + " session " + session.getID()));
-		add(new JLabel("Accession: " + session.getAccession()));
-		add(new JLabel("Date/time: " + session.getDateTime()));
-		add(new JLabel("Description: " + session.getDescription()));
-		add(buildModalitiesLabel(session));
-		add(new JLabel(describeScans(session)));
+
+		// for now, only allow selection of series from DICOM
+		if (session instanceof Study) {
+			add(createScanDetails(session));
+		}
+
+		add(createSessionSummary(session));
+
 		validate();
 		setVisible(true);
 	}
+
+	private static JPanel createScanDetails(final Session session) {
+		final JPanel panel = new JPanel();
+		panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
 		
+		panel.add(new JLabel("<html><b>Scan Details</b></html>"));
+		panel.add(buildScansTable((Study) session));
+		panel.add(new JLabel("Note: Unchecked scans will not be uploaded."));
+		
+		panel.setBorder(BorderFactory.createEmptyBorder(0,0,15,0));
+		
+		return panel;
+	}
+
+	private static JPanel createSessionSummary(final Session session) {
+		final JPanel panel = new JPanel();
+		panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
+		
+		panel.add(new JLabel("<html><b>Session Summary</b></html>"));
+		panel.add(new JLabel(session.getFormat() + " session " + session.getID()));
+		panel.add(new JLabel("Accession: " + session.getAccession()));
+		panel.add(new JLabel("Date/time: " + session.getDateTime()));
+		panel.add(new JLabel("Description: " + session.getDescription()));
+		panel.add(buildModalitiesLabel(session));
+		panel.add(new JLabel(describeScans(session)));
+		
+		return panel;
+	}
+	
 	private static JLabel buildModalitiesLabel(final Session session) {
 		final Set<String> modalities = session.getModalities();
 		if (1 == modalities.size()) {
 			return new JLabel(DicomUtils.join(new StringBuilder("Modalities: "), modalities, ",").toString());
 		}
 	}
+
+	private static JScrollPane buildScansTable(final Study study){
+		final ScansTableModel tableModel = new ScansTableModel(study);
+		final JTable table = new JTable(tableModel);
+		final JScrollPane scrollPane = new JScrollPane(table);
+		// not available in Java 1.5
+		//table.setFillsViewportHeight(true);
+		table.getTableHeader().setReorderingAllowed(false);
+		return scrollPane;
+	}
 	
 	public Session getSession() { return session; }
 
 		sb.append(")");
 		return sb.toString();
 	}
+
+	static class ScansTableModel extends DefaultTableModel {
+		private static final long serialVersionUID = 3558061608731992249L;
+		private static final int SELECT_COLUMN = 0;
+		private static final String[] COLUMNS = new String[] { "Upload", "Scan Type", "File Count" , "Size (bytes)"};
+		private static final Class<?>[] COLUMN_TYPES = new Class[] {Boolean.class, String.class, Integer.class, Long.class};
+		
+		public ScansTableModel(final Study study) {
+			super(COLUMNS, 0);
+			
+			// use a list so the TableModelListener has random-access ability on the series 
+			final List<Series> seriesList = new ArrayList<Series>();
+			
+			for (final Series series : study.getSeries()) {
+				seriesList.add(series);
+				final String description = series.getSampleObject().getString(Tag.SeriesDescription);
+				addRow(new Object[] { Boolean.valueOf(series.isUploadAllowed()), description, series.getFileCount(),
+						Utils.showNearestUnits(new StringBuilder(), series.getSize(), "b").toString() });
+			}
+			
+			addTableModelListener(new TableModelListener() {
+				public void tableChanged(TableModelEvent e) {
+					final int row = e.getFirstRow();
+					seriesList.get(row).setUploadAllowed((Boolean) getValueAt(row, SELECT_COLUMN));
+				}
+			});
+		}
+
+		@Override
+		public Class<?> getColumnClass(final int col) {
+	        return COLUMN_TYPES[col];
+		}
+
+		@Override
+		public boolean isCellEditable(final int row, final int col) {
+			// user can only click the usable checkbox in the first column
+			return col == SELECT_COLUMN;
+		}
+	}
+
 }

src/main/java/org/nrg/util/Utils.java

 		return slurp(new StringBuilder(), in).toString();
 	}
 
-
-	/**
-	 * Base64 encoding adapted from http://www.wikihow.com/Encode-a-String-to-Base64-With-Java
-	 * Article authors John Comeau, et al.
-	 */
-	private static final String base64code =
-		"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-	private static final int splitLinesAt = 76;
-
-	public static byte[] zeroPad(final int length, final byte[] bytes) {
-		final byte[] padded = new byte[length];
-		System.arraycopy(bytes, 0, padded, 0, bytes.length);
-		return padded;
-	}
-
-	public static String base64encode(final String string) {
-		final StringBuilder encoded = new StringBuilder();
-		byte[] stringArray;
-		try {
-			stringArray = string.getBytes("UTF-8");  // use appropriate encoding string
-		} catch (Exception ignored) {
-			stringArray = string.getBytes();  // use locale default rather than croak
-		}
-
-		// determine how many padding bytes to add to the output
-		int paddingCount = (3 - (stringArray.length % 3)) % 3;
-
-		// add any necessary padding to the input
-		stringArray = zeroPad(stringArray.length + paddingCount, stringArray);
-
-		// process 3 bytes at a time, churning out 4 output bytes
-		// worry about CRLF insertions later
-		for (int i = 0; i < stringArray.length; i += 3) {
-			final int j = (stringArray[i] << 16) + (stringArray[i + 1] << 8) +  stringArray[i + 2];
-			encoded.append(base64code.charAt((j >> 18) & 0x3f));
-			encoded.append(base64code.charAt((j >> 12) & 0x3f));
-			encoded.append(base64code.charAt((j >> 6) & 0x3f));
-			encoded.append(base64code.charAt(j & 0x3f));
-		}
-
-		// replace encoded padding nulls with "="
-		return splitLines(encoded.substring(0, encoded.length() - paddingCount) + "==".substring(0, paddingCount));
-	}
-
-
-	public static String splitLines(final String string) {
-		final StringBuilder lines = new StringBuilder();
-		lines.append(string.substring(0, Math.min(string.length(), splitLinesAt)));
-		for (int i = splitLinesAt; i < string.length(); i += splitLinesAt) {
-			lines.append("\r\n");
-			lines.append(string.substring(i, Math.min(string.length(), i + splitLinesAt)));
-		}
-		return lines.toString();
-	}
-
-
 	/**
 	 * Object equality comparison that is safe if o1 or o2 == null.
 	 * @param o1 object to be compared to o2