//-----------------------------------------------------------------------
//
// Copyright (c) 2009 Deltares. All rights reserved.
//
// B. Faassen
// barry.faassen@deltares.nl
// 9-2-2009
// Base class to convert between domain collections and xml (dto) collections
//-----------------------------------------------------------------------
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Deltares.Standard.IO.DtoAssembler;
namespace Deltares.Standard
{
///
/// Base class for a data transfer collection assembler
///
/// The type of class to be assembled
public abstract class DtoCollectionAssembler : IDtoCollectionAssembler
where TDomainObject : new()
{
///
/// Holds a reference to the entity assembler
///
private DtoAssembler entityAssembler;
public DtoCollectionAssembler(DtoAssembler entityAssembler, string elementName)
{
this.entityAssembler = entityAssembler;
this.ElementName = elementName;
}
#region IDtoCollectionAssembler Members
///
/// Gets the entity assembler
///
public IDtoAssembler EntityAssembler
{
get { return this.entityAssembler; }
}
///
/// Gets or sets the xml element name
///
public string ElementName { get; private set; }
///
///
///
///
///
public virtual IEnumerable CreateDomainObjectCollection(XElement dtoSequenceElement)
{
IEnumerable dto = from x in dtoSequenceElement.Descendants()
where x.Name.LocalName == this.EntityAssembler.ElementName && x.Parent.Name.LocalName == this.ElementName
select x;
return dto.ToDomainObjectIterator(this.entityAssembler);
}
///
///
///
///
///
public virtual XElement CreateDataTransferObject(IEnumerable domainObjColl)
{
if (!this.ElementName.HasValidStringValue())
throw new DtoAssemblerException("There is no element name specified");
if (this.entityAssembler == null)
{
// TODO: need to support serialization based on reflection
}
// is there a schema attached to the assembler so we can
// validate the collection?
XDocument schema = this.entityAssembler.Schema;
if (schema != null)
{
if (this.entityAssembler == null)
{
// TODO: need to support serialization based on reflection
}
else
{
// get the collection rules (min and max requirements) (if any)
var collRules = from x in schema.Descendants()
where x.Name.LocalName == "element" && x.Attribute("name").Value == this.entityAssembler.ElementName
select new
{
MinOccurs = x.AttributeAs("minOccurs") == "unbounded" ? 0 : x.AttributeAs("minOccurs"),
MaxOccurs = x.AttributeAs("maxOccurs") == "unbounded" ? -1 : x.AttributeAs("maxOccurs")
};
if (collRules.Any())
{
var rules = collRules.Single();
// validate the min and max values of the collection according to the xsd
int count = domainObjColl.Count();
if (domainObjColl == null || (count == 0 && rules.MinOccurs > 0)
|| (count > 0 & rules.MaxOccurs >= 0 && count > rules.MaxOccurs))
{
throw new CollectionRequirementsNotSatisfiedException(this.ElementName, this.EntityAssembler.ElementName, domainObjColl);
}
}
}
}
else if (domainObjColl == null)
{
return null; // Use empty sequence instead?
}
return new XElement(this.ElementName, domainObjColl.ToDtoIterator(this.entityAssembler).ToArray());
}
#endregion
///
/// Creates a domain object collection from an xml document
///
///
///
public IEnumerable CreateDomainObjectCollection(string xmlString)
{
XDocument doc = XDocument.Parse(xmlString);
// assemble the collection
return this.CreateDomainObjectCollection(doc);
}
///
/// Creates a domain object collection from an xml document
///
///
///
public IEnumerable CreateDomainObjectCollection(XDocument doc)
{
IEnumerable dto = from x in doc.Descendants()
where x.Name.LocalName == this.EntityAssembler.ElementName && x.Parent.Name.LocalName == this.ElementName
select x;
// assemble the collection
return this.CreateDomainObjectCollection(dto);
}
///
///
///
///
///
public IEnumerable CreateDomainObjectCollection(IEnumerable dtoObjColl)
{
return dtoObjColl.ToDomainObjectIterator(this.entityAssembler);
}
///
///
///
///
///
public XElement CreateDataTransferObject(IEnumerable domainObjColl, XNamespace elementNamespace)
{
XElement el = this.CreateDataTransferObject(domainObjColl);
var nel = new XElement(elementNamespace + this.ElementName);
el.Name = nel.Name;
return el;
}
}
}