예제 #1
0
        private Type GetObjectType(Type[] types, Example example)
        {
            Type matchingType = null;

            if (types != null)
            {
                if (types.Length == 1)
                {
                    matchingType = types[0];
                }
                else
                {
                    if (example.MimeType != null)
                    {
                        foreach (Type type in types)
                        {
                            if (type.GetCustomAttributes <ContentTypeAttribute>().Any(a => a.ContentType.Equals(example.MimeType)))
                            {
                                matchingType = type;
                                break;
                            }
                        }
                    }

                    if (matchingType == null)
                    {
                        SerialisationLog.Warning(string.Concat("There are multiple request or response types for ", example.ClassName, ".", example.MethodName, " ", example.ExampleType, " but no mimetype specified in the example tag in ", example.DocFilename));
                    }
                }
            }
            return(matchingType);
        }
예제 #2
0
        private static string FindAssemblyPath()
        {
            string path   = null;
            string binDir = string.Concat(GetRootDirectory(), "/src/", WEBSERVICE_NAME, "/bin");

            string[] filenames = null;

            Console.WriteLine(string.Concat("Searching for DeviceServer assemblies in ", binDir, "..."));
            try
            {
                filenames = Directory.GetFiles(binDir, string.Concat("*", WEBSERVICE_NAME, ".exe"), SearchOption.AllDirectories);
            }
            catch (DirectoryNotFoundException)
            {
                SerialisationLog.Error("Could not find bin directory - has the Device Server been built?");
            }
            if (filenames != null)
            {
                List <FileInfo> files = filenames.Select(f => new FileInfo(f))
                                        .Where(f => f.Directory.GetDirectories().Length == 0) // must be bottom level directory to include all dependencies
                                        .OrderBy(f => f.LastWriteTime)                        // select the latest built configuration
                                        .ToList();

                Console.WriteLine(string.Concat("Found ", files.Count, " assemblies:"));
                foreach (FileInfo fileInfo in files)
                {
                    Console.WriteLine(string.Concat("*", fileInfo.FullName.Substring(binDir.Length)));
                }
                if (files.Count > 0)
                {
                    path = files.Last().FullName;
                    Console.WriteLine("Latest assembly: " + path.Substring(binDir.Length));
                }
            }

            return(path);
        }
예제 #3
0
        public static void Main(string[] args)
        {
            if (args.Length == 0 || args.Any(a => a.Equals("-h") || a.Equals("--help")))
            {
                WriteHelp();
            }
            else
            {
                string path = null;

                for (int i = 0; i < args.Length - 1; i++)
                {
                    bool argument = true;
                    if (args[i].Equals("-p") || args[i].Equals("--path"))
                    {
                        path = args[i + 1];
                    }
                    else if (args[i].Equals("-r") || args[i].Equals("--ramlVersion"))
                    {
                        DocumentationSerialiserFactory.RAMLVersion = args[i + 1];
                    }
                    else
                    {
                        argument = false;
                    }
                    if (argument)
                    {
                        List <string> temp = args.ToList();
                        temp.RemoveRange(i, 2);
                        args = temp.ToArray();
                        i--;
                    }
                }


                if (path == null)
                {
                    path = FindAssemblyPath();
                }

                if (string.IsNullOrEmpty(path))
                {
                    Console.WriteLine("Could not find Device Server Executable. ");
                    Console.Out.Flush();
                }
                else
                {
                    Assembly assembly = null;
                    try
                    {
                        assembly = AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(path));
                    }
                    catch (Exception exception)
                    {
                        SerialisationLog.Error(string.Concat("Failed to load assembly at ", path, ": ", exception));
                    }

                    if (assembly != null)
                    {
                        ResourceNode resourceTree = null;
                        try
                        {
                            Console.WriteLine("Gathering resources from assembly...");
                            resourceTree = AssemblyReader.ReadAssembly(assembly);
                        }
                        catch (Exception exception)
                        {
                            SerialisationLog.Error(string.Concat("Failed to generate resource tree from assembly at ", path, ": ", exception));
                        }

                        if (resourceTree != null)
                        {
                            IConfigurationBuilder builder = new ConfigurationBuilder()
                                                            .SetBasePath(Directory.GetCurrentDirectory())
                                                            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                                                            .AddEnvironmentVariables();
                            //.AddCommandLine(args);

                            IConfigurationRoot          root           = builder.Build();
                            DocumentationHeaderSettings headerSettings = new DocumentationHeaderSettings();
                            root.GetSection("HeaderSettings").Bind(headerSettings);

                            SchemaStore  schemaStore  = new SchemaStore(resourceTree);
                            ExampleStore exampleStore = new ExampleStore(string.Concat(GetRootDirectory(), "/doc/"), resourceTree);

                            args = args.Where(a => !a.StartsWith("-")).ToArray();  // remove options
                            int numSuccess = 0;
                            for (int i = 0; i < args.Length; i++)
                            {
                                try
                                {
                                    Console.WriteLine(string.Concat("Generating documentation file: ", args[i]));
                                    GenerateDocumentation(resourceTree, headerSettings, schemaStore, exampleStore, args[i]);
                                    numSuccess++;
                                }
                                catch (Exception exception)
                                {
                                    SerialisationLog.Error(string.Concat("Failed to generate documentation for ", args[i], ": ", exception));
                                }
                            }

                            Console.WriteLine(string.Concat(numSuccess, "/", args.Length, " documentation files generated successfully."));
                            Console.WriteLine(string.Concat(SerialisationLog.Errors, " errors, ", SerialisationLog.Warnings, " warnings."));
                        }
                    }
                }
            }
            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
예제 #4
0
        public void ReadExamples(string baseDirectory, string filename, ResourceNode resourceTree)
        {
            Example             currentExample       = null;
            StringBuilder       currentExampleBody   = null;
            TDataExchangeFormat currentExampleFormat = TDataExchangeFormat.None;
            bool   inExample   = false;
            string lastHeading = null;
            bool   generateXml = true;

            foreach (string line in File.ReadLines(filename))
            {
                string trimmed = line.Trim();
                if (trimmed.StartsWith("#"))
                {
                    lastHeading = trimmed.Replace("#", "").Trim().Replace(" ", "-").ToLower();
                }
                else if (trimmed.StartsWith("[]: [!generateXml]"))
                {
                    generateXml = false;
                }
                if (trimmed.StartsWith("```"))
                {
                    if (currentExample != null)
                    {
                        string exampleFormat = trimmed.Substring("```".Length);
                        if (exampleFormat.Equals(TDataExchangeFormat.Json.ToString().ToLower()))
                        {
                            currentExampleFormat = TDataExchangeFormat.Json;
                            inExample            = true;
                        }
                        else if (exampleFormat.Equals(FORM_EXAMPLE))
                        {
                            currentExampleFormat = TDataExchangeFormat.FormUrlEncoded;
                            inExample            = true;
                        }
                        else if (inExample && exampleFormat.Length == 0)
                        {
                            if (currentExampleFormat == TDataExchangeFormat.FormUrlEncoded)
                            {
                                currentExample.Content.Add(currentExampleFormat, currentExampleBody.ToString());
                            }
                            else
                            {
                                currentExample.Content.Add(TDataExchangeFormat.Json, currentExampleBody.ToString());
                                if (generateXml)
                                {
                                    currentExample.Content.Add(TDataExchangeFormat.Xml, JsonToXml(currentExample, resourceTree, currentExampleBody.ToString()));
                                }
                            }
                            currentExample = null;
                            inExample      = false;
                            generateXml    = true;
                        }
                    }
                }
                else
                {
                    if (inExample)
                    {
                        if (line.Trim().Length > 0)
                        {
                            currentExampleBody.Append(line);// string.Concat(line, "\r\n"));
                        }
                    }
                    else
                    {
                        MatchCollection matches = EXAMPLE_NAME_REGEX.Matches(trimmed);
                        if (matches.Count == 1)
                        {
                            string   fullExampleName       = matches[0].Value;
                            string   prefix                = "[]: [";
                            string   suffix                = "]";
                            string   withoutSquareBrackets = fullExampleName.Substring(prefix.Length, matches[0].Value.Length - prefix.Length - suffix.Length);
                            string[] parts      = withoutSquareBrackets.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
                            string   className  = parts[0];
                            string   methodName = parts[1];
                            string   mimeType   = trimmed.Substring(fullExampleName.Length);
                            if (mimeType.Length > 0)
                            {
                                if (mimeType.StartsWith("[") && mimeType.EndsWith("]"))
                                {
                                    mimeType = mimeType.Substring(1, mimeType.Length - 2);
                                }
                                else
                                {
                                    SerialisationLog.Warning(string.Concat("Invalid mimetype on example tag: ", trimmed, " in ", filename));
                                    mimeType = "";
                                }
                            }

                            if (resourceTree.Find(className, methodName) != null)
                            {
                                TMessageType messageType     = (TMessageType)Enum.Parse(typeof(TMessageType), parts[2]);
                                string       exampleFilename = filename.Substring(baseDirectory.Length);
                                currentExample     = new Example(exampleFilename, lastHeading, className, methodName, messageType, mimeType);
                                currentExampleBody = new StringBuilder();

                                string key = string.Concat(currentExample.ClassName, currentExample.MethodName, currentExample.ExampleType.ToString(), mimeType);
                                if (!_Examples.ContainsKey(key))
                                {
                                    _Examples.Add(key, currentExample);
                                }
                                else
                                {
                                    SerialisationLog.Error(string.Concat("An example already exists for ", currentExample.ClassName, ".", currentExample.MethodName, ".", currentExample.ExampleType.ToString(), "files: [", currentExample.DocFilename, ", ", _Examples[key].DocFilename, "]"));
                                }
                            }
                            else
                            {
                                SerialisationLog.Error(string.Concat("The method ", className, ".", methodName, " in ", filename, " does not exist"));
                            }
                        }
                    }
                }
            }
        }
예제 #5
0
        private string JsonToXml(Example currentExample, ResourceNode resourceTree, string json)
        {
            string     xml    = null;
            MethodInfo method = resourceTree.Find(currentExample.ClassName, currentExample.MethodName).Method;
            MethodDocumentationAttribute attribute = method.GetCustomAttributes <MethodDocumentationAttribute>().FirstOrDefault();

            if (attribute != null)
            {
                Type objectType = null;

                if (currentExample.ExampleType == TMessageType.Request)
                {
                    objectType = GetObjectType(attribute.RequestTypes, currentExample);
                }
                else
                {
                    objectType = GetObjectType(attribute.ResponseTypes, currentExample);
                }

                if (objectType != null)
                {
                    try
                    {
                        object deserialisedObject = JsonConvert.DeserializeObject(json, objectType);

                        Stream                  stream     = new MemoryStream();
                        XmlSerializer           serializer = new XmlSerializer(objectType);
                        XmlSerializerNamespaces xns        = new XmlSerializerNamespaces();
                        xns.Add(string.Empty, string.Empty);
                        serializer.Serialize(stream, deserialisedObject, xns);

                        stream.Position = 0;
                        using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
                        {
                            reader.ReadLine();  // skip <?xml version="1.0"?>
                            xml = reader.ReadToEnd().Replace("+json", "+xml");
                        }
                    }
                    catch (InvalidOperationException)
                    {
                        SerialisationLog.Warning(string.Concat("Failed to serialise XML example for ", currentExample.ClassName, ".", currentExample.MethodName));
                    }
                    catch (Exception ex)
                    {
                        if (ex is JsonReaderException || ex is JsonSerializationException)
                        {
                            SerialisationLog.Warning(string.Concat("Failed to deserialise JSON example for ", currentExample.ClassName, ".", currentExample.MethodName));
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
                else
                {
                    SerialisationLog.Warning(string.Concat("No ", currentExample.ExampleType.ToString().ToLower(), " type for ", currentExample.ClassName, ".", currentExample.MethodName));
                }
            }
            else
            {
                SerialisationLog.Warning(string.Concat("Could not convert JSON example to XML due to no method documentation for ", currentExample.ClassName, ".", currentExample.MethodName));
            }
            return(xml);
        }
예제 #6
0
        public static ResourceNode ReadAssembly(Assembly assembly)
        {
            ResourceNode tree = new ResourceNode();

            Type[] types = assembly.GetTypes()
                           .Where(t => t.IsSubclassOf(typeof(ControllerBase)) && t.GetCustomAttribute <RouteAttribute>() != null)
                           .OrderBy(t => t.GetCustomAttribute <RouteAttribute>(), new RouteComparer())
                           .ToArray();

            foreach (Type classType in types)
            {
                object[] attributes    = classType.GetCustomAttributes(true);
                string   resourceRoute = classType.GetCustomAttribute <RouteAttribute>().Template;
                if (resourceRoute != null)
                {
                    MethodInfo[] methods = classType.GetMethods()
                                           .Where(m => m.GetCustomAttribute <HttpMethodAttribute>() != null)
                                           .OrderBy(m => m.GetCustomAttribute <HttpMethodAttribute>(), new MethodTemplateComparer())
                                           .ToArray();

                    ResourceNode classNode = CreateResourceNode(tree, resourceRoute, classType);

                    foreach (MethodInfo methodInfo in methods)
                    {
                        HttpMethodAttribute methodAttribute = methodInfo.GetCustomAttribute <HttpMethodAttribute>();
                        string httpMethod   = methodAttribute.HttpMethods.FirstOrDefault().ToLower();
                        string template     = null;
                        bool   rootTemplate = false;
                        if (methodAttribute.Template != null)
                        {
                            template = string.Concat(methodAttribute.Template, "/");
                            if (!template.StartsWith("/"))
                            {
                                template = string.Concat("/", template);
                            }
                            else if (template.StartsWith(resourceRoute))
                            {
                                template = template.Substring(resourceRoute.Length);
                            }
                            else
                            {
                                rootTemplate = true;
                            }
                        }
                        else
                        {
                            template = "/";
                        }

                        string fullPath = string.Concat(template, httpMethod);
                        if (!rootTemplate)
                        {
                            fullPath = string.Concat(resourceRoute, fullPath);
                        }

                        ResourceNode methodNode = CreateResourceNode(tree, fullPath, classType);
                        if (methodNode.Method != null)
                        {
                            SerialisationLog.Error(string.Concat("Multiple versions of ", methodNode.Class.Name, ".", methodNode.Method.Name, " exist"));
                        }
                        methodNode.Method = methodInfo;
                    }
                }
            }

            return(tree);
        }