Tulip  4.8.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
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 information 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, std::vector<unsigned int> > getElementsForRow(const std::vector<std::string>& tokens, const std::vector<PropertyInterface*> props)=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,
145  const std::vector<unsigned int>& columnIds,
146  const std::vector<std::string>& propertyNames);
147  virtual ~AbstractCSVToGraphDataMapping() {}
148 
149  void init(unsigned int rowNumber);
150  std::pair<tlp::ElementType, std::vector<unsigned int> > getElementsForRow(const std::vector<std::string>& tokens, const std::vector<PropertyInterface*> props);
151 protected:
152  /**
153  * @brief Create a new element if no elements for the given row was found.
154  * @return Return the graph element id or UINT_MAX if no new element is created.
155  **/
156  virtual unsigned int buildIndexForRow(unsigned int row,
157  const std::vector<std::string>& keys)=0;
158 
159 protected:
160  TLP_HASH_MAP<std::string,unsigned int> valueToId;
161  tlp::Graph* graph;
162  tlp::ElementType type;
163  std::vector<unsigned int> columnIds;
164  std::vector<tlp::PropertyInterface*> keyProperties;
165 };
166 /**
167  * @brief Map each row of the CSV file on a new node.
168  **/
169 class TLP_QT_SCOPE CSVToNewNodeIdMapping: public CSVToGraphDataMapping {
170 public:
171  CSVToNewNodeIdMapping(tlp::Graph* graph);
172  void init(unsigned int rowNumber);
173  std::pair<tlp::ElementType, std::vector<unsigned int> > getElementsForRow(const std::vector<std::string>& tokens, const std::vector<PropertyInterface*> props);
174 private:
175  tlp::Graph* graph;
176 };
177 
178 /**
179  * @brief Try to map CSV file rows to nodes according to value between a CSV column and a graph property.
180  *
181  * Be sure there is a property with the given name in the graph before using it.
182  **/
183 class TLP_QT_SCOPE CSVToGraphNodeIdMapping: public AbstractCSVToGraphDataMapping {
184 public:
185  /**
186  * @param graph The graph where the nodes will be searched.
187  * @param columnIndex The index of the column with the ids in the CSV file.
188  * @param propertyName The name of the property to search ids.
189  * @param firstRow The first row to search ids.
190  * @param lastRow The last row to search ids.
191  * @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.
192  **/
193  CSVToGraphNodeIdMapping(tlp::Graph* graph,
194  const std::vector<unsigned int>& columnIds,
195  const std::vector<std::string>& propertyNames,
196  bool createNode=false);
197  void init(unsigned int rowNumber);
198 protected:
199  unsigned int buildIndexForRow(unsigned int row,
200  const std::vector<std::string>& keys);
201 private:
202  bool createMissingNodes;
203 };
204 /**
205  * @brief Try to map CSV file rows to edges according to value between a CSV column and a graph property.
206  *
207  * Be sure there is a property with the given name in the graph before using it.
208  **/
209 class TLP_QT_SCOPE CSVToGraphEdgeIdMapping: public AbstractCSVToGraphDataMapping {
210 public:
211  /**
212  * @param graph The graph where the edges will be searched.
213  * @param columnIndex The index of the column with the ids in the CSV file.
214  * @param propertyName The name of the property to search ids.
215  * @param firstRow The first row to search ids.
216  * @param lastRow The last row to search ids.
217  **/
218  CSVToGraphEdgeIdMapping(tlp::Graph* graph,
219  const std::vector<unsigned int>& columnIds,
220  const std::vector<std::string>& propertyNames);
221 protected:
222  unsigned int buildIndexForRow(unsigned int row,
223  const std::vector<std::string>& keys);
224 };
225 
226 /**
227  * @brief Try to map CSV file rows to edges according to edge source and destination.
228  *
229  * 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.
230  **/
231 class TLP_QT_SCOPE CSVToGraphEdgeSrcTgtMapping: public CSVToGraphDataMapping {
232 public:
233  /**
234  * @param graph The graph where the edges will be searched.
235  * @param srcColumnIndex The index of the column with the source node id in the CSV file.
236  * @param tgtColumnIndex The index of the column with the taret node id in the CSV file.
237  * @param srcPropertyName The name of the property to search source node id.
238  * @param tgtPropertyName The name of the property to search target node id.
239  * @param firstRow The first row to search ids.
240  * @param lastRow The last row to search ids.
241  * @param createMissinElements If true create source node, destination node if one of them is not found in the graph.
242  **/
243  CSVToGraphEdgeSrcTgtMapping(tlp::Graph* graph,
244  const std::vector<unsigned int>& srcColumnIds,
245  const std::vector<unsigned int>& tgtColumnIds,
246  const std::vector<std::string>& srcPropNames,
247  const std::vector<std::string>& tgtPropNames,
248  bool createMissinElements=false);
249  std::pair<tlp::ElementType,unsigned int> getElementForRow(unsigned int row);
250  void init(unsigned int lineNumbers);
251  std::pair<tlp::ElementType, std::vector<unsigned int> > getElementsForRow(const std::vector<std::string>& tokens, const std::vector<PropertyInterface*> props);
252 private:
253  tlp::Graph* graph;
254  TLP_HASH_MAP<std::string,unsigned int> srcValueToId;
255  TLP_HASH_MAP<std::string,unsigned int> tgtValueToId;
256  std::vector<unsigned int> srcColumnIds;
257  std::vector<unsigned int> tgtColumnIds;
258  std::vector<tlp::PropertyInterface*> srcProperties;
259  std::vector<tlp::PropertyInterface*> tgtProperties;
260  bool sameSrcTgtProperties;
261  bool buildMissingElements;
262 };
263 
264 /**
265  * @brief Interface to perform mapping between CSV columns and graph properties during the CSV import process.
266  *
267  **/
268 class TLP_QT_SCOPE CSVImportColumnToGraphPropertyMapping {
269 public:
270  virtual ~CSVImportColumnToGraphPropertyMapping() {}
271  /**
272  * @brief Return the property corresponding to the column index.
273  * @param column The index of the column.
274  * @param token The current token. May be needed to determine column data type.
275  *
276  * The token parameter is used to guess property type if needed.
277  **/
278  virtual tlp::PropertyInterface* getPropertyInterface(unsigned int column,const std::string& token)=0;
279 };
280 
281 /**
282  * @brief Proxy to handle all the properties operations like access, creation, data type detection during the CSV parsing process.
283  *
284  * Try to guess the type of the property in function of the first token if user don't tell which type the property is.
285  **/
286 class TLP_QT_SCOPE CSVImportColumnToGraphPropertyMappingProxy : public CSVImportColumnToGraphPropertyMapping {
287 public:
288  CSVImportColumnToGraphPropertyMappingProxy(tlp::Graph* graph,const CSVImportParameters& importParameters,QWidget* parent=NULL);
289  virtual ~CSVImportColumnToGraphPropertyMappingProxy() {}
290  tlp::PropertyInterface* getPropertyInterface(unsigned int column,const std::string& token);
291 
292 private:
293 
294  tlp::Graph* graph;
295  CSVImportParameters importParameters;
296  TLP_HASH_MAP<unsigned int,tlp::PropertyInterface*>propertiesBuffer;
297  QMessageBox::StandardButton overwritePropertiesButton;
298  QWidget* parent;
299 };
300 
301 /**
302  * @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.
303  * The import parameters are used to filter the rows and the columns to import.
304  **/
305 class TLP_QT_SCOPE CSVGraphImport : public tlp::CSVContentHandler {
306 public:
307  CSVGraphImport(CSVToGraphDataMapping* mapping,CSVImportColumnToGraphPropertyMapping* propertiesManager,const CSVImportParameters& importParameters);
308  virtual ~CSVGraphImport();
309  void begin();
310  void line(unsigned int row,const std::vector<std::string>& lineTokens);
311  void end(unsigned int rowNumber, unsigned int columnNumber);
312 protected:
313 
314  CSVToGraphDataMapping* mapping;
315  CSVImportColumnToGraphPropertyMapping* propertiesManager;
316  CSVImportParameters importParameters;
317 };
318 
319 }
320 #endif // CSVGRAPHIMPORT_H
321 ///@endcond
PropertyInterface describes the interface of a graph property.