public static int ExtractTypeId(TypeInfo type, TypeIdRegistry typeIdRegistry, Tuple tuple, int typeIdIndex, out TypeReferenceAccuracy accuracy)
        {
            accuracy = TypeReferenceAccuracy.Hierarchy;
            if (type.IsInterface)
            {
                accuracy = TypeReferenceAccuracy.BaseType;
            }

            if (typeIdIndex < 0)
            {
                if (type.IsLeaf)
                {
                    accuracy = TypeReferenceAccuracy.ExactType;
                }
                return(typeIdRegistry.GetTypeId(type));
            }

            accuracy = TypeReferenceAccuracy.ExactType;
            TupleFieldState state;
            var             value = tuple.GetValue <int>(typeIdIndex, out state);

            if (type.IsLeaf)
            {
                return(state.HasValue() ? typeIdRegistry.GetTypeId(type) : TypeInfo.NoTypeId);
            }
            // Hack here: 0 (default) = TypeInfo.NoTypeId
            return(value);
        }
        private StoredTypeInfo ConvertType(TypeInfo source)
        {
            var inheritedAssociatedFields = new HashSet <string>();
            var declaredFields            = source.Fields
                                            .Where(field => field.IsDeclared && !field.IsNested)
                                            .ToArray();
            var    sourceAncestor = source.GetAncestor();
            string hierarchyRoot  = null;

            if (source.Hierarchy != null && source.Hierarchy.Root == source)
            {
                hierarchyRoot = source.Hierarchy.InheritanceSchema.ToString();
            }
            var associations = source.GetOwnerAssociations()
                               .Where(a => {
                if (processedAssociations.Contains(a.Name))
                {
                    return(false);
                }
                if (declaredFields.Contains(a.OwnerField))
                {
                    return(true);
                }
                if (a.IsPaired)
                {
                    inheritedAssociatedFields.Add(a.OwnerField.Name);
                    return(true);
                }
                return(false);
            })
                               .Select(ConvertAssociation)
                               .ToArray();

            foreach (var association in associations)
            {
                processedAssociations.Add(association.Name);
            }

            var fields = source.Fields
                         .Where(field => (field.IsDeclared && !field.IsNested) || inheritedAssociatedFields.Contains(field.Name))
                         .ToArray();

            // hack: for SingleTable hierarchies mapping name is not set correctly
            // and always should be taken from hierarchy root
            var mappingNameSource =
                source.Hierarchy != null && source.Hierarchy.InheritanceSchema == InheritanceSchema.SingleTable
          ? source.Hierarchy.Root
          : source;
            var result = new StoredTypeInfo {
                Name                                               = source.Name,
                UnderlyingType                                     = GetTypeFullName(source.UnderlyingType),
                TypeId                                             = registry != null?registry.GetTypeId(source) : TypeInfo.NoTypeId,
                                                   MappingName     = mappingNameSource.MappingName,
                                                   MappingSchema   = source.MappingSchema ?? string.Empty,
                                                   MappingDatabase = source.MappingDatabase ?? string.Empty,
                                                   IsEntity        = source.IsEntity,
                                                   IsAbstract      = source.IsAbstract,
                                                   IsInterface     = source.IsInterface,
                                                   IsStructure     = source.IsStructure,
                                                   IsSystem        = source.IsSystem,
                                                   AncestorName    = sourceAncestor != null ? sourceAncestor.Name : null,
                                                   Associations    = associations,
                                                   HierarchyRoot   = hierarchyRoot,
                                                   Fields          = fields.Select(ConvertField).ToArray(),
            };

            return(result);
        }