Beispiel #1
0
        /// <summary>
        /// Marks a imaging as completed.
        /// </summary>
        void IImagingTaskProvider.ImagedPlate(Formulatrix.Integrations.ImagerLink.IRobot robot, string plateID, string imagingID)
        {
            // Check arguments - do it up front to avoid possible inconsistencies later
            if (null == robot)
            {
                throw new System.NullReferenceException("robot must not be null");
            }
            if (null == plateID)
            {
                throw new System.NullReferenceException("plateID must not be null");
            }
            if (null == imagingID)
            {
                throw new System.NullReferenceException("imagingID must not be null");
            }

            // Log the call to the method
            if (_log.IsDebugEnabled)
            {
                string msg = "Called " + this + ".ImagedPlate(robot=" + RobotUtils.iRobotToString(robot) + ", plateID=\"" + plateID + "\", imagingID=\"" + imagingID + "\")";
                _log.Debug(msg);
            }

            // Set the request
            imagedPlate request = new imagedPlate();

            request.robot     = OPPF.Utilities.RobotUtils.createProxy(robot);
            request.plateID   = plateID;
            request.imagingID = imagingID;

            // Make the call
            WSPlate             wsPlate  = new WSPlate();
            imagedPlateResponse response = null;

            try
            {
                response = wsPlate.imagedPlate(request);
            }
            catch (Exception e)
            {
                // Log it
                string msg = "WSPlate.imagedPlate threw " + e.GetType() + ": " + e.Message + " - panic!";
                msg = msg + "\nin " + this + ".ImagedPlate(robot=" + RobotUtils.iRobotToString(robot) + ", plateID=\"" + plateID + "\", imagingID=\"" + imagingID + "\")";
                if (e is System.Web.Services.Protocols.SoapException)
                {
                    System.Web.Services.Protocols.SoapException ee = (System.Web.Services.Protocols.SoapException)e;
                    msg = msg + "\n\n" + ee.Detail.InnerXml;
                }
                _log.Fatal(msg, e);

                // Panic
                throw e;
            }

            // Webservice always returns true if it doesn't throw an exception
            return;
        }
Beispiel #2
0
        /// <summary>
        /// If this <c>IImagingTaskProvider</c> supports changing priority,
        /// changes the priority of the IImagingTask with this <c>dateToImage</c>.
        /// </summary>
        void IImagingTaskProvider.UpdatedPriority(Formulatrix.Integrations.ImagerLink.IRobot robot, string plateID, DateTime dateToImage, int priority)
        {
            // Check arguments - do it up front to avoid possible inconsistencies later
            if (null == robot)
            {
                throw new System.NullReferenceException("robot must not be null");
            }
            if (null == plateID)
            {
                throw new System.NullReferenceException("plateID must not be null");
            }

            // Log the call to the method
            if (_log.IsDebugEnabled)
            {
                string msg = "Called " + this + ".UpdatedPriority(robot=" + RobotUtils.iRobotToString(robot) + ", plateID=\"" + plateID + "\", dateToImage=" + dateToImage.ToUniversalTime().ToString() + " UTC, priority=" + priority + ")";
                _log.Debug(msg);
            }

            // Set the request
            updatedPriority request = new updatedPriority();

            request.robot   = OPPF.Utilities.RobotUtils.createProxy(robot);
            request.plateID = plateID;
            // .NET < 2.0
            //request.dateToImage = dateToImage;
            // .NET >= 2.0
            request.dateToImage = dateToImage.ToUniversalTime();
            request.priority    = priority;

            // Make the call
            WSPlate wsPlate = new WSPlate();

            try
            {
                wsPlate.updatedPriority(request);
            }
            catch (Exception e)
            {
                // Log it
                string msg = "WSPlate.updatedPriority threw " + e.GetType() + ": " + e.Message + " - ignoring";
                if (e is System.Web.Services.Protocols.SoapException)
                {
                    System.Web.Services.Protocols.SoapException ee = (System.Web.Services.Protocols.SoapException)e;
                    msg = msg + "\n\n" + ee.Detail.InnerXml;
                }
                _log.Warn(msg, e);

                // Don't rethrow - just return - don't really care if this didn't work
                return;
            }

            // Webservice always returns true if there is no exception
            return;
        }
Beispiel #3
0
 public static WSPlate getWSPlate2()
 {
     if (null == wsPlate2)
     {
         ServicePointManager.Expect100Continue = false;
         wsPlate2             = new WSPlate();
         wsPlate2.Url         = OPPFConfigXML.GetWsPlateEndpoint();
         wsPlate2.Credentials = new NetworkCredential(OPPFConfigXML.GetUsername(), OPPFConfigXML.GetPassword());
     }
     return(wsPlate2);
 }
Beispiel #4
0
        /// <summary>
        /// Marks an imaging as skipped.
        /// </summary>
        void IImagingTaskProvider.SkippedImaging(Formulatrix.Integrations.ImagerLink.IRobot robot, string plateID, DateTime dateToImage)
        {
            // Check arguments - do it up front to avoid possible inconsistencies later
            if (null == robot)
            {
                throw new System.NullReferenceException("robot must not be null");
            }
            if (null == plateID)
            {
                throw new System.NullReferenceException("plateID must not be null");
            }

            // Log the call to the method
            if (_log.IsDebugEnabled)
            {
                string msg = "Called " + this + ".SkippedImaging(robot=" + RobotUtils.iRobotToString(robot) + ", plateID=\"" + plateID + "\", dateToImage=" + dateToImage.ToUniversalTime().ToString() + " UTC)";
                _log.Debug(msg);
            }

            // Set the request
            skippedImaging request = new skippedImaging();

            request.robot       = OPPF.Utilities.Robot2Utils.createProxy(robot);
            request.plateID     = plateID;
            request.dateToImage = dateToImage.ToUniversalTime();

            // Make the call
            WSPlate wsPlate = WSPlateFactory.getWSPlate2();
            skippedImagingResponse response = null;

            try
            {
                response = wsPlate.skippedImaging(request);
            }
            catch (Exception e)
            {
                // Log it
                string msg = "WSPlate.skippedImaging threw " + e.GetType() + ": " + e.Message + " - ignoring";
                msg = msg + "\nin " + this + ".SkippedImaging(robot=" + RobotUtils.iRobotToString(robot) + ", plateID=\"" + plateID + "\", dateToImage=" + dateToImage.ToUniversalTime().ToString() + " UTC)";
                if (e is System.Web.Services.Protocols.SoapException)
                {
                    System.Web.Services.Protocols.SoapException ee = (System.Web.Services.Protocols.SoapException)e;
                    msg = msg + "\n\n" + ee.Detail.InnerXml;
                }
                _log.Warn(msg, e);

                // Don't rethrow - just return - don't really care if this didn't work
                return;
            }

            // Webservice always returns true if it doesn't throw an exception
            return;
        }
Beispiel #5
0
        /// <summary>
        /// Return <c>true</c> if this provider supplies <c>IImagingTask.Priority</c>.
        /// Otherwise the imager should manage individual task priority.
        /// </summary>
        bool IImagingTaskProvider.SupportsPriority(Formulatrix.Integrations.ImagerLink.IRobot robot)
        {
            // OPPF PERFORMANCE BODGE - Actually this method should always return true!
            return(true);

            // Check arguments - do it up front to avoid possible inconsistencies later
            if (null == robot)
            {
                throw new System.NullReferenceException("robot must not be null");
            }

            // Log the call to the method
            if (_log.IsDebugEnabled)
            {
                string msg = "Called " + this + ".SupportsPriority(robot=" + RobotUtils.iRobotToString(robot) + ")";
                _log.Debug(msg);
            }

            // Set the request
            supportsPriority request = new supportsPriority();

            request.robot = OPPF.Utilities.RobotUtils.createProxy(robot);

            // Make the call
            WSPlate wsPlate = new WSPlate();
            supportsPriorityResponse response = null;

            try
            {
                response = wsPlate.supportsPriority(request);
            }
            catch (Exception e)
            {
                // Log it
                string msg = "WSPlate.supportsPriority threw " + e.GetType() + ": " + e.Message + " - ignoring";
                if (e is System.Web.Services.Protocols.SoapException)
                {
                    System.Web.Services.Protocols.SoapException ee = (System.Web.Services.Protocols.SoapException)e;
                    msg = msg + "\n\n" + ee.Detail.InnerXml;
                }
                _log.Warn(msg, e);

                // Don't rethrow - just return false
                return(false);
            }

            // Return the response's value
            //_log.Debug("supportsPriority returned " + response.supportsPriorityReturn);
            return(response.supportsPriorityReturn);
        }
Beispiel #6
0
        /// <summary>
        /// Retrieves a plate description from the web service.
        /// </summary>
        /// <param name="robot">The robot to find the plate type for.</param>
        /// <param name="plateID">The <c>plateID</c> of the plate.</param>
        /// <returns>The <c>IPlateInfo</c> describing the plate.</returns>
        public IPlateInfo FetchPlateInfo(IRobot robot, string plateID)
        {
            // Check arguments - do it up front to avoid possible inconsistencies later
            if (robot == null)
            {
                throw new System.NullReferenceException("robot must not be null");
            }
            if (plateID == null)
            {
                throw new System.NullReferenceException("plateID must not be null");
            }

            // Log the call
            if (_log.IsDebugEnabled)
            {
                string msg = "Called " + this + ".FetchPlateInfo(robot=" + robot.ToString() + ", plateID=\"" + plateID + "\")";
                _log.Debug(msg);
            }

            // Special case for ReliabilityTestPlate
            if ("ReliabilityTestPlate".Equals(plateID))
            {
                global::OPPF.Integrations.ImagerLink.PlateInfo dummy = new global::OPPF.Integrations.ImagerLink.PlateInfo();
                dummy.SetDateDispensed(DateTime.Now);
                dummy.SetExperimentName("Dummy Expt Name");
                dummy.SetPlateNumber(1);
                dummy.SetPlateTypeID("1");
                dummy.SetProjectName("Dummy Project Name");
                dummy.SetUserEmail("DummyEmailAddress");
                dummy.SetUserName("Dummy UserName");

                return(dummy);
            }

            // Declare the return variable
            global::OPPF.Integrations.ImagerLink.PlateInfo pi = null;

            try
            {
                // Create and populate the request object
                getPlateInfo request = new getPlateInfo();
                request.robot   = global::OPPF.Utilities.RobotUtils.createProxy(robot);
                request.plateID = plateID;

                // Make the web service call
                WSPlate wsPlate = new WSPlate();
                getPlateInfoResponse response = wsPlate.getPlateInfo(request);

                // Get the webservice proxy PlateInfo
                global::OPPF.Proxies.PlateInfo ppi = response.getPlateInfoReturn;

                // Map it into an IPlateInfo
                pi = new global::OPPF.Integrations.ImagerLink.PlateInfo();
                pi.SetDateDispensed(ppi.dateDispensed);
                pi.SetExperimentName(ppi.experimentName);
                pi.SetPlateNumber(ppi.plateNumber);
                pi.SetPlateTypeID(ppi.plateTypeID);
                pi.SetProjectName(ppi.projectName);
                pi.SetUserEmail(ppi.userEmail);
                pi.SetUserName(ppi.userName);
            }
            catch (Exception e)
            {
                string msg = "WSPlate.getPlateInfo threw " + e.GetType() + ":\n" + e.Message + "\nfor plate \"" + plateID + "\" in robot \"" + robot.Name + "\"\n - probably not in LIMS - not fatal.";
                msg = msg + global::OPPF.Utilities.WSPlateFactory.SoapExceptionToString(e);

                // Log it
                _log.Error(msg, e);

                // Don't rethrow - return null - don't want to stop imaging
            }

            // Return the IPlateInfo
            return(pi);
        }
Beispiel #7
0
        /// <summary>
        /// Plate is starting to image. Returns an imaging identifier that will be
        /// embedded in the image names, and returned in ImagedPlate or null if
        /// the ImagingID is unavailable.
        /// </summary>
        public string ImagingPlate(Formulatrix.Integrations.ImagerLink.IRobot robot, string plateID, bool scheduled, DateTime dateToImage, DateTime dateImaged)
        {
            // Check arguments - do it up front to avoid possible inconsistencies later
            if (null == robot)
            {
                throw new System.NullReferenceException("robot must not be null");
            }
            if (null == plateID)
            {
                throw new System.NullReferenceException("plateID must not be null");
            }

            // Log the call to the method
            if (_log.IsInfoEnabled)
            {
                string msg = "Called " + this + ".ImagingPlate(robot=" + RobotUtils.iRobotToString(robot) + ", plateID=\"" + plateID + "\", scheduled=\"" + scheduled + "\", dateToImage=" + dateToImage.ToUniversalTime().ToString() + " UTC, dateImaged=" + dateImaged.ToUniversalTime().ToString() + " UTC)";
                _log.Info(msg);
            }

            // Set the request
            imagingPlate request = new imagingPlate();

            request.robot     = global::OPPF.Utilities.Robot2Utils.createProxy(robot);
            request.plateID   = plateID;
            request.scheduled = scheduled;
            //request.dateToImage = dateToImage.ToUniversalTime();
            // Is this a fix for the date collision problem?
            if (scheduled)
            {
                request.dateToImage = dateToImage.ToUniversalTime();
            }
            else
            {
                request.dateToImage = dateImaged.ToUniversalTime();
            }
            request.dateImaged = dateImaged.ToUniversalTime();


            // Make the call
            WSPlate wsPlate = WSPlateFactory.getWSPlate2();
            imagingPlateResponse response = null;

            try
            {
                response = wsPlate.imagingPlate(request);
            }
            catch (Exception e)
            {
                string msg = "WSPlate.imagingPlate threw " + e.GetType() + ": " + e.Message + " - panic!";
                msg = msg + "\nin " + this + ".ImagingPlate(robot=" + RobotUtils.iRobotToString(robot) + ", plateID=\"" + plateID + "\", dateToImage=" + dateToImage.ToUniversalTime().ToString() + " UTC, dateImaged=" + dateImaged.ToUniversalTime().ToString() + " UTC)";
                msg = msg + WSPlateFactory.SoapExceptionToString(e);
                _log.Fatal(msg, e);

                // Panic
                throw;
            }

            // If we got no response
            if (null == response)
            {
                string msg = "WSPlate.imagingPlate returned null - panic!";
                msg = msg + "\nin " + this + ".ImagingPlate(robot=" + RobotUtils.iRobotToString(robot) + ", plateID=\"" + plateID + "\", dateToImage=" + dateToImage.ToUniversalTime().ToString() + " UTC, dateImaged=" + dateImaged.ToUniversalTime().ToString() + " UTC)";
                _log.Fatal(msg);

                // Panic
                throw new System.NullReferenceException(msg);
            }

            // If we got a null imagingID
            if (null == response.imagingPlateReturn)
            {
                string msg = "WSPlate.imagingPlate returned a null imagingID - panic!";
                msg = msg + "\nin " + this + ".ImagingPlate(robot=" + RobotUtils.iRobotToString(robot) + ", plateID=\"" + plateID + "\", dateToImage=" + dateToImage.ToUniversalTime().ToString() + " UTC, dateImaged=" + dateImaged.ToUniversalTime().ToString() + " UTC)";
                _log.Fatal(msg);

                // Panic
                throw new System.NullReferenceException(msg);
            }

            // Return the imagingID
            return(response.imagingPlateReturn);
        }
Beispiel #8
0
        /// <summary>
        /// Web service version of GetImagingTasks - useful because it will
        /// cause a full schedule to be written if one doesn't already
        /// exist.
        ///
        /// Warning - this is a lot slower than going straight to platedb!
        /// </summary>
        /// <param name="robot">The robot</param>
        /// <param name="plateID">The barcode of the plate</param>
        /// <returns></returns>
        public IImagingTask[] GetImagingTasksFromWebService(Formulatrix.Integrations.ImagerLink.IRobot robot, string plateID)
        {
            // Check arguments - do it up front to avoid possible inconsistencies later
            if (null == robot)
            {
                throw new System.NullReferenceException("robot must not be null");
            }
            if (null == plateID)
            {
                throw new System.NullReferenceException("plateID must not be null");
            }

            // Log the call
            if (_log.IsInfoEnabled)
            {
                string msg = "Calling WSPlate.getImagingTasks() for plate " + plateID + ", robot " + RobotUtils.iRobotToString(robot);
                _log.Info(msg);
            }

            // Declare the array that will be populated and returned
            // - default to a zero-length array
            IImagingTask[] iImagingTasks = new IImagingTask[0];

            // Set the request
            getImagingTasks request = new getImagingTasks();

            request.robot   = global::OPPF.Utilities.Robot2Utils.createProxy(robot);
            request.plateID = plateID;

            // Make the call
            getImagingTasksResponse response = null;

            try
            {
                WSPlate wsPlate = WSPlateFactory.getWSPlate2();
                wsPlate.Timeout = 10000;
                response        = wsPlate.getImagingTasks(request);
            }
            catch (Exception e)
            {
                // Log it
                string msg = "WSPlate.getImagingTasks threw " + e.GetType() + ": " + e.Message + " for plateid \"" + plateID + "\" in robot \"" + robot.Name + "\" - returning empty IImagingTask[]";
                msg = msg + WSPlateFactory.SoapExceptionToString(e);
                _log.Error(msg, e);

                // Don't rethrow - just return empty array
                return(iImagingTasks);
            }

            // If we got a response
            if (null != response)
            {
                // Get the array of ImagingTasks from the response
                global::OPPF.Proxies2.ImagingTask[] wrapper = response.wrapper;

                // Convert to IImagingTasks
                iImagingTasks = new IImagingTask[wrapper.GetLength(0)];
                for (int i = 0; i < wrapper.GetLength(0); i++)
                {
                    global::OPPF.Integrations.ImagerLink.Scheduling.ImagingTask task = new global::OPPF.Integrations.ImagerLink.Scheduling.ImagingTask();
                    if (wrapper[i].dateImaged.HasValue)
                    {
                        task.SetDateImaged(wrapper[i].dateImaged.Value);
                    }
                    task.SetDateToImage(wrapper[i].dateToImage);
                    task.SetInQueue(wrapper[i].inQueue);
                    task.SetPriority(wrapper[i].priority);
                    task.SetState((Formulatrix.Integrations.ImagerLink.Scheduling.ImagingState)wrapper[i].state);

                    iImagingTasks[i] = task;
                }
            }

            // Return the IImagingTask array
            return(iImagingTasks);
        }
Beispiel #9
0
        /// <summary>
        /// Plate is starting to image. Returns an imaging identifier that will be
        /// embedded in the image names, and returned in ImagedPlate or null if
        /// the ImagingID is unavailable.
        /// </summary>
        string IImagingTaskProvider.ImagingPlate(Formulatrix.Integrations.ImagerLink.IRobot robot, string plateID, bool scheduled, DateTime dateToImage, DateTime dateImaged)
        {
            // Check arguments - do it up front to avoid possible inconsistencies later
            if (null == robot)
            {
                throw new System.NullReferenceException("robot must not be null");
            }
            if (null == plateID)
            {
                throw new System.NullReferenceException("plateID must not be null");
            }

            // Log the call to the method
            if (_log.IsDebugEnabled)
            {
                string msg = "Called " + this + ".ImagingPlate(robot=" + RobotUtils.iRobotToString(robot) + ", plateID=\"" + plateID + "\", dateToImage=" + dateToImage.ToUniversalTime().ToString() + " UTC, dateImaged=" + dateImaged.ToUniversalTime().ToString() + " UTC)";
                _log.Debug(msg);
            }

            // Set the request
            imagingPlate request = new imagingPlate();

            request.robot       = OPPF.Utilities.RobotUtils.createProxy(robot);
            request.plateID     = plateID;
            request.scheduled   = scheduled;
            request.dateToImage = dateToImage.ToUniversalTime();
            request.dateImaged  = dateImaged.ToUniversalTime();

            // Make the call
            WSPlate wsPlate = new WSPlate();
            imagingPlateResponse response = null;

            try
            {
                response = wsPlate.imagingPlate(request);
            }
            catch (Exception e)
            {
                string msg = "WSPlate.imagingPlate threw " + e.GetType() + ": " + e.Message + " - panic!";
                msg = msg + "\nin " + this + ".ImagingPlate(robot=" + RobotUtils.iRobotToString(robot) + ", plateID=\"" + plateID + "\", dateToImage=" + dateToImage.ToUniversalTime().ToString() + " UTC, dateImaged=" + dateImaged.ToUniversalTime().ToString() + " UTC)";
                if (e is System.Web.Services.Protocols.SoapException)
                {
                    System.Web.Services.Protocols.SoapException ee = (System.Web.Services.Protocols.SoapException)e;
                    msg = msg + "\n\n" + ee.Detail.InnerXml;
                }
                _log.Fatal(msg, e);

                // Panic
                throw e;
            }

            // If we got no response
            if (null == response)
            {
                string msg = "WSPlate.imagingPlate returned null - panic!";
                msg = msg + "\nin " + this + ".ImagingPlate(robot=" + RobotUtils.iRobotToString(robot) + ", plateID=\"" + plateID + "\", dateToImage=" + dateToImage.ToUniversalTime().ToString() + " UTC, dateImaged=" + dateImaged.ToUniversalTime().ToString() + " UTC)";
                _log.Fatal(msg);

                // Panic
                throw new System.NullReferenceException(msg);
            }

            // If we got a null imagingID
            if (null == response.imagingPlateReturn)
            {
                string msg = "WSPlate.imagingPlate returned a null imagingID - panic!";
                msg = msg + "\nin " + this + ".ImagingPlate(robot=" + RobotUtils.iRobotToString(robot) + ", plateID=\"" + plateID + "\", dateToImage=" + dateToImage.ToUniversalTime().ToString() + " UTC, dateImaged=" + dateImaged.ToUniversalTime().ToString() + " UTC)";
                _log.Fatal(msg);

                // Panic
                throw new System.NullReferenceException(msg);
            }

            // Return the imagingID
            return(response.imagingPlateReturn);
        }
Beispiel #10
0
        /// <summary>
        /// Retrieve all the plate types. The list of PlateTypes is cached for _cacheLifetime min.
        /// </summary>
        /// <param name="robot">The robot to find the plate types for.</param>
        /// <returns>An array of plate types, or null if there are none.</returns>
        IPlateType[] IPlateInfoProvider.GetPlateTypes(IRobot robot)
        {
            // Check arguments - do it up front to avoid possible inconsistencies later
            if (robot == null)
            {
                throw new System.NullReferenceException("robot must not be null");
            }

            // Log the call
            if (_log.IsDebugEnabled)
            {
                string msg = "Called " + this + ".GetPlateTypes(robot=" + robot.ToString() + ")";
                _log.Debug(msg);
            }

            // Return cached values if appropriate
            if ((_plateTypes != null) && (System.DateTime.Now.Ticks <= _plateTypesCacheExpires))
            {
                _log.Debug("GetPlateTypes() using cached response");
                return(_plateTypes);
            }

            _log.Debug("GetPlateTypes() refreshing cache");

            // Sychronize this block as we are interacting with the cache
            lock (_plateTypesLock)
            {
                try
                {
                    // Create and populate the request object
                    getPlateTypes request = new getPlateTypes();
                    request.robot = OPPF.Utilities.RobotUtils.createProxy(robot);

                    // Make the web service call
                    WSPlate wsPlate = new WSPlate();

                    // New stuff
                    wsPlate.Url = "http://localhost:8080/xtalpims-ws/services/WSPlate.WSPlateSOAP12port_http/";
                    ServicePointManager.Expect100Continue = false;
                    wsPlate.Credentials = new NetworkCredential("jon", "test123");
                    // End new stuff

                    getPlateTypesResponse response = wsPlate.getPlateTypes(request);

                    // Get the array of proxy PlateType[]
                    OPPF.Proxies.PlateType[] pptArray = response.wrapper;

                    // Map into an array of IPlateType[]
                    OPPF.Integrations.ImagerLink.PlateType[] iptArray = new OPPF.Integrations.ImagerLink.PlateType[pptArray.Length];
                    int i = 0;
                    foreach (OPPF.Proxies.PlateType ppt in pptArray)
                    {
                        iptArray[i] = new OPPF.Integrations.ImagerLink.PlateType();
                        iptArray[i].SetID(ppt.iD);
                        iptArray[i].SetName(ppt.name);
                        iptArray[i].SetNumColumns(ppt.numColumns);
                        iptArray[i].SetNumDrops(ppt.numDrops);
                        iptArray[i].SetNumRows(ppt.numRows);
                        i++;
                    }

                    // Copy into the cache and update cache expiry
                    _plateTypes             = iptArray;
                    _plateTypesCacheExpires = System.DateTime.Now.Ticks + _cacheLifetime;

                    _log.Debug("GetPlateTypes() using fresh response");
                }
                catch (Exception e)
                {
                    // Log it
                    string msg = "WSPlate.getPlateTypes threw " + e.GetType() + ": " + e.Message + " for robot \"" + robot.Name + "\" - returning null";
                    if (e is System.Web.Services.Protocols.SoapException)
                    {
                        System.Web.Services.Protocols.SoapException ee = (System.Web.Services.Protocols.SoapException)e;
                        msg = msg + "\n\n" + ee.Detail.InnerXml;
                    }
                    _log.Error(msg, e);

                    // Don't rethrow - return cache (which might be null) - don't want to stop imaging
                }
            }

            // Return the array of IPlateType[]
            return(_plateTypes);
        }
        /// <summary>
        /// Find and process the ImageInfo xml files
        /// </summary>
        /// <returns>True if there may be more files to process.</returns>
        public bool processImageInfos()
        {
            bool moreImageInfos = false;

            DirectoryInfo di = new DirectoryInfo(imageInfosDir);

            DirectoryInfo processed = new DirectoryInfo(Path.Combine(di.FullName, @"Processed"));

            if (!processed.Exists)
            {
                processed.Create();
            }

            DirectoryInfo quarantine = new DirectoryInfo(Path.Combine(di.FullName, @"Quarantine"));

            if (!quarantine.Exists)
            {
                quarantine.Create();
            }

            // TODO Potentially expensive - can we iterate?
            FileInfo[] files = di.GetFiles("*.xml", SearchOption.TopDirectoryOnly);

            List <UploadImage> uploadImageList = new List <UploadImage>();
            //List<FileInfo> filesToProcess = new List<FileInfo>();
            Dictionary <string, FileInfo> urlToFiles = new Dictionary <string, FileInfo>();
            long threshold = DateTime.Now.Ticks - (TimeSpan.TicksPerSecond * 10);

            try
            {
                foreach (FileInfo fi in files)
                {
                    // File at least 10 seconds old
                    if ((threshold > fi.CreationTimeUtc.Ticks) && (threshold > fi.LastWriteTimeUtc.Ticks))
                    {
                        // Read XML
                        XmlSerializer serializer = new XmlSerializer(typeof(ImageInfo));
                        TextReader    reader     = new StreamReader(fi.FullName);
                        ImageInfo     imageInfo  = (ImageInfo)serializer.Deserialize(reader);
                        reader.Close();

                        OPPF.Proxies2.UploadImage uploadImage = parseImageInfo(imageInfo);

                        uploadImageList.Add(uploadImage);
                        //filesToProcess.Add(fi);
                        urlToFiles.Add(uploadImage.url, fi);

                        if (maxChunk <= uploadImageList.Count)
                        {
                            moreImageInfos = true;
                            break;
                        }
                    }
                }

                if (0 < uploadImageList.Count)
                {
                    OPPF.Proxies2.uploadImages uploadImagesElement = new uploadImages();
                    uploadImagesElement.wrapper = uploadImageList.ToArray();

                    WSPlate ws = WSPlateFactory.getWSPlate2();
                    OPPF.Proxies2.uploadImagesResponse  response  = ws.uploadImages(uploadImagesElement);
                    OPPF.Proxies2.UploadImageResponse[] responses = response.wrapper;

                    /*
                     * foreach (FileInfo src in filesToProcess)
                     * {
                     *  string dest = Path.Combine(processed.FullName, src.Name);
                     *  src.MoveTo(dest);
                     *  log.Info("Processed " + src.FullName);
                     * }
                     */

                    for (int i = 0; i < responses.Length; i++)
                    {
                        FileInfo src;
                        urlToFiles.TryGetValue(responses[i].url, out src);

                        if (null == src)
                        {
                            log.Error("Failed to match url " + responses[i].url + " to known image file");
                        }

                        else if (responses[i].ok)
                        {
                            string dest = Path.Combine(processed.FullName, src.Name);
                            src.MoveTo(dest);
                            log.Info("Processed " + src.FullName);
                        }
                        else
                        {
                            string dest = Path.Combine(quarantine.FullName, src.Name);
                            src.MoveTo(dest);
                            log.Warn("Quarantined " + src.FullName + ": " + responses[i].reason);
                        }
                    }
                }
                else
                {
                    log.Info("Nothing to do");
                }
            }
            catch (Exception e)
            {
                // Log it
                log.Error(e);

                Dictionary <string, FileInfo> .ValueCollection filesToProcess = urlToFiles.Values;
                foreach (FileInfo src in filesToProcess)
                {
                    try
                    {
                        string dest = Path.Combine(quarantine.FullName, src.Name);
                        src.MoveTo(dest);
                        log.Warn("Quarantined " + src.FullName + ": " + e.Message, e);
                    }
                    catch (Exception e2)
                    {
                        // Log it
                        log.Error("Failed to Quarantine " + src.FullName + ": " + e2.Message, e2);
                    }
                }
            }

            return(moreImageInfos);
        }