1. Kevin Archie
  2. UploadAssistant

Commits

Rick Herrick  committed bb698a2

XNAT-1591: Added warning when session label replicates a label that already exists in the project. Some other minor clean-up and fix of issue where Swing auth dialog didn't work.

  • Participants
  • Parent commits d1a8ae8
  • Branches default

Comments (0)

Files changed (8)

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

View file
  • Ignore whitespace
  */
 package org.nrg.dcm;
 
-import static org.nrg.upload.ui.UploadAssistantApplet.FIXED_SIZE_STREAMING_WIZ_PARAM;
-import static org.nrg.upload.ui.UploadAssistantApplet.N_UPLOAD_THREADS_WIZ_PARAM;
-import static org.nrg.upload.ui.UploadAssistantApplet.XNAT_ADMIN_EMAIL_WIZ_PARAM;
-import static org.nrg.upload.ui.UploadAssistantApplet.XNAT_REST_API_WIZ_PARAM;
-import static org.nrg.upload.ui.UploadAssistantApplet.XNAT_URL_WIZ_PARAM;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.text.ChoiceFormat;
-import java.text.MessageFormat;
-import java.text.SimpleDateFormat;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TimeZone;
-import java.util.TreeMap;
-import java.util.concurrent.CompletionService;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorCompletionService;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-import org.apache.log4j.Level;
+import com.google.common.base.Objects;
+import com.google.common.base.Predicate;
+import com.google.common.base.Strings;
+import com.google.common.collect.*;
 import org.dcm4che2.data.DicomObject;
 import org.dcm4che2.data.Tag;
 import org.json.JSONException;
 import org.nrg.dcm.edit.ScriptApplicator;
 import org.nrg.dcm.edit.Variable;
 import org.nrg.framework.constants.AutoArchive;
-import org.nrg.framework.logging.Analytics;
 import org.nrg.io.HttpUploadException;
 import org.nrg.io.UploadStatisticsReporter;
 import org.nrg.io.dcm.ZipSeriesUploader;
 import org.nrg.net.JSESSIONIDCookie;
 import org.nrg.net.JSONRequestConnectionProcessor;
 import org.nrg.net.RestServer;
-import org.nrg.upload.data.AssignedSessionVariable;
-import org.nrg.upload.data.Project;
-import org.nrg.upload.data.Session;
-import org.nrg.upload.data.SessionVariable;
-import org.nrg.upload.data.SessionVariableNames;
-import org.nrg.upload.data.Subject;
-import org.nrg.upload.data.UploadAbortedException;
-import org.nrg.upload.data.UploadFailureHandler;
+import org.nrg.upload.data.*;
 import org.nrg.upload.ui.AssignSessionVariablesPage;
 import org.nrg.upload.ui.SelectProjectPage;
 import org.nrg.upload.ui.SelectSubjectPage;
-import org.nrg.upload.ui.UploadAssistantApplet;
 import org.nrg.upload.ui.UploadResultPanel;
 import org.nrg.util.MapRegistry;
 import org.nrg.util.Registry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Objects;
-import com.google.common.base.Predicate;
-import com.google.common.base.Strings;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.Sets;
+import java.io.File;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.text.ChoiceFormat;
+import java.text.MessageFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.*;
 
-// import org.nrg.framework.logging.Analytics;
+import static org.nrg.upload.ui.UploadAssistantApplet.*;
 
 /**
  * @author Kevin A. Archie <karchie@wustl.edu>
                 applicators = project.getDicomScriptApplicators();
             } catch (RuntimeException exception) {
                 logger.error("problem retrieving script applicator", exception);
-                Analytics.enter(UploadAssistantApplet.class, "Error retrieving script applicator", exception);
+                // Analytics.enter(UploadAssistantApplet.class, "Error retrieving script applicator", exception);
                 throw exception;    // TODO: better handling;
             } catch (Exception exception) {
                 logger.error("problem retrieving script applicator", exception);
-                Analytics.enter(UploadAssistantApplet.class, "Error retrieving script applicator", exception);
+                // Analytics.enter(UploadAssistantApplet.class, "Error retrieving script applicator", exception);
                 throw new RuntimeException(exception);  // TODO: better handling
             }
 
             final int nThreads = (Integer) params.get(N_UPLOAD_THREADS_WIZ_PARAM);
             final JSESSIONIDCookie jsessionidCookie = ((RestServer) params.get(XNAT_REST_API_WIZ_PARAM)).getJSESSIONIDCookie();
 
-            enterUploadAnalytics(project, subject, session, fileCount, dataPostURL, useFixedSize, nThreads);
+            // enterUploadAnalytics(project, subject, session, fileCount, dataPostURL, useFixedSize, nThreads);
 
             progress.setBusy("Preparing upload...");
             logger.trace("creating thread pool and executors");
             final Set<String> uris = Sets.newLinkedHashSet();
             final Map<Series, Throwable> failures = Maps.newLinkedHashMap();
             while (progress.isRunning() && !uploaders.isEmpty()) {
-                Analytics.enter(UploadAssistantApplet.class, "Upload operation commenced");
+                // Analytics.enter(UploadAssistantApplet.class, "Upload operation commenced");
                 final Future<Set<String>> future;
                 try {
                     future = completionService.take();
                     logger.trace("retrieved completed future {}", future);
                 } catch (InterruptedException e) {
                     logger.debug("upload completion poll interrupted", e);
-                    Analytics.enter(UploadAssistantApplet.class, Level.DEBUG, "upload completion poll interrupted");
+                    // Analytics.enter(UploadAssistantApplet.class, Level.DEBUG, "upload completion poll interrupted");
                     continue;
                 }
                 try {
                         aborted = new UploadAbortedException(cause);
                     }
                     logger.info("upload aborted: shutting down executor", cause);
-                    Analytics.enter(UploadAssistantApplet.class, Level.WARN, "upload aborted: shutting down executor", cause);
+                    // Analytics.enter(UploadAssistantApplet.class, Level.WARN, "upload aborted: shutting down executor", cause);
 
                     for (final Map.Entry<Future<Set<String>>, ZipSeriesUploader> me : uploaders.entrySet()) {
                         me.getKey().cancel(true);
                     }
                     String message = buildFailureMessage(failures);
                     progress.failed(message, false);
-                    Analytics.enter(UploadAssistantApplet.class, Level.WARN, message, exception);
+                    // Analytics.enter(UploadAssistantApplet.class, Level.WARN, message, exception);
                     return false;
                 }
             }
 
             if (!uploaders.isEmpty()) {
                 logger.error("progress failed before uploaders complete: {}", uploaders);
-                Analytics.enter(UploadAssistantApplet.class, Level.ERROR, String.format("Progress failed before uploaders complete: %s", uploaders));
+                // Analytics.enter(UploadAssistantApplet.class, Level.ERROR, String.format("Progress failed before uploaders complete: %s", uploaders));
                 return false;
             } else if (1 == uris.size()) {
                 final String uri = uris.iterator().next();
                     sb.append("<p>").append(uri).append("</p>");
                     sb.append("<p>Please contact the system manager (").append(adminEmail).append(") for help.</p>");
                     progress.failed(sb.toString(), false);
-                    Analytics.enter(UploadAssistantApplet.class, Level.ERROR, sb.toString());
+                    // Analytics.enter(UploadAssistantApplet.class, Level.ERROR, sb.toString());
                     return false;
                 }
             } else {
                 sb.append(uris.size()).append(")</p>");
                 sb.append("<p>Please contact the system manager (").append(adminEmail).append(") for help.</p>");
                 progress.failed(sb.toString(), false);
-                Analytics.enter(UploadAssistantApplet.class, Level.ERROR, sb.toString());
+                // Analytics.enter(UploadAssistantApplet.class, Level.ERROR, sb.toString());
                 return false;
             }
         } finally {
             long duration = (new Date().getTime() - uploadStart) / 1000;
             logger.info("upload operation complete after {} sec", duration);
-            Analytics.enter(UploadAssistantApplet.class, "Upload operation completed after " + duration + " seconds");
+            // Analytics.enter(UploadAssistantApplet.class, "Upload operation completed after " + duration + " seconds");
         }
     }
 
-    private void enterUploadAnalytics(Project project, Subject subject, String session, int fileCount, URL dataPostURL, boolean useFixedSize, int nThreads) {
-        Map<String, String> map = new HashMap<String, String>();
-        map.put("project", project.toString());
-        map.put("subject", subject.toString());
-        map.put("session", session);
-        map.put("fileCount", Integer.toString(fileCount));
-        map.put("url", dataPostURL.toString());
-        map.put("useFixedSize", Boolean.toString(useFixedSize));
-        map.put("nThreads", Integer.toString(nThreads));
-        Analytics.enter(UploadAssistantApplet.class, map);
-    }
+//    private void enterUploadAnalytics(Project project, Subject subject, String session, int fileCount, URL dataPostURL, boolean useFixedSize, int nThreads) {
+//        Map<String, String> map = new HashMap<String, String>();
+//        map.put("project", project.toString());
+//        map.put("subject", subject.toString());
+//        map.put("session", session);
+//        map.put("fileCount", Integer.toString(fileCount));
+//        map.put("url", dataPostURL.toString());
+//        map.put("useFixedSize", Boolean.toString(useFixedSize));
+//        map.put("nThreads", Integer.toString(nThreads));
+//        Analytics.enter(UploadAssistantApplet.class, map);
+//    }
 
     private JSONObject buildCommitEntity(final Map<?, ?> params) {
         final JSONObject entity = new JSONObject();
                         } catch (JSONException exception) {
                             String message = "unable to assign session variable " + path;
                             logger.error(message, exception);
-                            Analytics.enter(UploadAssistantApplet.class, Level.ERROR, message, exception);
+                            // Analytics.enter(UploadAssistantApplet.class, Level.ERROR, message, exception);
                         }
                     }
                 }
             }
         }
         logger.trace("Built commit entity: {}", entity);
-        Analytics.enter(UploadAssistantApplet.class, String.format("Built commit entity: %s", entity));
+        // Analytics.enter(UploadAssistantApplet.class, String.format("Built commit entity: %s", entity));
         return entity;
     }
 

File src/main/java/org/nrg/ecat/EcatSession.java

View file
  • Ignore whitespace
  */
 package org.nrg.ecat;
 
-import static org.nrg.upload.ui.UploadAssistantApplet.XNAT_ADMIN_EMAIL_WIZ_PARAM;
-import static org.nrg.upload.ui.UploadAssistantApplet.XNAT_REST_API_WIZ_PARAM;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.text.SimpleDateFormat;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TimeZone;
-
-import javax.swing.JComboBox;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-
-import org.apache.log4j.Level;
+import com.google.common.base.Strings;
+import com.google.common.collect.*;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.json.JSONException;
 import org.netbeans.spi.wizard.Summary;
 import org.nrg.ecat.edit.ScriptApplicator;
 import org.nrg.ecat.edit.Variable;
-import org.nrg.framework.logging.Analytics;
 import org.nrg.net.HttpException;
 import org.nrg.net.HttpURLConnectionProcessor;
 import org.nrg.net.JSONRequestConnectionProcessor;
 import org.nrg.net.RestServer;
-import org.nrg.upload.data.AssignedSessionVariable;
-import org.nrg.upload.data.Project;
-import org.nrg.upload.data.Session;
-import org.nrg.upload.data.SessionVariable;
-import org.nrg.upload.data.SessionVariableNames;
-import org.nrg.upload.data.Subject;
-import org.nrg.upload.data.UploadFailureHandler;
+import org.nrg.upload.data.*;
 import org.nrg.upload.ui.AssignSessionVariablesPage;
 import org.nrg.upload.ui.SelectProjectPage;
 import org.nrg.upload.ui.SelectSubjectPage;
-import org.nrg.upload.ui.UploadAssistantApplet;
 import org.nrg.upload.ui.UploadResultPanel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Strings;
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Multimaps;
+import javax.swing.*;
+import java.io.File;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import static org.nrg.upload.ui.UploadAssistantApplet.XNAT_ADMIN_EMAIL_WIZ_PARAM;
+import static org.nrg.upload.ui.UploadAssistantApplet.XNAT_REST_API_WIZ_PARAM;
 
 /**
  * @author Kevin A. Archie <karchie@wustl.edu>
     private static final String FORMAT = "ECAT";
     private static final String MODALITY = "PET";
     private static final String TIMESTAMP_FORMAT = "yyyyMMdd_HHmmss";
-    private static final String URL_ENCODE_SCHEME = "UTF-8";
 
     private final Logger logger = LoggerFactory.getLogger(EcatSession.class);
     private final MatrixDataFile first;
         return builder.toString();
     }
 
-    private final static String makeTimestamp() {
+    private static String makeTimestamp() {
         return new SimpleDateFormat(TIMESTAMP_FORMAT).format(new Date());        
     }
     
         for (final Iterator<MatrixDataFile> iterator = data.iterator(); iterator.hasNext(); ) {
             final MatrixDataFile dataFile = iterator.next();
             final File f = dataFile.getFile();
-            TRY_FILE: while (true) {
+            while (true) {
                 try {
                     final String scan = String.format("%s&SUBJECT_ID=%s&overwrite=append&xnat:petSessionData/scans/scan/ID=%d", path, subject.getLabel(), ++i);
                     progress.setProgress(String.format("Uploading scan %d/%d", i, size), i - 1, size);
                     logger.trace("uploading {} as scan {}", f, i);
                     final long start = new Date().getTime();
                     xnat.doPost(scan, processor);
-                    logger.trace("upload successful: {} bytes in {} seconds", size, (new Date().getTime() - start)/1000L);
-                    break TRY_FILE;
+                    logger.trace("upload successful: {} bytes in {} seconds", size, (new Date().getTime() - start) / 1000L);
+                    break;
                 } catch (Throwable t) {
                     if (failureHandler.shouldRetry(dataFile.getFile(), t)) {
                         logger.info("upload failed, retrying", t);
                     } else {
-                        final Map<File,Object> failures = Maps.newLinkedHashMap();
+                        final Map<File, Object> failures = Maps.newLinkedHashMap();
                         failures.put(f, t);
                         final StringBuilder message = new StringBuilder("user canceled operation after errors:");
                         message.append(LINE_SEPARATOR);
                         } catch (JSONException exception) {
                             String message = "unable to assign session variable " + path;
                             logger.error(message, exception);
-                            Analytics.enter(UploadAssistantApplet.class, Level.ERROR, message, exception);
+                            // Analytics.enter(UploadAssistantApplet.class, Level.ERROR, message, exception);
                         }
                     }
                 }
             }
         }
         logger.trace("Built commit entity: {}", entity);
-        Analytics.enter(UploadAssistantApplet.class, String.format("Built commit entity: %s", entity));
+        // Analytics.enter(UploadAssistantApplet.class, String.format("Built commit entity: %s", entity));
         return entity;
     }
 
         return "User canceled upload";
     }
 
-    private static final <T> StringBuilder buildFailureMessage(final StringBuilder sb, final Map<File,T> failures) {
+    private static <T> StringBuilder buildFailureMessage(final StringBuilder sb, final Map<File,T> failures) {
         final Multimap<T,File> inverse = LinkedHashMultimap.create();
         Multimaps.invertFrom(Multimaps.forMap(failures), inverse);
         final Multimap<Object,File> causes = org.nrg.util.Utils.consolidateKeys(inverse, 4);

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

View file
  • Ignore whitespace
 /**
- * Copyright (c) 2010,2011 Washington University
+ * Copyright (c) 2013 Washington University School of Medicine
  */
 package org.nrg.net;
 
 import org.json.JSONTokener;
 import org.netbeans.spi.wizard.ResultProgressHandle;
 import org.nrg.IOUtils;
-import org.nrg.upload.ui.UploadAssistantApplet;
 import org.nrg.util.Base64;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * @author Kevin A. Archie <karchie@wustl.edu>
- *
  */
 public class RestServer {
     private static final Pattern userInfoPattern = Pattern.compile("([^:@/]*):([^:@]*)");
     private static final String AUTHORIZATION_HEADER = "Authorization";
     final static String TITLE;
     final static String VERSION;
+
     static {
         final Properties props = new Properties();
         final ClassLoader cl = RestServer.class.getClassLoader();
         VERSION = props.getProperty("application.version");
     }
 
-    private static final Map<String,String> defaultHeaders = ImmutableMap.of(
+    private static final Map<String, String> defaultHeaders = ImmutableMap.of(
             "User-Agent", "XNATUploadAssistant/" + VERSION,
             "Accept", "*/*");
 
     private final Logger logger = LoggerFactory.getLogger(RestServer.class);
-    private final URL base;
-    private final UploadAssistantApplet applet;
-    private final JSESSIONIDCookie jsessionidCookie;
+    private final URL _base;
+    private final JSESSIONIDCookie _jsessionidCookie;
 
-    public RestServer(final URL url, final UploadAssistantApplet uploadAssistantApplet, final JSESSIONIDCookie jsessionidCookie) {
-        applet = uploadAssistantApplet;
+    public RestServer(final URL url, final JSESSIONIDCookie jsessionidCookie) {
+
         final StringBuilder sb = new StringBuilder(url.toString());
         for (int i = sb.length() - 1; '/' == sb.charAt(i); i--) {
             sb.deleteCharAt(i);
         }
         try {
-            this.base = new URL(sb.toString());
+            _base = new URL(sb.toString());
         } catch (MalformedURLException e) {
-            throw new RuntimeException(e);	// can't imagine how this would happen
+            throw new RuntimeException(e);    // can't imagine how this would happen
         }
 
         final String userInfo = url.getUserInfo();
                 passStore.put(service, auth);
             }
         }
-        
-        this.jsessionidCookie = jsessionidCookie;
+
+        _jsessionidCookie = jsessionidCookie;
     }
 
-    public RestServer(final String url, final UploadAssistantApplet uploadAssistantApplet, final JSESSIONIDCookie jsessionidCookie) throws MalformedURLException {
-        this(new URL(url), uploadAssistantApplet, jsessionidCookie);
+    public RestServer(final String url, final JSESSIONIDCookie jsessionidCookie) throws MalformedURLException {
+        this(new URL(url), jsessionidCookie);
     }
 
-    private final Map<Service,PasswordAuthentication> passStore = Maps.newHashMap();
-    private final Map<Service,String> descriptions = Maps.newHashMap();
+    private final Map<Service, PasswordAuthentication> passStore = Maps.newHashMap();
+    private final Map<Service, String> descriptions = Maps.newHashMap();
 
     private static final class Service {
         private final String protocol;
          */
         public int hashCode() {
             int result = 17;
-            result = 37*result + protocol.hashCode();
-            result = 37*result + host.hashCode();
-            result = 37*result + port;
+            result = 37 * result + protocol.hashCode();
+            result = 37 * result + host.hashCode();
+            result = 37 * result + port;
             return result;
         }
 
          * @see java.lang.Object#equals(java.lang.Object)
          */
         public boolean equals(final Object o) {
-            if (! (o instanceof Service)) return false;
-            final Service other = (Service)o;
+            if (!(o instanceof Service)) return false;
+            final Service other = (Service) o;
             return protocol.equals(other.protocol) &&
-            host.equals(other.host) &&
-            port == other.port;
+                    host.equals(other.host) &&
+                    port == other.port;
         }
 
         /*
          */
         public String toString() {
             try {
-                return new URL(protocol,host,port,"").toString();
+                return new URL(protocol, host, port, "").toString();
             } catch (MalformedURLException e) {
                 return MessageFormat.format("{0}://{1}:{2}", protocol, host, port);
             }
 
     /**
      * Get the logged in user from the server
+     *
      * @return logged in user string
      * @throws IOException When error occurs during server I/O.
      */
             }
         }
 
-        public Collection<Object> getValues() { return c; }
+        public Collection<Object> getValues() {
+            return c;
+        }
     }
 
-    private static boolean isNullOrEmpty(final String s) { return null == s || "".equals(s); }
+    private static boolean isNullOrEmpty(final String s) {
+        return null == s || "".equals(s);
+    }
 
     private static final class JSONAliasesExtractor implements JSONDecoder {
         private final Logger logger = LoggerFactory.getLogger(JSONAliasesExtractor.class);
-        private final Map<String,String> m;
+        private final Map<String, String> m;
         private final String aliasKey, idKey;
 
-        JSONAliasesExtractor(final Map<String,String> m, final String aliasKey, final String idKey) {
+        JSONAliasesExtractor(final Map<String, String> m, final String aliasKey, final String idKey) {
             this.m = m;
             this.aliasKey = aliasKey;
             this.idKey = idKey;
             }
         }
 
-        public Map<String,String> getAliases() { return m; }
+        public Map<String, String> getAliases() {
+            return m;
+        }
     }
 
 
     static JSONObject extractJSONEntity(final InputStream in)
-    throws IOException,JSONException {
+            throws IOException, JSONException {
         return new JSONObject(new JSONTokener(new InputStreamReader(in)));
     }
 
     static JSONArray extractResultFromEntity(final JSONObject entity)
-    throws JSONException {
+            throws JSONException {
         return entity.getJSONObject("ResultSet").getJSONArray("Result");
     }
 
-    private static void addBasicAuthorizationToHeaderMap(final Map<String,String> m,
-            final PasswordAuthentication auth) {
+    private static void addBasicAuthorizationToHeaderMap(final Map<String, String> m,
+                                                         final PasswordAuthentication auth) {
         final StringBuilder unencoded = new StringBuilder();
         unencoded.append(auth.getUserName());
         unencoded.append(":");
 
 
     private void doGet(final String path, final JSONDecoder decoder)
-    throws IOException,JSONException {
+            throws IOException, JSONException {
         try {
             doGet(path, new JSONResultExtractor(decoder));
         } catch (IOException e) {
     }
 
     private void request(final String path, final String method, final HttpURLConnectionProcessor processor) throws Exception {
-        final Map<String,String> headers = Maps.newLinkedHashMap(defaultHeaders);
-        final StringBuilder sb = new StringBuilder(base.toString());
+
+        final Map<String, String> headers = Maps.newLinkedHashMap(defaultHeaders);
+        final StringBuilder sb = new StringBuilder(_base.toString());
         if ('/' != path.charAt(0)) {
             sb.append('/');
         }
         logger.trace("{} preparing request {}", this, url);
         if (logger.isTraceEnabled()) {
             final Callable<List<String>> callable = new Callable<List<String>>() {
-                public List<String> call() throws IOException,URISyntaxException {
+                public List<String> call() throws IOException, URISyntaxException {
                     final CookieHandler ch = CookieHandler.getDefault();
-                    final Map<String,List<String>> h = ch.get(url.toURI(), new HashMap<String,List<String>>());
+                    final Map<String, List<String>> h = ch.get(url.toURI(), new HashMap<String, List<String>>());
                     return h.get("Cookie");
                 }
             };
 
         logger.trace("opening connection to {}", url);
 
-        final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
-        connection.setRequestMethod(method);
-        connection.setDoInput(true);
-        connection.setDoOutput(true);
-        connection.setUseCaches(false);
-        for (final Map.Entry<String, String> me : headers.entrySet()) {
-            if (!connection.getRequestProperties().containsKey(me.getKey())) {
-                connection.setRequestProperty(me.getKey(), me.getValue());
+        HttpURLConnection connection = null;
+        int attempts = 0;
+        TRY_PUT:
+        for (; ; )
+            try {
+                connection = (HttpURLConnection) url.openConnection();
+                connection.setRequestMethod(method);
+                connection.setDoInput(true);
+                connection.setDoOutput(true);
+                connection.setUseCaches(false);
+                for (final Map.Entry<String, String> me : headers.entrySet()) {
+                    if (!connection.getRequestProperties().containsKey(me.getKey())) {
+                        connection.setRequestProperty(me.getKey(), me.getValue());
+                    }
+                }
+                getJSESSIONIDCookie().setInRequestHeader(connection);
+                processor.prepare(connection);
+                final int responseCode = connection.getResponseCode();
+
+                switch (responseCode) {
+                    case HTTP_ACCEPTED:
+                    case HTTP_NOT_AUTHORITATIVE:
+                    case HTTP_NO_CONTENT:
+                    case HTTP_RESET:
+                    case HTTP_PARTIAL:
+                    case HTTP_MOVED_PERM:
+                        logger.trace(connection.getRequestMethod() + " to {} returned "
+                                + responseCode + " ({})",
+                                url, connection.getResponseMessage());
+
+                    case HTTP_OK:
+                    case HTTP_CREATED:
+                        processor.process(connection);
+                        return;
+
+                    // Handle 302, at least temporarily: Spring auth redirects to login page,
+                    // so assume that's what's happened when we see a redirect at this point.
+                    case HTTP_MOVED_TEMP:
+                    case HTTP_UNAUTHORIZED:
+                        if (logger.isDebugEnabled()) {
+                            logger.debug("Received status code " + (responseCode == HTTP_MOVED_TEMP ? "302 (Redirect)" : "401 (Unauthorized)"));
+                            for (final Map.Entry<String, List<String>> me : connection.getHeaderFields().entrySet()) {
+                                logger.trace("Header {} : {}", me.getKey(), me.getValue());
+                            }
+                            logger.debug("Will request credentials for {}", url);
+                        }
+                        final PasswordAuthentication auth;
+                        synchronized (passStore) {
+                            if (headers.containsKey(AUTHORIZATION_HEADER)) {
+                                passStore.remove(service);
+                            }
+                            final String prompt = "Enter credentials for " +
+                                    (descriptions.containsKey(service) ? descriptions.get(service) : service);
+                            auth = Authenticator.requestPasswordAuthentication(url.getHost(),
+                                    null, url.getPort(), url.getProtocol(),
+                                    prompt, url.getProtocol());
+                            passStore.put(service, auth);
+                        }
+                        addBasicAuthorizationToHeaderMap(headers, auth);
+
+                        if (attempts++ < 3) {
+                            continue TRY_PUT;
+                        }
+                        throw new HttpException(responseCode, "Unable to connect to " + url.toString(), "Ugh");
+
+                    case HTTP_CONFLICT:
+                        throw new ConflictHttpException(getErrorEntity(connection));
+
+                    default:
+                        final StringBuilder message = new StringBuilder();
+                        message.append(connection.getRequestMethod());
+                        message.append(" to ").append(url).append(" failed ");
+                        try {
+                            final String entity = getErrorEntity(connection);
+                            if (null != entity) {
+                                message.append(": ").append(entity);
+                            }
+                        } catch (Throwable t) {
+                            message.append(" - ").append(t.getMessage());
+                        }
+                        throw new HttpException(responseCode, connection.getResponseMessage(), message.toString());
+                }
+            } finally {
+                if (connection != null) {
+                    connection.disconnect();
+                }
             }
-        }
-        getJSESSIONIDCookie().setInRequestHeader(connection);
-        processor.prepare(connection);
-
-        int attempts = 0;
-        TRY_PUT: for (;;) try {
-            final int responseCode = applet.getResponseCode(connection);
-
-            switch (responseCode) {
-            case HTTP_ACCEPTED:
-            case HTTP_NOT_AUTHORITATIVE:
-            case HTTP_NO_CONTENT:
-            case HTTP_RESET:
-            case HTTP_PARTIAL:
-            case HTTP_MOVED_PERM:
-                logger.trace(connection.getRequestMethod() + " to {} returned "
-                        + responseCode + " ({})",
-                        url, connection.getResponseMessage());
-
-            case HTTP_OK:
-            case HTTP_CREATED:
-                processor.process(connection);
-                return;
-
-            // Handle 302, at least temporarily: Spring auth redirects to login page,
-            // so assume that's what's happened when we see a redirect at this point.
-            case HTTP_MOVED_TEMP:
-            case HTTP_UNAUTHORIZED:
-                if (logger.isDebugEnabled()) {
-                    logger.debug("Received status code " + (responseCode == HTTP_MOVED_TEMP ? "302 (Redirect)" : "401 (Unauthorized)"));
-                    for (final Map.Entry<String,List<String>> me: connection.getHeaderFields().entrySet()) {
-                        logger.trace("Header {} : {}", me.getKey(), me.getValue());
-                    }
-                    logger.debug("Will request credentials for {}", url);
-                }
-                final PasswordAuthentication auth;
-                synchronized(passStore) {
-                    if (headers.containsKey(AUTHORIZATION_HEADER)) {
-                        passStore.remove(service);
-                    }
-                    final String prompt = "Enter credentials for " +
-                    (descriptions.containsKey(service) ? descriptions.get(service) : service);
-                     auth = Authenticator.requestPasswordAuthentication(url.getHost(),
-                            null, url.getPort(), url.getProtocol(),
-                            prompt, url.getProtocol());
-                    passStore.put(service, auth);
-                }
-                addBasicAuthorizationToHeaderMap(headers, auth);
-
-                if (attempts++ < 3) {
-                    continue TRY_PUT;
-                }
-                throw new HttpException(responseCode, "Unable to connect to " + url.toString(), "Ugh");
-
-            case HTTP_CONFLICT:
-                throw new ConflictHttpException(getErrorEntity(connection));
-
-            default:
-                final StringBuilder message = new StringBuilder();
-                message.append(connection.getRequestMethod());
-                message.append(" to ").append(url).append(" failed ");
-                try {
-                    final String entity = getErrorEntity(connection);
-                    if (null != entity) {
-                        message.append(": ").append(entity);
-                    }
-                } catch (Throwable t) {
-                    message.append(" - ").append(t.getMessage());
-                }
-                throw new HttpException(responseCode, connection.getResponseMessage(), message.toString());
-            }
-        } finally {
-            connection.disconnect();
-        }
     }
 
     private static String getErrorEntity(final HttpURLConnection connection) throws IOException {
-        IOException underlying = null;
         final InputStream errorStream = connection.getErrorStream();
         try {
             if (null == errorStream) {
                 }
             }
             return null;
-        } catch (IOException e) {
-            throw underlying = e;
         } finally {
-            try {
-                assert errorStream != null;
-                errorStream.close();
-            } catch (IOException e) {
-                throw null == underlying ? e : underlying;
+            if (errorStream != null) {
+                try {
+                    errorStream.close();
+                } catch (IOException ignored) {
+                    // Just ignore this if it happens. This will allow exceptions from the top through and just not say
+                    // anything if the close fails. Java gets unhappy about throwing exceptions from finally blocks.
+                }
             }
         }
     }
     }
 
     private void request(final String path, final String method,
-            final InputStream in, final String mimeMediaType, final Integer contentLength,
-            final ResultProgressHandle progress)
-    throws IOException {
+                         final InputStream in, final String mimeMediaType, final Integer contentLength,
+                         final ResultProgressHandle progress)
+            throws IOException {
         try {
             request(path, method, new StreamUploadProcessor(in, mimeMediaType, contentLength, progress));
         } catch (IOException e) {
     }
 
     private void request(final String path, final String method,
-            final File f, final String mimeMediaType, final ResultProgressHandle progress)
-    throws IOException {
+                         final File f, final String mimeMediaType, final ResultProgressHandle progress)
+            throws IOException {
         request(path, method, new FileInputStream(f),
                 mimeMediaType, Long.valueOf(f.length()).intValue(), progress);
     }
 
     public void doGet(final String path, final HttpURLConnectionProcessor processor)
-    throws Exception {
+            throws Exception {
         request(path, GET, processor);
     }
 
     public void doPost(final String path, final HttpURLConnectionProcessor processor)
-    throws Exception {
+            throws Exception {
         request(path, POST, processor);
     }
 
-    public void doPut(final String path, final HttpURLConnectionProcessor processor)
-    throws Exception {
+    public void doPut(final String path, final HttpURLConnectionProcessor processor) throws Exception {
         request(path, PUT, processor);
     }
 
 
     /**
      * Performs a POST request with empty entity.
+     *
      * @param path Path to POST resource.
      * @throws IOException When error occurs during server I/O.
      */
 
     /**
      * Performs a PUT request with empty entity.
+     *
      * @param path Path to PUT resource.
      * @throws IOException When error occurs during server I/O.
      */
     }
 
     public Collection<Object> getValues(final String path, final String key)
-    throws IOException,JSONException {
+            throws IOException, JSONException {
         final JSONValuesExtractor extractor = new JSONValuesExtractor(new LinkedHashSet<Object>(), key);
         doGet(path, extractor);
         return extractor.getValues();
     }
 
-    public Map<String,String> getAliases(final String path, final String aliasKey, final String idKey)
-    throws IOException,JSONException {
-        final JSONAliasesExtractor extractor = new JSONAliasesExtractor(new LinkedHashMap<String,String>(), aliasKey, idKey);
+    public Map<String, String> getAliases(final String path, final String aliasKey, final String idKey) throws IOException, JSONException {
+        final JSONAliasesExtractor extractor = new JSONAliasesExtractor(new LinkedHashMap<String, String>(), aliasKey, idKey);
         doGet(path, extractor);
         return extractor.getAliases();
     }
 
-    public URL getURL() { return base; }
+    public URL getURL() {
+        return _base;
+    }
 
     public void setDescription(final URL url, final String description) {
         descriptions.put(new Service(url), description);
     }
 
-	public JSESSIONIDCookie getJSESSIONIDCookie() {
-		return jsessionidCookie;
-	}
+    public JSESSIONIDCookie getJSESSIONIDCookie() {
+        return _jsessionidCookie;
+    }
 }

File src/main/java/org/nrg/net/SwingAuthenticator.java

View file
  • Ignore whitespace
 
 /**
  * @author Kevin A. Archie <karchie@npg.wustl.edu>
- *
  */
 public class SwingAuthenticator extends Authenticator {
-    private final Component parentComponent;
+    private final Component _parent;
 
     private final static GridBagConstraints labelConstraint = new GridBagConstraints();
     private final static GridBagConstraints fieldConstraint = new GridBagConstraints();
+
     static {
-	labelConstraint.gridx = 0;
-	labelConstraint.anchor = GridBagConstraints.LINE_START;
-
-	fieldConstraint.gridx = 1;
-	fieldConstraint.anchor = GridBagConstraints.LINE_END;
-	fieldConstraint.fill = GridBagConstraints.HORIZONTAL;
-	fieldConstraint.weightx = 1;
-    }
-    
-    /**
-     * 
-     */
-    public SwingAuthenticator(final Component parentComponent) {
-	this.parentComponent = parentComponent;
+        labelConstraint.gridx = 0;
+        labelConstraint.anchor = GridBagConstraints.LINE_START;
+        fieldConstraint.gridx = 1;
+        fieldConstraint.anchor = GridBagConstraints.LINE_END;
+        fieldConstraint.fill = GridBagConstraints.HORIZONTAL;
+        fieldConstraint.weightx = 1;
     }
 
-    
+    /**
+     *
+     */
+    public SwingAuthenticator(final Component parent) {
+        _parent = parent;
+    }
+
+
     protected PasswordAuthentication getPasswordAuthentication() {
-	final JPanel contents = new JPanel(new GridBagLayout());
-	
-	contents.add(new JLabel("User:"), labelConstraint);
-	final JTextField userField = new JTextField(16);
-	contents.add(userField, fieldConstraint);
+        final JPanel contents = new JPanel(new GridBagLayout());
 
-	contents.add(new JLabel("Password:"), labelConstraint);
-	final JPasswordField passField = new JPasswordField(16);
-	contents.add(passField, fieldConstraint);
+        contents.add(new JLabel("User:"), labelConstraint);
+        final JTextField userField = new JTextField(16);
+        contents.add(userField, fieldConstraint);
 
-	final JOptionPane optionPane = new JOptionPane(contents,
-		JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION);
-	final JDialog dialog = optionPane.createDialog(parentComponent, getRequestingPrompt());
-	dialog.addComponentListener(new ComponentAdapter() {
-	    public void componentShown(ComponentEvent e) {
-		userField.requestFocusInWindow();
-	    }
-	});
-	dialog.setVisible(true);
-	if (JOptionPane.OK_OPTION == ((Integer)optionPane.getValue()).intValue()) {
-	    final PasswordAuthentication auth = new PasswordAuthentication(userField.getText(), passField.getPassword());
-	    return auth;
-	} else {
-	    return null;
-	}
+        contents.add(new JLabel("Password:"), labelConstraint);
+        final JPasswordField passField = new JPasswordField(16);
+        contents.add(passField, fieldConstraint);
+
+        final JOptionPane optionPane = new JOptionPane(contents,
+                JOptionPane.QUESTION_MESSAGE, JOptionPane.OK_CANCEL_OPTION);
+        final JDialog dialog = optionPane.createDialog(_parent, getRequestingPrompt());
+        dialog.addComponentListener(new ComponentAdapter() {
+            public void componentShown(ComponentEvent e) {
+                userField.requestFocusInWindow();
+            }
+        });
+        dialog.setVisible(true);
+        if (JOptionPane.OK_OPTION == (Integer) optionPane.getValue()) {
+            return new PasswordAuthentication(userField.getText(), passField.getPassword());
+        } else {
+            return null;
+        }
     }
 }

File src/main/java/org/nrg/upload/data/SessionVariableNames.java

View file
  • Ignore whitespace
 	public static final String MODALITY_LABEL = "modalityLabel";
 	public static final String VISIT_LABEL = "*visit*";  //asterisks to avoid any problems with the anon script. this prevents visit from becoming a variable.
 	public static final String PROTOCOL_LABEL = "*protocol*";  //asterisks to avoid any problems with the anon script. this prevents protocol from becoming a variable.
+	public static final String WARN_ON_DUPE_SESSION_LABELS = "warn-on-dupe-session-labels";
 	
 	public static final String BLOOD_GLUCOSE = "blood glucose (mg/dL)";
 	public static final String BLOOD_GLUCOSE_PATH = "xnat:petSessionData/blood_glucose";

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

View file
  • Ignore whitespace
  */
 package org.nrg.upload.ui;
 
-import static org.nrg.upload.data.SessionVariableNames.MODALITY_LABEL;
-import static org.nrg.upload.data.SessionVariableNames.PREDEF_SESSION;
-import static org.nrg.upload.data.SessionVariableNames.PROJECT;
-import static org.nrg.upload.data.SessionVariableNames.SESSION_LABEL;
-import static org.nrg.upload.data.SessionVariableNames.SUBJECT;
-
-import java.awt.BorderLayout;
-import java.awt.Component;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TimeZone;
-
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-
+import com.google.common.base.Joiner;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.time.DateUtils;
 import org.netbeans.spi.wizard.Wizard;
 import org.netbeans.spi.wizard.WizardPage;
 import org.nrg.ecat.EcatSessionVariable;
 import org.nrg.framework.constants.AutoArchive;
 import org.nrg.framework.constants.PrearchiveCode;
-import org.nrg.upload.data.AssignedSessionVariable;
-import org.nrg.upload.data.ExcludingValueValidator;
-import org.nrg.upload.data.IndexedDependentSessionVariable;
-import org.nrg.upload.data.LabelValueValidator;
-import org.nrg.upload.data.Project;
-import org.nrg.upload.data.Session;
-import org.nrg.upload.data.SessionVariable;
+import org.nrg.upload.data.*;
 import org.nrg.upload.data.SessionVariable.InvalidValueException;
-import org.nrg.upload.data.SessionVariableConsumer;
-import org.nrg.upload.data.SessionVariableNames;
-import org.nrg.upload.data.Subject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Joiner;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import javax.swing.*;
+import java.awt.*;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import static org.nrg.upload.data.SessionVariableNames.*;
 
 /**
  * @author Kevin A. Archie <karchie@wustl.edu>
- *
  */
 public final class AssignSessionVariablesPage extends WizardPage implements SessionVariableConsumer, PropertyChangeListener {
     private static final long serialVersionUID = -2786166512597463435L;
             "<html><p>The session ID you've specified is already present in your project.</p>" +
                     "<p>Would you like to overwrite the existing session, append to the existing</p>" +
                     "<p>session, or provide a new session ID?</p></html>";
-    private static final String[] DUP_SESSION_ID_OPTIONS = { "Overwrite existing", "Append to existing", "Provide new session ID" };
+    private static final String[] DUP_SESSION_ID_OPTIONS = {"Overwrite existing", "Append to existing", "Provide new session ID"};
     private static final String NULL_SESSION_DATE_TITLE = "Session Has No Associated Date";
     private static final String NULL_SESSION_DATE_MESSAGE =
             "<html><p>The session you selected has no date associated with it, but you specified a date" +
     private static final String INVALID_SESSION_DATE_MESSAGE =
             "<html><p>The date and/or time you indicated for your scan session does</p>" +
                     "<p>not match the date of the selected session. Please re-check</p>" +
-                    "<p>the date for your new session and start over or click <b>Prev</b></p>"  +
+                    "<p>the date for your new session and start over or click <b>Prev</b></p>" +
                     "<p>and select another session that matches the indicated date.</p></html>";
     private static final String UNEXPECTED_MODALITY_TITLE = "Unexpected Modality";
-    private static final String UNEXPECTED_MODALITY_MESSAGE = 
+    private static final String UNEXPECTED_MODALITY_MESSAGE =
             "<html><p>The expected modality does not match that of the session.</p>" +
                     "<p>Please re-check the modality of your new session and start</p>" +
-                    "<p>over or click <b>Prev</b> and select another session that matches</p>"  +
+                    "<p>over or click <b>Prev</b> and select another session that matches</p>" +
                     "<p>the indicated modality.</p></html>";
 
     private final Logger logger = LoggerFactory.getLogger(AssignSessionVariablesPage.class);
     private SessionVariable sessionLabel;
     private Date confirmedDate;
     private boolean isAutoArchiving = false;
+    private boolean warnOnDupeSessionLabels = true;
 
     private static final GridBagConstraints SPANNING = new GridBagConstraints() {
         private static final long serialVersionUID = 5114328188210435952L;
+
         {
             gridx = 0;
             gridwidth = 2;
             insets = new Insets(8, 0, 0, 0);
-        }};
+        }
+    };
 
-        //If d1's hours and minutes are both == 0 we assume we're testing
-        //to see if both dates occured on the same day.  If there is data
-        //in the hours and minutes, we return true if both dates are within
-        // a 61 minute window of each other.
-        private boolean isSessionDateOk(Date d1, Date session, TimeZone sessionTimeZone){
-            Calendar cal = Calendar.getInstance(); 
-            cal.setTime(d1);
-            int hour = cal.get(Calendar.HOUR_OF_DAY);
-            int minute = cal.get(Calendar.MINUTE);
-            if(hour == 0 && minute == 0){
-                return DateUtils.isSameDay(d1, session);
+    //If d1's hours and minutes are both == 0 we assume we're testing
+    //to see if both dates occurred on the same day.  If there is data
+    //in the hours and minutes, we return true if both dates are within
+    // a 61 minute window of each other.
+    private boolean isSessionDateOk(Date d1, Date session, TimeZone sessionTimeZone) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(d1);
+        int hour = cal.get(Calendar.HOUR_OF_DAY);
+        int minute = cal.get(Calendar.MINUTE);
+        if (hour == 0 && minute == 0) {
+            return DateUtils.isSameDay(d1, session);
+        } else {
+            //check the 61 minute window
+            if (sessionTimeZone != null) {
+                //if the session has a time zone, we have to deal with conversion...
+                Calendar sessionCal = Calendar.getInstance();
+                sessionCal.setTimeZone(sessionTimeZone);
+                sessionCal.setTime(session);
+                int sessionHour = sessionCal.get(Calendar.HOUR_OF_DAY);
+                //make sure the date is the same day (within 24 hours) and assure the hour is within 1 hour.
+                return Math.abs(d1.getTime() - session.getTime()) < 86400000 && Math.abs(hour - sessionHour) < 2;
             } else {
-                //check the 61 minute window
-            	if(sessionTimeZone != null){
-            		//if the session has a time zone, we have to deal with conversion... 
-            		Calendar sessionCal = Calendar.getInstance();
-            		sessionCal.setTimeZone(sessionTimeZone);
-            		sessionCal.setTime(session);
-                	int sessionHour = sessionCal.get(Calendar.HOUR_OF_DAY);
-                	int sessionMinute = sessionCal.get(Calendar.MINUTE);
-                	//make sure the date is the same day (within 24 hours) and assure the hour is within 1 hour.
-                    return Math.abs(d1.getTime() - session.getTime()) < 86400000 && Math.abs(hour - sessionHour) < 2; 
-            	} else {
-            		return Math.abs(d1.getTime() - session.getTime()) < 3660000; 
-            	}
-            	   		
+                return Math.abs(d1.getTime() - session.getTime()) < 3660000;
+            }
+
+        }
+    }
+
+    /**
+     * Gets the description of this step for the wizard framework.
+     *
+     * @return The step description.
+     */
+    public static String getDescription() {
+        return STEP_DESCRIPTION;
+    }
+
+    /**
+     * Default constructor.
+     */
+    public AssignSessionVariablesPage() {
+        setLayout(new BorderLayout());
+        setLongDescription(LONG_DESCRIPTION);
+    }
+
+    /**
+     * Implementation of the method.
+     *
+     * @see org.nrg.upload.data.SessionVariableConsumer#update(org.nrg.upload.data.SessionVariable, boolean)
+     */
+    @Override
+    public void update(final SessionVariable v, final boolean isValidValue) {
+        logger.trace("{} updated to {}", v, isValidValue ? "valid" : "invalid");
+        if (isValidValue) {
+            invalid.remove(v);
+        } else {
+            invalid.add(v);
+            setProblem(v.getValueMessage());
+        }
+        setProblem(validateContents(null, null));
+    }
+
+    /**
+     * Verifies whether or not user wants to proceed in the case of a verification date mismatch.
+     *
+     * @param stepName The name of the current step.
+     * @param settings Any settings for the current step.
+     * @param wizard   The current wizard.
+     * @return Returns <b>WizardPanelNavResult.REMAIN_ON_PAGE</b> if the user doesn't confirm, <b>WizardPanelNavResult.PROCEED</b> otherwise.
+     */
+    @Override
+    public WizardPanelNavResult allowNext(String stepName, @SuppressWarnings("rawtypes") Map settings, Wizard wizard) {
+        return isOkToProceed() ? WizardPanelNavResult.PROCEED : WizardPanelNavResult.REMAIN_ON_PAGE;
+    }
+
+    /**
+     * Verifies whether or not user wants to proceed in the case of a verification date mismatch.
+     *
+     * @param stepName The name of the current step.
+     * @param settings Any settings for the current step.
+     * @param wizard   The current wizard.
+     * @return Returns <b>WizardPanelNavResult.REMAIN_ON_PAGE</b> if the user doesn't confirm, <b>WizardPanelNavResult.PROCEED</b> otherwise.
+     */
+    @Override
+    public WizardPanelNavResult allowFinish(String stepName, @SuppressWarnings("rawtypes") Map settings, Wizard wizard) {
+        return isOkToProceed() ? WizardPanelNavResult.PROCEED : WizardPanelNavResult.REMAIN_ON_PAGE;
+    }
+
+    /**
+     * Implements the {@link PropertyChangeListener#propertyChange(PropertyChangeEvent)} method. This is used to
+     * prompt the wizard framework to take notice when something has changed on the page.
+     *
+     * @param event The property change event.
+     */
+    @Override
+    public void propertyChange(PropertyChangeEvent event) {
+        userInputReceived(this, event);
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.netbeans.spi.wizard.WizardPage#recycle()
+     */
+    @Override
+    protected void recycle() {
+        removeAll();
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.netbeans.spi.wizard.WizardPage#renderingPage()
+     */
+    @Override
+    protected void renderingPage() {
+        initialize();
+
+        String expectedModality = (String) this.getWizardData(UploadAssistantApplet.EXPECTED_MODALITY_LABEL);
+        Set<String> modalities = session.getModalities();
+
+        if (expectedModality != null && modalities != null) {
+            if ("PT".equalsIgnoreCase(expectedModality) || "PET".equalsIgnoreCase(expectedModality)) {
+                if (!(modalities.contains("PT") || modalities.contains("PET"))) {
+                    JOptionPane.showMessageDialog(this, UNEXPECTED_MODALITY_MESSAGE, UNEXPECTED_MODALITY_TITLE, JOptionPane.WARNING_MESSAGE);
+                }
+            } else {
+                if (!modalities.contains(expectedModality)) {
+                    JOptionPane.showMessageDialog(this, UNEXPECTED_MODALITY_MESSAGE, UNEXPECTED_MODALITY_TITLE, JOptionPane.WARNING_MESSAGE);
+                }
             }
         }
-        /**
-         * Gets the description of this step for the wizard framework.
-         * @return The step description.
-         */
-        public static String getDescription() {
-            return STEP_DESCRIPTION;
+        if (sessionDate == null && confirmedDate != null) {
+            JOptionPane.showMessageDialog(this, NULL_SESSION_DATE_MESSAGE, NULL_SESSION_DATE_TITLE, JOptionPane.WARNING_MESSAGE);
+        } else if (!isSessionDateOk(confirmedDate, sessionDate, session.getTimeZone())) {
+            JOptionPane.showMessageDialog(this, INVALID_SESSION_DATE_MESSAGE, INVALID_SESSION_DATE_TITLE, JOptionPane.ERROR_MESSAGE);
+        } else {
+            add(addContent(new JPanel(new GridBagLayout())), BorderLayout.CENTER);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.netbeans.spi.wizard.WizardPage#validateContents(java.awt.Component, java.lang.Object)
+     */
+    @Override
+    protected String validateContents(final Component component, final Object event) {
+        if (!isSessionDateOk(confirmedDate, sessionDate, session.getTimeZone())) {
+            // We have to go through this whole rigamarole to deal with the Java Date class's inadequacies and general crappiness.
+            // The year being set by dcm4che seems to absolute, i.e. setting 2012 when it really means 2012. The nerve. Instead,
+            // according to Java, it should be setting the offset from 1900, i.e. 112, when it means 2012. But we get what we get.
+            // So, check for a year greater than 1900 and, if found, offset by -1900 and hope like crazy that that's the right thing.
+            Calendar calendar = Calendar.getInstance();
+            calendar.setTime(confirmedDate);
+            //            int year = calendar.get(Calendar.YEAR);
+            //            if (year > 1900) {
+            //                calendar.set(Calendar.YEAR, year - 1900);
+            //            }
+            return "Click the Previous button and select a session with scan date of " + FORMATTER.format(calendar.getTime());
         }
 
-        /**
-         * Default constructor.
-         */
-        public AssignSessionVariablesPage() {
-            setLayout(new BorderLayout());
-            setLongDescription(LONG_DESCRIPTION);
+        // If verifyDate is empty, we won't allow user to proceed, but we won't do any other validation.
+        if (component != null && component instanceof JTextField) {
+            String candidate = sessionLabel != null ? sessionLabel.getValue() : ((JTextField) component).getText();
+            boolean stopForDuplicateSessionId = stopForDuplicateSessionId(candidate, false);
+            if (stopForDuplicateSessionId) {
+                return "You must either select another session, change the session ID, or indicate how you want to handle the duplicate session ID for your auto-archiving project.";
+            }
+        }
+        final SortedSet<String> names = Sets.newTreeSet();
+        for (final SessionVariable v : invalid) {
+            names.add(v.getName());
+        }
+        if (names.size() > 0) {
+            final StringBuilder buffer = new StringBuilder("Some fields have invalid values: ");
+            final Joiner joiner = Joiner.on(", ");
+            return joiner.appendTo(buffer, names).toString();
+        }
+        return null;
+    }
+
+    /**
+     * Initializes all incoming data from the wizard's data map.
+     */
+    private void initialize() {
+        project = (Project) getWizardData(SelectProjectPage.PRODUCT_NAME);
+        subject = (Subject) getWizardData(SelectSubjectPage.PRODUCT_NAME);
+        session = (Session) getWizardData(SelectSessionPage.PRODUCT_NAME);
+        sessionDate = session.getDateTime();
+        sessionLabel = (SessionVariable) getWizardData(SessionVariableNames.SESSION_LABEL);
+        if (getWizardDataMap().containsKey(SessionVariableNames.WARN_ON_DUPE_SESSION_LABELS)) {
+            warnOnDupeSessionLabels = Boolean.parseBoolean(getWizardData(SessionVariableNames.WARN_ON_DUPE_SESSION_LABELS).toString());
+        }
+        Object candidate = getWizardData(ConfirmSessionDatePage.PRODUCT_NAME);
+        // If we got a candidate for the confirmed date...
+        if (candidate != null) {
+            // See if it's a date.
+            if (candidate instanceof Date) {
+                // If so, stash that.
+                confirmedDate = (Date) candidate;
+            }
+            // If it wasn't a date, check if it's a string and is the no_session_date qualifier.
+            else if (candidate instanceof String && "no_session_date".equals(candidate)) {
+                // So if it's no session date, there's a good chance the session date is null. If so, initialize both
+                // of the dates so that they're matching and we can pass through the date-check logic cleanly.
+                if (sessionDate == null) {
+                    sessionDate = new Date();
+                }
+                confirmedDate = sessionDate;
+            }
+        }
+    }
+
+    private JPanel addContent(final JPanel panel) {
+        logger.trace("adding content");
+
+        try {
+            isAutoArchiving = project.getPrearchiveCode() != PrearchiveCode.Manual;
+        } catch (Exception exception) {
+            logger.warn("Error when retrieving project prearchive code", exception);
         }
 
-        /**
-         * Implementation of the method.
-         * @see org.nrg.upload.data.SessionVariableConsumer#update(org.nrg.upload.data.SessionVariable, boolean)
-         */
-        @Override
-        public void update(final SessionVariable v, final boolean isValidValue) {
-            logger.trace("{} updated to {}", v, isValidValue ? "valid" : "invalid");
-            if (isValidValue) {
-                invalid.remove(v);
-            } else {
-                invalid.add(v);
-                setProblem(v.getValueMessage());
-            }
-            setProblem(validateContents(null, null));
+        final Map<String, SessionVariable> predefs = Maps.newLinkedHashMap();
+        predefs.put(PROJECT, new AssignedSessionVariable(PROJECT, project.toString()).fixValue());
+        predefs.put(SUBJECT, new AssignedSessionVariable(SUBJECT, subject.toString()).fixValue());
+        SessionVariable vSession = (SessionVariable) getWizardData(PREDEF_SESSION);
+        if (null != vSession) {
+            predefs.put(SESSION_LABEL, vSession);
         }
 
-        /**
-         * Verifies whether or not user wants to proceed in the case of a verification date mismatch.
-         * @param stepName The name of the current step.
-         * @param settings Any settings for the current step.
-         * @param wizard The current wizard.
-         * @return Returns <b>WizardPanelNavResult.REMAIN_ON_PAGE</b> if the user doesn't confirm, <b>WizardPanelNavResult.PROCEED</b> otherwise.
-         */
-        @Override
-        public WizardPanelNavResult allowNext(String stepName, @SuppressWarnings("rawtypes") Map settings, Wizard wizard) {
-            return sessionDate != null && isSessionDateOk(confirmedDate, sessionDate, session.getTimeZone()) ? WizardPanelNavResult.PROCEED : WizardPanelNavResult.REMAIN_ON_PAGE;
-        }
+        final LinkedList<SessionVariable> vars = Lists.newLinkedList(session.getVariables(getWizardDataMap()));
+        putWizardData(PRODUCT_NAME, vars);
+        logger.trace("initialized session variables: {}", vars);
 
-        /**
-         * Verifies whether or not user wants to proceed in the case of a verification date mismatch.
-         * @param stepName The name of the current step.
-         * @param settings Any settings for the current step.
-         * @param wizard The current wizard.
-         * @return Returns <b>WizardPanelNavResult.REMAIN_ON_PAGE</b> if the user doesn't confirm, <b>WizardPanelNavResult.PROCEED</b> otherwise.
-         */
-        @Override
-        public WizardPanelNavResult allowFinish(String stepName, @SuppressWarnings("rawtypes") Map settings, Wizard wizard) {
-            return WizardPanelNavResult.PROCEED;
-        }
+        final Set<String> modalities = session.getModalities();
 
-        /**
-         * Implements the {@link PropertyChangeListener#propertyChange(PropertyChangeEvent)} method. This is used to
-         * prompt the wizard framework to take notice when something has changed on the page.
-         * @param event    The property change event.
-         */
-        @Override
-        public void propertyChange(PropertyChangeEvent event) {
-            userInputReceived(this, event);
-        }
+        // modality = PET indicates an ECAT data set, so obviously that's PET.
+        final String leadModality = modalities.contains("PET") ? "PET" : SOPModel.getLeadModality(modalities);
 
-        /*
-         * (non-Javadoc)
-         * @see org.netbeans.spi.wizard.WizardPage#recycle()
-         */
-        @Override
-        protected void recycle() {
-            removeAll();
-        }
+        // Strip project and subject out of the List: these are immutable and we'll
+        // display them separately.  Also check whether session has been defined;
+        // we'll use the existing variable if so, or add a new one if not.
+        SessionVariable modalityLabel = null;
+        for (final ListIterator<SessionVariable> i = vars.listIterator(); i.hasNext(); ) {
+            final SessionVariable v = i.next();
+            final String name = v.getName();
+            if (SESSION_LABEL.equals(name)) {
+                vSession = v;
+            } // no else clause: session might also be a predef and we want normal predef handling
 
-        /*
-         * (non-Javadoc)
-         * @see org.netbeans.spi.wizard.WizardPage#renderingPage()
-         */
-        @Override
-        protected void renderingPage() {
-            initialize();
-
-            String expectedModality = (String)this.getWizardData(UploadAssistantApplet.EXPECTED_MODALITY_LABEL);
-            Set<String> modalities = session.getModalities();
-
-            if(expectedModality != null && modalities != null ){
-                if("PT".equalsIgnoreCase(expectedModality) || "PET".equalsIgnoreCase(expectedModality)){
-                    if(! (modalities.contains("PT") || modalities.contains("PET"))){	
-                        JOptionPane.showMessageDialog(this, UNEXPECTED_MODALITY_MESSAGE, UNEXPECTED_MODALITY_TITLE, JOptionPane.WARNING_MESSAGE);
-                    }            	
-                } else {
-                    if(! modalities.contains(expectedModality)){	
-                        JOptionPane.showMessageDialog(this, UNEXPECTED_MODALITY_MESSAGE, UNEXPECTED_MODALITY_TITLE, JOptionPane.WARNING_MESSAGE);
-                    }
+            if (predefs.containsKey(name)) {
+                final SessionVariable predef = predefs.get(name);
+                logger.trace("found predefined variable {} in script", v);
+                i.remove();
+                try {
+                    v.fixValue(predef.getValue());
+                } catch (InvalidValueException e) {
+                    throw new RuntimeException(e);
                 }
-            }
-            if (sessionDate == null && confirmedDate != null) {
-                JOptionPane.showMessageDialog(this, NULL_SESSION_DATE_MESSAGE, NULL_SESSION_DATE_TITLE, JOptionPane.WARNING_MESSAGE);
-            } else if (!isSessionDateOk(confirmedDate, sessionDate, session.getTimeZone())) {
-                JOptionPane.showMessageDialog(this, INVALID_SESSION_DATE_MESSAGE, INVALID_SESSION_DATE_TITLE, JOptionPane.ERROR_MESSAGE);
-            } else {
-                add(addContent(new JPanel(new GridBagLayout())), BorderLayout.CENTER);
+                predefs.put(v.getName(), v);
+            } else if (MODALITY_LABEL.equals(name)) {
+                modalityLabel = v;   // Process this later
             }
         }
 
-        /*
-         * (non-Javadoc)
-         * @see org.netbeans.spi.wizard.WizardPage#validateContents(java.awt.Component, java.lang.Object)
-         */
-        @Override
-        protected String validateContents(final Component component, final Object event) {
-            if (!isSessionDateOk(confirmedDate, sessionDate, session.getTimeZone())) {
-                // We have to go through this whole rigamarole to deal with the Java Date class's inadequacies and general crappiness.
-                // The year being set by dcm4che seems to absolute, i.e. setting 2012 when it really means 2012. The nerve. Instead,
-                // according to Java, it should be setting the offset from 1900, i.e. 112, when it means 2012. But we get what we get.
-                // So, check for a year greater than 1900 and, if found, offset by -1900 and hope like crazy that that's the right thing.
-                Calendar calendar = Calendar.getInstance();
-                calendar.setTime(confirmedDate);
-                //            int year = calendar.get(Calendar.YEAR);
-                //            if (year > 1900) {
-                //                calendar.set(Calendar.YEAR, year - 1900);
-                //            }
-                return "Click the Previous button and select a session with scan date of " +  FORMATTER.format(calendar.getTime());
-            }
-
-            // If verifyDate is empty, we won't allow user to proceed, but we won't do any other validation.
-            boolean stopForDuplicateSessionId = stopForDuplicateSessionId();
-            if (stopForDuplicateSessionId) {
-                return "You must either select another session, change the session ID, or indicate how you want to handle the duplicate session ID for your auto-archiving project.";
-            }
-            final SortedSet<String> names = Sets.newTreeSet();
-            for (final SessionVariable v : invalid) {
-                names.add(v.getName());
-            }
-            if (names.size() > 0) {
-                final StringBuilder buffer = new StringBuilder("Some fields have invalid values: ");
-                final Joiner joiner = Joiner.on(", ");
-                return joiner.appendTo(buffer, names).toString();
-            }
-            return null;
-        }
-
-        /**
-         * Initializes all incoming data from the wizard's data map.
-         */
-        private void initialize() {
-            project = (Project) getWizardData(SelectProjectPage.PRODUCT_NAME);
-            subject = (Subject) getWizardData(SelectSubjectPage.PRODUCT_NAME);
-            session = (Session) getWizardData(SelectSessionPage.PRODUCT_NAME);
-            sessionDate = session.getDateTime();
-            sessionLabel = (SessionVariable) getWizardData(SessionVariableNames.SESSION_LABEL);
-            Object candidate = getWizardData(ConfirmSessionDatePage.PRODUCT_NAME);
-            // If we got a candidate for the confirmed date...
-            if (candidate != null) {
-                // See if it's a date.
-                if (candidate instanceof Date) {
-                    // If so, stash that.
-                    confirmedDate = (Date) candidate;
+        if (null != modalityLabel) {
+            if (modalityLabel instanceof DicomSessionVariable) {
+                final DicomSessionVariable dsv = (DicomSessionVariable) modalityLabel;
+                try {
+                    logger.trace("setting (hidden) modality label from lead modality {}", leadModality);
+                    dsv.setInitialValue(new org.nrg.dcm.edit.ConstantValue(leadModality));
+                    dsv.setIsHidden(true);
+                } catch (MultipleInitializationException exception) {
+                    logger.debug("Got MultipleInitializationException", exception);
                 }
-                // If it wasn't a date, check if it's a string and is the no_session_date qualifier.
-                else if (candidate instanceof String && "no_session_date".equals(candidate)) {
-                    // So if it's no session date, there's a good chance the session date is null. If so, initialize both
-                    // of the dates so that they're matching and we can pass through the date-check logic cleanly.
-                    if (sessionDate == null) {
-                        sessionDate = new Date();
-                    }
-                    confirmedDate = sessionDate;
+            } else if (modalityLabel instanceof EcatSessionVariable) {
+                final EcatSessionVariable esv = (EcatSessionVariable) modalityLabel;
+                try {
+                    esv.setInitialValue(new org.nrg.ecat.edit.ConstantValue("PET"));
+                    esv.setIsHidden(true);
+                } catch (org.nrg.ecat.edit.MultipleInitializationException exception) {
+                    logger.debug("Got MultipleInitializationException", exception);
                 }
             }
         }
 
-        private JPanel addContent(final JPanel panel) {
-            logger.trace("adding content");
+        final ExcludingValueValidator excludeExistingSessions = getSessionExcluder(project, true);
 
-            try {
-                isAutoArchiving = project.getPrearchiveCode() != PrearchiveCode.Manual;
-            } catch (Exception exception) {
-                logger.warn("Error when retrieving project prearchive code", exception);
-            }
+        logger.trace("starting upload for {}", predefs);
 
-            final Map<String,SessionVariable> predefs = Maps.newLinkedHashMap();
-            predefs.put(PROJECT, new AssignedSessionVariable(PROJECT, project.toString()).fixValue());
-            predefs.put(SUBJECT, new AssignedSessionVariable(SUBJECT, subject.toString()).fixValue());
-            SessionVariable vSession = (SessionVariable) getWizardData(PREDEF_SESSION);
-            if (null != vSession) {
-                predefs.put(SESSION_LABEL, vSession);
-            }
+        // If no initial value was provided for session, construct one in the format
+        // {subject}_{modality}{index}, where index is the smallest positive integer
+        // that results in a session label not already defined in this project.
+        final IndexedDependentSessionVariable defaultSessionLabel;
 
-            final LinkedList<SessionVariable> vars = Lists.newLinkedList(session.getVariables(getWizardDataMap()));
-            putWizardData(PRODUCT_NAME, vars);
-            logger.trace("initialized session variables: {}",  vars);
+        logger.trace("building indexed modality default session label from {}", leadModality);
+        defaultSessionLabel = new IndexedDependentSessionVariable(SESSION_LABEL,
+                predefs.get(SUBJECT), "%s_" + leadModality + "%d", excludeExistingSessions);
 
-            final Set<String> modalities = session.getModalities();
-            final String leadModality = modalities.contains("PET") ? "PET" : SOPModel.getLeadModality(modalities);
-            // modality = PET indicates an ECAT dataset, so obviously that's PET.
+        if (null == vSession) {
+            vars.addFirst(vSession = defaultSessionLabel);
+        } else {
+            if (vSession.isMutable() &&
+                    !LabelValueValidator.getInstance().isValid(vSession.getValue())) {
+                // The existing session variable doesn't have a useful initial value,
+                // so shadow it with the default label format.
+                final SessionVariable scriptSession = vSession;
+                try {
+                    vSession.setValue(defaultSessionLabel.getValue());
+                } catch (InvalidValueException e) {
+                    logger.error("unable to set shadowed session variable", e);
+                }
 
-            // Strip project and subject out of the List: these are immutable and we'll
-            // display them separately.  Also check whether session has been defined;
-            // we'll use the existing variable if so, or add a new one if not.
-            SessionVariable modalityLabel = null;
-            for (final ListIterator<SessionVariable> i = vars.listIterator(); i.hasNext(); ) {
-                final SessionVariable v = i.next();
-                final String name = v.getName();
-                if (SESSION_LABEL.equals(name)) {
-                    vSession = v;
-                } // no else clause: session might also be a predef and we want normal predef handling
-
-                if (predefs.containsKey(name)) {
-                    final SessionVariable predef = predefs.get(name);
-                    logger.trace("found predefined variable {} in script", v);
-                    i.remove();
-                    try {
-                        v.fixValue(predef.getValue());
-                    } catch (InvalidValueException e) {
-                        throw new RuntimeException(e);
-                    }
-                    predefs.put(v.getName(), v);
-                } else if (MODALITY_LABEL.equals(name)) {
-                    modalityLabel = v;   // Process this later
-                }
-            }
-
-            if (null != modalityLabel) {
-                if (modalityLabel instanceof DicomSessionVariable) {
-                    final DicomSessionVariable dsv = (DicomSessionVariable)modalityLabel;
-                    try {                    
-                        logger.trace("setting (hidden) modality label from lead modality {}", leadModality);
-                        dsv.setInitialValue(new org.nrg.dcm.edit.ConstantValue(leadModality));
-                        dsv.setIsHidden(true);
-                    } catch (MultipleInitializationException exception) {
-                        logger.debug("Got MultipleInitializationException", exception);
-                    }
-                } else if (modalityLabel instanceof EcatSessionVariable) {
-                    final EcatSessionVariable esv = (EcatSessionVariable)modalityLabel;
-                    try {
-                        esv.setInitialValue(new org.nrg.ecat.edit.ConstantValue("PET"));
-                        esv.setIsHidden(true);
-                    } catch (org.nrg.ecat.edit.MultipleInitializationException exception) {
-                        logger.debug("Got MultipleInitializationException", exception);
+                defaultSessionLabel.addShadow(vSession);
+                vSession = defaultSessionLabel;
+                for (final ListIterator<SessionVariable> li = vars.listIterator(); li.hasNext(); ) {
+                    if (scriptSession == li.next()) {
+                        li.set(vSession);
+                        break;
                     }
                 }
             }
+        }
+        if (vSession.isMutable()) {
 
-            final ExcludingValueValidator excludeExistingSessions = getSessionExcluder(project, true);
+            vSession.addValidator(LabelValueValidator.getInstance());
+            // vSession.addValidator(excludeExistingSessions);
+        }
 
-            logger.trace("starting upload for {}", predefs);
+        // Session name, like project and subject, must be available in the wizard params.
+        putWizardData(vSession.getName(), vSession);
 
-            // If no initial value was provided for session, construct one in the format
-            // {subject}_{modality}{index}, where index is the smallest positive integer
-            // that results in a session label not already defined in this project.
-            final IndexedDependentSessionVariable defaultSessionLabel;
+        addSessionIdentifiers(panel, predefs, vars);
 
-            logger.trace("building indexed modality default session label from {}", leadModality);
-            defaultSessionLabel = new IndexedDependentSessionVariable(SESSION_LABEL,
-                    predefs.get(SUBJECT), "%s_" + leadModality + "%d", excludeExistingSessions);
+        return panel;
+    }
 
-            if (null == vSession) {
-                vars.addFirst(vSession = defaultSessionLabel);
-            } else {
-                if (vSession.isMutable() &&
-                        !LabelValueValidator.getInstance().isValid(vSession.getValue())) {
-                    // The existing session variable doesn't have a useful initial value,
-                    // so shadow it with the default label format.
-                    final SessionVariable scriptSession = vSession;
-                    try {
-                        vSession.setValue(defaultSessionLabel.getValue());
-                    } catch (InvalidValueException e) {
-                        logger.error("unable to set shadowed session variable", e);
-                    }
-
-                    defaultSessionLabel.addShadow(vSession);
-                    vSession = defaultSessionLabel;
-                    for (final ListIterator<SessionVariable> li = vars.listIterator(); li.hasNext(); ) {
-                        if (scriptSession == li.next()) {
-                            li.set(vSession);
-                            break;
+    /**
+     * Indicates whether a duplicate session ID has been identified for an auto-archived project and if the user has
+     * indicated how to handle it.
+     *
+     * @return <b>false</b> if the project is not set to auto-archive, the selected session ID is not a duplicate of an
+     *         existing session ID, or the user has indicated whether the duplicate session should be appended to or
+     *         overwrite the existing session with the duplicate ID. In the case where a duplicate session ID is found
+     *         for an auto-archiving project and the user selects <b>Cancel</b> on the option dialog, this method
+     *         returns <b>true</b>.
+     */
+    private boolean stopForDuplicateSessionId(String candidate, boolean showDialog) {
+        // Notify about duplicate session IDs when warning flag is set or the project is auto-archived.
+        if (warnOnDupeSessionLabels || isAutoArchiving) {
+            try {
+                Map<String, String> labels = project.getSessionLabels();
+                if (!StringUtils.isBlank(candidate) && labels.containsKey(candidate)) {
+                    if (showDialog) {
+                        int selected = JOptionPane.showOptionDialog(this, DUP_SESSION_ID_MESSAGE, DUP_SESSION_ID_TITLE, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, DUP_SESSION_ID_OPTIONS, DUP_SESSION_ID_OPTIONS[2]);
+                        switch (selected) {
+                            case JOptionPane.YES_OPTION:
+                                putWizardData(Project.AUTO_ARCHIVE, AutoArchive.Overwrite);
+                                break;
+                            case JOptionPane.NO_OPTION:
+                                putWizardData(Project.AUTO_ARCHIVE, AutoArchive.Append);
+                                break;
+                            case JOptionPane.CLOSED_OPTION:
+                            case JOptionPane.CANCEL_OPTION:
+                                return true;
                         }
+                    } else {
+                        return true;
                     }
                 }
+            } catch (Exception exception) {
+                logger.warn("Error when retrieving project session labels for project", exception);
             }
-            if (vSession.isMutable()) {
-
-                vSession.addValidator(LabelValueValidator.getInstance());
-                // vSession.addValidator(excludeExistingSessions);
-            }
-
-            // Session name, like project and subject, must be available in the wizard params.
-            putWizardData(vSession.getName(), vSession);
-
-            addSessionIdentifiers(panel, predefs, vars);
-
-            return panel;
         }
 
-        /**
-         * Indicates whether a duplicate session ID has been identified for an auto-archived project and if the user has
-         * indicated how to handle it.
-         * @return <b>false</b> if the project is not set to auto-archive, the selected session ID is not a duplicate of an
-         *         existing session ID, or the user has indicated whether the duplicate session should be appended to or
-         *         overwrite the existing session with the duplicate ID. In the case where a duplicate session ID is found
-         *         for an auto-archiving project and the user selects <b>Cancel</b> on the option dialog, this method
-         *         returns <b>true</b>.
-         */
-        private boolean stopForDuplicateSessionId() {
-            // We only care about duplicate session IDs when the project is auto-archived.
-            if (isAutoArchiving) {
-                try {
-                    Map<String, String> labels = project.getSessionLabels();
-                    if (labels.containsKey(sessionLabel.getValue())) {
-                        int selected = JOptionPane.showOptionDialog(this, DUP_SESSION_ID_MESSAGE, DUP_SESSION_ID_TITLE, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, DUP_SESSION_ID_OPTIONS, DUP_SESSION_ID_OPTIONS[2]);
-                        switch (selected) {
-                        case JOptionPane.YES_OPTION:
-                            putWizardData(Project.AUTO_ARCHIVE, AutoArchive.Overwrite);
-                            break;
-                        case JOptionPane.NO_OPTION:
-                            putWizardData(Project.AUTO_ARCHIVE, AutoArchive.Append);
-                            break;
-                        case JOptionPane.CANCEL_OPTION:
-                            return true;
-                        }
-                    }
-                } catch (Exception exception) {
-                    logger.warn("Error when retrieving project session labels for project", exception);
-                }
-            }
+        return false;
+    }
 
+    private void addSessionIdentifiers(JPanel panel, Map<String, SessionVariable> predefs, LinkedList<SessionVariable> vars) {
+        for (final SessionVariable v : predefs.values()) {
+            panel.add(new JLabel(v.getDescription()), VariableAssignmentManager.labelConstraint);
+            panel.add(new JLabel(v.getValue()), VariableAssignmentManager.valueConstraint);
+        }
+
+        if (vars.size() > 0) {
+            panel.add(new JLabel("<html><b>Set session identifiers:</b></html>"), SPANNING);
+            panel.add(new JLabel(), VariableAssignmentManager.messageConstraint);
+        }
+        new VariableAssignmentManager(panel, vars, this);
+    }
+
+    private ExcludingValueValidator getSessionExcluder(final Project project, final boolean isStrict) {
+        Set<String> labels;
+        try {
+            labels = project.getSessionLabels().keySet();
+        } catch (Exception e) {
+            labels = Collections.emptySet();
+        }
+        return new ExcludingValueValidator(labels, "Project already contains a session named %s.", isStrict);
+    }
+