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