packages feed

dataflow 0.5.3.0 → 0.5.4.0

raw patch · 4 files changed

+118/−86 lines, 4 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ DataFlow.DFD: color :: String -> String -> String
+ DataFlow.DFD: convertDiagram :: Diagram -> DFD Graph
+ DataFlow.DFD: incrStep :: DFD ()
+ DataFlow.DFD: nextStep :: DFD Int
+ DataFlow.DFD: type DFD v = State Step v
+ DataFlow.DFD: type Step = Int
- DataFlow.DFD: convertObject :: Object -> StmtList
+ DataFlow.DFD: convertObject :: Object -> DFD StmtList
- DataFlow.DFD: convertObjects :: [Object] -> StmtList
+ DataFlow.DFD: convertObjects :: [Object] -> DFD StmtList

Files

dataflow.cabal view
@@ -1,5 +1,5 @@ name:                dataflow-version:             0.5.3.0+version:             0.5.4.0 synopsis:            Generate Graphviz documents from a Haskell representation. description:         Outputs .dot files that can be processed by the dot                      command. Currently it only supports the DFD output format
examples/legend.svg view
@@ -4,49 +4,52 @@ <!-- Generated by graphviz version 2.38.0 (20140413.2041)  --> <!-- Title: Untitled Pages: 1 -->-<svg width="370pt" height="300pt"- viewBox="0.00 0.00 370.00 300.48" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">-<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 296.481)">+<svg width="406pt" height="308pt"+ viewBox="0.00 0.00 406.00 308.32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 304.316)"> <title>Untitled</title>-<polygon fill="white" stroke="none" points="-4,4 -4,-296.481 366,-296.481 366,4 -4,4"/>+<polygon fill="white" stroke="none" points="-4,4 -4,-304.316 402,-304.316 402,4 -4,4"/> <g id="clust1" class="cluster"><title>cluster_trust</title>-<polygon fill="none" stroke="#595959" stroke-dasharray="5,2" points="8,-8 8,-284.481 354,-284.481 354,-8 8,-8"/>-<text text-anchor="start" x="148.393" y="-273.481" font-family="Arial" font-style="italic" font-size="10.00" fill="#595959">TrustBoundary</text>+<polygon fill="none" stroke="#595959" stroke-dasharray="5,2" points="8,-8 8,-292.316 390,-292.316 390,-8 8,-8"/>+<text text-anchor="start" x="166.393" y="-281.316" font-family="Arial" font-style="italic" font-size="10.00" fill="#595959">TrustBoundary</text> </g> <!-- function --> <g id="node1" class="node"><title>function</title>-<ellipse fill="none" stroke="black" cx="190" cy="-210.074" rx="46.8172" ry="46.8172"/>-<text text-anchor="start" x="163.152" y="-207.923" font-family="Arial" font-weight="bold" font-size="14.00">Function</text>+<ellipse fill="none" stroke="black" cx="208" cy="-217.908" rx="46.8172" ry="46.8172"/>+<text text-anchor="start" x="181.152" y="-215.758" font-family="Arial" font-weight="bold" font-size="14.00">Function</text> </g> <!-- database --> <g id="node2" class="node"><title>database</title>-<text text-anchor="start" x="58.5347" y="-58.3825" font-family="Arial" font-weight="bold" font-size="14.00">Database</text>-<polyline fill="none" stroke="black" points="53.5,-47.5825 122.5,-47.5825 "/>-<polyline fill="none" stroke="black" points="122.5,-73.5825 53.5,-73.5825 "/>+<text text-anchor="start" x="58.5347" y="-62.3" font-family="Arial" font-weight="bold" font-size="14.00">Database</text>+<polyline fill="none" stroke="black" points="53.5,-51.5 122.5,-51.5 "/>+<polyline fill="none" stroke="black" points="122.5,-77.5 53.5,-77.5 "/> </g> <!-- function&#45;&gt;database --> <g id="edge3" class="edge"><title>function&#45;&gt;database</title>-<path fill="none" stroke="black" d="M156.061,-177.629C146.51,-167.788 136.58,-156.519 128.664,-145.165 116.243,-127.349 105.643,-105.165 98.3825,-88.129"/>-<polygon fill="black" stroke="black" points="101.565,-86.6655 94.5049,-78.7656 95.0974,-89.3438 101.565,-86.6655"/>-<text text-anchor="start" x="129" y="-132.464" font-family="Arial" font-weight="bold" font-size="12.00">Flow</text>+<path fill="none" stroke="black" d="M169.293,-191.395C155.216,-180.751 139.998,-167.488 128.664,-153 114.295,-134.632 103.528,-110.364 96.6951,-92.0459"/>+<polygon fill="black" stroke="black" points="99.9655,-90.7966 93.3059,-82.5564 93.3733,-93.151 99.9655,-90.7966"/>+<text text-anchor="start" x="129" y="-140.299" font-family="Arial" font-weight="bold" font-size="12.00" fill="#3184e4">(3) </text>+<text text-anchor="start" x="147" y="-140.299" font-family="Arial" font-weight="bold" font-size="12.00">Flow</text> </g> <!-- io --> <g id="node3" class="node"><title>io</title>-<polygon fill="none" stroke="black" stroke-width="2" points="313.665,-105.248 224.335,-105.248 224.335,-15.9173 313.665,-15.9173 313.665,-105.248"/>-<text text-anchor="start" x="232.417" y="-58.4318" font-family="Arial" font-weight="bold" font-size="14.00">InputOutput</text>+<polygon fill="none" stroke="black" stroke-width="2" points="337.5,-113 240.5,-113 240.5,-16 337.5,-16 337.5,-113"/>+<text text-anchor="start" x="252.917" y="-62.3" font-family="Arial" font-weight="bold" font-size="14.00">InputOutput</text> </g> <!-- function&#45;&gt;io --> <g id="edge1" class="edge"><title>function&#45;&gt;io</title>-<path fill="none" stroke="black" d="M173.056,-166.198C170.005,-151.853 169.686,-136.207 176.664,-123.165 185.251,-107.116 200.073,-94.5268 215.359,-85.0284"/>-<polygon fill="black" stroke="black" points="217.483,-87.8421 224.369,-79.7904 213.965,-81.7904 217.483,-87.8421"/>-<text text-anchor="start" x="177" y="-132.464" font-family="Arial" font-weight="bold" font-size="12.00">Flow</text>+<path fill="none" stroke="black" d="M191.196,-174.107C188.156,-159.768 187.808,-144.107 194.664,-131 202.93,-115.197 216.936,-102.441 231.662,-92.5323"/>+<polygon fill="black" stroke="black" points="233.794,-95.3258 240.378,-87.0254 230.054,-89.408 233.794,-95.3258"/>+<text text-anchor="start" x="195" y="-140.299" font-family="Arial" font-weight="bold" font-size="12.00" fill="#3184e4">(1) </text>+<text text-anchor="start" x="213" y="-140.299" font-family="Arial" font-weight="bold" font-size="12.00">Flow</text> </g> <!-- function&#45;&gt;io --> <g id="edge2" class="edge"><title>function&#45;&gt;io</title>-<path fill="none" stroke="black" d="M216.6,-159.412C226.002,-141.858 236.5,-122.259 245.616,-105.241"/>-<polygon fill="black" stroke="black" points="213.433,-157.913 211.796,-168.381 219.603,-161.218 213.433,-157.913"/>-<text text-anchor="start" x="248.561" y="-136.565" font-family="Arial" font-weight="bold" font-size="12.00">Flow</text>-<text text-anchor="start" x="234" y="-126.165" font-family="Arial" font-size="10.00">(backwards)</text>+<path fill="none" stroke="black" d="M241.242,-170.972C245.053,-165.037 248.737,-158.952 252,-153 258.898,-140.418 265.381,-126.282 270.934,-113.101"/>+<polygon fill="black" stroke="black" points="238.183,-169.252 235.599,-179.527 244.027,-173.106 238.183,-169.252"/>+<text text-anchor="start" x="267.561" y="-144.4" font-family="Arial" font-weight="bold" font-size="12.00" fill="#3184e4">(2) </text>+<text text-anchor="start" x="285.561" y="-144.4" font-family="Arial" font-weight="bold" font-size="12.00">Flow</text>+<text text-anchor="start" x="262" y="-134" font-family="Arial" font-size="10.00">(backwards)</text> </g> </g> </svg>
examples/webapp.svg view
@@ -4,68 +4,72 @@ <!-- Generated by graphviz version 2.38.0 (20140413.2041)  --> <!-- Title: Webapp Pages: 1 -->-<svg width="333pt" height="450pt"- viewBox="0.00 0.00 333.01 450.40" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">+<svg width="364pt" height="450pt"+ viewBox="0.00 0.00 364.30 450.40" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 446.4)"> <title>Webapp</title>-<polygon fill="white" stroke="none" points="-4,4 -4,-446.4 329.01,-446.4 329.01,4 -4,4"/>-<text text-anchor="start" x="125.44" y="-423.4" font-family="Arial" font-weight="bold" font-size="20.00">Webapp</text>+<polygon fill="white" stroke="none" points="-4,4 -4,-446.4 360.298,-446.4 360.298,4 -4,4"/>+<text text-anchor="start" x="141.084" y="-423.4" font-family="Arial" font-weight="bold" font-size="20.00">Webapp</text> <g id="clust1" class="cluster"><title>cluster_browser</title>-<polygon fill="none" stroke="#595959" stroke-dasharray="5,2" points="115,-298.185 115,-403.402 201,-403.402 201,-298.185 115,-298.185"/>-<text text-anchor="start" x="139.663" y="-392.402" font-family="Arial" font-style="italic" font-size="10.00" fill="#595959">Browser</text>+<polygon fill="none" stroke="#595959" stroke-dasharray="5,2" points="124.298,-298.185 124.298,-403.402 210.298,-403.402 210.298,-298.185 124.298,-298.185"/>+<text text-anchor="start" x="148.961" y="-392.402" font-family="Arial" font-style="italic" font-size="10.00" fill="#595959">Browser</text> </g> <g id="clust2" class="cluster"><title>cluster_aws</title>-<polygon fill="none" stroke="#595959" stroke-dasharray="5,2" points="8,-8 8,-258.185 144,-258.185 144,-8 8,-8"/>-<text text-anchor="start" x="45.3408" y="-247.185" font-family="Arial" font-style="italic" font-size="10.00" fill="#595959">Amazon AWS</text>+<polygon fill="none" stroke="#595959" stroke-dasharray="5,2" points="75.2982,-8 75.2982,-258.185 211.298,-258.185 211.298,-8 75.2982,-8"/>+<text text-anchor="start" x="112.639" y="-247.185" font-family="Arial" font-style="italic" font-size="10.00" fill="#595959">Amazon AWS</text> </g> <!-- client --> <g id="node1" class="node"><title>client</title>-<ellipse fill="none" stroke="black" cx="158" cy="-341.044" rx="34.7182" ry="34.7182"/>-<text text-anchor="start" x="140.104" y="-338.893" font-family="Arial" font-weight="bold" font-size="14.00">Client</text>+<ellipse fill="none" stroke="black" cx="167.298" cy="-341.044" rx="34.7182" ry="34.7182"/>+<text text-anchor="start" x="149.402" y="-338.893" font-family="Arial" font-weight="bold" font-size="14.00">Client</text> </g> <!-- server --> <g id="node2" class="node"><title>server</title>-<ellipse fill="none" stroke="black" cx="76" cy="-170.343" rx="60.1865" ry="60.1865"/>-<text text-anchor="start" x="39.1714" y="-168.192" font-family="Arial" font-weight="bold" font-size="14.00">Web Server</text>+<ellipse fill="none" stroke="black" cx="143.298" cy="-170.343" rx="60.1865" ry="60.1865"/>+<text text-anchor="start" x="106.47" y="-168.192" font-family="Arial" font-weight="bold" font-size="14.00">Web Server</text> </g> <!-- client&#45;&gt;server --> <g id="edge1" class="edge"><title>client&#45;&gt;server</title>-<path fill="none" stroke="black" d="M123.059,-338.065C89.5097,-334.089 40.5091,-322.371 16.6367,-288.185 2.08217,-267.343 11.5388,-242.438 26.8205,-220.986"/>-<polygon fill="black" stroke="black" points="29.6634,-223.03 32.9246,-212.949 24.0889,-218.796 29.6634,-223.03"/>-<text text-anchor="start" x="17" y="-275.484" font-family="Arial" font-weight="bold" font-size="12.00">Request /</text>+<path fill="none" stroke="black" d="M132.239,-339.791C94.5448,-337.407 36.2297,-327.148 7.93494,-288.185 -19.1714,-250.859 30.7957,-217.498 77.4951,-196.076"/>+<polygon fill="black" stroke="black" points="79.0523,-199.214 86.7676,-191.953 76.2082,-192.817 79.0523,-199.214"/>+<text text-anchor="start" x="8.29822" y="-275.484" font-family="Arial" font-weight="bold" font-size="12.00" fill="#3184e4">(1) </text>+<text text-anchor="start" x="26.2982" y="-275.484" font-family="Arial" font-weight="bold" font-size="12.00">Request /</text> </g> <!-- client&#45;&gt;server --> <g id="edge3" class="edge"><title>client&#45;&gt;server</title>-<path fill="none" stroke="black" d="M138.654,-300.242C127.716,-277.74 113.896,-249.306 102.019,-224.873"/>-<polygon fill="black" stroke="black" points="135.631,-302.03 143.15,-309.493 141.927,-298.97 135.631,-302.03"/>-<text text-anchor="start" x="132" y="-279.585" font-family="Arial" font-weight="bold" font-size="12.00">Response</text>-<text text-anchor="start" x="132.899" y="-269.185" font-family="Arial" font-size="10.00">User Profile</text>+<path fill="none" stroke="black" d="M156.033,-297.404C155.38,-294.295 154.78,-291.199 154.263,-288.185 151.076,-269.61 148.761,-249.204 147.103,-230.715"/>+<polygon fill="black" stroke="black" points="152.647,-298.299 158.261,-307.284 159.475,-296.759 152.647,-298.299"/>+<text text-anchor="start" x="154.298" y="-279.585" font-family="Arial" font-weight="bold" font-size="12.00" fill="#3184e4">(3) </text>+<text text-anchor="start" x="172.298" y="-279.585" font-family="Arial" font-weight="bold" font-size="12.00">Response</text>+<text text-anchor="start" x="164.198" y="-269.185" font-family="Arial" font-size="10.00">User Profile</text> </g> <!-- analytics --> <g id="node4" class="node"><title>analytics</title>-<polygon fill="none" stroke="black" stroke-width="2" points="325.021,-206.364 252.979,-206.364 252.979,-134.323 325.021,-134.323 325.021,-206.364"/>-<text text-anchor="start" x="266.428" y="-174.143" font-family="Arial" font-weight="bold" font-size="14.00">Google</text>-<text text-anchor="start" x="260.99" y="-160.143" font-family="Arial" font-weight="bold" font-size="14.00">Analytics</text>+<polygon fill="none" stroke="black" stroke-width="2" points="356.298,-210.343 276.298,-210.343 276.298,-130.343 356.298,-130.343 356.298,-210.343"/>+<text text-anchor="start" x="293.726" y="-174.143" font-family="Arial" font-weight="bold" font-size="14.00">Google</text>+<text text-anchor="start" x="288.288" y="-160.143" font-family="Arial" font-weight="bold" font-size="14.00">Analytics</text> </g> <!-- client&#45;&gt;analytics --> <g id="edge4" class="edge"><title>client&#45;&gt;analytics</title>-<path fill="none" stroke="black" d="M181.196,-314.881C188.653,-306.533 196.835,-297.095 204,-288.185 223.027,-264.524 243.063,-237.118 258.9,-214.798"/>-<polygon fill="black" stroke="black" points="261.843,-216.698 264.754,-206.51 256.126,-212.659 261.843,-216.698"/>-<text text-anchor="start" x="248.681" y="-279.585" font-family="Arial" font-weight="bold" font-size="12.00">Log</text>-<text text-anchor="start" x="222" y="-269.185" font-family="Arial" font-size="10.00">Page Navigation</text>+<path fill="none" stroke="black" d="M196.993,-322.619C211.093,-313.472 227.595,-301.419 240.298,-288.185 259.899,-267.764 277.455,-241.61 290.743,-219.226"/>+<polygon fill="black" stroke="black" points="293.797,-220.937 295.803,-210.534 287.747,-217.415 293.797,-220.937"/>+<text text-anchor="start" x="275.979" y="-279.585" font-family="Arial" font-weight="bold" font-size="12.00" fill="#3184e4">(4) </text>+<text text-anchor="start" x="293.979" y="-279.585" font-family="Arial" font-weight="bold" font-size="12.00">Log</text>+<text text-anchor="start" x="258.298" y="-269.185" font-family="Arial" font-size="10.00">Page Navigation</text> </g> <!-- logs --> <g id="node3" class="node"><title>logs</title>-<text text-anchor="start" x="72.8208" y="-31.8" font-family="Arial" font-weight="bold" font-size="14.00">Logs</text>-<polyline fill="none" stroke="black" points="68,-21 108,-21 "/>-<polyline fill="none" stroke="black" points="108,-47 68,-47 "/>+<text text-anchor="start" x="140.119" y="-31.8" font-family="Arial" font-weight="bold" font-size="14.00">Logs</text>+<polyline fill="none" stroke="black" points="135.298,-21 175.298,-21 "/>+<polyline fill="none" stroke="black" points="175.298,-47 135.298,-47 "/> </g> <!-- server&#45;&gt;logs --> <g id="edge2" class="edge"><title>server&#45;&gt;logs</title>-<path fill="none" stroke="black" d="M81.2983,-110.027C82.7846,-93.3881 84.3291,-76.0972 85.5602,-62.3138"/>-<polygon fill="black" stroke="black" points="89.0697,-62.3631 86.4733,-52.0913 82.0974,-61.7403 89.0697,-62.3631"/>-<text text-anchor="start" x="91.6592" y="-83.4" font-family="Arial" font-weight="bold" font-size="12.00">Log</text>-<text text-anchor="start" x="85" y="-73" font-family="Arial" font-size="10.00">User IP</text>+<path fill="none" stroke="black" d="M148.597,-110.027C150.083,-93.3881 151.627,-76.0972 152.858,-62.3138"/>+<polygon fill="black" stroke="black" points="156.368,-62.3631 153.772,-52.0913 149.396,-61.7403 156.368,-62.3631"/>+<text text-anchor="start" x="152.298" y="-83.4" font-family="Arial" font-weight="bold" font-size="12.00" fill="#3184e4">(2) </text>+<text text-anchor="start" x="170.298" y="-83.4" font-family="Arial" font-weight="bold" font-size="12.00">Log</text>+<text text-anchor="start" x="154.639" y="-73" font-family="Arial" font-size="10.00">User IP</text> </g> </g> </svg>
src/DataFlow/DFD.hs view
@@ -1,10 +1,24 @@ module DataFlow.DFD where  import Text.Printf+import Control.Monad+import Control.Monad.State import qualified DataFlow.Core as C import DataFlow.Graphviz import DataFlow.Graphviz.EdgeNormalization +type Step = Int+type DFD v = State Step v++incrStep :: DFD ()+incrStep = modify (+ 1)++-- | Get the next \"step\" number (the order of flow arrows in the diagram).+nextStep :: DFD Int+nextStep = do+  incrStep+  get+ inQuotes :: String -> String inQuotes s = "\"" ++ s ++ "\"" @@ -25,21 +39,25 @@  small :: String -> String small "" = ""-small s = "<font point-size=\"10\">" ++ s ++ "</font>"+small s = printf "<font point-size=\"10\">%s</font>" s -convertObject :: C.Object -> StmtList+color :: String -> String -> String+color _ "" = ""+color c s = printf "<font color=\"%s\">%s</font>" c s -convertObject (C.InputOutput id' name) = [+convertObject :: C.Object -> DFD StmtList++convertObject (C.InputOutput id' name) = return [     NodeStmt (ID id') [       Attr (ID "shape") (ID "square"),       Attr (ID "style") (ID "bold"),-      label $ bold name+      label $ printf "<table border=\"0\" cellborder=\"0\" cellpadding=\"2\"><tr><td>%s</td></tr></table>" (bold name)     ]   ] -convertObject (C.TrustBoundary id' name objects) =-  let sgId = (ID $ "cluster_" ++ id')-      objectStmts = convertObjects objects+convertObject (C.TrustBoundary id' name objects) = do+  objectStmts <- convertObjects objects+  let sgId = ID $ "cluster_" ++ id'       sgAttrStmt = AttrStmt Graph [           Attr (ID "fontsize") (ID "10"),           Attr (ID "fontcolor") (ID "grey35"),@@ -48,35 +66,35 @@           label $ italic name         ]       stmts = sgAttrStmt : objectStmts-  in [SubgraphStmt $ Subgraph sgId stmts]+  return [SubgraphStmt $ Subgraph sgId stmts] -convertObject (C.Function id' name) =-  [+convertObject (C.Function id' name) = return [     NodeStmt (ID id') [       Attr (ID "shape") (ID "circle"),       label $ bold name     ]   ] -convertObject (C.Database id' name) =-  [+convertObject (C.Database id' name) = return [     NodeStmt (ID id') [       Attr (ID "shape") (ID "none"),       label $ printf "<table sides=\"TB\" cellborder=\"0\"><tr><td>%s</td></tr></table>" (bold name)     ]   ] -convertObject (C.Flow i1 i2 op desc) =-  [-    EdgeStmt (EdgeExpr (IDOperand (NodeID (ID i1) Nothing))-                       Arrow-                       (IDOperand (NodeID (ID i2) Nothing))) [-      label $ bold op ++ "<br/>" ++ small desc-    ]-  ]+convertObject (C.Flow i1 i2 op desc) = do+    step <- nextStep+    let stepStr = color "#3184e4" $ bold $ printf "(%d) " step+    return [+        EdgeStmt (EdgeExpr (IDOperand (NodeID (ID i1) Nothing))+                          Arrow+                          (IDOperand (NodeID (ID i2) Nothing))) [+          label $ stepStr ++ bold op ++ "<br/>" ++ small desc+        ]+      ] -convertObjects :: [C.Object] -> StmtList-convertObjects = concatMap convertObject+convertObjects :: [C.Object] -> DFD StmtList+convertObjects = liftM concat . mapM convertObject  defaultGraphStmts :: StmtList defaultGraphStmts = [@@ -99,11 +117,18 @@     EqualsStmt (ID "rankdir") (ID "t")   ] +convertDiagram :: C.Diagram -> DFD Graph++convertDiagram (C.Diagram (Just name) objects) = do+  let lbl = EqualsStmt (ID "label") (ID $ inAngleBrackets $ bold name)+  objs <- convertObjects objects+  let stmts = lbl : defaultGraphStmts ++ objs+  return $ normalize $ Digraph (ID $ inQuotes name) stmts++convertDiagram (C.Diagram Nothing objects) = do+  objs <- convertObjects objects+  return $ normalize $ Digraph (ID "Untitled") $ defaultGraphStmts ++ objs+ asDFD :: C.Diagram -> Graph-asDFD (C.Diagram (Just name) objects) =-  normalize $ Digraph (ID $ inQuotes name) $-    let lbl = EqualsStmt (ID "label") (ID $ inAngleBrackets $ bold name)-    in lbl : defaultGraphStmts ++ convertObjects objects-asDFD (C.Diagram Nothing objects) =-  normalize $ Digraph (ID "Untitled") $-    defaultGraphStmts ++ convertObjects objects+asDFD d = evalState (convertDiagram d) 0+