create ( String treeName, String treeType, String[] buildingParameters, Dictionary<String, String[]> nodeAttrList, Dictionary<String, String[]> edgeAttrList) { /////////////////////////////////////////////////////////////////////// /* * Il parametro buildingParameters e' un array di stringhe ciascuna * contenente un'informazione utile alla costruzione del generico * grafo, in questo caso "splitSize" e "depth" per determinare la * struttura dell'albero. I dizionari devono essere cosi impiegati: * Dictionary<String -> NomeAttributo, String[] -> ParametriAddizionali * Nello specifico: * <String[0] -> Tipo, String[1] -> RegolaGenerazione * Tipo := "string", "numeric" * RegolaGenerazione := "string", "random" * Nota: la regola di generazione random e' acquisita inserendo un dash * per indicare l'intervallo K-N (e.g. "17-244" ). */ int splitSize = int.Parse(buildingParameters[0]); int depth = int.Parse(buildingParameters[1]); Albero tree = new Albero (treeName, treeType, splitSize, depth, nodeAttrList, edgeAttrList); /*** buildingParameters[0] = splitSize; buildingParameters[1] = depth; ***/ MemoryStream XmlCompressedStream = new MemoryStream(); XmlCompressedStream = FileEngine.assembleXML(tree); /* * * * * * * * * * * * * * * * * * * * * * * * * * * * ATTENZIONE: Chiusura del writer, cleanup finale * da effettuare nel Main(), dopo l'invio dello stream * al client! * * XmlStream.Close(); * XmlStream.Dispose(); * * * * * * * * * * * * * * * * * * * * * * * * * * */ return XmlCompressedStream; } // End of method create()
XmlTraversal( XmlWriter writer, Albero tree ) { //////////////////////////////// return XmlTraversal(writer, tree.radice); }
parseXML( MemoryStream XmlCompressedStream ) { //////////////////////////////////////////////////// MemoryStream XmlDecompressedStream = new MemoryStream(); XmlDecompressedStream = Exflator.decompress(XmlCompressedStream); /*** Rimozione dall'heap degli oggetti oramai non più utili ***/ XmlCompressedStream.Close(); XmlCompressedStream.Dispose(); XmlDecompressedStream.Position = 0; XmlReader reader = XmlReader.Create(XmlDecompressedStream); /* /*** Controllo se il file XML contiene un albero *** while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { switch(reader.Name) { case "tree": break; case "header": return null; } } } */ /*** Analisi del custom XML header ***/ /*** Strutture ed oggetti che verranno riempiti per costruire l'albero ***/ String treeName = ""; String treeType = ""; int treeSplit = 0; int treeDepth = 0; Dictionary<String, String[]> nodeAttributeList = new Dictionary<String, String[]>(); Dictionary<String, String[]> edgeAttributeList = new Dictionary<String, String[]>(); /*** Finchè non si raggiunge la treeDepth non si e' conclusa l'analisi dell'header ***/ bool EndOfTreeInfo = false; while (reader.Read() && !EndOfTreeInfo) { if (reader.NodeType == XmlNodeType.Element) { switch(reader.Name) { case "treeName": while (reader.Read()) { if (reader.NodeType == XmlNodeType.Text) { treeName = reader.Value; break; } } break; case "treeType": while (reader.Read()) { if (reader.NodeType == XmlNodeType.Text) { treeType = reader.Value; break; } } break; case "treeSplit": while (reader.Read()) { if (reader.NodeType == XmlNodeType.Text) { treeSplit = Int32.Parse(reader.Value); break; } } break; case "treeDepth": while (reader.Read()) { if (reader.NodeType == XmlNodeType.Text) { treeDepth = Int32.Parse(reader.Value); EndOfTreeInfo = true; break; } } break; } } } nodeAttributeList = FileEngine.nodeAttrParser(XmlDecompressedStream); edgeAttributeList = FileEngine.edgeAttrParser(XmlDecompressedStream); Albero Tree = new Albero(treeName, treeType, treeSplit, treeDepth, nodeAttributeList, edgeAttributeList); /*** Analisi dell'XML elementTable ***/ restoreValues(Tree, XmlDecompressedStream); return Tree; } // End of method parseXML()
restoreValues( Albero tree, MemoryStream XmlStream) { //////////////////////////////////////// XmlStream.Position = 0; XmlReader reader = XmlReader.Create(XmlStream); reader.MoveToContent(); restoreValues(tree.radice, reader); } // End of method restoreValues()
assembleXML( Albero Tree ) { /////////////////////////////////// /*** Settaggio impostazioni XmlWriter ***/ XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = ("\t"); settings.Encoding = System.Text.Encoding.UTF8; settings.NewLineChars = Environment.NewLine; settings.NewLineHandling = NewLineHandling.Replace; settings.OmitXmlDeclaration = false; MemoryStream XmlStream = new MemoryStream(); XmlWriter writer = XmlWriter.Create(XmlStream, settings); /*** Inizio scrittura del codice XML ***/ String depth = Convert.ToString(Tree.depth); String splitSize = Convert.ToString(Tree.splitSize); writer.WriteStartDocument(); writer.WriteStartElement("tree"); writer.WriteStartElement("header"); writer.WriteElementString("treeName", Tree.nome); writer.WriteElementString("treeType", Tree.tipo); writer.WriteElementString("treeSplit", splitSize); writer.WriteElementString("treeDepth", depth); writer.WriteStartElement("treeNodeAttributeList"); foreach (KeyValuePair<String, String[]> pair in Tree.VertexAttributeList) { writer.WriteStartElement("treeNodeAttribute"); writer.WriteElementString("treeNodeAttrName", pair.Key.ToString()); writer.WriteElementString("treeNodeAttrType", pair.Value[0].ToString()); writer.WriteElementString("treeNodeAttrGenRule", pair.Value[1].ToString()); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteStartElement("treeEdgeAttributeList"); foreach (KeyValuePair<String, String[]> pair in Tree.EdgeAttributeList) { writer.WriteStartElement("treeEdgeAttribute"); writer.WriteElementString("treeEdgeAttrName", pair.Key.ToString()); writer.WriteElementString("treeEdgeAttrType", pair.Value[0].ToString()); writer.WriteElementString("treeEdgeAttrGenRule", pair.Value[1].ToString()); writer.WriteEndElement(); } writer.WriteEndElement(); /*** Chiusura di header ***/ writer.WriteEndElement(); writer.WriteStartElement("elementTable"); FileEngine.XmlTraversal(writer, Tree); /*** Chiusura di elementTable ***/ writer.WriteEndElement(); /*** Chiusura di tree ***/ writer.WriteEndElement(); writer.WriteEndDocument(); writer.Flush(); MemoryStream XmlCompressedStream = new MemoryStream(); XmlCompressedStream = Exflator.compress(XmlStream); XmlStream.Close(); XmlStream.Dispose(); return XmlCompressedStream; } // End of method assembleXML()
/* modifica i valori di attributi dell'albero con struttura dati albero */ public int editValues(Albero a, int sVertex, int eVertex, Dictionary<String, String> vAttrList, Dictionary<String,String> eAttrList) { Elemento[] eList = this.getPath(a, sVertex, eVertex); SqlCommand cmd = new SqlCommand("", this.connection); this.connection.Open(); this.connection.ChangeDatabase(a.nome); SqlDataReader res; Dictionary<String,Guid> vAttrUid = new Dictionary<String,Guid>(); foreach (KeyValuePair<String, String> attr in vAttrList) { cmd.CommandText = "SELECT AttrDefUid FROM AttrDefVertex WHERE Name='"+ attr.Key +"'"; res = cmd.ExecuteReader(); res.Read(); vAttrUid.Add(attr.Key, res.GetGuid(0)); res.Close(); } Dictionary<String,Guid> eAttrUid = new Dictionary<String,Guid>(); foreach (KeyValuePair<String, String> attr in eAttrList) { cmd.CommandText = "SELECT AttrDefUid FROM AttrDefEdge WHERE Name='"+ attr.Key +"'"; res = cmd.ExecuteReader(); res.Read(); eAttrUid.Add(attr.Key, res.GetGuid(0)); res.Close(); } Guid eUid; foreach(Elemento e in eList) { // caso di e nodo if (e.GetType().Name.Equals("Nodo")) { // prendo uid dell'elemento corrente cmd.CommandText = "SELECT VertexUid FROM Vertex WHERE VertexId=" + ((Nodo)e).ID; res = cmd.ExecuteReader(); res.Read(); eUid = res.GetGuid(0); res.Close(); foreach (KeyValuePair<String, String> attr in vAttrList) { ((Nodo)e).attributi[attr.Key] = new String[] { ((Nodo)e).attributi[attr.Key][0], attr.Value }; cmd.CommandText = "UPDATE AttrUsageVertex SET Value='"+ attr.Value +"' WHERE AttrDefUid='"+ vAttrUid[attr.Key] + "' AND VertexUid='" + eUid + "'"; cmd.ExecuteNonQuery(); } } else { // caso di e arco // prendo uid dell'elemento corrente cmd.CommandText = "SELECT EdgeUid FROM Edge WHERE EdgeId=" + ((Arco)e).ID; res = cmd.ExecuteReader(); res.Read(); eUid = res.GetGuid(0); res.Close(); foreach (KeyValuePair<String, String> attr in eAttrList) { ((Arco)e).attributi[attr.Key] = new String[] { ((Arco)e).attributi[attr.Key][0], attr.Value }; cmd.CommandText = "UPDATE AttrUsageEdge SET Value='" + attr.Value + "' WHERE AttrDefUid='" + eAttrUid[attr.Key] + "' AND EdgeUid='" + eUid + "'"; cmd.ExecuteNonQuery(); } } } this.connection.Close(); return 0; }
public Albero getAlbero(String nomeAlbero) { // controlliamo se esiste l'albero nella lista dei nostri alberi InfoAlbero[] list = getListaAlberi(); bool alberoEsiste = false; foreach (InfoAlbero a in list) { if (a.nome.Equals(nomeAlbero)) { alberoEsiste = true; break; } } if (!alberoEsiste) return null; // Se arriviamo qui l'albero esiste, dobbiamo raccogliere i dati // dal database e costruire la struttura dati da restituire all'esterno // raccogliamo attributi per creazione dell'albero di base SqlCommand meta = new SqlCommand ("SELECT * FROM Tree WHERE Name='"+ nomeAlbero +"'", this.connection); this.connection.Open (); this.connection.ChangeDatabase ("metadata"); SqlDataReader res = meta.ExecuteReader (); res.Read (); string type = res.GetString (1); int splitSize = res.GetInt32 (2); int depth = res.GetInt32 (3); string eal = res.GetString (4); string val = res.GetString (5); // conversione eal e val in dictionaries Dictionary<String, String[]> edgeAttributeList = new Dictionary<string, string[]>(); Dictionary<String, String[]> vertexAttributeList = new Dictionary<string, string[]>(); string[] splitLvlOne = eal.Split (','); string[] splitLvlTwo; foreach (string attr in splitLvlOne) { splitLvlTwo = attr.Split ('.'); edgeAttributeList.Add (splitLvlTwo[0], new String[]{splitLvlTwo[1], splitLvlTwo[2]}); } splitLvlOne = val.Split (','); foreach (string attr in splitLvlOne) { splitLvlTwo = attr.Split ('.'); vertexAttributeList.Add (splitLvlTwo[0], new String[]{splitLvlTwo[1], splitLvlTwo[2]}); } // istanziazione albero Albero alberoRisultante = new Albero(nomeAlbero, type, splitSize, depth, vertexAttributeList, edgeAttributeList); // visita ricorsiva su archi e nodi per assegnare i valori presenti nel database res.Close (); this.connection.ChangeDatabase (nomeAlbero); setValoriCorretti (alberoRisultante.radice); this.connection.Close (); return alberoRisultante; }
// Scomponi una struttura dati albero e salvala nel database public int storeAlbero(Albero a) { this.connection.Open(); SqlCommand creaDb; // creazione database this.connection.ChangeDatabase("master"); string[] queries = this.dbCreationQuery(a.nome).Split('$'); try { /* * CREAZIONE DATABASE */ foreach (string query in queries) { creaDb = new SqlCommand(query, this.connection); creaDb.ExecuteNonQuery(); } /* * INSERIMENTO METADATA ALBERO */ // costruzione vertex ed edge attribute list // nel formato stringa da salvare in db string eal = ""; this.connection.ChangeDatabase(a.nome); // mentre creo le attribute list per metadata // approfitto per popolare le tabelle degli // attributi nel db dell'albero appena creato SqlCommand insAttr; Dictionary<string, Guid> edgeAttributeGuid = new Dictionary<string, Guid>(); foreach (KeyValuePair<String, String[]> d in a.EdgeAttributeList) { eal += d.Key + "." + d.Value[0] + "." + d.Value[1] + ","; insAttr = new SqlCommand("INSERT INTO AttrDefEdge (Name, Type, GenerationRule) OUTPUT (inserted.AttrDefUid) VALUES ('"+ d.Key + "', '" + d.Value[0] + "', '" + d.Value[1] + "')", this.connection); SqlDataReader res = insAttr.ExecuteReader(); res.Read(); edgeAttributeGuid.Add(new String(d.Key.ToCharArray()), (Guid)res["AttrDefUid"]); res.Close(); } if (eal.Length != 0) { eal = eal.Substring(0, eal.Length - 1); } string val = ""; Dictionary<string, Guid> vertexAttributeGuid = new Dictionary<string, Guid>(); foreach (KeyValuePair<String, String[]> d in a.VertexAttributeList) { val += d.Key + "." + d.Value[0] + "." + d.Value[1] + ","; insAttr = new SqlCommand("INSERT INTO AttrDefVertex (Name, Type, GenerationRule) OUTPUT (inserted.AttrDefUid) VALUES ('"+ d.Key + "', '" + d.Value[0] + "', '" + d.Value[1] + "')", this.connection); SqlDataReader res = insAttr.ExecuteReader(); res.Read(); vertexAttributeGuid.Add(new String(d.Key.ToCharArray()), (Guid)res["AttrDefUid"]); res.Close(); } if (val.Length != 0) { val = val.Substring(0, val.Length - 1); } // query di inserimento this.connection.ChangeDatabase("metadata"); creaDb = new SqlCommand("INSERT INTO dbo.Tree (Name,Type,SplitSize,Depth,EdgeAttributeList,VertexAttributeList) VALUES ('" + a.nome + "','" + a.tipo + "'," + a.splitSize + "," + a.depth + ",'" + eal + "','" + val + "')", this.connection); creaDb.ExecuteNonQuery(); // visito l'albero a partire dalla radice. Nodo current = a.radice; this.connection.ChangeDatabase(a.nome); addNodoRecur(current, current.nodiFigli, vertexAttributeGuid, edgeAttributeGuid, Guid.Empty); } catch (Exception e) { this.lastException = e.Message; Console.WriteLine(this.lastException); this.connection.Close(); return 1; } this.connection.Close(); return 0; }
/* restituisce un array di elementi che formano un percorso tra i due vertici passati come parametri */ public Elemento[] getPath(Albero a, int sVertex, int eVertex) { // controllo che esistano nodo di partenza e nodo di arrivo int nodiTotali = (int)(Math.Pow((Double)(a.splitSize), (Double)(a.depth + 1))) -1; if (a.splitSize > 2) { nodiTotali = nodiTotali / (a.splitSize - 1); } if (sVertex < 0 || sVertex >= nodiTotali || eVertex < 0 || eVertex >= nodiTotali) return null; // non posso sapere qual è più grande, me li organizzo int start, end; if (sVertex <= eVertex) { start = sVertex; end = eVertex; } else { start = eVertex; end = sVertex; } // inizio la ricerca del path /* cerco di andare verso il nodo iniziale. * Una volta trovato lo aggiungo al risultato * ed aggiungo ogni nodo su cui mi muovo al risultato. * Se arrivo ad un nodo senza figli prima di arrivare * al nodo finale ho fallito e restituisco null. * Per ogni nodo aggiunto (tranne quello iniziale) * aggiungo alla lista anche l'arco entrante. */ List<Elemento> res = new List<Elemento> (); Nodo curr = a.radice; int obj = start; while (curr.ID != end) { // arrivo in fondo senza trovare il nodo che mi interessava if (curr.nodiFigli [0] == null) return null; // aggiunta elementi se necessario if (curr.ID == start) { res.Add (curr); obj = end; } else if (curr.ID > start) { res.Add (curr.arcoEntrante); res.Add (curr); } // mi dirigo verso l'obiettivo for (int i=a.splitSize-1; i>=0; i--) { if (obj >= curr.nodiFigli [i].ID) { curr = curr.nodiFigli [i]; break; } } } if (start != end) { res.Add (curr.arcoEntrante); } res.Add (curr); Elemento[] arrRes = res.ToArray<Elemento>(); return arrRes; }
/* restituisce valori di attributi di archi e nodi su un percorso tra sVertex e eVertex partendo da un albero */ public List<String> getValues(Albero a, int sVertex, int eVertex, List<String> vAttr, List<String> eAttr) { // prendo tutti gli elementi tra sVertex e eVertex usando il metodo getPath Elemento[] path = getPath(a, sVertex, eVertex); // prendo i valori degli attributi richiesti e li inserisco in una List<String>; List<String> result = new List<String>(); for (int i = 0; i < path.Length; i++) { if (path[i].GetType().Name.Equals("Nodo")) { // cerca attributi da vAttr foreach (String att in vAttr) { result.Add(((Nodo)path[i]).attributi[att][1]); } } else { // cerca attributi da eAttr foreach (String att in eAttr) { result.Add(((Arco)path[i]).attributi[att][1]); } } } return result; }