private static AssemblyMappingInfo GetAssemblyMappingInfo(Assembly assembly)
        {
            var ret = new AssemblyMappingInfo();
            var baseIdentifierAttr =
                assembly.GetCustomAttributes(typeof(TypeIdentifierPrefixAttribute), false).OfType <TypeIdentifierPrefixAttribute>().
                FirstOrDefault();

            if (baseIdentifierAttr != null)
            {
                ret.BaseUri = new Uri(baseIdentifierAttr.BaseUri);
            }
            else
            {
                ret.BaseUri = DefaultBaseUri;
            }

            foreach (var prefixAttr in assembly.GetCustomAttributes(typeof(NamespaceDeclarationAttribute), false).OfType <NamespaceDeclarationAttribute>())
            {
                ret.PrefixMappings[prefixAttr.Prefix] = prefixAttr.Reference;
            }
            return(ret);
        }
        private static IdentityInfo GetIdentityInfo(AssemblyMappingInfo assemblyMappingInfo, Type entityType,
                                                    PropertyInfo identityProperty, IdentifierAttribute identifierAttr)
        {
            string baseUri = identifierAttr == null || identifierAttr.BaseAddress == null
                                 ? Constants.GeneratedUriPrefix
                                 : assemblyMappingInfo.ResolveIdentifier(identifierAttr.BaseAddress);

            if (identifierAttr != null && identifierAttr.KeyProperties != null && identifierAttr.KeyProperties.Length > 0)
            {
                var keyProperties = new PropertyInfo[identifierAttr.KeyProperties.Length];
                for (var i = 0; i < identifierAttr.KeyProperties.Length; i++)
                {
                    var property = entityType.GetProperty(identifierAttr.KeyProperties[i]);
                    if (property == null)
                    {
                        throw new ReflectionMappingException(
                                  String.Format("Could not find key property {0} on type {1}.", identifierAttr.KeyProperties[i], entityType.FullName));
                    }
                    keyProperties[i] = property;
                }
                IKeyConverter keyConverter = null;
                if (identifierAttr.KeyConverterType != null)
                {
                    keyConverter = Activator.CreateInstance(identifierAttr.KeyConverterType) as IKeyConverter;
                    if (keyConverter == null)
                    {
                        throw new ReflectionMappingException(
                                  String.Format("Could not instantiate type {0} as a key converter for entity type {1}. Ensure that this type implements the IKeyConverter interface.",
                                                identifierAttr.KeyConverterType.FullName, entityType.FullName));
                    }
                }
                return(new IdentityInfo(baseUri, identityProperty, keyProperties,
                                        identifierAttr.KeySeparator ?? Constants.DefaultKeySeparator,
                                        keyConverter ?? new DefaultKeyConverter()));
            }
            return(new IdentityInfo(baseUri, identityProperty, null, null, null));
        }
        private static void AddMappingsForType(EntityMappingStore mappingStore, AssemblyMappingInfo assemblyMappingInfo, Type mappedType)
        {
            var entityAttribute =
                mappedType.GetCustomAttributes(typeof (EntityAttribute), false).OfType<EntityAttribute>().
                    FirstOrDefault();
            
            if (entityAttribute != null)
            {
                var entityTypeIdentifier = entityAttribute.Identifier ?? GetImplTypeName(mappedType);

                mappingStore.SetTypeMapping(mappedType, assemblyMappingInfo.ResolveIdentifier(entityTypeIdentifier));
                var identityProperty = GetIdentityProperty(mappedType);
                if (identityProperty != null)
                {
                    var identifierAttr =
                        identityProperty.GetCustomAttributes(typeof (IdentifierAttribute), true).Cast
                            <IdentifierAttribute>().FirstOrDefault();
                    var identityInfo = GetIdentityInfo(assemblyMappingInfo, mappedType, identityProperty, identifierAttr);
                    mappingStore.SetIdentityInfo(mappedType, identityInfo);
                    mappingStore.SetPropertyHint(identityProperty, new PropertyHint(PropertyMappingType.Id));
                }

                foreach (var p in mappedType.GetProperties())
                {
                    if (p.Equals(identityProperty))
                    {
                        // Identity property is already mapped (above)
                        continue;
                    }

                    foreach (var attr in p.GetCustomAttributes(false))
                    {
                        /*
                        if (attr is IdentifierAttribute)
                        {
                            mappingStore.SetPropertyHint(p, new PropertyHint(PropertyMappingType.Address));
                            var idAttr = attr as IdentifierAttribute;
                            if (idAttr.BaseAddress != null)
                            {
                                mappingStore.SetIdentifierPrefix(mappedType, assemblyMappingInfo.ResolveIdentifier(idAttr.BaseAddress));
                            }
                        }
                        else*/
                        if (attr is PropertyTypeAttribute)
                        {
                            var propertyUri =
                                assemblyMappingInfo.ResolveIdentifier((attr as PropertyTypeAttribute).Identifier);
                            mappingStore.SetPropertyHint(p,
                                                         IsResource(p.PropertyType)
                                                             ? new PropertyHint(PropertyMappingType.Arc, propertyUri)
                                                             : new PropertyHint(PropertyMappingType.Property,
                                                                                propertyUri));
                        }
                        else if (attr is InversePropertyTypeAttribute)
                        {
                            var propertyUri =
                                assemblyMappingInfo.ResolveIdentifier((attr as InversePropertyTypeAttribute).Identifier);
                            var targetType = p.PropertyType;
                            if (targetType.IsGenericType)
                            {
                                targetType = targetType.GetGenericArguments().First();
                            }
                            if (targetType.GetCustomAttributes(typeof(EntityAttribute), false).Any())
                            {
                                mappingStore.SetPropertyHint(p,
                                                             new PropertyHint(PropertyMappingType.InverseArc,
                                                                              propertyUri));
                            }
                            else
                            {
                                throw new ReflectionMappingException(
                                    String.Format(
                                        "The property '{0}' on type '{1}' is marked with the InverseProperty attribute but its referenced type ('{2}') is not marked with a Entity attribute.",
                                        p.Name, mappedType.FullName, p.PropertyType.FullName));
                            }
                        }
                        else if (attr is InversePropertyAttribute)
                        {
                            var inversePropertyAttr = attr as InversePropertyAttribute;
                            var targetType = p.PropertyType;
                            if (targetType.IsGenericType) targetType = targetType.GetGenericArguments().First();
                            if (!targetType.GetCustomAttributes(typeof(EntityAttribute), true).Any())
                            {
                                throw new ReflectionMappingException(
                                    String.Format(
                                        "The type of property '{0}' on interface '{1}' is not marked with an Entity attribute.",
                                        p.Name, mappedType.FullName));
                            }
                            var forwardProperty = targetType.GetProperty(inversePropertyAttr.InversePropertyName);
                            if (forwardProperty == null)
                            {
                                throw new ReflectionMappingException(String.Format("The property '{0}' does not exist on type '{1}'.", inversePropertyAttr.InversePropertyName, targetType.FullName));
                            }
                            var inversePropertyTypeUri =
                                assemblyMappingInfo.ResolveIdentifier(GetForwardPropertyTypeUri(forwardProperty, p));
                            mappingStore.SetPropertyHint(p, new PropertyHint(PropertyMappingType.InverseArc, inversePropertyTypeUri));
                        }
                    }
                    if (mappingStore.GetPropertyHint(p) == null)
                    {
                        // If there has been no mapping at all, then we create a property mapping
                        var propertyName = Char.ToLowerInvariant(p.Name[0]) + p.Name.Substring(1);
                        var propertyUri = assemblyMappingInfo.ResolveIdentifier(propertyName);

                        mappingStore.SetPropertyHint(p,
                            IsResource(p.PropertyType) ? 
                            new PropertyHint(PropertyMappingType.Arc, propertyUri) : 
                            new PropertyHint(PropertyMappingType.Property, propertyUri));
                    }
                }
            }
        }
        private static AssemblyMappingInfo GetAssemblyMappingInfo(Assembly assembly)
        {
            var ret = new AssemblyMappingInfo();
            var baseIdentifierAttr =
                assembly.GetCustomAttributes(typeof (TypeIdentifierPrefixAttribute), false).OfType<TypeIdentifierPrefixAttribute>().
                    FirstOrDefault();
            if (baseIdentifierAttr != null)
            {
                ret.BaseUri = new Uri(baseIdentifierAttr.BaseUri);
            }
            else
            {
                ret.BaseUri = DefaultBaseUri;
            }

            foreach(var prefixAttr in assembly.GetCustomAttributes(typeof(NamespaceDeclarationAttribute), false).OfType<NamespaceDeclarationAttribute>())
            {
                ret.PrefixMappings[prefixAttr.Prefix] = prefixAttr.Reference;
            }
            return ret;
        }
 private static IdentityInfo GetIdentityInfo(AssemblyMappingInfo assemblyMappingInfo, Type entityType,
     PropertyInfo identityProperty, IdentifierAttribute identifierAttr)
 {
     string baseUri = identifierAttr == null || String.IsNullOrWhiteSpace(identifierAttr.BaseAddress)
                          ? Constants.GeneratedUriPrefix
                          : assemblyMappingInfo.ResolveIdentifier(identifierAttr.BaseAddress);
     if (identifierAttr != null && identifierAttr.KeyProperties != null && identifierAttr.KeyProperties.Length > 0)
     {
         var keyProperties = new PropertyInfo[identifierAttr.KeyProperties.Length];
         for (var i = 0; i < identifierAttr.KeyProperties.Length; i++)
         {
             var property = entityType.GetProperty(identifierAttr.KeyProperties[i]);
             if (property == null)
             {
                 throw new ReflectionMappingException(
                     String.Format("Could not find key property {0} on type {1}.", identifierAttr.KeyProperties[i], entityType.FullName));
             }
             keyProperties[i] = property;
         }
         IKeyConverter keyConverter = null;
         if (identifierAttr.KeyConverterType != null)
         {
             keyConverter = Activator.CreateInstance(identifierAttr.KeyConverterType) as IKeyConverter;
             if (keyConverter == null)
             {
                 throw new ReflectionMappingException(
                     String.Format("Could not instantiate type {0} as a key converter for entity type {1}. Ensure that this type implements the IKeyConverter interface.",
                                   identifierAttr.KeyConverterType.FullName, entityType.FullName));
             }
         }
         return new IdentityInfo(baseUri, identityProperty, keyProperties,
                                 identifierAttr.KeySeparator ?? Constants.DefaultKeySeparator,
                                 keyConverter ?? new DefaultKeyConverter());
     }
     return new IdentityInfo(baseUri, identityProperty, null, null, null);
 }
        private static void AddMappingsForType(EntityMappingStore mappingStore, AssemblyMappingInfo assemblyMappingInfo, Type mappedType)
        {
            var entityAttribute =
                mappedType.GetCustomAttributes(typeof(EntityAttribute), false).OfType <EntityAttribute>().
                FirstOrDefault();

            if (entityAttribute != null)
            {
                var entityTypeIdentifier = entityAttribute.Identifier ?? GetImplTypeName(mappedType);

                mappingStore.SetTypeMapping(mappedType, assemblyMappingInfo.ResolveIdentifier(entityTypeIdentifier));
                var identityProperty = GetIdentityProperty(mappedType);
                if (identityProperty != null)
                {
                    var identifierAttr =
                        identityProperty.GetCustomAttributes(typeof(IdentifierAttribute), true).Cast
                        <IdentifierAttribute>().FirstOrDefault();
                    var identityInfo = GetIdentityInfo(assemblyMappingInfo, mappedType, identityProperty, identifierAttr);
                    mappingStore.SetIdentityInfo(mappedType, identityInfo);
                    mappingStore.SetPropertyHint(identityProperty, new PropertyHint(PropertyMappingType.Id));
                }

                foreach (var p in mappedType.GetProperties())
                {
                    if (p.Equals(identityProperty))
                    {
                        // Identity property is already mapped (above)
                        continue;
                    }

                    foreach (var attr in p.GetCustomAttributes(false))
                    {
                        /*
                         * if (attr is IdentifierAttribute)
                         * {
                         *  mappingStore.SetPropertyHint(p, new PropertyHint(PropertyMappingType.Address));
                         *  var idAttr = attr as IdentifierAttribute;
                         *  if (idAttr.BaseAddress != null)
                         *  {
                         *      mappingStore.SetIdentifierPrefix(mappedType, assemblyMappingInfo.ResolveIdentifier(idAttr.BaseAddress));
                         *  }
                         * }
                         * else*/
                        if (attr is PropertyTypeAttribute)
                        {
                            var propertyUri =
                                assemblyMappingInfo.ResolveIdentifier((attr as PropertyTypeAttribute).Identifier);
                            mappingStore.SetPropertyHint(p,
                                                         IsResource(p.PropertyType)
                                                             ? new PropertyHint(PropertyMappingType.Arc, propertyUri)
                                                             : new PropertyHint(PropertyMappingType.Property,
                                                                                propertyUri));
                        }
                        else if (attr is InversePropertyTypeAttribute)
                        {
                            var propertyUri =
                                assemblyMappingInfo.ResolveIdentifier((attr as InversePropertyTypeAttribute).Identifier);
                            var targetType = p.PropertyType;
                            if (targetType.IsGenericType)
                            {
                                targetType = targetType.GetGenericArguments().First();
                            }
                            if (targetType.GetCustomAttributes(typeof(EntityAttribute), false).Any())
                            {
                                mappingStore.SetPropertyHint(p,
                                                             new PropertyHint(PropertyMappingType.InverseArc,
                                                                              propertyUri));
                            }
                            else
                            {
                                throw new ReflectionMappingException(
                                          String.Format(
                                              "The property '{0}' on type '{1}' is marked with the InverseProperty attribute but its referenced type ('{2}') is not marked with a Entity attribute.",
                                              p.Name, mappedType.FullName, p.PropertyType.FullName));
                            }
                        }
                        else if (attr is InversePropertyAttribute)
                        {
                            var inversePropertyAttr = attr as InversePropertyAttribute;
                            var targetType          = p.PropertyType;
                            if (targetType.IsGenericType)
                            {
                                targetType = targetType.GetGenericArguments().First();
                            }
                            if (!targetType.GetCustomAttributes(typeof(EntityAttribute), true).Any())
                            {
                                throw new ReflectionMappingException(
                                          String.Format(
                                              "The type of property '{0}' on interface '{1}' is not marked with an Entity attribute.",
                                              p.Name, mappedType.FullName));
                            }
                            var forwardProperty = targetType.GetProperty(inversePropertyAttr.InversePropertyName);
                            if (forwardProperty == null)
                            {
                                throw new ReflectionMappingException(String.Format("The property '{0}' does not exist on type '{1}'.", inversePropertyAttr.InversePropertyName, targetType.FullName));
                            }
                            var inversePropertyTypeUri =
                                assemblyMappingInfo.ResolveIdentifier(GetForwardPropertyTypeUri(forwardProperty, p));
                            mappingStore.SetPropertyHint(p, new PropertyHint(PropertyMappingType.InverseArc, inversePropertyTypeUri));
                        }
                    }
                    if (mappingStore.GetPropertyHint(p) == null)
                    {
                        // If there has been no mapping at all, then we create a property mapping
                        var propertyName = Char.ToLowerInvariant(p.Name[0]) + p.Name.Substring(1);
                        var propertyUri  = assemblyMappingInfo.ResolveIdentifier(propertyName);

                        mappingStore.SetPropertyHint(p,
                                                     IsResource(p.PropertyType) ?
                                                     new PropertyHint(PropertyMappingType.Arc, propertyUri) :
                                                     new PropertyHint(PropertyMappingType.Property, propertyUri));
                    }
                }
            }
        }