public void Publish(CogsModel model) { if (TargetDirectory == null) { throw new InvalidOperationException("Target directory must be specified"); } if (Overwrite && Directory.Exists(TargetDirectory)) { Directory.Delete(TargetDirectory, true); } // TODO: if Overwrite is false and Directory.Exists(TargetDirectory)) throw an error and exit Directory.CreateDirectory(TargetDirectory); // create graphs for each item var builder = new DotSchemaPublisher { TargetDirectory = Path.Combine(Path.Combine(TargetDirectory, "source"), "images"), Overwrite = Overwrite, Format = "svg", Output = "single", Inheritance = false, ShowReusables = true, DotLocation = DotLocation }; builder.Publish(model); // create documentation var doc = new BuildSphinxDocumentation(); doc.Build(model, TargetDirectory); //copy over image css file var path = Path.Combine(Path.Combine(Path.Combine(Path.Combine(TargetDirectory, "build"), "html"), "_static"), "css"); Directory.CreateDirectory(path); using (var stream = new FileStream(Path.Combine(path, "image.css"), FileMode.Create)) { Assembly.GetExecutingAssembly().GetManifestResourceStream("Cogs.Publishers.image.css").CopyTo(stream); } }
public void Publish(CogsModel model) { if (TargetDirectory == null) { throw new InvalidOperationException("Target directory must be specified"); } if (Overwrite && Directory.Exists(TargetDirectory)) { Directory.Delete(TargetDirectory, true); } // TODO: if Overwrite is false and Directory.Exists(TargetDirectory)) throw an error and exit Directory.CreateDirectory(TargetDirectory); //TODO: get project name and set it here string projectName = model.Settings.Slug; // set namespaces based on output format XNamespace xmins = "http://www.omg.org/spec/XMI/20110701"; XNamespace umlns = "http://www.omg.org/spec/UML/20110701"; if (!Normative) { xmins = "http://www.omg.org/spec/XMI/20131001"; umlns = "http://www.omg.org/spec/UML/20131001"; } XElement xmodel = new XElement("packagedElement", new XAttribute(xmins + "type", "uml:Package"), new XAttribute(xmins + "id", projectName), new XAttribute("name", projectName)); XElement diagramElements = new XElement("elements"); List <XElement> nodes = null; var xOff = 0.0; var yOff = 0.0; XNamespace ns = "http://www.w3.org/2000/svg"; if (!Normative) { // run svg publisher to create svg file to use for positioning DotSchemaPublisher publisher = new DotSchemaPublisher { TargetDirectory = TargetDirectory, Overwrite = Overwrite, Format = "svg", Output = "all", Inheritance = true, DotLocation = DotLocation, ShowReusables = true }; publisher.Publish(model); // read created svg file nodes = XDocument.Load(Path.Combine(TargetDirectory, "output.svg")).Root.Descendants(ns + "g") .Where(x => x.Attribute("class").Value == "node").ToList(); File.Delete(Path.Combine(TargetDirectory, "output.svg")); //get leftmost and topmost value to shift graph accordingly foreach (var item in nodes.Descendants(ns + "title").ToList()) { var node = XElement.Parse(item.NextNode.ToString()); if (Convert.ToDouble(node.Attribute("cx").Value) < xOff) { xOff = Convert.ToDouble(node.Attribute("cx").Value); } if (Convert.ToDouble(node.Attribute("cy").Value) < yOff) { yOff = Convert.ToDouble(node.Attribute("cy").Value); } } xOff = Math.Abs(xOff); yOff = Math.Abs(yOff); } int count = model.ItemTypes.Count; var offset = 2.5; // loop through classes and reusable data types foreach (var item in model.ItemTypes) { // Create class var newItem = new XElement(new XElement("packagedElement", new XAttribute(xmins + "type", "uml:Class"), new XAttribute(xmins + "id", CreateId(item.Name)), new XAttribute("name", item.Name))); // add class to diagram if (!Normative) { var node = XElement.Parse(nodes.Descendants(ns + "text").Where(x => x.FirstNode.ToString().Contains(item.Name)).ToList()[0].PreviousNode.ToString()); var left = (Double.Parse(node.Attribute("cx").Value) - Double.Parse(node.Attribute("rx").Value) + xOff) * offset; var right = (Double.Parse(node.Attribute("cx").Value) + Double.Parse(node.Attribute("rx").Value) + xOff) * offset; var top = (Double.Parse(node.Attribute("cy").Value) - Double.Parse(node.Attribute("ry").Value) + yOff) * offset; var bottom = (Double.Parse(node.Attribute("cy").Value) + Double.Parse(node.Attribute("ry").Value) + yOff) * offset; diagramElements.Add(new XElement("element", new XAttribute("geometry", "Left=" + left + ";Top=" + top + ";Right=" + right + ";Bottom=" + bottom + ";"), new XAttribute("subject", item.Name), new XAttribute("seqno", count.ToString()), new XAttribute("style", "DUID=" + "item.Name" + ";NSL=0;BCol=-1;BFol=-1;LCol=-1;LWth=-1;fontsz=0;bold=0;black=0;italic=0;ul=0;charset=0;pitch=0;));"))); } string extends = item.ExtendsTypeName; // loop through properties of class and add to class foreach (var property in item.Properties) { var newProperty = new XElement("ownedAttribute", new XAttribute(xmins + "type", "uml:Property"), new XAttribute(xmins + "id", CreateId(item.Name + "." + property.Name)), new XAttribute("name", property.Name)); if (string.Equals(property.DataTypeName, "cogsDate", StringComparison.OrdinalIgnoreCase)) { property.DataTypeName = "string"; } newProperty.Add(new XElement("type", new XAttribute(xmins + "idref", property.DataTypeName))); if (property.MinCardinality != null) { newProperty.Add(new XElement("lowerValue", new XAttribute(xmins + "type", "uml:LiteralInteger"), new XAttribute(xmins + "id", CreateId(item.Name + "." + property.Name + ".MinCardinality")), new XAttribute("value", property.MinCardinality))); } if (property.MaxCardinality != null) { var attribute = new XAttribute("value", property.MaxCardinality); // if max is "n" change to "*" if (property.MaxCardinality.Equals("n")) { attribute = new XAttribute("value", "*"); } newProperty.Add(new XElement("upperValue", new XAttribute(xmins + "type", "uml:LiteralUnlimitedNatural"), new XAttribute(xmins + "id", CreateId(item.Name + "." + property.Name + ".MaxCardinality")), attribute)); } newItem.Add(newProperty); // see if property is a type of class if (model.ItemTypes.Contains(property.DataType) && !IdList.Contains("Association.from" + property.Name + ".to." + property.DataTypeName)) { // create link association var classLink = new XElement("packagedElement", new XAttribute(xmins + "type", "uml:Association"), new XAttribute(xmins + "id", CreateId("Association.from" + property.Name + ".to." + property.DataTypeName))); classLink.Add(new XElement("memberEnd", new XAttribute(xmins + "idref", item.Name + "." + property.Name + ".association"))); classLink.Add(new XElement("memberEnd", new XAttribute(xmins + "idref", "Association.from" + property.Name + ".to." + property.DataTypeName + ".ownedEnd"))); var ownedEnd = new XElement("ownedEnd", new XAttribute(xmins + "type", "uml:Property"), new XAttribute(xmins + "id", CreateId("Association.from" + property.Name + ".to." + property.DataTypeName + ".ownedEnd")), new XAttribute("association", "Association.from" + property.Name + ".to." + property.DataTypeName), new XAttribute("isOrdered", "true")); ownedEnd.Add(new XElement("type", new XAttribute(xmins + "idref", item.Name))); var min = "0"; var max = "*"; // check to see if item being referenced is a ReusableDataType if (model.ReusableDataTypes.Contains(property.DataType)) { min = "1"; max = "1"; } ownedEnd.Add(new XElement("lowerValue", new XAttribute(xmins + "type", "uml:LiteralInteger"), new XAttribute(xmins + "id", CreateId("Association.from" + property.Name + ".to." + property.DataTypeName + ".ownedEnd.MinCardinality")), new XAttribute("value", min))); ownedEnd.Add(new XElement("upperValue", new XAttribute(xmins + "type", "uml:LiteralUnlimitedNatural"), new XAttribute(xmins + "id", CreateId("Association.from" + property.Name + ".to." + property.DataTypeName + ".ownedEnd.MaxCardinality")), new XAttribute("value", max))); classLink.Add(ownedEnd); xmodel.Add(classLink); // reference link from current class as attribute var link = new XElement("ownedAttribute", new XAttribute(xmins + "type", "uml:Property"), new XAttribute(xmins + "id", CreateId(item.Name + "." + property.Name + ".association")), new XAttribute("name", property.Name), new XAttribute("association", "Association.from" + property.Name + ".to." + property.DataTypeName), new XAttribute("isOrdered", "true")); link.Add(new XElement("type", new XAttribute(xmins + "idref", property.DataTypeName))); link.Add(new XElement("lowerValue", new XAttribute(xmins + "type", "uml:LiteralInteger"), new XAttribute(xmins + "id", CreateId(item.Name + "." + property.Name + ".association.MinCardinality")), new XAttribute("value", min))); link.Add(new XElement("upperValue", new XAttribute(xmins + "type", "uml:LiteralUnlimitedNatural"), new XAttribute(xmins + "id", CreateId(item.Name + "." + property.Name + ".association.MaxCardinality")), new XAttribute("value", max))); newItem.Add(link); } } // adds pointers for inheritance where applicable if (!string.IsNullOrWhiteSpace(extends)) { newItem.Add(new XElement("generalization", new XAttribute(xmins + "type", "uml:Generalization"), new XAttribute(xmins + "id", CreateId(item.Name + ".Generalization")), new XAttribute("general", extends))); } // add class to model xmodel.Add(newItem); count -= 1; } //create document header based on format specified XDocument xDoc; if (Normative) { xDoc = new XDocument( new XDeclaration("1.0", "utf-8", null), new XElement(xmins + "XMI", new XAttribute(XNamespace.Xmlns + "uml", "http://www.omg.org/spec/UML/20110701"), new XAttribute(XNamespace.Xmlns + "xmi", "http://www.omg.org/spec/XMI/20110701"), new XElement(xmins + "Documentation", new XElement("exporter", "Enterprise Architect"), new XElement("exporterVersion", "6.5")), new XElement(umlns + "Model", new XAttribute(xmins + "type", "uml:Model"), new XAttribute("name", "EA_Model"), xmodel))); } else { // get current date and time for when setting created and last modified settings var currentTime = DateTime.UtcNow.Year + "-" + DateTime.UtcNow.Month + "-" + DateTime.UtcNow.Day + " " + DateTime.UtcNow.Hour + ":" + DateTime.UtcNow.Minute + ":" + DateTime.UtcNow.Second; // create header + structure of xml 2.5.1 (chunky and unpleasing, but works) xDoc = new XDocument( new XDeclaration("1.0", "utf-8", null), new XElement(xmins + "XMI", new XAttribute(XNamespace.Xmlns + "uml", "http://www.omg.org/spec/UML/20131001"), new XAttribute(XNamespace.Xmlns + "xmi", "http://www.omg.org/spec/XMI/20131001"), new XElement(xmins + "Documentation", new XAttribute("exporter", "Enterprise Architect"), new XAttribute("exporterVersion", "6.5")), new XElement(umlns + "Model", new XAttribute(xmins + "type", "uml:Model"), new XAttribute("name", "EA_Model"), xmodel), new XElement(xmins + "Extension", new XAttribute("extender", "Enterprise Architect"), new XAttribute("extenderID", "6.5"), new XElement("diagrams", new XElement("diagram", new XAttribute(xmins + "id", CreateId("ModelDiagram")), new XElement("model", new XAttribute("package", projectName), new XAttribute("localID", "28"), new XAttribute("owner", projectName)), new XElement("properties", new XAttribute("name", projectName), new XAttribute("type", "Logical")), new XElement("project", new XAttribute("author", "computer"), new XAttribute("version", "1.0"), new XAttribute("created", currentTime), new XAttribute("modified", currentTime)), new XElement("style1", new XAttribute("value", "ShowPrivate=1;ShowProtected=1;ShowPublic=1;HideRelationships=0;Locked=0;Border=1;HighlightForeign=1;" + "PackageContents=1;SequenceNotes=0;ScalePrintImage=0;PPgs.cx=1;PPgs.cy=1;DocSize.cx=815;DocSize.cy=1067;ShowDetails=0;Orientation=P;" + "Zoom=100;ShowTags=0;OpParams=1;VisibleAttributeDetail=0;ShowOpRetType=1;ShowIcons=1;CollabNums=0;HideProps=0;ShowReqs=0;ShowCons=0;PaperSize=1;" + "HideParents=0;UseAlias=0;HideAtts=0;HideOps=0;HideStereo=0;HideElemStereo=0;ShowTests=0;ShowMaint=0;ConnectorNotation=UML 2.1;ExplicitNavigability=0;" + "ShowShape=1;AdvancedElementProps=1;AdvancedFeatureProps=1;AdvancedConnectorProps=1;m_bElementClassifier=1;ShowNotes=0;SuppressBrackets=0;SuppConnectorLabels=0;" + "PrintPageHeadFoot=0;ShowAsList=0;")), new XElement("style2", new XAttribute("value", "ExcludeRTF=0;DocAll=0;HideQuals=0;AttPkg=1;ShowTests=0;ShowMaint=0;" + "SuppressFOC=1;MatrixActive=0;SwimlanesActive=1;KanbanActive=0;MatrixLineWidth=1;MatrixLineClr=0;MatrixLocked=0;TConnectorNotation=UML 2.1;TExplicitNavigability=0;" + "AdvancedElementProps=1;AdvancedFeatureProps=1;AdvancedConnectorProps=1;m_bElementClassifier=1;ProfileData=;MDGDgm=;STBLDgm=;ShowNotes=0;VisibleAttributeDetail=0;" + "ShowOpRetType=1;SuppressBrackets=0;SuppConnectorLabels=0;PrintPageHeadFoot=0;ShowAsList=0;SuppressedCompartments=;Theme=:119;SaveTag=D7ED2A20;")), new XElement("swimlanes", new XAttribute("value", "locked=false;orientation=0;width=0;inbar=false;names=false;color=-1;bold=false;fcol=0;tcol=-1;ofCol=-1;ufCol=-1;" + "hl=0;ufh=0;cls=0;SwimlaneFont=lfh:-10,lfw:0,lfi:0,lfu:0,lfs:0,lfface:Calibri,lfe:0,lfo:0,lfchar:1,lfop:0,lfcp:0,lfq:0,lfpf=0,lfWidth=0;")), new XElement("matrixitems", new XAttribute("value", "locked=false;matrixactive=false;swimlanesactive=true;kanbanactive=false;width=1;clrLine=0;")), new XElement("extendedProperties"), diagramElements))))); } //write collection to file using (StreamWriter outputFile = new StreamWriter(Path.Combine(TargetDirectory, "uml" + ".xmi.xml"))) { XmlTextWriter writer = new XmlTextWriter(outputFile); writer.Formatting = Formatting.Indented; xDoc.WriteTo(writer); writer.Flush(); } }