Beispiel #1
0
        private static List <SKEMAObject> FlattenTree(SKEMAObject skema, bool skipOptional = false)
        {
            // This would be a set if we where targeting .NET greater than 3.5
            List <SKEMAObject> result = new List <SKEMAObject>();

            FlattenTreeInternal(result, skema, skipOptional);

            return(result);
        }
Beispiel #2
0
        private static void FlattenTreeInternal(List <SKEMAObject> result, SKEMAObject skema, bool skipOptional)
        {
            result.Add(skema);

            switch (skema.Type)
            {
            case SKEMAType.REFERENCE:
                if (skema.ReferenceSKEMA != null)
                {
                    if (result.Contains(skema.ReferenceSKEMA) == false)
                    {
                        FlattenTreeInternal(result, skema.ReferenceSKEMA, skipOptional);
                    }
                }
                break;

            case SKEMAType.ANY:
            case SKEMAType.STRING:
            case SKEMAType.INTEGER:
            case SKEMAType.FLOAT:
            case SKEMAType.BOOLEAN:
            case SKEMAType.DATETIME:
                break;

            case SKEMAType.MAP:
                foreach (string key in skema.Keys)
                {
                    if (skipOptional && skema.IsOptional(key) == true)
                    {
                        //Console.WriteLine("Key " + key + " is optional. Skipping!");
                        continue;
                    }

                    if (result.Contains(skema[key]) == false)
                    {
                        FlattenTreeInternal(result, skema[key], skipOptional);
                    }
                }
                break;

            case SKEMAType.ARRAY:
                if (skema.ArrayElementSKEMA != null)
                {
                    if (result.Contains(skema.ArrayElementSKEMA) == false)
                    {
                        FlattenTreeInternal(result, skema.ArrayElementSKEMA, skipOptional);
                    }
                }
                break;

            default:
                break;
            }
        }
Beispiel #3
0
        private static List <SKEMAObject> FindReferences(SKEMAObject skema, bool skipOptional = false, bool removeSelf = true)
        {
            List <SKEMAObject> references = new List <SKEMAObject>();

            references = FlattenTree(skema, skipOptional).FindAll(s => s.Type == SKEMAType.REFERENCE);

            if (removeSelf && skema.Type == SKEMAType.REFERENCE)
            {
                references.Remove(skema);
            }

            return(references);
        }
Beispiel #4
0
            internal bool ResolveReferences(SKEMAObject data, Dictionary <string, SKEMAObject> definitions, out List <LinkedList <SKEMAObject> > components)
            {
                //Console.WriteLine($"Resolving references... ({definitions.Count} definitions)");

                // See https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm for the algorithm used

                components = FindStronglyConnectedComponents(definitions, (v) =>
                {
                    List <SKEMAObject> successors = new List <SKEMAObject>();
                    foreach (var successor in FindReferences(v, true, false))
                    {
                        if (definitions.ContainsKey(successor.Reference))
                        {
                            successors.Add(definitions[successor.Reference]);
                        }
                        else
                        {
                            throw new DefinitionNotFoundException(successor);
                        }
                    }
                    return(successors);
                });

                if (components.Count > 0)
                {
                    foreach (var comp in components)
                    {
                        if (comp.Count == 1 && comp.First.Value.Type == SKEMAType.REFERENCE)
                        {
                            if (definitions[comp.First.Value.Reference] == comp.First.Value)
                            {
                                return(false);
                            }
                        }

                        if (comp.Count > 1)
                        {
                            return(false);
                        }
                    }
                }

                //Console.WriteLine("Substituting references...");

                SubstituteDefinitionReferences(definitions);

                SubstituteReferences(data, definitions);

                return(true);
            }
Beispiel #5
0
            private void StrongConnect(SKEMAObject v, VertexSuccessors VertexSuccessors)
            {
                indexMap[v]   = index;
                lowlinkMap[v] = index;
                index++;
                S.Push(v);

                List <SKEMAObject> successors = VertexSuccessors(v);

                SKEMAObject w;

                // Find the referenced definitions in the SKEMAObject
                foreach (SKEMAObject reference in successors)
                {
                    w = reference;

                    if (indexMap.ContainsKey(w) == false)
                    {
                        StrongConnect(w, VertexSuccessors);

                        lowlinkMap[v] = Math.Min(lowlinkMap[v], lowlinkMap[w]);
                    }
                    else if (S.Contains(w))
                    {
                        lowlinkMap[v] = Math.Min(lowlinkMap[v], indexMap[w]);
                    }
                }

                if (lowlinkMap[v] == indexMap[v])
                {
                    LinkedList <SKEMAObject> component = new LinkedList <SKEMAObject>();
                    do
                    {
                        w = S.Pop();
                        component.AddLast(w);
                    } while (w != v);

                    //Console.WriteLine("Added strongly connected component of lenght " + component.Count);
                    stronglyConnectedComponents.Add(component);
                }
            }
Beispiel #6
0
            private void SubstituteReferences(SKEMAObject obj, Dictionary <string, SKEMAObject> definitions)
            {
                List <SKEMAObject> references = FindReferences(obj);

                foreach (var reference in references)
                {
                    if (reference.ReferenceSKEMA != null)
                    {
                        continue;
                    }

                    //Console.WriteLine($"Replacing reference with definition for {reference.Reference}");
                    if (definitions.ContainsKey(reference.Reference))
                    {
                        reference.ReferenceSKEMA = definitions[reference.Reference];
                        SubstituteReferences(reference.ReferenceSKEMA, definitions);
                    }
                    else
                    {
                        throw new DefinitionNotFoundException(reference);
                    }
                }
            }
Beispiel #7
0
        /// <summary>
        /// Writes a SKEMAObject.
        /// </summary>
        /// <param name="obj">The object to write.</param>
        /// <returns>A string to write into a file.</returns>
        public static string Write(SKEMAObject obj, SKONMetadata metadata = default(SKONMetadata))
        {
            if (obj.Type != SKEMAType.MAP)
            {
                throw new ArgumentException("SKEMAObject to write must be of type map!");
            }

            // We might want to do something here?
            metadata.LanguageVersion = LanguageVersion;

            StringBuilder sb = new StringBuilder();

            sb.Append($"{SKON.Metadelimit}Version: {metadata.LanguageVersion}{SKON.Metadelimit}\n");
            sb.Append($"{SKON.Metadelimit}DocumentVersion: \"{metadata.DocuemntVersion}\"{SKON.Metadelimit}\n");
            if (metadata.SKEMA != null && metadata.SKEMA.Length > 0)
            {
                sb.Append($"{SKON.Metadelimit}SKEMA: \"{metadata.SKEMA}\"{SKON.Metadelimit}\n");
            }

            List <LinkedList <SKEMAObject> > sccs = new ReferenceSolver().FindStronglyConnectedComponents(obj, (v) =>
            {
                List <SKEMAObject> successors = new List <SKEMAObject>();

                switch (v.Type)
                {
                case SKEMAType.REFERENCE:
                    if (v.ReferenceSKEMA.Type == SKEMAType.REFERENCE || v.ReferenceSKEMA.Type == SKEMAType.ARRAY || v.ReferenceSKEMA.Type == SKEMAType.MAP)
                    {
                        successors.Add(v.ReferenceSKEMA);
                    }
                    break;

                case SKEMAType.ANY:
                case SKEMAType.STRING:
                case SKEMAType.INTEGER:
                case SKEMAType.FLOAT:
                case SKEMAType.BOOLEAN:
                case SKEMAType.DATETIME:
                    break;

                case SKEMAType.MAP:
                    foreach (string key in v.Keys)
                    {
                        SKEMAObject w = v[key];
                        if (w.Type == SKEMAType.REFERENCE || w.Type == SKEMAType.ARRAY || w.Type == SKEMAType.MAP)
                        {
                            successors.Add(w);
                        }
                    }
                    break;

                case SKEMAType.ARRAY:
                    if (v.ArrayElementSKEMA.Type == SKEMAType.REFERENCE || v.ArrayElementSKEMA.Type == SKEMAType.ARRAY || v.ArrayElementSKEMA.Type == SKEMAType.MAP)
                    {
                        successors.Add(v.ArrayElementSKEMA);
                    }
                    break;

                default:
                    break;
                }

                //Console.WriteLine($"Found {successors.Count} successsors!");
                foreach (var s in successors)
                {
                    //Console.WriteLine(s.Type);
                }

                return(successors);
            });

            if (sccs.Count > 1)
            {
                List <LinkedList <SKEMAObject> > badSccs = new List <LinkedList <SKEMAObject> >();

                foreach (var scc in sccs)
                {
                    //Console.WriteLine($"Component (Length {scc.Count}):");

                    if (scc.Count == 1 && scc.First.Value.Type != SKEMAType.REFERENCE)
                    {
                        // This strongly connected component can't be bad
                        continue;
                    }

                    bool containsDefiniton = false;

                    foreach (SKEMAObject element in scc)
                    {
                        //Console.WriteLine(element.Type);

                        if (element.Type == SKEMAType.REFERENCE && element.ReferenceSKEMA != null)
                        {
                            containsDefiniton = true;
                            //Console.WriteLine("Component Contains Definition!");
                            break;
                        }
                    }

                    if (containsDefiniton == false)
                    {
                        badSccs.Add(scc);
                    }
                }

                if (badSccs.Count > 0)
                {
                    throw new CouldNotSolveReferencesException(badSccs);
                }
            }

            List <SKEMAObject> references = FindReferences(obj);

            foreach (SKEMAObject reference in references)
            {
                sb.Append("define " + reference.Reference + ": " + WriteObject(reference.ReferenceSKEMA, 0) + ",\n");
            }

            foreach (string key in obj.Keys)
            {
                sb.Append(key + ": " + WriteObject(obj[key], 0) + ",\n");
            }

            return(sb.ToString());
        }
Beispiel #8
0
 public static void WriteToFile(string filepath, SKEMAObject obj)
 {
     File.WriteAllText(filepath, Write(obj), Encoding.UTF8);
 }
Beispiel #9
0
 internal DefinitionNotFoundException(SKEMAObject reference) : base($"Could not find definition for #{reference.Reference}")
 {
     Reference = reference;
 }
Beispiel #10
0
            internal List <LinkedList <SKEMAObject> > FindStronglyConnectedComponents(SKEMAObject obj, VertexSuccessors VertexSuccessors)
            {
                foreach (string v in obj.Keys)
                {
                    if (indexMap.ContainsKey(obj[v]) == false)
                    {
                        StrongConnect(obj[v], VertexSuccessors);
                    }
                }

                return(stronglyConnectedComponents);
            }
Beispiel #11
0
        /// <summary>
        /// Writes a SKEMAObject value.
        /// </summary>
        /// <param name="obj">The object to write.</param>
        /// <param name="indent">The amount of indentation.</param>
        /// <returns>A string to write into a file.</returns>
        private static string WriteObject(SKEMAObject obj, int indent)
        {
            if (obj == null)
            {
                return(string.Empty);
            }

            string indentString = string.Empty;

            for (int i = 0; i < indent; i++)
            {
                indentString += SKON.IndentString;
            }

            switch (obj.Type)
            {
            case SKEMAType.REFERENCE:
                return("#" + obj.Reference);

            case SKEMAType.ANY:
                return("Any");

            case SKEMAType.STRING:
                return("String");

            case SKEMAType.INTEGER:
                return("Integer");

            case SKEMAType.FLOAT:
                return("Float");

            case SKEMAType.BOOLEAN:
                return("Boolean");

            case SKEMAType.DATETIME:
                return("DateTime");

            case SKEMAType.MAP:
                StringBuilder mapsb = new StringBuilder();

                if (obj.Keys.Count <= 0)
                {
                    mapsb.Append("{  }");
                    return(mapsb.ToString());
                }

                mapsb.Append("\n" + indentString + "{\n");

                foreach (string key in obj.Keys)
                {
                    mapsb.Append(indentString + SKON.IndentString + (obj.IsOptional(key) ? "optional " : "") + $"{key}: {WriteObject(obj[key], indent + 1)},\n");
                }

                mapsb.Append(indentString + "}");

                return(mapsb.ToString());

            case SKEMAType.ARRAY:
                if (obj.ArrayElementSKEMA == null)
                {
                    return("[  ]");
                }
                return("\n" +
                       indentString + "[" + ((obj.ArrayElementSKEMA.Type != SKEMAType.MAP && obj.ArrayElementSKEMA.Type != SKEMAType.ARRAY) ? "\n" : "") +
                       indentString + SKON.IndentString + WriteObject(obj.ArrayElementSKEMA, indent + 1) + "\n" +
                       indentString + "]");

            default:
                return(null);
            }
        }