protected virtual void InheritFrom(MetaMetadataRepository repository,
MetaMetadataCompositeField inheritedStructure,
InheritanceHandler inheritanceHandler)
{
// init nested fields inside this
var subfields = Kids.Values;
foreach (MetaMetadataField f in subfields)
{
if (f is MetaMetadataNestedField)
{
f.Repository = (repository);
MetaMetadataNestedField nested = (MetaMetadataNestedField)f;
if (nested.PackageName == null)
{
nested.PackageName = PackageName;
}
nested.Scope = Scope;
}
}
// inherit fields with attributes from inheritedStructure
// if inheritedStructure == null, this must be the root meta-metadata
if (inheritedStructure != null)
{
var inheritedStructSubfields = inheritedStructure.Kids.Values;
foreach (MetaMetadataField field in inheritedStructSubfields)
{
if (field is MetaMetadataNestedField)
{
((MetaMetadataNestedField)field).InheritMetaMetadata(inheritanceHandler);
}
string fieldName = field.Name;
MetaMetadataField fieldLocal;
kids.TryGetValue(fieldName, out fieldLocal);
if (fieldLocal == null && inheritanceHandler.IsUsingGenerics(field))
{
// if the super field is using generics, we will need to re-evaluate generic type vars
fieldLocal = (MetaMetadataField)Activator.CreateInstance(field.GetType());
//Prepare Child Field For Inheritance
fieldLocal.Repository = (repository);
if (fieldLocal is MetaMetadataNestedField)
{
MetaMetadataNestedField nested = (MetaMetadataNestedField)fieldLocal;
if (nested.PackageName == null)
{
nested.PackageName = PackageName;
}
nested.Scope = Scope;
}
}
if (fieldLocal != null)
{
Debug.WriteLine("inheriting field: " + fieldLocal + " <= " + field);
if (field.GetType() != fieldLocal.GetType())
{
Debug.WriteLine("local field " + fieldLocal + " hides field " + fieldLocal +
" with the same name in super mmd type!");
}
// debug("inheriting field " + fieldLocal + " from " + field);
if (field != fieldLocal)
{
fieldLocal.SuperField = field;
}
fieldLocal.DeclaringMmd = field.DeclaringMmd;
fieldLocal.InheritAttributes(field);
if (fieldLocal is MetaMetadataNestedField)
{
((MetaMetadataNestedField)fieldLocal).PackageName =
((MetaMetadataNestedField)field).PackageName;
}
}
}
}
// recursively call inheritMetaMetadata() on nested fields
foreach (MetaMetadataField f in subfields)
{
// a new field is defined inside this mmd
if (f.DeclaringMmd == this && f.SuperField == null)
{
SetNewMetadataClass(true);
}
// recursively call this method on nested fields
f.Repository = repository;
if (f is MetaMetadataNestedField)
{
MetaMetadataNestedField f1 = (MetaMetadataNestedField)f;
f1.InheritMetaMetadata(inheritanceHandler);
if (f1.IsNewMetadataClass())
{
SetNewMetadataClass(true);
}
MetaMetadataNestedField f0 = (MetaMetadataNestedField)f.SuperField;
if (f0 != null && f0.GetTypeName() != f1.GetTypeName())
{
// inherited field w changing base type (polymorphic case)
f1.InheritMetaMetadata(inheritanceHandler);
MetaMetadata mmd0 = f0.TypeMmd;
MetaMetadata mmd1 = f1.TypeMmd;
if (mmd1.IsDerivedFrom(mmd0))
{
SetNewMetadataClass(true);
}
else
{
throw new MetaMetadataException("incompatible types: " + mmd0 + " => " + mmd1);
}
}
}
}
// clone fields only declared in inheritedStructure.
// must clone them after recursively calling inheritMetaMetadata(), so that their nested
// structures (which may be inherited too) can be cloned.
if (inheritedStructure != null)
{
var inheritedStructSubfields = inheritedStructure.Kids.Values;
foreach (MetaMetadataField field in inheritedStructSubfields)
{
string fieldName = field.Name;
MetaMetadataField fieldLocal;
kids.TryGetValue(fieldName, out fieldLocal);
if (fieldLocal == null)
{
// MetaMetadataField clonedField = (MetaMetadataField) field.clone();
// clonedField.setParent(this);
// this.getChildMetaMetadata().put(fieldName, clonedField);
kids.Put(fieldName, field);
}
}
}
}