#region MigraDoc - Creating Documents on the Fly
//
// Authors:
// Stefan Lange
// Klaus Potzesny
// David Stephensen
//
// Copyright (c) 2001-2017 empira Software GmbH, Cologne Area (Germany)
//
// http://www.pdfsharp.com
// http://www.migradoc.com
// http://sourceforge.net/projects/pdfsharp
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#endregion
using System;
using System.Reflection;
namespace MigraDoc.DocumentObjectModel.publics
{
///
/// Meta class for document objects.
///
public sealed class Meta
{
///
/// Initializes a new instance of the DomMeta class.
///
public Meta(Type documentObjectType)
{
AddValueDescriptors(this, documentObjectType);
}
///
/// Gets the meta object of the specified document object.
///
/// The document object the meta is returned for.
public static Meta GetMeta(DocumentObject documentObject)
{
return documentObject.Meta;
}
///
/// Gets the object specified by name from dom.
///
public object GetValue(DocumentObject dom, string name, GV flags)
{
int dot = name.IndexOf('.');
if (dot == 0)
throw new ArgumentException(DomSR.InvalidValueName(name));
string trail = null;
if (dot > 0)
{
trail = name.Substring(dot + 1);
name = name.Substring(0, dot);
}
ValueDescriptor vd = _vds[name];
if (vd == null)
throw new ArgumentException(DomSR.InvalidValueName(name));
object value = vd.GetValue(dom, flags);
if (value == null && flags == GV.GetNull) //??? also for GV.ReadOnly?
return null;
//REVIEW DaSt: Create object in case of GV.ReadWrite?
if (trail != null)
{
if (value == null || trail == "")
throw new ArgumentException(DomSR.InvalidValueName(name));
DocumentObject doc = value as DocumentObject;
if (doc == null)
throw new ArgumentException(DomSR.InvalidValueName(name));
value = doc.GetValue(trail, flags);
}
return value;
}
///
/// Sets the member of dom specified by name to val.
/// If a member with the specified name does not exist an ArgumentException will be thrown.
///
public void SetValue(DocumentObject dom, string name, object val)
{
int dot = name.IndexOf('.');
if (dot == 0)
throw new ArgumentException(DomSR.InvalidValueName(name));
string trail = null;
if (dot > 0)
{
trail = name.Substring(dot + 1);
name = name.Substring(0, dot);
}
ValueDescriptor vd = _vds[name];
if (vd == null)
throw new ArgumentException(DomSR.InvalidValueName(name));
if (trail != null)
{
//REVIEW DaSt: dom.GetValue(name) and call SetValue recursively,
// or dom.GetValue(name.BisVorletzteElement) and then call SetValue?
DocumentObject doc = (DocumentObject)dom.GetValue(name);
doc.SetValue(trail, val);
}
else
vd.SetValue(dom, val);
}
///
/// Determines whether this meta contains a value with the specified name.
///
public bool HasValue(string name)
{
ValueDescriptor vd = _vds[name];
return vd != null;
}
///
/// Sets the member of dom specified by name to null.
/// If a member with the specified name does not exist an ArgumentException will be thrown.
///
public void SetNull(DocumentObject dom, string name)
{
ValueDescriptor vd = _vds[name];
if (vd == null)
throw new ArgumentException(DomSR.InvalidValueName(name));
vd.SetNull(dom);
}
///
/// Determines whether the member of dom specified by name is null.
/// If a member with the specified name does not exist an ArgumentException will be thrown.
///
public /* not virtual */ bool IsNull(DocumentObject dom, string name)
{
//bool isNull = false;
int dot = name.IndexOf('.');
if (dot == 0)
throw new ArgumentException(DomSR.InvalidValueName(name));
string trail = null;
if (dot > 0)
{
trail = name.Substring(dot + 1);
name = name.Substring(0, dot);
}
ValueDescriptor vd = _vds[name];
if (vd == null)
throw new ArgumentException(DomSR.InvalidValueName(name));
if (vd is NullableDescriptor || vd is ValueTypeDescriptor)
{
if (trail != null)
throw new ArgumentException(DomSR.InvalidValueName(name));
return vd.IsNull(dom);
}
DocumentObject docObj = (DocumentObject)vd.GetValue(dom, GV.ReadOnly);
if (docObj == null)
return true;
if (trail != null)
return docObj.IsNull(trail);
return docObj.IsNull();
// DomValueDescriptor vd = vds[name];
// if (vd == null)
// throw new ArgumentException(DomSR.InvalidValueName(name));
//
// return vd.IsNull(dom);
}
///
/// Sets all members of the specified dom to null.
///
public /*virtual*/ void SetNull(DocumentObject dom)
{
int count = _vds.Count;
for (int index = 0; index < count; index++)
{
if (!_vds[index].IsRefOnly)
_vds[index].SetNull(dom);
}
}
///
/// Determines whether all members of the specified dom are null. If dom contains no members IsNull
/// returns true.
///
public bool IsNull(DocumentObject dom)
{
int count = _vds.Count;
for (int index = 0; index < count; index++)
{
ValueDescriptor vd = _vds[index];
if (vd.IsRefOnly)
continue;
if (!vd.IsNull(dom))
return false;
}
return true;
}
///
/// Gets the DomValueDescriptor of the member specified by name from the DocumentObject.
///
public ValueDescriptor this[string name]
{
get { return _vds[name]; }
}
///
/// Gets the DomValueDescriptorCollection of the DocumentObject.
///
public ValueDescriptorCollection ValueDescriptors
{
get { return _vds; }
}
readonly ValueDescriptorCollection _vds = new ValueDescriptorCollection();
///
/// Adds a value descriptor for each field and property found in type to meta.
///
static void AddValueDescriptors(Meta meta, Type type)
{
#if !NETFX_CORE
FieldInfo[] fieldInfos = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
#else
var fieldInfos = type.GetTypeInfo().DeclaredFields;
#endif
foreach (FieldInfo fieldInfo in fieldInfos)
{
#if DEBUG_
string name = fieldInfo.Name;
if (name == "parent")
name.GetType();
#endif
DVAttribute[] dvs = (DVAttribute[])fieldInfo.GetCustomAttributes(typeof(DVAttribute), false);
if (dvs.Length == 1)
{
ValueDescriptor vd = ValueDescriptor.CreateValueDescriptor(fieldInfo, dvs[0]);
meta.ValueDescriptors.Add(vd);
}
}
#if !NETFX_CORE
PropertyInfo[] propInfos = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
#else
var propInfos = type.GetTypeInfo().DeclaredProperties;
#endif
foreach (PropertyInfo propInfo in propInfos)
{
#if DEBUG_
string name = propInfo.Name;
if (name == "Font")
name.GetType();
#endif
DVAttribute[] dvs = (DVAttribute[])propInfo.GetCustomAttributes(typeof(DVAttribute), false);
if (dvs.Length == 1)
{
ValueDescriptor vd = ValueDescriptor.CreateValueDescriptor(propInfo, dvs[0]);
meta.ValueDescriptors.Add(vd);
}
}
}
}
}