Tulip  4.1.0
Better Visualization Through Research
 All Classes Files Functions Variables Enumerations Enumerator Properties Groups Pages
CSVGraphImport.h
1 /*
2  *
3  * This file is part of Tulip (www.tulip-software.org)
4  *
5  * Authors: David Auber and the Tulip development Team
6  * from LaBRI, University of Bordeaux 1 and Inria Bordeaux - Sud Ouest
7  *
8  * Tulip is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation, either version 3
11  * of the License, or (at your option) any later version.
12  *
13  * Tulip is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU General Public License for more details.
17  *
18  */
19 ///@cond DOXYGEN_HIDDEN
20 
21 #ifndef CSVGRAPHIMPORT_H
22 #define CSVGRAPHIMPORT_H
23 
24 #include <tulip/CSVParser.h>
25 #include <tulip/CSVContentHandler.h>
26 #include <tulip/Graph.h>
27 #include <map>
28 #include <QtGui/QWidget>
29 #include <QtGui/QMessageBox>
30 #include <tulip/tuliphash.h>
31 namespace tlp {
32 class PropertyInterface;
33 
34 /**
35  * @brief Store import parameters for a CSV file column.
36  *
37  * Contains all the parameters defined by user for a given CSV column (the name of the column, its data type and if user want to import it).
38  **/
39 class TLP_QT_SCOPE CSVColumn {
40 public:
41  CSVColumn(const std::string& columnName="",bool isUsed=false,const std::string& columnType=""):name(columnName),used(isUsed),type(columnType) {
42 
43  }
44 
45  /**
46  * @brief Get the name of the column.
47  **/
48  std::string columnName()const {
49  return name;
50  }
51 
52  /**
53  * @brief Tells if the property marked for import.
54  **/
55  bool isUsed()const {
56  return used;
57  }
58  /**
59  * @brief Return the property data type.
60  **/
61  std::string columnDataType()const {
62  return type;
63  }
64 
65 private:
66  std::string name;
67  bool used;
68  std::string type;
69 };
70 /**
71  * @brief Store all the advanced import parameters for the CSV file.
72  *
73  * Store the informations about columns and rows to import.
74  * Use this object to configure the import process of a CSVImportGraph object.
75  **/
76 class TLP_QT_SCOPE CSVImportParameters {
77 public:
78  CSVImportParameters(unsigned int fromLine=0,unsigned int toLine=UINT_MAX,const std::vector<CSVColumn>& columns = std::vector<CSVColumn>());
79  virtual ~CSVImportParameters();
80 
81  /**
82  * @brief Return the number of column.
83  **/
84  unsigned int columnNumber()const;
85 
86  /**
87  * @brief return true if the column is marked for import.
88  **/
89  bool importColumn(unsigned int column)const;
90  /**
91  * @brief Get the column name.
92  **/
93  std::string getColumnName(unsigned int column)const;
94  /**
95  * @brief Get the column data type.
96  **/
97  std::string getColumnDataType(unsigned int column)const;
98 
99  /**
100  * @brief Return the index of the first line to import.
101  **/
102  unsigned int getFirstLineIndex()const;
103  /**
104  * @brief Return the index of the last line to import.
105  **/
106  unsigned int getLastLineIndex()const;
107  /**
108  * @brief Return true if the given row is between the first row to import and the last row to import.
109  **/
110  bool importRow(unsigned int row)const;
111 private:
112  unsigned int fromLine;
113  unsigned int toLine;
114  std::vector<CSVColumn> columns;
115 };
116 
117 /**
118  * @brief Interface to map CSV rows to graph elements.
119  *
120  * To build the mapping user had to parse the CSV file.
121  * @code
122  * CSVParser *parser;
123  * CSVToGraphDataMapping *mapping;
124  * parser->parse(mapping);
125  * //Now the mapping has been built.
126  * //Get the element for the first row.
127  * pair<tlp::ElementType,unsigned int> element = mapping->getElementForRow(0);
128  * @endcode
129  **/
130 class TLP_QT_SCOPE CSVToGraphDataMapping {
131 public:
132  virtual ~CSVToGraphDataMapping() {}
133  virtual std::pair<tlp::ElementType,unsigned int> getElementForRow(const std::vector<std::string>& tokens)=0;
134  virtual void init(unsigned int rowNumber)=0;
135 };
136 
137 /**
138  * @brief Abstract class handling node or edge mapping between a CSV column and a graph property.
139  *
140  * Be sure there is a property with the given name in the graph or an error will occur.
141  * Automatically handle CSV file parsing just implements the buildIndexForRow function to fill the rowToGraphId map with the right graph element.
142  **/
143 class TLP_QT_SCOPE AbstractCSVToGraphDataMapping : public CSVToGraphDataMapping {
144 public:
145  AbstractCSVToGraphDataMapping(tlp::Graph* graph,tlp::ElementType type,unsigned int columnIndex,const std::string& propertyName);
146  virtual ~AbstractCSVToGraphDataMapping() {}
147 
148  void init(unsigned int rowNumber);
149  std::pair<tlp::ElementType,unsigned int> getElementForRow(const std::vector<std::string>& tokens);
150 protected:
151  /**
152  * @brief Create a new element if no elements for the given row was found.
153  * @return Return the graph element id or UINT_MAX if no new element is created.
154  **/
155  virtual unsigned int buildIndexForRow(unsigned int row,const std::string& indexKey,tlp::Graph* graph,tlp::PropertyInterface* keyProperty)=0;
156 
157 protected:
158  TLP_HASH_MAP<std::string,unsigned int> valueToId;
159  tlp::Graph* graph;
160  tlp::ElementType type;
161  unsigned int columnIndex;
162  tlp::PropertyInterface* keyProperty;
163 };
164 /**
165  * @brief Map each row of the CSV file on a new node.
166  **/
167 class TLP_QT_SCOPE CSVToNewNodeIdMapping: public CSVToGraphDataMapping {
168 public:
169  CSVToNewNodeIdMapping(tlp::Graph* graph);
170  void init(unsigned int rowNumber);
171  std::pair<tlp::ElementType,unsigned int> getElementForRow(const std::vector<std::string>& tokens);
172 private:
173  tlp::Graph* graph;
174 };
175 
176 /**
177  * @brief Try to map CSV file rows to nodes according to value between a CSV column and a graph property.
178  *
179  * Be sure there is a property with the given name in the graph before using it.
180  **/
181 class TLP_QT_SCOPE CSVToGraphNodeIdMapping: public AbstractCSVToGraphDataMapping {
182 public:
183  /**
184  * @param graph The graph where the nodes will be searched.
185  * @param columnIndex The index of the column with the ids in the CSV file.
186  * @param propertyName The name of the property to search ids.
187  * @param firstRow The first row to search ids.
188  * @param lastRow The last row to search ids.
189  * @param createNode If set to true if there is no node for an id in the CSV file a new node will be created for this id.
190  **/
191  CSVToGraphNodeIdMapping(tlp::Graph* graph,unsigned int columnIndex,const std::string& propertyName,bool createNode=false);
192  void init(unsigned int rowNumber);
193 protected:
194  unsigned int buildIndexForRow(unsigned int row,const std::string& indexKey,tlp::Graph* graph,tlp::PropertyInterface* keyProperty);
195 private:
196  bool createMissingNodes;
197 };
198 /**
199  * @brief Try to map CSV file rows to edges according to value between a CSV column and a graph property.
200  *
201  * Be sure there is a property with the given name in the graph before using it.
202  **/
203 class TLP_QT_SCOPE CSVToGraphEdgeIdMapping: public AbstractCSVToGraphDataMapping {
204 public:
205  /**
206  * @param graph The graph where the edges will be searched.
207  * @param columnIndex The index of the column with the ids in the CSV file.
208  * @param propertyName The name of the property to search ids.
209  * @param firstRow The first row to search ids.
210  * @param lastRow The last row to search ids.
211  **/
212  CSVToGraphEdgeIdMapping(tlp::Graph* graph,unsigned int columnIndex,const std::string& propertyName);
213 protected:
214  unsigned int buildIndexForRow(unsigned int row,const std::string& indexKey,tlp::Graph* graph,tlp::PropertyInterface* keyProperty);
215 };
216 
217 /**
218  * @brief Try to map CSV file rows to edges according to edge source and destination.
219  *
220  * For each row in the CSV file create an edge in the graph between source and destination nodes. Find source node by comparing id in the source CSV column and destination node by comparing id in the destination CSV column.
221  **/
222 class TLP_QT_SCOPE CSVToGraphEdgeSrcTgtMapping: public CSVToGraphDataMapping {
223 public:
224  /**
225  * @param graph The graph where the edges will be searched.
226  * @param srcColumnIndex The index of the column with the source node id in the CSV file.
227  * @param tgtColumnIndex The index of the column with the taret node id in the CSV file.
228  * @param srcPropertyName The name of the property to search source node id.
229  * @param tgtPropertyName The name of the property to search target node id.
230  * @param firstRow The first row to search ids.
231  * @param lastRow The last row to search ids.
232  * @param createMissinElements If true create source node, destination node if one of them is not found in the graph.
233  **/
234  CSVToGraphEdgeSrcTgtMapping(tlp::Graph* graph,unsigned int srcColumnIndex,unsigned int tgtColumnIndex,const std::string& propertyName,bool createMissinElements=false);
235  std::pair<tlp::ElementType,unsigned int> getElementForRow(unsigned int row);
236  void init(unsigned int lineNumbers);
237  std::pair<tlp::ElementType,unsigned int> getElementForRow(const std::vector<std::string>& tokens);
238 private:
239  tlp::Graph* graph;
240  TLP_HASH_MAP<std::string,unsigned int> valueToId;
241  unsigned int srcColumnIndex;
242  unsigned int tgtColumnIndex;
243  tlp::PropertyInterface* keyProperty;
244  bool buildMissingElements;
245 };
246 
247 /**
248  * @brief Interface to perform mapping between CSV columns and graph properties during the CSV import process.
249  *
250  **/
251 class TLP_QT_SCOPE CSVImportColumnToGraphPropertyMapping {
252 public:
253  virtual ~CSVImportColumnToGraphPropertyMapping() {}
254  /**
255  * @brief Return the property corresponding to the column index.
256  * @param column The index of the column.
257  * @param token The current token. May be needed to determine column data type.
258  *
259  * The token parameter is used to guess property type if needed.
260  **/
261  virtual tlp::PropertyInterface* getPropertyInterface(unsigned int column,const std::string& token)=0;
262 };
263 
264 /**
265  * @brief Proxy to handle all the properties operations like access, creation, data type detection during the CSV parsing process.
266  *
267  * Try to guess the type of the property in function of the first token if user don't tell which type the property is.
268  **/
269 class TLP_QT_SCOPE CSVImportColumnToGraphPropertyMappingProxy : public CSVImportColumnToGraphPropertyMapping {
270 public:
271  CSVImportColumnToGraphPropertyMappingProxy(tlp::Graph* graph,const CSVImportParameters& importParameters,QWidget* parent=NULL);
272  virtual ~CSVImportColumnToGraphPropertyMappingProxy() {}
273  tlp::PropertyInterface* getPropertyInterface(unsigned int column,const std::string& token);
274 
275 private:
276 
277  tlp::Graph* graph;
278  CSVImportParameters importParameters;
279  TLP_HASH_MAP<unsigned int,tlp::PropertyInterface*>propertiesBuffer;
280  QMessageBox::StandardButton overwritePropertiesButton;
281  QWidget* parent;
282 };
283 
284 /**
285  * @brief Manage all the CSV import process. Use the mapping object to find the graph element in function of the row and the propertiesManager to find the property corresponding to the column.
286  * The import parameters are used to filter the rows and the columns to import.
287  **/
288 class TLP_QT_SCOPE CSVGraphImport : public tlp::CSVContentHandler {
289 public:
290  CSVGraphImport(CSVToGraphDataMapping* mapping,CSVImportColumnToGraphPropertyMapping* propertiesManager,const CSVImportParameters& importParameters);
291  virtual ~CSVGraphImport();
292  void begin();
293  void line(unsigned int row,const std::vector<std::string>& lineTokens);
294  void end(unsigned int rowNumber, unsigned int columnNumber);
295 protected:
296 
297  CSVToGraphDataMapping* mapping;
298  CSVImportColumnToGraphPropertyMapping* propertiesManager;
299  CSVImportParameters importParameters;
300 };
301 
302 }
303 #endif // CSVGRAPHIMPORT_H
304 ///@endcond