context: #region License
  
  // Copyright (c) 2013, ClearCanvas Inc.
  // All rights reserved.
  // http://www.clearcanvas.ca
  //
  // This file is part of the ClearCanvas RIS/PACS open source project.
  //
  // The ClearCanvas RIS/PACS open source project is free software: you can
  // redistribute it and/or modify it under the terms of the GNU General Public
  // License as published by the Free Software Foundation, either version 3 of the
  // License, or (at your option) any later version.
  //
  // The ClearCanvas RIS/PACS open source project is distributed in the hope that it
  // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
  // Public License for more details.
  //
  // You should have received a copy of the GNU General Public License along with
  // the ClearCanvas RIS/PACS open source project.  If not, see
  // <http://www.gnu.org/licenses/>.
  
  #endregion
  
  using System;
  using System.Collections.Generic;
  using ClearCanvas.Common;
  using ClearCanvas.Enterprise.Core;
  using ClearCanvas.Enterprise.Core.Imex;
  using ClearCanvas.Healthcare.Brokers;
  using ClearCanvas.Common.Utilities;
  using ClearCanvas.Enterprise.Core.Modelling;
  
  namespace ClearCanvas.Healthcare.Imex
  {
  	[ExtensionOf(typeof(CsvDataImporterExtensionPoint), Name = "External Practitioner Importer")]
  	[ExtensionOf(typeof(ApplicationRootExtensionPoint))]
  	public class ExternalPractitionerImporter : CsvDataImporterBase
  	{
  		private const int _numFields = 25;
  
  		IPersistenceContext _context;
  
  		#region CsvDataImporterBase overrides
  
  		/// <summary>
  		/// Import external practitioner from CSV format.
  		/// </summary>
  		/// <param name="rows">
  		/// Each string in the list must contain 25 CSV fields, as follows:
  		///     0 - FamilyName
  		///     1 - GivenName
  		///     2 - MiddleName
  		///     3 - Prefix
  		///     4 - Suffix
  		///     5 - Degree
  		///     6 - LicenseNumber
  		///     7 - BillingNumber
  		///     8 - Street
  		///     9 - Unit
  		///     10 - City
  		///     11 - Province
  		///     12 - PostalCode
  		///     13 - Country
  		///     14 - ValidFrom
  		///     15 - ValidUntil
  		///     16 - Phone CountryCode
  		///     17 - Phone AreaCode
  		///     18 - Phone Number
  		///     19 - Phone Extension
  		///     20 - ValidFrom
  		///     21 - ValidUntil
  		///     22 - Fax CountryCode
  		///     23 - Fax AreaCode
  		///     24 - Fax Number
  		///     25 - Fax Extension
  		///     26 - ValidFrom
  		///     27 - ValidUntil
  		/// </param>
  		/// <param name="context"></param>
  		public override void Import(List<string> rows, IUpdateContext context)
  		{
  			_context = context;
  
  			var  importedEPs = new List<ExternalPractitioner>();
  			var validator = new DomainObjectValidator();
  
  			foreach (var row in rows)
  			{
  				var fields = ParseCsv(row, _numFields);
  
  				var epFamilyName = fields[0];
  				var epGivenName = fields[1];
  				var epMiddlename = fields[2];
  				var epPrefix = fields[3];
  				var epSuffix = fields[4];
  				var epDegree = fields[5];
  
  				var epLicense = fields[6];
  				var epBillingNumber = fields[7];
  
  				var addressStreet = fields[8];
  				var addressUnit = fields[9];
  				var addressCity = fields[10];
  				var addressProvince = fields[11];
  				var addressPostalCode = fields[12];
  				var addressCountry = fields[13];
  
  				var addressValidFrom = ParseDateTime(fields[14]);
  				var addressValidUntil = ParseDateTime(fields[15]);
  
  				var phoneCountryCode = fields[16];
  				var phoneAreaCode = fields[17];
  				var phoneNumber = fields[18];
  				var phoneExtension = fields[19];
  				var phoneValidFrom = ParseDateTime(fields[20]);
  				var phoneValidUntil = ParseDateTime(fields[21]);
  
  				var faxCountryCode = fields[22];
  				var faxAreaCode = fields[23];
  				var faxNumber = fields[24];
  				var faxExtension = fields[25];
  				var faxValidFrom = ParseDateTime(fields[26]);
  				var faxValidUntil = ParseDateTime(fields[27]);
  
  
  				ExternalPractitioner ep = GetExternalPracitioner(epLicense, importedEPs);
  
  				if (ep != null)
  					continue;
  
  				ep = new ExternalPractitioner {LicenseNumber = epLicense, BillingNumber = epBillingNumber};
  				ep.Name = new PersonName(epFamilyName, epGivenName, epMiddlename, epPrefix, epSuffix, epDegree);
  
  				// create a single default contact point
  				var contactPoint = new ExternalPractitionerContactPoint(ep) {Name = "Default", IsDefaultContactPoint = true};
  
  				try
  				{
  					var epAddress = new Address(
  						addressStreet,
  						addressUnit,
  						addressCity,
  						addressProvince,
  						addressPostalCode,
  						addressCountry,
  						AddressType.B,
  						new DateTimeRange(addressValidFrom, addressValidUntil));
  					validator.Validate(epAddress);
  					contactPoint.Addresses.Add(epAddress);
  				}
  				catch(EntityValidationException)
  				{
  					/* invalid address - ignore */
  				}
  
  				try
  				{
  					var epTelephone = new TelephoneNumber(
  						phoneCountryCode,
  						phoneAreaCode,
  						phoneNumber,
  						phoneExtension,
  						TelephoneUse.WPN,
  						TelephoneEquipment.PH,
  						new DateTimeRange(phoneValidFrom, phoneValidUntil));
  
  					validator.Validate(epTelephone);
  					contactPoint.TelephoneNumbers.Add(epTelephone);
  				}
  				catch (EntityValidationException)
  				{
  					/* invalid phone - ignore */
  				}
  
  				try
  				{
  					var epFax = new TelephoneNumber(
  						faxCountryCode,
  						faxAreaCode,
  						faxNumber,
  						faxExtension,
  						TelephoneUse.WPN,
  						TelephoneEquipment.FX,
  						new DateTimeRange(faxValidFrom, faxValidUntil));
  
  					validator.Validate(epFax);
  					contactPoint.TelephoneNumbers.Add(epFax);
  				}
  				catch (EntityValidationException)
  				{
  					/* invalid fax - ignore */
  				}
  
  				_context.Lock(ep, DirtyState.New);
  
  				importedEPs.Add(ep);
  			}
  		}
  
  		#endregion
  
  		#region Private Methods
  
  		private ExternalPractitioner GetExternalPracitioner(string license, IEnumerable<ExternalPractitioner> importedEPs)
  		{
  			// if licenseId is not supplied, then assume the record does not exist
  			if (string.IsNullOrEmpty(license))
  				return null;
  
  			var externalPractitioner = CollectionUtils.SelectFirst(importedEPs, ep => Equals(ep.LicenseNumber, license));
  
  			if (externalPractitioner == null)
  			{
  
gt: 				var criteria = new ExternalPractitionerSearchCriteria();