Пример #1
0
        public void RunVocab(String[] args)
        {
            if (args.Length < 2)
            {
                Console.Error.WriteLine("rdfWebDeploy: Error: 2 Arguments are required in order to use the -vocab mode");
                return;
            }

            if (File.Exists(args[1]))
            {
                Console.Error.WriteLine("rdfWebDeploy: Error: Cannot output the configuration vocabulary to " + args[1] + " as a file already exists at that location");
                return;
            }

            TurtleParser ttlparser = new TurtleParser();
            StreamReader reader    = new StreamReader(Assembly.GetAssembly(typeof(IGraph)).GetManifestResourceStream("VDS.RDF.Configuration.configuration.ttl"));
            Graph        g         = new Graph();

            ttlparser.Load(g, reader);

            IRdfWriter writer;

            try
            {
                writer = MimeTypesHelper.GetWriterByFileExtension(MimeTypesHelper.GetTrueFileExtension(args[1]));
            }
            catch (RdfWriterSelectionException)
            {
                writer = new CompressingTurtleWriter(WriterCompressionLevel.High);
            }
            writer.Save(g, args[1]);
            Console.WriteLine("rdfWebDeploy: Configuration Vocabulary output to " + args[1]);
        }
Пример #2
0
        public void Run()
        {
            if (this._args.Length == 0)
            {
                this.ShowUsage();
            }
            else
            {
                if (!this.ParseOptions())
                {
                    Console.Error.WriteLine("rdfOptStats: Error: One/More options were invalid");
                    return;
                }

                if (this._inputs.Count == 0)
                {
                    Console.Error.WriteLine("rdfOptStats: Error: No Inputs Specified");
                    return;
                }

                List <BaseStatsHandler> handlers = new List <BaseStatsHandler>();
                if (this._subjects && this._predicates && this._objects)
                {
                    handlers.Add(new SPOStatsHandler(this._literals));
                }
                else if (this._subjects && this._predicates)
                {
                    handlers.Add(new SPStatsHandler(this._literals));
                }
                else
                {
                    if (this._subjects)
                    {
                        handlers.Add(new SubjectStatsHandler(this._literals));
                    }
                    if (this._predicates)
                    {
                        handlers.Add(new PredicateStatsHandler(this._literals));
                    }
                    if (this._objects)
                    {
                        handlers.Add(new ObjectStatsHandler(this._literals));
                    }
                }
                if (this._nodes)
                {
                    handlers.Add(new NodeStatsHandler());
                }

                bool        ok = true;
                IRdfHandler handler;
                if (handlers.Count == 1)
                {
                    handler = handlers[0];
                }
                else
                {
                    handler = new MultiHandler(handlers.OfType <IRdfHandler>());
                }

                Stopwatch timer = new Stopwatch();
                timer.Start();
                for (int i = 0; i < this._inputs.Count; i++)
                {
                    Console.WriteLine("rdfOptStats: Processing Input " + (i + 1) + " of " + this._inputs.Count + " - '" + this._inputs[i] + "'");

                    try
                    {
                        FileLoader.Load(handler, this._inputs[i]);
                    }
                    catch (RdfParserSelectionException selEx)
                    {
                        ok = false;
                        Console.Error.WriteLine("rdfOptStats: Error: Unable to select a Parser to read input");
                        break;
                    }
                    catch (RdfParseException parseEx)
                    {
                        ok = false;
                        Console.Error.WriteLine("rdfOptStats: Error: Parsing Error while reading input");
                        break;
                    }
                    catch (RdfException parseEx)
                    {
                        ok = false;
                        Console.Error.WriteLine("rdfOptStats: Error: RDF Error while reading input");
                        break;
                    }
                    catch (Exception ex)
                    {
                        ok = false;
                        Console.Error.WriteLine("rdfOptStats: Error: Unexpected Error while reading input");
                        break;
                    }
                }
                Console.WriteLine("rdfOptStats: Finished Processing Inputs");
                timer.Stop();
                Console.WriteLine("rdfOptStats: Took " + timer.Elapsed + " to process inputs");
                timer.Reset();

                if (ok)
                {
                    //Output the Stats
                    timer.Start();
                    Graph g = new Graph();
                    g.NamespaceMap.Import(handlers.First().Namespaces);
                    try
                    {
                        foreach (BaseStatsHandler h in handlers)
                        {
                            h.GetStats(g);
                        }
                        IRdfWriter writer = MimeTypesHelper.GetWriterByFileExtension(MimeTypesHelper.GetTrueFileExtension(this._file));
                        if (writer is ICompressingWriter)
                        {
                            ((ICompressingWriter)writer).CompressionLevel = WriterCompressionLevel.High;
                        }
                        if (writer is IHighSpeedWriter)
                        {
                            ((IHighSpeedWriter)writer).HighSpeedModePermitted = false;
                        }
                        writer.Save(g, this._file);

                        Console.WriteLine("rdfOptStats: Statistics output to " + this._file);
                        timer.Stop();
                        Console.WriteLine("rdfOptStats: Took " + timer.Elapsed + " to output statistics");
                    }
                    catch (Exception ex)
                    {
                        Console.Error.WriteLine("rdfOptStats: Error: Unexpected error outputting statistics to " + this._file);
                        Console.Error.WriteLine(ex.Message);
                        Console.Error.WriteLine(ex.StackTrace);
                    }
                }
                else
                {
                    Console.Error.WriteLine("rdfOptStats: Error: Unable to output statistics due to errors during input processing");
                }
            }
        }
Пример #3
0
        private void mnuSaveConnection_Click(object sender, EventArgs e)
        {
            if (this.ActiveMdiChild != null)
            {
                if (this.ActiveMdiChild is StoreManagerForm)
                {
                    Object manager;
                    if (this.ActiveMdiChild is StoreManagerForm)
                    {
                        manager = ((StoreManagerForm)this.ActiveMdiChild).Manager;
                    }
                    else
                    {
                        return;
                    }
                    if (manager is IConfigurationSerializable)
                    {
                        this.sfdConnection.Filter = MimeTypesHelper.GetFilenameFilter(true, false, false, false, false, false);
                        if (this.sfdConnection.ShowDialog() == DialogResult.OK)
                        {
                            //Append to existing configuration file or overwrite?
                            ConfigurationSerializationContext context;
                            if (File.Exists(this.sfdConnection.FileName))
                            {
                                DialogResult result = MessageBox.Show("The selected connection file already exists - would you like to append this connection to that file?  Click Yes to append to this file, No to overwrite and Cancel to abort", "Append Connection?", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
                                switch (result)
                                {
                                case DialogResult.Yes:
                                    Graph g = new Graph();
                                    FileLoader.Load(g, this.sfdConnection.FileName);
                                    context = new ConfigurationSerializationContext(g);
                                    break;

                                case DialogResult.No:
                                    context = new ConfigurationSerializationContext();
                                    break;

                                default:
                                    return;
                                }
                            }
                            else
                            {
                                //Create new configuration file
                                context = new ConfigurationSerializationContext();
                            }

                            //Save the Connection
                            ((IConfigurationSerializable)manager).SerializeConfiguration(context);

                            try
                            {
                                IRdfWriter writer = MimeTypesHelper.GetWriterByFileExtension(MimeTypesHelper.GetTrueFileExtension(this.sfdConnection.FileName));
                                writer.Save(context.Graph, this.sfdConnection.FileName);
                            }
                            catch (RdfWriterSelectionException)
                            {
                                CompressingTurtleWriter ttlwriter = new CompressingTurtleWriter(WriterCompressionLevel.High);
                                ttlwriter.Save(context.Graph, this.sfdConnection.FileName);
                            }
                        }
                    }
                    else
                    {
                        MessageBox.Show("Unable to save the current connection as it does not support this feature", "Save Unavailable", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }
                else
                {
                    this.mnuSaveConnection.Enabled = false;
                }
            }
            else
            {
                this.mnuSaveConnection.Enabled = false;
            }
        }
Пример #4
0
        private bool SetOptions(String[] args)
        {
            if (args.Length == 0 || args.Length == 1 && args[0].Equals("-help"))
            {
                this.ShowUsage();
                return(false);
            }

            String arg;
            int    i = 0;

            while (i < args.Length)
            {
                arg = args[i];

                if (arg.StartsWith("-uri:"))
                {
                    if (this._mode == RdfQueryMode.Remote)
                    {
                        Console.Error.WriteLine("rdfQuery: Cannot specify input URIs as well as specifying a remote endpoint to query");
                        return(false);
                    }

                    String uri = arg.Substring(5);
                    try
                    {
                        this._mode = RdfQueryMode.Local;

                        //Try and parse RDF from the given URI
                        if (!this._print)
                        {
                            Uri   u = new Uri(uri);
                            Graph g = new Graph();
                            UriLoader.Load(g, u);
                            this._store.Add(g);
                        }
                        else
                        {
                            Console.Error.WriteLine("rdfQuery: Ignoring the input URI '" + uri + "' since -print has been specified so the query will not be executed so no need to load the data");
                        }
                    }
                    catch (UriFormatException uriEx)
                    {
                        Console.Error.WriteLine("rdfQuery: Ignoring the input URI '" + uri + "' since this is not a valid URI");
                        if (this._debug)
                        {
                            this.DebugErrors(uriEx);
                        }
                    }
                    catch (RdfParseException parseEx)
                    {
                        Console.Error.WriteLine("rdfQuery: Ignoring the input URI '" + uri + "' due to the following error:");
                        Console.Error.WriteLine("rdfQuery: Parser Error: " + parseEx.Message);
                        if (this._debug)
                        {
                            this.DebugErrors(parseEx);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.Error.WriteLine("rdfQuery: Ignoring the input URI '" + uri + "' due to the following error:");
                        Console.Error.WriteLine("rdfQuery: Error: " + ex.Message);
                        if (this._debug)
                        {
                            this.DebugErrors(ex);
                        }
                    }
                }
                else if (arg.StartsWith("-endpoint:"))
                {
                    if (this._mode == RdfQueryMode.Local)
                    {
                        Console.Error.WriteLine("rdfQuery: Cannot specify a remote endpoint to query as well as specifying local files and/or input URIs");
                        return(false);
                    }
                    else if (this._mode == RdfQueryMode.Remote)
                    {
                        if (!(this._endpoint is FederatedSparqlRemoteEndpoint))
                        {
                            this._endpoint = new FederatedSparqlRemoteEndpoint(this._endpoint);
                        }
                    }

                    try
                    {
                        this._mode = RdfQueryMode.Remote;
                        if (this._endpoint is FederatedSparqlRemoteEndpoint)
                        {
                            ((FederatedSparqlRemoteEndpoint)this._endpoint).AddEndpoint(new SparqlRemoteEndpoint(new Uri(arg.Substring(arg.IndexOf(':') + 1))));
                        }
                        else
                        {
                            this._endpoint = new SparqlRemoteEndpoint(new Uri(arg.Substring(arg.IndexOf(':') + 1)));
                        }
                    }
                    catch (UriFormatException uriEx)
                    {
                        Console.Error.WriteLine("rdfQuery: Unable to use remote endpoint with URI '" + arg.Substring(arg.IndexOf(':') + 1) + "' since this is not a valid URI");
                        if (this._debug)
                        {
                            this.DebugErrors(uriEx);
                        }
                        return(false);
                    }
                }
                else if (arg.StartsWith("-output:") || arg.StartsWith("-out:"))
                {
                    this._output = arg.Substring(arg.IndexOf(':') + 1);
                }
                else if (arg.StartsWith("-outformat:"))
                {
                    String format = arg.Substring(arg.IndexOf(':') + 1);
                    try
                    {
                        if (format.Contains("/"))
                        {
                            //MIME Type
                            this._graphWriter   = MimeTypesHelper.GetWriter(format);
                            this._resultsWriter = MimeTypesHelper.GetSparqlWriter(format);
                        }
                        else
                        {
                            //File Extension
                            this._graphWriter   = MimeTypesHelper.GetWriterByFileExtension(format);
                            this._resultsWriter = MimeTypesHelper.GetSparqlWriterByFileExtension(format);
                        }
                    }
                    catch (RdfException)
                    {
                        Console.Error.WriteLine("rdfQuery: The file extension '" + format + "' could not be used to determine a MIME Type and select a writer - default writers will be used");
                    }
                }
                else if (arg.StartsWith("-syntax"))
                {
                    if (arg.Contains(':'))
                    {
                        String syntax = arg.Substring(arg.IndexOf(':') + 1);
                        switch (syntax)
                        {
                        case "1":
                        case "1.0":
                            this._parser.SyntaxMode = SparqlQuerySyntax.Sparql_1_0;
                            break;

                        case "1.1":
                            this._parser.SyntaxMode = SparqlQuerySyntax.Sparql_1_1;
                            break;

                        case "E":
                        case "e":
                            this._parser.SyntaxMode = SparqlQuerySyntax.Extended;
                            break;

                        default:
                            Console.Error.WriteLine("rdfQuery: The value '" + syntax + "' is not a valid query syntax specifier - assuming SPARQL 1.1 with Extensions");
                            this._parser.SyntaxMode = SparqlQuerySyntax.Extended;
                            break;
                        }
                    }
                    else
                    {
                        this._parser.SyntaxMode = SparqlQuerySyntax.Extended;
                    }
                }
                else if (arg.StartsWith("-timeout:"))
                {
                    long timeout;
                    if (Int64.TryParse(arg.Substring(arg.IndexOf(':') + 1), out timeout))
                    {
                        this._timeout = timeout;
                    }
                    else
                    {
                        Console.Error.WriteLine("rdfQuery: The value '" + arg.Substring(arg.IndexOf(':') + 1) + "' is not a valid timeout in milliseconds - default timeouts will be used");
                    }
                }
                else if (arg.StartsWith("-r:"))
                {
                    arg = arg.Substring(arg.IndexOf(':') + 1);
                    switch (arg)
                    {
                    case "rdfs":
                        ((IInferencingTripleStore)this._store).AddInferenceEngine(new RdfsReasoner());
                        break;

                    case "skos":
                        ((IInferencingTripleStore)this._store).AddInferenceEngine(new SkosReasoner());
                        break;

                    default:
                        Console.Error.WriteLine("rdfQuery: The value '" + arg + "' is not a valid Reasoner - ignoring this option");
                        break;
                    }
                }
                else if (arg.StartsWith("-partialResults"))
                {
                    if (arg.Contains(':'))
                    {
                        bool partial;
                        if (Boolean.TryParse(arg.Substring(arg.IndexOf(':') + 1), out partial))
                        {
                            this._partialResults = partial;
                        }
                        else
                        {
                            Console.Error.WriteLine("rdfQuery: The value '" + arg.Substring(arg.IndexOf(':') + 1) + "' is not a valid boolean - partial results mode is disabled");
                        }
                    }
                    else
                    {
                        this._partialResults = true;
                    }
                }
                else if (arg.StartsWith("-noopt"))
                {
                    if (arg.Equals("-noopt"))
                    {
                        Options.QueryOptimisation   = false;
                        Options.AlgebraOptimisation = false;
                    }
                    else if (arg.Length >= 7)
                    {
                        String opts = arg.Substring(7);
                        foreach (char c in opts.ToCharArray())
                        {
                            if (c == 'a' || c == 'A')
                            {
                                Options.AlgebraOptimisation = false;
                            }
                            else if (c == 'q' || c == 'Q')
                            {
                                Options.QueryOptimisation = false;
                            }
                            else
                            {
                                Console.Error.WriteLine("rdfQuery: The value '" + c + "' as part of the -noopt argument is not supported - it has been ignored");
                            }
                        }
                    }
                }
                else if (arg.Equals("-nocache"))
                {
                    Options.UriLoaderCaching = false;
                }
                else if (arg.Equals("-nobom"))
                {
                    Options.UseBomForUtf8 = false;
                }
                else if (arg.Equals("-print"))
                {
                    this._print = true;
                }
                else if (arg.Equals("-debug"))
                {
                    this._debug = true;
                }
                else if (arg.StartsWith("-explain"))
                {
                    this._explain = true;
                    if (arg.Length > 9)
                    {
                        try
                        {
                            this._level = (ExplanationLevel)Enum.Parse(typeof(ExplanationLevel), arg.Substring(9));
                            this._level = (this._level | ExplanationLevel.OutputToConsoleStdErr | ExplanationLevel.Simulate) ^ ExplanationLevel.OutputToConsoleStdOut;
                        }
                        catch
                        {
                            Console.Error.WriteLine("rdfQuery: The argument '" + arg + "' does not specify a valid Explanation Level");
                            return(false);
                        }
                    }
                }
                else if (arg.Equals("-help"))
                {
                    //Ignore Help Argument if other arguments present
                }
                else if (arg.StartsWith("-"))
                {
                    //Report Invalid Argument
                    Console.Error.WriteLine("rdfQuery: The argument '" + arg + "' is not a supported argument - it has been ignored");
                }
                else if (i == args.Length - 1)
                {
                    //Last Argument must be the Query
                    this._query = arg;
                }
                else
                {
                    //Treat as an input file

                    if (this._mode == RdfQueryMode.Remote)
                    {
                        Console.Error.WriteLine("rdfQuery: Cannot specify local files as well as specifying a remote endpoint to query");
                        return(false);
                    }

                    try
                    {
                        this._mode = RdfQueryMode.Local;

                        //Try and parse RDF from the given file
                        if (!this._print)
                        {
                            Graph g = new Graph();
                            FileLoader.Load(g, arg);
                            this._store.Add(g);
                        }
                        else
                        {
                            Console.Error.WriteLine("rdfQuery: Ignoring the local file '" + arg + "' since -print has been specified so the query will not be executed so no need to load the data");
                        }
                    }
                    catch (RdfParseException parseEx)
                    {
                        Console.Error.WriteLine("rdfQuery: Ignoring the local file '" + arg + "' due to the following error:");
                        Console.Error.WriteLine("rdfQuery: Parser Error: " + parseEx.Message);
                        if (this._debug)
                        {
                            this.DebugErrors(parseEx);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.Error.WriteLine("rdfQuery: Ignoring the local file '" + arg + "' due to the following error:");
                        Console.Error.WriteLine("rdfQuery: Error: " + ex.Message);
                        if (this._debug)
                        {
                            this.DebugErrors(ex);
                        }
                    }
                }


                i++;
            }

            return(true);
        }
        /// <summary>
        /// Launch the RDF export wizard and save resulting RDF file to disk.
        /// </summary>
        public void ExportRDF()
        {
            // Generate candidate list of namespaces to map, for the export dialog to consume
            candidateNamespacesToMap = new HashSet <Uri>();
            foreach (Worksheet worksheet in Globals.ThisAddIn.Application.Worksheets)
            {
                int    lastUsedColumnIndex = worksheet.UsedRange.Columns.Count;
                string lastUsedColumnName  = Helper.GetExcelColumnName(lastUsedColumnIndex);
                Range  headerRange         = worksheet.get_Range(String.Format("A1:{0}1", lastUsedColumnName));
                candidateNamespacesToMap.UnionWith(Helper.getNamespaceUrisFromComments(headerRange));
            }

            ExportOptionsForm exportOptionsForm = new ExportOptionsForm();

            if (exportOptionsForm.ShowDialog() == DialogResult.OK)
            {
                // Set up save file UI
                SaveFileDialog saveRdfFileDialog = new SaveFileDialog();
                saveRdfFileDialog.Filter = "RDF/XML (*.rdf)|*.rdf|Turtle (*.ttl)|*.ttl|NTriples (*.nt)|*.nt";
                saveRdfFileDialog.Title  = "Save RDF file";
                if (saveRdfFileDialog.ShowDialog() == DialogResult.OK)
                {
                    // Initiate DotNetRdf Graph and shared IRI:s
                    IGraph   g       = new Graph();
                    IUriNode rdfType = g.CreateUriNode(UriFactory.Create(RdfSpecsHelper.RdfType));

                    // Assign namespace mappings from export dialog
                    foreach (KeyValuePair <string, Uri> entry in exportPrefixMappings)
                    {
                        g.NamespaceMap.AddNamespace(entry.Key, entry.Value);
                    }

                    // Used to trim URI:s
                    Char[] trimUrisChars = new Char[] { '<', '>' };

                    // Iterate over all worksheets
                    foreach (Worksheet worksheet in Globals.ThisAddIn.Application.Worksheets)
                    {
                        // Which bits of the sheet are being used
                        Range usedRange      = worksheet.UsedRange;
                        int   lastUsedRow    = usedRange.Row + usedRange.Rows.Count - 1;
                        int   lastUsedColumn = usedRange.Column + usedRange.Columns.Count - 1;

                        // Identifier column metadata
                        int identifierColumn = 0;

                        // Class name is tentatively in the data namespace until the identifier column is found
                        Uri className = new Uri(exportNamespace.ToString() + worksheet.Name);

                        // Set up lookup table. Note that we use 1-indexing to simplify mapping to/from Excel
                        // ranges. The 0:th column will thus be empty and should not be adressed, as will the
                        // identifier column.
                        HeaderFields[] headerLookupTable = new HeaderFields[lastUsedColumn + 1];

                        // Parse the header row.
                        string lastUsedColumnName = Helper.GetExcelColumnName(lastUsedColumn);
                        Range  headerRange        = worksheet.get_Range(String.Format("A1:{0}1", lastUsedColumnName));
                        foreach (Range headerCell in headerRange.Cells)
                        {
                            int column = headerCell.Column;

                            // If there is an embedded note, proceed
                            if (headerCell.Comment != null)
                            {
                                string   noteText           = headerCell.Comment.Text(Type.Missing, Type.Missing, Type.Missing);
                                string[] noteTextComponents = noteText.Split('\n');

                                string iriComponent = noteTextComponents[0];
                                if (iriComponent.Equals("<IRI>") && noteTextComponents.Count() == 2)
                                {
                                    // This is the identifier column; update worksheet metadata accordingly
                                    identifierColumn = headerCell.Column;
                                    string classComponent        = noteTextComponents[1];
                                    string classComponentTrimmed = classComponent.Trim(trimUrisChars);
                                    className = new Uri(classComponentTrimmed);
                                }
                                else if (noteTextComponents.Count() == 3)
                                {
                                    HeaderFields hf = new HeaderFields();
                                    hf.propertyIri = g.CreateUriNode(UriFactory.Create(iriComponent.Trim(trimUrisChars)));

                                    string propertyTypeComponent = noteTextComponents[1];
                                    hf.propertyType = new Uri(propertyTypeComponent.Trim(trimUrisChars));

                                    string propertyRangeComponent = noteTextComponents[2];
                                    hf.propertyRange = new Uri(propertyRangeComponent.Trim(trimUrisChars));

                                    headerLookupTable[column] = hf;
                                }
                                else if (noteTextComponents.Count() == 6)
                                {
                                    HeaderFields hf = new HeaderFields();
                                    hf.propertyIri = g.CreateUriNode(UriFactory.Create(iriComponent.Trim(trimUrisChars)));

                                    string propertyTypeComponent = noteTextComponents[1];
                                    hf.propertyType = new Uri(propertyTypeComponent.Trim(trimUrisChars));

                                    string propertyRangeComponent = noteTextComponents[2];
                                    hf.propertyRange = new Uri(propertyRangeComponent.Trim(trimUrisChars));

                                    string nestedIriComponent = noteTextComponents[3];
                                    hf.nestedIri = g.CreateUriNode(UriFactory.Create(nestedIriComponent.Trim(trimUrisChars)));

                                    string nestedTypeComponent = noteTextComponents[4];
                                    hf.nestedType = new Uri(nestedTypeComponent.Trim(trimUrisChars));

                                    string nestedRangeComponent = noteTextComponents[5].Trim(trimUrisChars);
                                    if (nestedRangeComponent.Length > 0)
                                    {
                                        hf.nestedRange = new Uri(nestedRangeComponent);
                                    }

                                    headerLookupTable[column] = hf;
                                }
                            }
                        }

                        // Now, assuming an identifier column has been found, we can finally start parsing the rows
                        if (identifierColumn != 0)
                        {
                            // All entities will have the same class
                            IUriNode worksheetClass = g.CreateUriNode(className);

                            // For every row in the spreadsheet..
                            for (int rowIndex = 2; rowIndex <= lastUsedRow; rowIndex++)
                            {
                                string rowRangeIdentifier = String.Format("{0}{1}:{2}{3}", Helper.GetExcelColumnName(1), rowIndex, Helper.GetExcelColumnName(lastUsedColumn), rowIndex);
                                Range  row = worksheet.get_Range(rowRangeIdentifier);

                                // Set subject node ID.
                                string identifierCellIdentifier = String.Format("{0}{1}", Helper.GetExcelColumnName(identifierColumn), rowIndex);
                                Range  identifierCell           = worksheet.get_Range(identifierCellIdentifier);

                                // Used to store the references to any intermediate (nested) blank nodes for the row
                                Dictionary <IUriNode, IBlankNode> intermediateNodes = new Dictionary <IUriNode, IBlankNode>();

                                // Only parse rows that have an identifier
                                if (identifierCell.Text != "")
                                {
                                    Uri      subjectUri  = new Uri(exportNamespace.ToString() + identifierCell.Text);
                                    IUriNode subjectNode = g.CreateUriNode(subjectUri);
                                    g.Assert(new Triple(subjectNode, rdfType, worksheetClass));

                                    // Iterate over remaining columns, i.e., property instances, skipping the identifier column if it reappears
                                    foreach (Range dataCell in row.Cells)
                                    {
                                        if (dataCell.Column == identifierColumn)
                                        {
                                            continue;
                                        }

                                        // Get header fields
                                        HeaderFields hf = headerLookupTable[dataCell.Column];

                                        // Check that there actually are header fields for the cell under consideration; otherwise, ignore cell
                                        // This is not a simple null check since HeaderFields is a struct, e.g., value type, which cannot be null
                                        if (hf.Equals(default(HeaderFields)))
                                        {
                                            continue;
                                        }

                                        if (hf.nestedIri != null)
                                        {
                                            // This is a nested anonymous individual

                                            // Assert the intermediate (nested) individual
                                            IUriNode   predicateNode = hf.propertyIri;
                                            IBlankNode intermediateBlank;
                                            if (intermediateNodes.ContainsKey(predicateNode))
                                            {
                                                intermediateBlank = intermediateNodes[predicateNode];
                                            }
                                            else
                                            {
                                                intermediateBlank = g.CreateBlankNode();
                                                intermediateNodes.Add(predicateNode, intermediateBlank);
                                            }
                                            IUriNode intermediateType = g.CreateUriNode(hf.propertyRange);
                                            g.Assert(new Triple(subjectNode, predicateNode, intermediateBlank));
                                            g.Assert(new Triple(intermediateBlank, rdfType, intermediateType));

                                            IUriNode nestedPredicateNode = hf.nestedIri;

                                            // Get out and parse object.
                                            // "Raw" cell value, will need treatment (TODO!)
                                            INode  objectNode;
                                            string cellValue = dataCell.Text;

                                            // Check so cell isn't empty
                                            if (!cellValue.Equals(""))
                                            {
                                                switch (hf.nestedType.ToString())
                                                {
                                                case OntologyHelper.OwlDatatypeProperty:
                                                    objectNode = g.CreateLiteralNode(cellValue, hf.nestedRange);
                                                    break;

                                                case OntologyHelper.OwlObjectProperty:
                                                    // If there is a valid URI in the cell, use that as-is, otherwise generate one frame the export namespace
                                                    if (Uri.TryCreate(cellValue, UriKind.Absolute, out Uri tempObjectPropertyValue) == true)
                                                    {
                                                        objectNode = g.CreateUriNode(tempObjectPropertyValue);
                                                    }
                                                    else
                                                    {
                                                        objectNode = g.CreateUriNode(new Uri(exportNamespace.ToString() + cellValue));
                                                    }
                                                    break;

                                                case OntologyHelper.OwlAnnotationProperty:
                                                    // For annotation properties we use literal object nodes if property range is in XSD namespace
                                                    // and uri nodes otherwise.
                                                    if (hf.nestedRange.ToString().Contains(XmlSpecsHelper.NamespaceXmlSchema))
                                                    {
                                                        objectNode = g.CreateLiteralNode(cellValue, hf.nestedRange);
                                                    }
                                                    else
                                                    {
                                                        // If there is a valid URI in the cell, use that as-is, otherwise generate one frame the export namespace
                                                        if (Uri.TryCreate(cellValue, UriKind.Absolute, out Uri tempAnnotationPropertyValue) == true)
                                                        {
                                                            objectNode = g.CreateUriNode(tempAnnotationPropertyValue);
                                                        }
                                                        else
                                                        {
                                                            objectNode = g.CreateUriNode(new Uri(exportNamespace.ToString() + cellValue));
                                                        }
                                                    }
                                                    break;

                                                default:
                                                    continue;
                                                }

                                                g.Assert(new Triple(intermediateBlank, nestedPredicateNode, objectNode));
                                            }
                                        }
                                        else
                                        {
                                            IUriNode predicateNode = hf.propertyIri;

                                            // Get out and parse object.
                                            // "Raw" cell value, will need treatment (TODO!)
                                            INode  objectNode;
                                            string cellValue = dataCell.Text;

                                            // Check so cell isn't empty
                                            if (!cellValue.Equals(""))
                                            {
                                                switch (hf.propertyType.ToString())
                                                {
                                                case OntologyHelper.OwlDatatypeProperty:
                                                    objectNode = g.CreateLiteralNode(cellValue, hf.propertyRange);
                                                    break;

                                                case OntologyHelper.OwlObjectProperty:
                                                    // If there is a valid URI in the cell, use that as-is, otherwise generate one frame the export namespace
                                                    if (Uri.TryCreate(cellValue, UriKind.Absolute, out Uri tempObjectPropertyValue) == true)
                                                    {
                                                        objectNode = g.CreateUriNode(tempObjectPropertyValue);
                                                    }
                                                    else
                                                    {
                                                        objectNode = g.CreateUriNode(new Uri(exportNamespace.ToString() + cellValue));
                                                    }
                                                    break;

                                                case OntologyHelper.OwlAnnotationProperty:
                                                    // For annotation properties we use literal object nodes if property range is in XSD namespace
                                                    // and uri nodes otherwise.
                                                    if (hf.propertyRange.ToString().Contains(XmlSpecsHelper.NamespaceXmlSchema))
                                                    {
                                                        objectNode = g.CreateLiteralNode(cellValue, hf.propertyRange);
                                                    }
                                                    else
                                                    {
                                                        // If there is a valid URI in the cell, use that as-is, otherwise generate one frame the export namespace
                                                        if (Uri.TryCreate(cellValue, UriKind.Absolute, out Uri tempAnnotationPropertyValue) == true)
                                                        {
                                                            objectNode = g.CreateUriNode(tempAnnotationPropertyValue);
                                                        }
                                                        else
                                                        {
                                                            objectNode = g.CreateUriNode(new Uri(exportNamespace.ToString() + cellValue));
                                                        }
                                                    }
                                                    break;

                                                default:
                                                    continue;
                                                }

                                                g.Assert(new Triple(subjectNode, predicateNode, objectNode));
                                            }
                                        }
                                    }
                                }
                            }
                            String     saveFileExtension = Path.GetExtension(saveRdfFileDialog.FileName);
                            IRdfWriter writer            = MimeTypesHelper.GetWriterByFileExtension(saveFileExtension);
                            writer.Save(g, saveRdfFileDialog.FileName);
                        }
                    }
                }
            }
        }