/// <summary> /// Parses object model defined in RDFS/XML to DataModelModule object. /// </summary> /// <param name="baseResourceType">Instance of Base ResourceType.</param> /// <param name="rdfDocument">RDF/XML Document.</param> /// <param name="xsdDocument">XSD Documet.</param> /// <param name="namespaceName">User defined Namespace.</param> /// <param name="isStrictExecutionMode">Execution Mode (Strict/Loose).</param> /// <returns>Parsed object of DataModelModule class.</returns> /// <exception cref="Zentity.Rdf.Xml.RdfXmlParserException"/> /// <exception cref="Zentity.Core.RdfsException"/> /// <example> This example shows how to create a <see cref="Zentity.Core.DataModelModule"/> /// from an RDF Schema document. Though, the example uses reflection to show how to use the /// generated assembly, we recommend creating clients that are compiled with references to /// the extensions assembly to avoid the reflection based code. /// <br/> /// The listing below shows the contents of RDF Schema document. The example assumes that /// this document is saved as 'C:\Sample.rdf'. /// <code lang="xml"> ///<?xml version="1.0"?> ///<!DOCTYPE rdf:RDF [ /// <!ENTITY dt "http://contoso.com/2008/" > ///]> ///<rdf:RDF /// xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" /// xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" /// xml:base="http://www.sample.org/"> /// /// <rdfs:Class rdf:about="Person"> /// </rdfs:Class> /// /// <rdfs:Class rdf:about="Employee"> /// <rdfs:subClassOf rdf:resource="Person"/> /// </rdfs:Class> /// /// <rdfs:Class rdf:about="Book"> /// </rdfs:Class> /// /// <rdf:Property rdf:about="AuthoredBy"> /// <rdfs:range rdf:resource="Person"/> /// <rdfs:domain rdf:resource="Book"/> /// </rdf:Property> /// /// <rdf:Property rdf:about="EditedBy"> /// <rdfs:range rdf:resource="Person"/> /// <rdfs:domain rdf:resource="Book"/> /// </rdf:Property> /// /// <rdf:Property rdf:about="Name"> /// <rdfs:range rdf:resource="&dt;string128"/> /// <rdfs:domain rdf:resource="Person"/> /// </rdf:Property> /// /// <rdf:Property rdf:about="Designation"> /// <rdfs:range rdf:resource="&dt;string256"/> /// <rdfs:domain rdf:resource="Employee"/> /// </rdf:Property> /// /// <rdf:Property rdf:about="//Book/Name"> /// <rdfs:range rdf:resource="&dt;string128"/> /// <rdfs:domain rdf:resource="Book"/> /// </rdf:Property> /// ///</rdf:RDF> /// </code> /// <br/> /// The listing below shows the contents of XSD that contains additional type definitions /// used in the example. The example assumes that this document is saved as 'C:\Sample.xsd'. /// <code lang="xml"> ///<xs:schema /// targetNamespace="http://contoso.com/2008/" /// xmlns:xs="http://www.w3.org/2001/XMLSchema"> /// /// <xs:simpleType name="string128" id="string128"> /// <xs:restriction base="xs:string"> /// <xs:maxLength value="128"/> /// </xs:restriction> /// </xs:simpleType> /// /// <xs:simpleType name="string256" id="string256"> /// <xs:restriction base="xs:string"> /// <xs:maxLength value="256"/> /// </xs:restriction> /// </xs:simpleType> /// ///</xs:schema> /// </code> /// <br/> /// Example: /// <code> ///using System; ///using System.Linq; ///using Zentity.Core; ///using System.Reflection; ///using System.Collections; ///using System.Xml.Linq; /// ///namespace ZentitySamples ///{ /// class Program /// { /// const string nameSpace = "Zentity.Samples"; /// const string connectionStringFormat = @"provider=System.Data.SqlClient; /// metadata=res://{0}; provider connection string='Data Source=.; /// Initial Catalog=Zentity;Integrated Security=True;MultipleActiveResultSets=True'"; /// const string rdfsPath = @"C:\Sample.rdf"; /// const string dataTypesXsdPath = @"C:\Sample.xsd"; /// const string extensionsAssemblyName = "Extensions"; /// const string extensionsAssemblyFileName = "Extensions.dll"; /// /// static void Main(string[] args) /// { /// Assembly extensions = SynchronizeAndGenerateAssembly(); /// CreateRepositoryItems(extensions); /// FetchRepositoryItems(extensions); /// } /// /// private static void FetchRepositoryItems(Assembly extensionsAssembly) /// { /// using (ZentityContext context = new ZentityContext( /// string.Format(connectionStringFormat, extensionsAssemblyName))) /// { /// Console.WriteLine("Getting books..."); /// Type resourceTypeBook = extensionsAssembly.GetType("Zentity.Samples.Book"); /// MethodInfo ofTypeMethod = context.Resources.GetType().GetMethod("OfType"). /// MakeGenericMethod(resourceTypeBook); /// var customTypeInstances = ofTypeMethod.Invoke(context.Resources, null); /// foreach (Resource book in (IEnumerable)customTypeInstances) /// Console.WriteLine(book.Id); /// /// Console.WriteLine("\nGetting persons..."); /// Type resourceTypePerson = extensionsAssembly.GetType("Zentity.Samples.Person"); /// ofTypeMethod = context.Resources.GetType().GetMethod("OfType"). /// MakeGenericMethod(resourceTypePerson); /// customTypeInstances = ofTypeMethod.Invoke(context.Resources, null); /// foreach (Resource person in (IEnumerable)customTypeInstances) /// Console.WriteLine(person.Id); /// /// Console.WriteLine("\nGetting AuthoredBy relationships..."); /// NavigationProperty authoredByProperty = context.DataModel.Modules[nameSpace]. /// ResourceTypes["Book"].NavigationProperties["AuthoredBy"]; /// Predicate predicate = context.Predicates. /// Where(tuple => tuple.Id == authoredByProperty.Association.PredicateId).First(); /// predicate.Relationships.Load(); /// foreach (Relationship rel in predicate.Relationships) /// Console.WriteLine("[{0}] <--{1}--> [{2}]", rel.Subject.Id, predicate.Name, /// rel.Object.Id); /// } /// } /// /// private static void CreateRepositoryItems(Assembly extensionsAssembly) /// { /// using (ZentityContext context = new ZentityContext( /// string.Format(connectionStringFormat, extensionsAssemblyName))) /// { /// Type resourceTypeBook = extensionsAssembly.GetType("Zentity.Samples.Book"); /// PropertyInfo propertyAuthoredBy = resourceTypeBook.GetProperty("AuthoredBy"); /// Type resourceTypePerson = extensionsAssembly.GetType("Zentity.Samples.Person"); /// /// var aPerson = Activator.CreateInstance(resourceTypePerson); /// var aBook = Activator.CreateInstance(resourceTypeBook); /// var anotherBook = Activator.CreateInstance(resourceTypeBook); /// /// // AuthoredBy is actually a an EntityCollection<Person>. /// var instanceAuthoredBy = propertyAuthoredBy.GetValue(aBook, null); /// Type entityCollectionOfPerson = instanceAuthoredBy.GetType(); /// // Get the "Add" method. /// MethodInfo methodAdd = entityCollectionOfPerson.GetMethod("Add"); /// // Add author to book. /// methodAdd.Invoke(instanceAuthoredBy, new object[] { aPerson }); /// /// instanceAuthoredBy = propertyAuthoredBy.GetValue(anotherBook, null); /// methodAdd.Invoke(instanceAuthoredBy, new object[] { aPerson }); /// /// // Save the entities to repository. /// context.AddToResources((Resource)aPerson); /// context.SaveChanges(); /// } /// } /// /// private static Assembly SynchronizeAndGenerateAssembly() /// { /// using (ZentityContext context = new ZentityContext( /// string.Format(connectionStringFormat, "Zentity.Core"))) /// { /// ResourceType defaultBaseResourceType = context.DataModel. /// Modules["Zentity.Core"].ResourceTypes["Resource"]; /// /// XDocument rdfDocument = XDocument.Load(rdfsPath); /// XDocument xsdDocument = XDocument.Load(dataTypesXsdPath); /// DataModelModule module = DataModelModule.CreateFromRdfs(defaultBaseResourceType, /// rdfDocument, xsdDocument, nameSpace, false); /// /// context.DataModel.Modules.Add(module); /// /// // Synchronize to alter the database schema. /// // This method sometimes takes a few minutes to complete depending on the actions /// // taken by other modules (such as change history logging) in response to schema /// // changes. Everything happens in a single transaction. Make sure that the timeout /// // values are set correct for the command and transaction. Transaction timeout is /// // controlled from App.Config, Web.Config and machine.config configuration files. /// context.CommandTimeout = 300; /// context.DataModel.Synchronize(); /// /// // Generate the module assembly to use. /// byte[] rawAssembly = context.DataModel.GenerateExtensionsAssembly( /// extensionsAssemblyName, true, new string[] { nameSpace }, /// new string[] { nameSpace }, null); /// /// return Assembly.Load(rawAssembly); /// } /// } /// } ///} /// </code> /// </example> public static DataModelModule CreateFromRdfs(ResourceType baseResourceType, XDocument rdfDocument, XDocument xsdDocument, string namespaceName, bool isStrictExecutionMode) { //Validate parameters. if (baseResourceType == null) { throw new ArgumentNullException("baseResourceType", RdfsResources.ExceptionArgumentIsNull); } if (rdfDocument == null) { throw new ArgumentNullException("rdfDocument", RdfsResources.ExceptionArgumentIsNull); } if (string.IsNullOrEmpty(namespaceName)) { throw new ArgumentNullException("namespaceName", RdfsResources.ExceptionArgumentIsNull); } ExecutionMode executionMode = isStrictExecutionMode ? ExecutionMode.Strict : ExecutionMode.Loose; //Parse Rdf/Xml to Graph. RdfXmlParser rdfParser = new RdfXmlParser(rdfDocument); Graph rdfGraph = rdfParser.Parse(true); //Create collection of xsd datatypes. XsdDataTypeCollection dataTypeCollection = null; if (xsdDocument != null) { dataTypeCollection = new XsdDataTypeCollection(xsdDocument); } else { dataTypeCollection = new XsdDataTypeCollection(); } //Create context for current execution. Context context = new Context { Graph = rdfGraph, XsdDataTypeCollection = dataTypeCollection, ExecutionMode = executionMode, BaseResourceType = baseResourceType }; //Create list of interpreters. List <RdfsInterpreter> interpreters = new List <RdfsInterpreter>(); interpreters.Add(new PredicateInterpreter(context)); interpreters.Add(new TypeInterpreter(context)); interpreters.Add(new SubClassOfInterpreter(context)); interpreters.Add(new DomainRangeInterpreter(context)); //Create data model module object. DataModelModule dataModelModule = new DataModelModule { NameSpace = namespaceName, Uri = rdfDocument.BaseUri }; //Execute interpreters. foreach (RdfsInterpreter interpreter in interpreters) { interpreter.Interpret(dataModelModule); } return(dataModelModule); }