Apache GraphAr C++ Library
The C++ Library for Apache GraphAr
edges_builder.h
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #pragma once
21 
22 #include <algorithm>
23 #include <any>
24 #include <memory>
25 #include <string>
26 #include <unordered_map>
27 #include <utility>
28 #include <vector>
29 
30 #include "graphar/arrow/chunk_writer.h"
31 #include "graphar/fwd.h"
32 #include "graphar/graph_info.h"
33 #include "graphar/types.h"
34 
35 namespace arrow {
36 class Array;
37 }
38 
39 namespace graphar::builder {
40 
45 class Edge {
46  public:
53  explicit Edge(IdType src_id, IdType dst_id)
54  : src_id_(src_id), dst_id_(dst_id), empty_(true) {}
55 
61  inline bool Empty() const noexcept { return empty_; }
62 
68  inline IdType GetSource() const noexcept { return src_id_; }
69 
75  inline IdType GetDestination() const noexcept { return dst_id_; }
76 
83  // TODO(@acezen): Enable the property to be a vector(list).
84  inline void AddProperty(const std::string& name, const std::any& val) {
85  empty_ = false;
86  properties_[name] = val;
87  }
88 
95  inline const std::any& GetProperty(const std::string& property) const {
96  return properties_.at(property);
97  }
98 
104  inline const std::unordered_map<std::string, std::any>& GetProperties()
105  const {
106  return properties_;
107  }
108 
115  inline bool ContainProperty(const std::string& property) const {
116  return (properties_.find(property) != properties_.end());
117  }
118 
119  private:
120  IdType src_id_, dst_id_;
121  bool empty_;
122  std::unordered_map<std::string, std::any> properties_;
123 };
124 
132 inline bool cmp_src(const Edge& a, const Edge& b) {
133  return a.GetSource() < b.GetSource();
134 }
135 
143 inline bool cmp_dst(const Edge& a, const Edge& b) {
144  return a.GetDestination() < b.GetDestination();
145 }
146 
153  public:
166  explicit EdgesBuilder(
167  const std::shared_ptr<EdgeInfo>& edge_info, const std::string& prefix,
168  AdjListType adj_list_type, IdType num_vertices,
169  const ValidateLevel& validate_level = ValidateLevel::no_validate)
170  : edge_info_(std::move(edge_info)),
171  prefix_(prefix),
172  adj_list_type_(adj_list_type),
173  num_vertices_(num_vertices),
174  validate_level_(validate_level) {
175  if (validate_level_ == ValidateLevel::default_validate) {
176  throw std::runtime_error(
177  "default_validate is not allowed to be set as the global validate "
178  "level for EdgesBuilder");
179  }
180  edges_.clear();
181  num_edges_ = 0;
182  is_saved_ = false;
183  switch (adj_list_type) {
184  case AdjListType::unordered_by_source:
185  vertex_chunk_size_ = edge_info_->GetSrcChunkSize();
186  break;
187  case AdjListType::ordered_by_source:
188  vertex_chunk_size_ = edge_info_->GetSrcChunkSize();
189  break;
190  case AdjListType::unordered_by_dest:
191  vertex_chunk_size_ = edge_info_->GetDstChunkSize();
192  break;
193  case AdjListType::ordered_by_dest:
194  vertex_chunk_size_ = edge_info_->GetDstChunkSize();
195  break;
196  default:
197  vertex_chunk_size_ = edge_info_->GetSrcChunkSize();
198  }
199  }
200 
206  inline void SetValidateLevel(const ValidateLevel& validate_level) {
207  if (validate_level == ValidateLevel::default_validate) {
208  return;
209  }
210  validate_level_ = validate_level;
211  }
212 
218  inline ValidateLevel GetValidateLevel() const { return validate_level_; }
219 
223  inline void Clear() {
224  edges_.clear();
225  num_edges_ = 0;
226  is_saved_ = false;
227  }
228 
250  Status AddEdge(const Edge& e, const ValidateLevel& validate_level =
251  ValidateLevel::default_validate) {
252  // validate
253  GAR_RETURN_NOT_OK(validate(e, validate_level));
254  // add an edge
255  IdType vertex_chunk_index = getVertexChunkIndex(e);
256  edges_[vertex_chunk_index].push_back(e);
257  num_edges_++;
258  return Status::OK();
259  }
260 
266  IdType GetNum() const { return num_edges_; }
267 
273  Status Dump();
274 
285  static Result<std::shared_ptr<EdgesBuilder>> Make(
286  const std::shared_ptr<EdgeInfo>& edge_info, const std::string& prefix,
287  AdjListType adj_list_type, IdType num_vertices,
288  const ValidateLevel& validate_level = ValidateLevel::no_validate) {
289  if (!edge_info->HasAdjacentListType(adj_list_type)) {
290  return Status::KeyError(
291  "The adjacent list type ", AdjListTypeToString(adj_list_type),
292  " doesn't exist in edge ", edge_info->GetEdgeLabel(), ".");
293  }
294  return std::make_shared<EdgesBuilder>(edge_info, prefix, adj_list_type,
295  num_vertices, validate_level);
296  }
297 
310  static Result<std::shared_ptr<EdgesBuilder>> Make(
311  const std::shared_ptr<GraphInfo>& graph_info,
312  const std::string& src_label, const std::string& edge_label,
313  const std::string& dst_label, const AdjListType& adj_list_type,
314  IdType num_vertices,
315  const ValidateLevel& validate_level = ValidateLevel::no_validate) {
316  auto edge_info = graph_info->GetEdgeInfo(src_label, edge_label, dst_label);
317  if (!edge_info) {
318  return Status::KeyError("The edge ", src_label, " ", edge_label, " ",
319  dst_label, " doesn't exist.");
320  }
321  return Make(edge_info, graph_info->GetPrefix(), adj_list_type, num_vertices,
322  validate_level);
323  }
324 
325  private:
332  IdType getVertexChunkIndex(const Edge& e) {
333  switch (adj_list_type_) {
334  case AdjListType::unordered_by_source:
335  return e.GetSource() / vertex_chunk_size_;
336  case AdjListType::ordered_by_source:
337  return e.GetSource() / vertex_chunk_size_;
338  case AdjListType::unordered_by_dest:
339  return e.GetDestination() / vertex_chunk_size_;
340  case AdjListType::ordered_by_dest:
341  return e.GetDestination() / vertex_chunk_size_;
342  default:
343  return e.GetSource() / vertex_chunk_size_;
344  }
345  }
346 
354  Status validate(const Edge& e, ValidateLevel validate_level) const;
355 
365  Status appendToArray(const std::shared_ptr<DataType>& type,
366  const std::string& property_name,
367  std::shared_ptr<arrow::Array>& array, // NOLINT
368  const std::vector<Edge>& edges);
369 
380  template <Type type>
381  Status tryToAppend(const std::string& property_name,
382  std::shared_ptr<arrow::Array>& array, // NOLINT
383  const std::vector<Edge>& edges);
384 
394  Status tryToAppend(int src_or_dest,
395  std::shared_ptr<arrow::Array>& array, // NOLINT
396  const std::vector<Edge>& edges);
397 
404  Result<std::shared_ptr<arrow::Table>> convertToTable(
405  const std::vector<Edge>& edges);
406 
413  Result<std::shared_ptr<arrow::Table>> getOffsetTable(
414  IdType vertex_chunk_index, const std::vector<Edge>& edges);
415 
416  private:
417  std::shared_ptr<EdgeInfo> edge_info_;
418  std::string prefix_;
419  AdjListType adj_list_type_;
420  std::unordered_map<IdType, std::vector<Edge>> edges_;
421  IdType vertex_chunk_size_;
422  IdType num_vertices_;
423  IdType num_edges_;
424  bool is_saved_;
425  ValidateLevel validate_level_;
426 };
427 
428 } // namespace graphar::builder
Edge contains information of certain edge.
Definition: graph_reader.h:103
Status outcome object (success or error)
Definition: status.h:123
static Status KeyError(Args &&... args)
Definition: status.h:172
static Status OK()
Definition: status.h:157
Edge is designed for constructing edges builder.
Definition: edges_builder.h:45
const std::any & GetProperty(const std::string &property) const
Get a property of the edge.
Definition: edges_builder.h:95
const std::unordered_map< std::string, std::any > & GetProperties() const
Get all properties of the edge.
IdType GetSource() const noexcept
Get source id of the edge.
Definition: edges_builder.h:68
bool Empty() const noexcept
Check if the edge is empty.
Definition: edges_builder.h:61
void AddProperty(const std::string &name, const std::any &val)
Add a property to the edge.
Definition: edges_builder.h:84
IdType GetDestination() const noexcept
Get destination id of the edge.
Definition: edges_builder.h:75
Edge(IdType src_id, IdType dst_id)
Initialize the edge with its source and destination.
Definition: edges_builder.h:53
bool ContainProperty(const std::string &property) const
Check if the edge contains a property.
EdgeBuilder is designed for building and writing a collection of edges.
EdgesBuilder(const std::shared_ptr< EdgeInfo > &edge_info, const std::string &prefix, AdjListType adj_list_type, IdType num_vertices, const ValidateLevel &validate_level=ValidateLevel::no_validate)
Initialize the EdgesBuilder.
IdType GetNum() const
Get the current number of edges in the collection.
static Result< std::shared_ptr< EdgesBuilder > > Make(const std::shared_ptr< GraphInfo > &graph_info, const std::string &src_label, const std::string &edge_label, const std::string &dst_label, const AdjListType &adj_list_type, IdType num_vertices, const ValidateLevel &validate_level=ValidateLevel::no_validate)
Construct an EdgesBuilder from graph info.
static Result< std::shared_ptr< EdgesBuilder > > Make(const std::shared_ptr< EdgeInfo > &edge_info, const std::string &prefix, AdjListType adj_list_type, IdType num_vertices, const ValidateLevel &validate_level=ValidateLevel::no_validate)
Construct an EdgesBuilder from edge info.
void SetValidateLevel(const ValidateLevel &validate_level)
Set the validate level.
void Clear()
Clear the edges in this EdgesBuilder.
ValidateLevel GetValidateLevel() const
Get the validate level.
Status Dump()
Dump the collection into files.
Status AddEdge(const Edge &e, const ValidateLevel &validate_level=ValidateLevel::default_validate)
Add an edge to the collection.