/// <summary>
        /// Creates a new object by copying data from an species observation object.
        /// </summary>
        /// <param name="obs">The species observation object.</param>
        /// <param name="speciesObservationFieldDescriptions">The species observation field descriptions.</param>
        /// <returns></returns>
        public static SpeciesObservationViewModel CreateFromSpeciesObservation(
            ISpeciesObservation obs,
            ISpeciesObservationFieldDescriptionsViewModel speciesObservationFieldDescriptions)
        {
            var model = new SpeciesObservationViewModel();

            model.ObservationId = obs.Id.ToString(CultureInfo.InvariantCulture);
            model.CopyDataFromObservationToModel(obs, model, speciesObservationFieldDescriptions);
            //model.Projects.AddRange(GetSampleProjects()); // used for testing purpose
            return(model);
        }
        /// <summary>
        /// Copies the project parameters to model.
        /// </summary>
        /// <param name="observation">The observation.</param>
        /// <param name="model">The model.</param>
        /// <param name="speciesObservationFieldDescriptions"></param>
        private void CopyProjectParametersToModel(
            ISpeciesObservation observation,
            SpeciesObservationViewModel model,
            ISpeciesObservationFieldDescriptionsViewModel speciesObservationFieldDescriptions)
        {
            model.Projects = new List <ProjectViewModel>();
            if (observation.Project == null || observation.Project.ProjectParameters == null)
            {
                return;
            }

            var projectParametersDictionary = new Dictionary <int, List <ISpeciesObservationProjectParameter> >();

            foreach (var projectParameter in observation.Project.ProjectParameters)
            {
                if (!projectParametersDictionary.ContainsKey(projectParameter.ProjectId))
                {
                    projectParametersDictionary.Add(projectParameter.ProjectId, new List <ISpeciesObservationProjectParameter>());
                }

                projectParametersDictionary[projectParameter.ProjectId].Add(projectParameter);
            }

            // loop all projects
            foreach (var pair in projectParametersDictionary)
            {
                ProjectViewModel projectViewModel;
                if (!speciesObservationFieldDescriptions.ProjectsDictionary.TryGetValue(pair.Key, out projectViewModel))
                {
                    projectViewModel = CreateProjectViewModel(pair);
                }
                else
                {
                    projectViewModel = projectViewModel.Clone();
                    // map values
                    foreach (var projectParameter in pair.Value)
                    {
                        projectViewModel.ProjectParameters[projectParameter.PropertyIdentifier].Value = projectParameter.Value;
                    }
                }

                model.Projects.Add(projectViewModel);
            }
        }
        /// <summary>
        /// Copies the data from observation to model.
        /// The observation object contains hierarchical data, while the model is flat.
        /// </summary>
        /// <param name="observation">The observation.</param>
        /// <param name="model">The model.</param>
        /// <param name="speciesObservationFieldDescriptions"></param>
        private void CopyDataFromObservationToModel(
            ISpeciesObservation observation,
            SpeciesObservationViewModel model,
            ISpeciesObservationFieldDescriptionsViewModel speciesObservationFieldDescriptions)
        {
            // Create detalis list out of propery and resource string
            Type type = observation.GetType();

            PropertyInfo[] propInfos = type.GetProperties();
            for (int i = 0; i < propInfos.Length; i++)
            {
                PropertyInfo pi           = (PropertyInfo)propInfos.GetValue(i);
                string       propertyName = pi.Name;
                object       propValue    = pi.GetValue(observation, null);
                if (propValue is ISpeciesObservationConservation || propValue is ISpeciesObservationEvent ||
                    propValue is ISpeciesObservationGeologicalContext ||
                    propValue is ISpeciesObservationIdentification || propValue is ISpeciesObservationLocation ||
                    propValue is ISpeciesObservationMeasurementOrFact ||
                    propValue is ISpeciesObservationOccurrence || propValue is ISpeciesObservationProject ||
                    propValue is ISpeciesObservationResourceRelationship ||
                    propValue is ISpeciesObservationTaxon)
                {
                    PropertyInfo[] subSpeciesPropertyInfos = null;
                    if (propValue is ISpeciesObservationConservation)
                    {
                        subSpeciesPropertyInfos = typeof(ISpeciesObservationConservation).GetProperties();
                    }
                    else if (propValue is ISpeciesObservationEvent)
                    {
                        subSpeciesPropertyInfos = typeof(ISpeciesObservationEvent).GetProperties();
                    }
                    else if (propValue is ISpeciesObservationGeologicalContext)
                    {
                        subSpeciesPropertyInfos = typeof(ISpeciesObservationGeologicalContext).GetProperties();
                    }
                    else if (propValue is ISpeciesObservationIdentification)
                    {
                        subSpeciesPropertyInfos = typeof(ISpeciesObservationIdentification).GetProperties();
                    }
                    else if (propValue is ISpeciesObservationLocation)
                    {
                        subSpeciesPropertyInfos = typeof(ISpeciesObservationLocation).GetProperties();
                    }
                    else if (propValue is ISpeciesObservationMeasurementOrFact)
                    {
                        subSpeciesPropertyInfos = typeof(ISpeciesObservationMeasurementOrFact).GetProperties();
                    }
                    else if (propValue is ISpeciesObservationOccurrence)
                    {
                        subSpeciesPropertyInfos = typeof(ISpeciesObservationOccurrence).GetProperties();
                    }
                    else if (propValue is ISpeciesObservationProject)
                    {
                        subSpeciesPropertyInfos = typeof(ISpeciesObservationProject).GetProperties();
                    }
                    else if (propValue is ISpeciesObservationResourceRelationship)
                    {
                        subSpeciesPropertyInfos = typeof(ISpeciesObservationResourceRelationship).GetProperties();
                    }
                    else if (propValue is ISpeciesObservationTaxon)
                    {
                        subSpeciesPropertyInfos = typeof(ISpeciesObservationTaxon).GetProperties();
                    }

                    CopyDataFromSubProperty(observation, subSpeciesPropertyInfos, propValue, model);
                }
                else
                {
                    //Get string value for property
                    string propertyValue = GetPropertyValueAsString(propValue);

                    PropertyInfo modelPi;
                    if (ObservationDarwinCoreViewModelPropertiesDictionary.TryGetValue(propertyName, out modelPi))
                    {
                        modelPi.SetValue(model, propertyValue, null);
                    }
                }
            }

            CopyProjectParametersToModel(observation, model, speciesObservationFieldDescriptions);
        }