// Copyright (C) Stichting Deltares 2016. All rights reserved.
//
// This file is part of Ringtoets.
//
// Ringtoets is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see .
//
// All names, logos, and references to "Deltares" are registered trademarks of
// Stichting Deltares and remain full property of Stichting Deltares at all times.
// All rights reserved.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Core.Common.Utils;
namespace Core.Common.Base
{
///
/// A collection to store unique elements based on their feature and the source path
/// they were imported from.
///
/// The type of elements in the collection.
public class ObservableUniqueItemCollectionWithSourcePath : Observable, IEnumerable
where TObject : class
{
private readonly List collection = new List();
///
/// Gets the element at index in the collection.
///
/// The index.
/// The element at index in the collection.
/// Thrown when is not
/// between [0, )
public TObject this[int i]
{
get
{
return collection[i];
}
}
///
/// Gets the amount of items stored in the collection.
///
public int Count
{
get
{
return collection.Count;
}
}
///
/// Gets the last known file path from which the elements were imported.
///
/// The path where the elements originate
/// from, or null if the collection is cleared.
public string SourcePath { get; private set; }
///
/// Removes the first occurrence of in the collection.
///
/// The item of type to be removed.
/// True if the was successfully removed from the collection;
/// False if otherwise or if the was not found in the collection.
public bool Remove(TObject item)
{
bool remove = collection.Remove(item);
if (remove && Count == 0)
{
SourcePath = null;
}
return remove;
}
///
/// Clears the imported items in the collection and the .
///
public void Clear()
{
SourcePath = null;
collection.Clear();
}
///
/// Adds all elements originating from a source file.
///
/// The elements to add
/// The path to the source file.
/// Thrown when any input argument is null.
/// Thrown when:
///
/// - contains null.
/// - is not a valid file path.
/// - an element in is invalid.
///
///
public void AddRange(IEnumerable items, string filePath)
{
if (items == null)
{
throw new ArgumentNullException(nameof(items));
}
if (filePath == null)
{
throw new ArgumentNullException(nameof(filePath));
}
if (!IOUtils.IsValidFilePath(filePath))
{
throw new ArgumentException($"'{filePath}' is not a valid filepath.", nameof(filePath));
}
InternalValidateItems(items);
SourcePath = filePath;
collection.AddRange(items);
}
private void InternalValidateItems(IEnumerable items)
{
if (items.Contains(null))
{
throw new ArgumentException("Collection cannot contain null.", nameof(items));
}
ValidateItems(items);
}
///
/// Perform additional validations over .
///
/// The items to validate.
/// Throw an exception when validation fails.
protected virtual void ValidateItems(IEnumerable items) {}
///
/// Validates the items of an based on their names.
///
/// The feautre that needs to be validated on.
/// The collection that needs to be validated.
/// The feature of the items contained by the collection
/// that needs to be validated on.
/// The description of the item which was validated.
/// The description of the feature which was validated on.
/// Thrown when any parameters are null.
/// Thrown when a duplicate item was found.
protected void ValidateListOnDuplicateFeature(IEnumerable items,
Func getUniqueFeature,
string typeDescriptor,
string featureDescription)
{
IEnumerable> duplicateItems =
items.GroupBy(getUniqueFeature)
.Where(group => group.Count() > 1);
if (duplicateItems.Any())
{
var duplicateFeatures = string.Join(", ", duplicateItems.Select(group => group.First()));
string exceptionMessage = string.Format("{0} moeten een unieke {1} hebben. Gevonden dubbele elementen: {2}.",
typeDescriptor,
featureDescription,
duplicateFeatures);
throw new ArgumentException(exceptionMessage);
}
}
public IEnumerator GetEnumerator()
{
return collection.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}