From d0be7b83b0206c635028f5f990ce7cecbab67036 Mon Sep 17 00:00:00 2001 From: dutor <440396+dutor@users.noreply.github.com> Date: Mon, 9 Nov 2020 10:17:23 +0800 Subject: [PATCH 001/213] Initial commit --- .gitignore | 23 +++++++++++++++++++++++ README.md | 2 ++ 2 files changed, 25 insertions(+) create mode 100644 .gitignore create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a1c2a23 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* diff --git a/README.md b/README.md new file mode 100644 index 0000000..4c5ad19 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# nebula-spark-utils +Spark related libraries and tools From 7218a663334724b7bd60b40c851fd95d9aa62b35 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 9 Dec 2020 19:14:04 +0800 Subject: [PATCH 002/213] add exchange 2.0 --- .github/workflows/ISSUE_TEMPLATE.md | 11 + .github/workflows/PULL_REQUEST_TEMPLATE.md | 11 + .gitignore | 6 + nebula-exchange/README.md | 20 + nebula-exchange/pom.xml | 682 ++ nebula-exchange/src/main/.DS_Store | Bin 0 -> 6148 bytes .../src/main/resources/application.conf | 129 + .../main/resources/server_application.conf | 183 + .../main/resources/stream_application.conf | 143 + .../tools/importer/CheckPointHandler.scala | 41 + .../nebula/tools/importer/ErrorHandler.scala | 33 + .../nebula/tools/importer/Exchange.scala | 285 + .../nebula/tools/importer/GraphProvider.scala | 55 + .../nebula/tools/importer/MetaProvider.scala | 95 + .../tools/importer/config/Configs.scala | 738 +++ .../tools/importer/config/SchemaConfigs.scala | 145 + .../tools/importer/config/SinkConfigs.scala | 49 + .../tools/importer/config/SourceConfigs.scala | 219 + .../nebula/tools/importer/package.scala | 92 + .../importer/processor/EdgeProcessor.scala | 164 + .../tools/importer/processor/Processor.scala | 77 + .../importer/processor/ReloadProcessor.scala | 50 + .../processor/VerticesProcessor.scala | 145 + .../importer/reader/FileBaseReader.scala | 115 + .../nebula/tools/importer/reader/Reader.scala | 64 + .../importer/reader/ServerBaseReader.scala | 249 + .../importer/reader/StreamingBaseReader.scala | 62 + .../tools/importer/utils/HDFSUtils.scala | 67 + .../tools/importer/utils/KafkaUtils.scala | 15 + .../tools/importer/utils/NebulaUtils.scala | 94 + .../importer/writer/FileBaseWriter.scala | 56 + .../importer/writer/ServerBaseWriter.scala | 242 + .../nebula/tools/importer/writer/Writer.scala | 17 + .../src/test/scala/mock/MockConfigs.scala | 50 + .../src/test/scala/mock/MockGraphData.scala | 213 + .../test/scala/mock/MockQueryProcessor.scala | 63 + .../src/test/scala/mock/MockQueryServer.java | 117 + nebula-exchange/target/classes.timestamp | 1 + .../target/classes/application.conf | 129 + .../target/classes/server_application.conf | 183 + .../target/classes/stream_application.conf | 143 + .../target/classes/test_application.conf | 109 + .../target/maven-archiver/pom.properties | 5 + .../compile/default-compile/inputFiles.lst | 0 .../default-testCompile/createdFiles.lst | 2 + .../default-testCompile/inputFiles.lst | 1 + .../target/site/scaladocs/com/package.html | 118 + .../scaladocs/com/vesoft/nebula/package.html | 118 + .../nebula/tools/importer/Argument.html | 544 ++ .../tools/importer/CheckPointHandler$.html | 534 ++ .../nebula/tools/importer/ErrorHandler$.html | 516 ++ .../nebula/tools/importer/Exchange$.html | 500 ++ .../nebula/tools/importer/GraphProvider.html | 644 ++ .../nebula/tools/importer/MetaProvider.html | 628 ++ .../importer/TooManyErrorsException.html | 684 ++ .../nebula/tools/importer/VidType$.html | 786 +++ .../tools/importer/config/Configs$.html | 540 ++ .../nebula/tools/importer/config/Configs.html | 632 ++ .../config/ConnectionConfigEntry.html | 511 ++ .../importer/config/DataBaseConfigEntry.html | 562 ++ .../importer/config/DataSinkConfigEntry.html | 506 ++ .../config/DataSourceConfigEntry.html | 506 ++ .../importer/config/EdgeConfigEntry.html | 750 +++ .../importer/config/ErrorConfigEntry.html | 511 ++ .../importer/config/ExecutionConfigEntry.html | 528 ++ .../config/FileBaseSinkConfigEntry.html | 530 ++ .../config/FileBaseSourceConfigEntry.html | 549 ++ .../config/FileDataSourceConfigEntry.html | 524 ++ .../config/HBaseSourceConfigEntry.html | 599 ++ .../importer/config/HiveConfigEntry.html | 561 ++ .../config/HiveSourceConfigEntry.html | 515 ++ .../config/JanusGraphSourceConfigEntry.html | 531 ++ .../config/KafkaSourceConfigEntry.html | 549 ++ .../config/MySQLSourceConfigEntry.html | 617 ++ .../config/NebulaSinkConfigEntry.html | 513 ++ .../config/Neo4JSourceConfigEntry.html | 651 ++ .../config/PulsarSourceConfigEntry.html | 566 ++ .../importer/config/RateConfigEntry.html | 511 ++ .../importer/config/SchemaConfigEntry.html | 625 ++ .../config/ServerDataSourceConfigEntry.html | 524 ++ .../tools/importer/config/SinkCategory$.html | 790 +++ .../tools/importer/config/SinkCategory.html | 504 ++ .../importer/config/SourceCategory$.html | 976 +++ .../tools/importer/config/SourceCategory.html | 504 ++ .../importer/config/SparkConfigEntry$.html | 505 ++ .../importer/config/SparkConfigEntry.html | 496 ++ .../StreamingDataSourceConfigEntry.html | 524 ++ .../tools/importer/config/TagConfigEntry.html | 648 ++ .../nebula/tools/importer/config/Type$.html | 786 +++ .../importer/config/UserConfigEntry.html | 511 ++ .../nebula/tools/importer/config/package.html | 700 +++ .../nebula/tools/importer/package$$Edge.html | 578 ++ .../nebula/tools/importer/package$$Edges.html | 561 ++ .../tools/importer/package$$KeyPolicy$.html | 786 +++ .../tools/importer/package$$Offset.html | 493 ++ .../tools/importer/package$$Vertex.html | 527 ++ .../tools/importer/package$$Vertices.html | 544 ++ .../vesoft/nebula/tools/importer/package.html | 709 +++ .../importer/processor/EdgeProcessor.html | 582 ++ .../tools/importer/processor/Processor.html | 568 ++ .../importer/processor/ReloadProcessor.html | 582 ++ .../importer/processor/VerticesProcessor.html | 582 ++ .../tools/importer/processor/package.html | 172 + .../tools/importer/reader/CSVReader.html | 580 ++ .../importer/reader/CheckPointSupport.html | 506 ++ .../tools/importer/reader/CustomReader.html | 581 ++ .../tools/importer/reader/FileBaseReader.html | 583 ++ .../tools/importer/reader/HBaseReader.html | 578 ++ .../tools/importer/reader/HiveReader.html | 579 ++ .../tools/importer/reader/JSONReader.html | 579 ++ .../importer/reader/JanusGraphReader.html | 597 ++ .../tools/importer/reader/KafkaReader.html | 561 ++ .../tools/importer/reader/MySQLReader.html | 580 ++ .../tools/importer/reader/NebulaReader.html | 578 ++ .../tools/importer/reader/Neo4JReader.html | 598 ++ .../tools/importer/reader/ORCReader.html | 579 ++ .../tools/importer/reader/ParquetReader.html | 579 ++ .../tools/importer/reader/PulsarReader.html | 561 ++ .../nebula/tools/importer/reader/Reader.html | 544 ++ .../importer/reader/ServerBaseReader.html | 583 ++ .../importer/reader/StreamingBaseReader.html | 566 ++ .../nebula/tools/importer/reader/package.html | 419 ++ .../tools/importer/utils/HDFSUtils$.html | 584 ++ .../tools/importer/utils/KafkaUtils$.html | 516 ++ .../tools/importer/utils/NebulaUtils$.html | 550 ++ .../nebula/tools/importer/utils/package.html | 152 + .../writer/NebulaGraphClientWriter.html | 646 ++ .../importer/writer/NebulaSSTWriter.html | 610 ++ .../writer/NebulaStorageClientWriter.html | 629 ++ .../importer/writer/NebulaWriterCallback.html | 538 ++ .../importer/writer/ServerBaseWriter.html | 616 ++ .../nebula/tools/importer/writer/Writer.html | 526 ++ .../nebula/tools/importer/writer/package.html | 203 + .../com/vesoft/nebula/tools/package.html | 118 + .../site/scaladocs/com/vesoft/package.html | 118 + .../target/site/scaladocs/index.html | 80 + .../target/site/scaladocs/index.js | 1 + .../target/site/scaladocs/index/index-a.html | 29 + .../target/site/scaladocs/index/index-b.html | 17 + .../target/site/scaladocs/index/index-c.html | 74 + .../target/site/scaladocs/index/index-d.html | 44 + .../target/site/scaladocs/index/index-e.html | 80 + .../target/site/scaladocs/index/index-f.html | 32 + .../target/site/scaladocs/index/index-g.html | 74 + .../target/site/scaladocs/index/index-h.html | 53 + .../target/site/scaladocs/index/index-i.html | 35 + .../target/site/scaladocs/index/index-j.html | 29 + .../target/site/scaladocs/index/index-k.html | 29 + .../target/site/scaladocs/index/index-l.html | 29 + .../target/site/scaladocs/index/index-m.html | 35 + .../target/site/scaladocs/index/index-n.html | 59 + .../target/site/scaladocs/index/index-o.html | 32 + .../target/site/scaladocs/index/index-p.html | 89 + .../target/site/scaladocs/index/index-r.html | 53 + .../target/site/scaladocs/index/index-s.html | 104 + .../target/site/scaladocs/index/index-t.html | 59 + .../target/site/scaladocs/index/index-u.html | 32 + .../target/site/scaladocs/index/index-v.html | 50 + .../target/site/scaladocs/index/index-w.html | 38 + .../target/site/scaladocs/lib/arrow-down.png | Bin 0 -> 6232 bytes .../target/site/scaladocs/lib/arrow-right.png | Bin 0 -> 6220 bytes .../target/site/scaladocs/lib/class.png | Bin 0 -> 3357 bytes .../target/site/scaladocs/lib/class_big.png | Bin 0 -> 7516 bytes .../site/scaladocs/lib/class_diagram.png | Bin 0 -> 3910 bytes .../scaladocs/lib/class_to_object_big.png | Bin 0 -> 9006 bytes .../site/scaladocs/lib/constructorsbg.gif | Bin 0 -> 1206 bytes .../site/scaladocs/lib/conversionbg.gif | Bin 0 -> 167 bytes .../target/site/scaladocs/lib/defbg-blue.gif | Bin 0 -> 1544 bytes .../target/site/scaladocs/lib/defbg-green.gif | Bin 0 -> 1341 bytes .../target/site/scaladocs/lib/diagrams.css | 143 + .../target/site/scaladocs/lib/diagrams.js | 324 + .../site/scaladocs/lib/filter_box_left.png | Bin 0 -> 1692 bytes .../site/scaladocs/lib/filter_box_left2.gif | Bin 0 -> 1462 bytes .../site/scaladocs/lib/filter_box_right.png | Bin 0 -> 1803 bytes .../target/site/scaladocs/lib/filterbg.gif | Bin 0 -> 1324 bytes .../site/scaladocs/lib/filterboxbarbg.gif | Bin 0 -> 1104 bytes .../site/scaladocs/lib/filterboxbarbg.png | Bin 0 -> 965 bytes .../target/site/scaladocs/lib/filterboxbg.gif | Bin 0 -> 1366 bytes .../site/scaladocs/lib/fullcommenttopbg.gif | Bin 0 -> 1115 bytes .../target/site/scaladocs/lib/index.css | 339 + .../target/site/scaladocs/lib/index.js | 577 ++ .../target/site/scaladocs/lib/jquery-ui.js | 6 + .../target/site/scaladocs/lib/jquery.js | 2 + .../site/scaladocs/lib/jquery.layout.js | 5486 +++++++++++++++++ .../site/scaladocs/lib/modernizr.custom.js | 4 + .../site/scaladocs/lib/navigation-li-a.png | Bin 0 -> 1198 bytes .../site/scaladocs/lib/navigation-li.png | Bin 0 -> 2441 bytes .../target/site/scaladocs/lib/object.png | Bin 0 -> 3356 bytes .../target/site/scaladocs/lib/object_big.png | Bin 0 -> 7653 bytes .../site/scaladocs/lib/object_diagram.png | Bin 0 -> 3903 bytes .../scaladocs/lib/object_to_class_big.png | Bin 0 -> 9158 bytes .../scaladocs/lib/object_to_trait_big.png | Bin 0 -> 9200 bytes .../site/scaladocs/lib/object_to_type_big.png | Bin 0 -> 9158 bytes .../target/site/scaladocs/lib/ownderbg2.gif | Bin 0 -> 1145 bytes .../target/site/scaladocs/lib/ownerbg.gif | Bin 0 -> 1118 bytes .../target/site/scaladocs/lib/ownerbg2.gif | Bin 0 -> 1145 bytes .../target/site/scaladocs/lib/package.png | Bin 0 -> 3335 bytes .../target/site/scaladocs/lib/package_big.png | Bin 0 -> 7312 bytes .../target/site/scaladocs/lib/packagesbg.gif | Bin 0 -> 1201 bytes .../target/site/scaladocs/lib/permalink.png | Bin 0 -> 943 bytes .../target/site/scaladocs/lib/ref-index.css | 30 + .../target/site/scaladocs/lib/remove.png | Bin 0 -> 3186 bytes .../target/site/scaladocs/lib/scheduler.js | 71 + .../site/scaladocs/lib/selected-implicits.png | Bin 0 -> 1150 bytes .../lib/selected-right-implicits.png | Bin 0 -> 646 bytes .../site/scaladocs/lib/selected-right.png | Bin 0 -> 1380 bytes .../target/site/scaladocs/lib/selected.png | Bin 0 -> 1864 bytes .../site/scaladocs/lib/selected2-right.png | Bin 0 -> 1434 bytes .../target/site/scaladocs/lib/selected2.png | Bin 0 -> 1965 bytes .../target/site/scaladocs/lib/signaturebg.gif | Bin 0 -> 1214 bytes .../site/scaladocs/lib/signaturebg2.gif | Bin 0 -> 1209 bytes .../target/site/scaladocs/lib/template.css | 893 +++ .../target/site/scaladocs/lib/template.js | 500 ++ .../site/scaladocs/lib/tools.tooltip.js | 14 + .../target/site/scaladocs/lib/trait.png | Bin 0 -> 3374 bytes .../target/site/scaladocs/lib/trait_big.png | Bin 0 -> 7410 bytes .../site/scaladocs/lib/trait_diagram.png | Bin 0 -> 3882 bytes .../scaladocs/lib/trait_to_object_big.png | Bin 0 -> 8967 bytes .../target/site/scaladocs/lib/type.png | Bin 0 -> 1445 bytes .../target/site/scaladocs/lib/type_big.png | Bin 0 -> 4236 bytes .../site/scaladocs/lib/type_diagram.png | Bin 0 -> 1841 bytes .../site/scaladocs/lib/type_to_object_big.png | Bin 0 -> 4969 bytes .../target/site/scaladocs/lib/typebg.gif | Bin 0 -> 1206 bytes .../target/site/scaladocs/lib/unselected.png | Bin 0 -> 1879 bytes .../site/scaladocs/lib/valuemembersbg.gif | Bin 0 -> 1206 bytes .../target/site/scaladocs/package.html | 118 + nebula-exchange/target/test-classes.timestamp | 1 + nebula-spark-connector/pom.xml | 14 + .../target/maven-archiver/pom.properties | 5 + pom.xml | 80 + 230 files changed, 63782 insertions(+) create mode 100644 .github/workflows/ISSUE_TEMPLATE.md create mode 100644 .github/workflows/PULL_REQUEST_TEMPLATE.md create mode 100644 nebula-exchange/README.md create mode 100644 nebula-exchange/pom.xml create mode 100644 nebula-exchange/src/main/.DS_Store create mode 100644 nebula-exchange/src/main/resources/application.conf create mode 100644 nebula-exchange/src/main/resources/server_application.conf create mode 100644 nebula-exchange/src/main/resources/stream_application.conf create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/CheckPointHandler.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/ErrorHandler.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/Exchange.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/GraphProvider.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/MetaProvider.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/Configs.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SchemaConfigs.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SinkConfigs.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SourceConfigs.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/package.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/Processor.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/ReloadProcessor.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/FileBaseReader.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/Reader.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/ServerBaseReader.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/StreamingBaseReader.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/HDFSUtils.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/KafkaUtils.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/NebulaUtils.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/FileBaseWriter.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.scala create mode 100644 nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/Writer.scala create mode 100644 nebula-exchange/src/test/scala/mock/MockConfigs.scala create mode 100644 nebula-exchange/src/test/scala/mock/MockGraphData.scala create mode 100644 nebula-exchange/src/test/scala/mock/MockQueryProcessor.scala create mode 100644 nebula-exchange/src/test/scala/mock/MockQueryServer.java create mode 100644 nebula-exchange/target/classes.timestamp create mode 100644 nebula-exchange/target/classes/application.conf create mode 100644 nebula-exchange/target/classes/server_application.conf create mode 100644 nebula-exchange/target/classes/stream_application.conf create mode 100644 nebula-exchange/target/classes/test_application.conf create mode 100644 nebula-exchange/target/maven-archiver/pom.properties create mode 100644 nebula-exchange/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst create mode 100644 nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst create mode 100644 nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst create mode 100644 nebula-exchange/target/site/scaladocs/com/package.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/package.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Argument.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/CheckPointHandler$.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/ErrorHandler$.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Exchange$.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/GraphProvider.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/MetaProvider.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/TooManyErrorsException.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/VidType$.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs$.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ConnectionConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataBaseConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSinkConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSourceConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/EdgeConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ErrorConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ExecutionConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSinkConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSourceConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileDataSourceConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HBaseSourceConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveSourceConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/JanusGraphSourceConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/KafkaSourceConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/MySQLSourceConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/NebulaSinkConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Neo4JSourceConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/PulsarSourceConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/RateConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SchemaConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ServerDataSourceConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory$.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory$.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry$.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/StreamingDataSourceConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/TagConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Type$.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/UserConfigEntry.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/package.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edge.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edges.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$KeyPolicy$.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Offset.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertex.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertices.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/Processor.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/ReloadProcessor.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/package.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CSVReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CheckPointSupport.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CustomReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/FileBaseReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HBaseReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HiveReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JSONReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JanusGraphReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/KafkaReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/MySQLReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/NebulaReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Neo4JReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ORCReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ParquetReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/PulsarReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Reader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ServerBaseReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/StreamingBaseReader.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/package.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/HDFSUtils$.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/KafkaUtils$.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/NebulaUtils$.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/package.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaGraphClientWriter.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaSSTWriter.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaStorageClientWriter.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaWriterCallback.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/Writer.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/package.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/package.html create mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/package.html create mode 100644 nebula-exchange/target/site/scaladocs/index.html create mode 100644 nebula-exchange/target/site/scaladocs/index.js create mode 100644 nebula-exchange/target/site/scaladocs/index/index-a.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-b.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-c.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-d.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-e.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-f.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-g.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-h.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-i.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-j.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-k.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-l.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-m.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-n.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-o.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-p.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-r.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-s.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-t.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-u.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-v.html create mode 100644 nebula-exchange/target/site/scaladocs/index/index-w.html create mode 100644 nebula-exchange/target/site/scaladocs/lib/arrow-down.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/arrow-right.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/class.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/class_big.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/class_diagram.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/class_to_object_big.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/constructorsbg.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/conversionbg.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/defbg-blue.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/defbg-green.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/diagrams.css create mode 100644 nebula-exchange/target/site/scaladocs/lib/diagrams.js create mode 100644 nebula-exchange/target/site/scaladocs/lib/filter_box_left.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/filter_box_left2.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/filter_box_right.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/filterbg.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/filterboxbarbg.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/filterboxbarbg.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/filterboxbg.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/fullcommenttopbg.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/index.css create mode 100644 nebula-exchange/target/site/scaladocs/lib/index.js create mode 100644 nebula-exchange/target/site/scaladocs/lib/jquery-ui.js create mode 100644 nebula-exchange/target/site/scaladocs/lib/jquery.js create mode 100644 nebula-exchange/target/site/scaladocs/lib/jquery.layout.js create mode 100644 nebula-exchange/target/site/scaladocs/lib/modernizr.custom.js create mode 100644 nebula-exchange/target/site/scaladocs/lib/navigation-li-a.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/navigation-li.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/object.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/object_big.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/object_diagram.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/object_to_class_big.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/object_to_trait_big.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/object_to_type_big.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/ownderbg2.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/ownerbg.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/ownerbg2.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/package.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/package_big.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/packagesbg.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/permalink.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/ref-index.css create mode 100644 nebula-exchange/target/site/scaladocs/lib/remove.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/scheduler.js create mode 100644 nebula-exchange/target/site/scaladocs/lib/selected-implicits.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/selected-right-implicits.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/selected-right.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/selected.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/selected2-right.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/selected2.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/signaturebg.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/signaturebg2.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/template.css create mode 100644 nebula-exchange/target/site/scaladocs/lib/template.js create mode 100644 nebula-exchange/target/site/scaladocs/lib/tools.tooltip.js create mode 100644 nebula-exchange/target/site/scaladocs/lib/trait.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/trait_big.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/trait_diagram.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/trait_to_object_big.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/type.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/type_big.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/type_diagram.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/type_to_object_big.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/typebg.gif create mode 100644 nebula-exchange/target/site/scaladocs/lib/unselected.png create mode 100644 nebula-exchange/target/site/scaladocs/lib/valuemembersbg.gif create mode 100644 nebula-exchange/target/site/scaladocs/package.html create mode 100644 nebula-exchange/target/test-classes.timestamp create mode 100644 nebula-spark-connector/pom.xml create mode 100644 nebula-spark-connector/target/maven-archiver/pom.properties create mode 100644 pom.xml diff --git a/.github/workflows/ISSUE_TEMPLATE.md b/.github/workflows/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..8efba33 --- /dev/null +++ b/.github/workflows/ISSUE_TEMPLATE.md @@ -0,0 +1,11 @@ +#### Expected behavior + +#### Actual behavior + +#### Steps to reproduce + +#### JVM version (e.g. `java -version`) + +#### Scala version (e.g. `scala -version`) + +#### OS version (e.g. `uname -a`) diff --git a/.github/workflows/PULL_REQUEST_TEMPLATE.md b/.github/workflows/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..bb3eb3e --- /dev/null +++ b/.github/workflows/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,11 @@ +Motivation: + +Why you're making that change and what is the problem you're trying to solve. + +Modification: + +Describe the modifications you've done. + +Result: + +Fixes #. diff --git a/.gitignore b/.gitignore index a1c2a23..b5562b0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,12 @@ # BlueJ files *.ctxt +# iml +*.iml + +# .idea +.idea + # Mobile Tools for Java (J2ME) .mtj.tmp/ diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md new file mode 100644 index 0000000..f5a1d46 --- /dev/null +++ b/nebula-exchange/README.md @@ -0,0 +1,20 @@ +# 欢迎使用 Nebula Graph Exchange 2.0 + +Nebula Graph Exchange(简称为 Exchange),是一款 Apache Spark™ 应用,用于在分布式环境中将集群中的数据批量迁移到 Nebula Graph 中,能支持多种不同格式的批式数据和流式数据的迁移。 + +## 使用说明 + +关于 Nebula Graph Exchange 2.0 的详细使用说明,请参考1.0的使用文档[《Nebula Graph Exchange 用户手册》](https://docs.nebula-graph.com.cn/nebula-exchange/about-exchange/ex-ug-what-is-exchange/ "点击前往 Nebula Graph 网站")。 + +注意事项: + +*1. Nebula Graph 2.0暂时只支持String类型的vid,请勿配置点id或者边的src_id、dst_id的policy* + +*2. Exchange 2.0 支持Date、DateTime、Time类型数据的导入* +## 贡献 + +Nebula Graph Exchange 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: + +- 前往 [Nebula Graph 论坛](https://discuss.nebula-graph.com.cn/ "点击前往“Nebula Graph 论坛") 上参与 Issue 讨论,如答疑、提供想法或者报告无法解决的问题 +- 撰写或改进文档 +- 提交优化代码 diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml new file mode 100644 index 0000000..4ca28fc --- /dev/null +++ b/nebula-exchange/pom.xml @@ -0,0 +1,682 @@ + + + + nebula-spark + com.vesoft + 2.0.0 + ../pom.xml + + 4.0.0 + + nebula-exchange + + + 1.8 + 1.8 + 2.10.7 + 2.11.12 + 2.12.10 + ${scala.2.11.version} + 2.12 + 2.4.4 + 1.5.0 + 3.2.0 + 6.7.3 + 1.4.0 + 3.9.2 + 2.11.0-M4 + 3.7.1 + 2.0.0-beta + 1.0.0-rc2 + 1.0.0 + 2.4.5-M1 + 3.4.6 + 0.5.0 + 2.4.5 + 1.14 + 2.6.1 + 1.2.0 + + + + src/test + + + org.scala-tools + maven-scala-plugin + 2.15.2 + + ${scala.version} + + -target:jvm-1.8 + + + -Xss4096K + + + + + scala-compile + + compile + + + + com/vesoft/tools/** + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + scala-test-compile + + testCompile + + + + com/vesoft/tools/** + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + true + + + + org.scalatest + scalatest-maven-plugin + 2.0.0 + + + test + + test + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.1 + + + package + + shade + + + false + + + org.apache.spark:* + org.apache.hadoop:* + org.apache.hive:* + log4j:log4j + org.apache.orc:* + xml-apis:xml-apis + javax.inject:javax.inject + org.spark-project.hive:hive-exec + stax:stax-api + org.glassfish.hk2.external:aopalliance-repackaged + + + + + *:* + + com/vesoft/tools/** + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.0 + + + attach-sources + + jar + + + + + + net.alchim31.maven + scala-maven-plugin + + + + Scaladoc + + doc + + prepare-package + + + -nobootcp + -no-link-warnings + + + + + attach-javadocs + + doc-jar + + + + -nobootcp + -no-link-warnings + + + + + + + + + + + io.streamnative.connectors + pulsar-spark-connector_2.11 + ${pulsar.version} + + + org.apache.spark + spark-core_2.11 + ${spark.version} + + + snappy-java + org.xerial.snappy + + + paranamer + com.thoughtworks.paranamer + + + slf4j-api + org.slf4j + + + commons-codec + commons-codec + + + avro + org.apache.avro + + + commons-lang + commons-lang + + + commons-collections + commons-collections + + + commons-compress + org.apache.commons + + + commons-math3 + org.apache.commons + + + guava + com.google.guava + + + httpclient + org.apache.httpcomponents + + + slf4j-log4j12 + org.slf4j + + + netty + io.netty + + + jackson-annotations + com.fasterxml.jackson.core + + + scala-reflect + org.scala-lang + + + scala-library + org.scala-lang + + + jackson-databind + com.fasterxml.jackson.core + + + scala-xml_2.11 + org.scala-lang.modules + + + log4j + log4j + + + javassist + org.javassist + + + commons-io + commons-io + + + commons-configuration + commons-configuration + + + jul-to-slf4j + org.slf4j + + + + + org.apache.spark + spark-sql_2.11 + ${spark.version} + + + snappy-java + org.xerial.snappy + + + jsr305 + com.google.code.findbugs + + + slf4j-api + org.slf4j + + + jackson-core + com.fasterxml.jackson.core + + + joda-time + joda-time + + + commons-codec + commons-codec + + + snappy-java + org.xerial.snappy + + + hppc + com.carrotsearch + + + + + org.apache.spark + spark-catalyst_2.11 + ${spark.version} + + + org.apache.spark + spark-hive_2.11 + ${spark.version} + + + commons-codec + commons-codec + + + commons-logging + commons-logging + + + avro + org.apache.avro + + + commons-compress + org.apache.commons + + + commons-lang3 + org.apache.commons + + + jackson-mapper-asl + org.codehaus.jackson + + + antlr-runtime + org.antlr + + + jackson-core-asl + org.codehaus.jackson + + + derby + org.apache.derby + + + httpclient + org.apache.httpcomponents + + + httpcore + org.apache.httpcomponents + + + commons-io + commons-io + + + + + org.apache.spark + spark-yarn_2.11 + ${spark.version} + + + guava + com.google.guava + + + commons-codec + commons-codec + + + commons-compress + org.apache.commons + + + activation + javax.activation + + + slf4j-api + org.slf4j + + + commons-io + commons-io + + + + + com.databricks + spark-csv_2.11 + ${spark-csv.version} + + + scala-library + org.scala-lang + + + univocity-parsers + com.univocity + + + + + org.scalatest + scalatest_2.11 + ${scalatest.version} + test + + + org.rocksdb + rocksdbjni + ${rocksdb.version} + + + com.typesafe + config + ${config.version} + + + com.typesafe.scala-logging + scala-logging_2.11 + ${scala-logging.version} + + + scala-library + org.scala-lang + + + scala-reflect + org.scala-lang + + + slf4j-api + org.slf4j + + + + + com.github.scopt + scopt_2.11 + ${scopt.version} + + + io.sgr + s2-geometry-library-java + ${s2.version} + + + com.vesoft + client + ${nebula.version} + + + commons-lang3 + org.apache.commons + + + commons-codec + commons-codec + + + + + com.vesoft + nebula-utils + ${nebula-utils.version} + + + neo4j-contrib + neo4j-spark-connector + ${neo.version} + + + scala-library + org.scala-lang + + + slf4j-api + org.slf4j + + + xbean-asm6-shaded + org.apache.xbean + + + + + org.apache.tinkerpop + spark-gremlin + ${gremlin.version} + + + guava + com.google.guava + + + commons-lang3 + org.apache.commons + + + jcl-over-slf4j + org.slf4j + + + commons-codec + commons-codec + + + spark-core_2.11 + org.apache.spark + + + scala-xml_2.11 + org.scala-lang.modules + + + scala-library + org.scala-lang + + + jackson-databind + com.fasterxml.jackson.core + + + hadoop-client + org.apache.hadoop + + + netty-all + io.netty + + + + + org.janusgraph + janusgraph-core + ${janusgraph.version} + + + commons-codec + commons-codec + + + commons-logging + commons-logging + + + jsr305 + com.google.code.findbugs + + + metrics-core + io.dropwizard.metrics + + + slf4j-api + org.slf4j + + + metrics-graphite + io.dropwizard.metrics + + + commons-lang3 + org.apache.commons + + + + + org.janusgraph + janusgraph-driver + ${janusgraph.version} + + + guava + com.google.guava + + + commons-lang3 + org.apache.commons + + + netty-all + io.netty + + + ivy + org.apache.ivy + + + slf4j-api + org.slf4j + + + + + commons-codec + commons-codec + ${commons-codec.version} + + + org.apache.hadoop + hadoop-client + ${hadoop.version} + + + org.apache.hbase + hbase-client + ${hbase.version} + + + org.apache.hbase + hbase-common + ${hbase.version} + + + org.apache.hbase + hbase-server + ${hbase.version} + + + org.scala-lang + scala-xml + ${scala-xml.version} + + + + + SparkPackagesRepo + http://dl.bintray.com/spark-packages/maven + + + bintray-streamnative-maven + bintray + https://dl.bintray.com/streamnative/maven + + + \ No newline at end of file diff --git a/nebula-exchange/src/main/.DS_Store b/nebula-exchange/src/main/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..0e98056ead8b2b4ddd22a5b0719be234dbd12c0a GIT binary patch literal 6148 zcmeHKI|>3p3{BKRv9YwAD|mxJ^aNf&P_YpOMeD6Rmq+vEgD9(wU?VS(yqQeiEc=Sh zMnrUaUQa|uBGQK&%GE;K?A*L%oy;f@jyukBl$C7cbXl~j-zSVa01F&BJoAtH-C@6t zo8MEJr2a0lP&G#k4Lb5A>uO>X7ausK8$-puO2*HpMGtZ*9Gt_1Xeo!mZ{8H^bT~2;Po?-j1=cc0Bf? bs4KR{c};8rosPWIf&3XTU1(I`*9zPLYRVP2 literal 0 HcmV?d00001 diff --git a/nebula-exchange/src/main/resources/application.conf b/nebula-exchange/src/main/resources/application.conf new file mode 100644 index 0000000..61bfa28 --- /dev/null +++ b/nebula-exchange/src/main/resources/application.conf @@ -0,0 +1,129 @@ +{ + # Spark relation config + spark: { + app: { + name: Nebula Exchange 2.0 + } + + driver: { + cores: 1 + maxResultSize: 1G + } + + executor: { + memory:1G + } + + cores:{ + max: 16 + } + } + + # Nebula Graph relation config + nebula: { + address:{ + graph:["127.0.0.1:3699"] + meta:["127.0.0.1:45500"] + } + user: user + pswd: password + space: test + + connection { + timeout: 3000 + retry: 3 + } + + execution { + retry: 3 + } + + error: { + max: 32 + # failed import job will be recorded in output path + output: /tmp/errors + } + + rate: { + limit: 1024 + timeout: 1000 + } + } + + # Processing tags + tags: [ + + # Loading tag from HDFS and data type is parquet + { + name: tag-name-0 + type: { + source: parquet + sink: client + } + path: hdfs tag path 0 + fields: [parquet-field-0, parquet-field-1, parquet-field-2] + nebula.fields: [nebula-field-0 nebula-field-1 nebula-field-2] + vertex: hive-field-0 + batch: 256 + partition: 32 + } + + # Loading tag from HDFS and data type is csv + { + name: tag-name-2 + type: { + source: csv + sink: client + } + path: hdfs tag path 2 + fields: [csv-field-0, csv-field-1, csv-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: hive-field-0 + separator: "," + header: true + batch: 256 + partition: 32 + } + + # Loading tag from HDFS and data type is csv + { + name: tag-name-2 + type: { + source: csv + sink: client + } + path: hdfs tag path 2 + fields: [csv-field-0, csv-field-1, csv-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: hive-field-0 + separator: "," + header: true + batch: 256 + partition: 32 + } + ] + + # Processing edges + edges: [ + # Loading tag from HDFS and data type is json + { + name: edge-name-0 + type: { + source: json + sink: client + } + path: hdfs edge path 0 + fields: [json-field-0, json-field-1, json-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: { + field: hive-field-0 + } + target: { + field: hive-field-1 + } + ranking: hive-field-2 + batch: 256 + partition: 32 + } + ] +} diff --git a/nebula-exchange/src/main/resources/server_application.conf b/nebula-exchange/src/main/resources/server_application.conf new file mode 100644 index 0000000..64df37b --- /dev/null +++ b/nebula-exchange/src/main/resources/server_application.conf @@ -0,0 +1,183 @@ +{ + # Spark relation config + spark: { + driver: { + cores: 1 + maxResultSize: 1G + } + + cores { + max: 16 + } + } + + # if the hive is in the same cluster with spark, you can ignore this hive configure + hive: { + waredir: "hdfs://NAMENODE_IP:9000/apps/svr/hive-xxx/warehouse/" + connectionURL: "jdbc:mysql://your_ip:3306/hive_spark?characterEncoding=UTF-8" + connectionDriverName: "com.mysql.jdbc.Driver" + connectionUserName: "user" + connectionPassword: "password" + } + + # Nebula Graph relation config + nebula: { + address:{ + graph:["127.0.0.1:3699"] + meta:["127.0.0.1:45500"] + } + user: user + pswd: password + space: test + + connection { + timeout: 3000 + retry: 3 + } + + execution { + retry: 3 + } + + error: { + max: 32 + # failed import job will be recorded in output path + output: /tmp/errors + } + + rate: { + limit: 1024 + timeout: 1000 + } + } + + # Processing tags + tags: [ + # Loading from Hive + { + name: tag-name-1 + type: { + source: hive + sink: client + } + exec: "select hive-field0, hive-field1, hive-field2 from database.table" + fields: [hive-field-0, hive-field-1, hive-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: { + field: hive-field-0 + # nebula 2.0 does not support int vid yet, so do not config policy. + # policy: "hash" + } + vertex: hive-field-0 + batch: 256 + partition: 32 + } + + # Loading tag from neo4j + { + name: tag-name-0 + type: { + source: neo4j + sink: client + } + server: "bolt://127.0.0.1:7687" + user: neo4j + password: neo4j + exec: "match (n:label) return n.neo4j-field-0 as neo4j-field-0, n.neo4j-field-1 as neo4j-field-1 order by (n.neo4j-field-0)" + fields: [neo4j-field-0, neo4j-field-1] + nebula.fields: [nebula-field-0, nebula-field-1] + vertex: { + field:neo4j-field-0 + # nebula 2.0 does not support int vid yet, so do not config policy. + # policy:uuid + } + partition: 10 + batch: 1000 + check_point_path: /tmp/test + } + + # Loading from HBase, if fields or vertex contains rowkey, please configure it as rowkey. + { + name: hbase-table-name + type: { + source: hbase + sink: client + } + host:127.0.0.1 + port:2181 + table:hbase-table + columnFamily:hbase-table-cloumnfamily + fields: [hbase-column-0, hbase-column-1] + nebula.fields: [nebula-field-0, nebula-field-1] + vertex: rowkey + partition: 10 + batch: 1000 + } + ] + + # Processing edges + edges: [ + # Loading from Hive + { + name: edge-name-1 + type: { + source: hive + sink: client + } + exec: "select hive-field0, hive-field1, hive-field2 from database.table" + fields: [ hive-field-0, hive-field-1, hive-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: hive-field-0 + target: hive-field-1 + batch: 256 + partition: 32 + } + + # Loading from neo4j + { + name: edge-name-0 + type: { + source: neo4j + sink: client + } + server: "bolt://127.0.0.1:7687" + user: neo4j + password: neo4j + exec: "match (a:vertex_label)-[r:edge_label]->(b:vertex_label) return a.neo4j-source-field, b.neo4j-target-field, r.neo4j-field-0 as neo4j-field-0, r.neo4j-field-1 as neo4j-field-1 order by id(r)" + fields: [neo4j-field-0, neo4j-field-1] + nebula.fields: [nebula-field-0, nebula-field-1] + source: { + field: a.neo4j-source-field + } + target: { + field: b.neo4j-target-field + } + partition: 10 + batch: 1000 + check_point_path: /tmp/test + } + + # Loading from hbase + { + name: hbase-table-name + type: { + source: hbase + sink: client + } + host:127.0.0.1 + port:2181 + table:hbase-table + columnFamily:hbase-table-cloumnfamily + fields: [hbase-column-0, hbase-column-1] + nebula.fields:[nebula-field-0, nebula-field-1] + source: { + field: hbase-column-k + } + target: { + field: hbase-column-h + } + partition: 10 + batch: 1000 + } + ] +} diff --git a/nebula-exchange/src/main/resources/stream_application.conf b/nebula-exchange/src/main/resources/stream_application.conf new file mode 100644 index 0000000..ab0a201 --- /dev/null +++ b/nebula-exchange/src/main/resources/stream_application.conf @@ -0,0 +1,143 @@ +{ + # Spark relation config + spark: { + app: { + name: Spark Writer + } + + driver: { + cores: 1 + maxResultSize: 1G + } + + cores { + max: 16 + } + } + + # Nebula Graph relation config + nebula: { + address:{ + graph:["127.0.0.1:3699"] + meta:["127.0.0.1:45500"] + } + user: user + pswd: password + space: test + + connection { + timeout: 3000 + retry: 3 + } + + execution { + retry: 3 + } + + error: { + max: 32 + # failed import job will be recorded in output path + output: /tmp/errors + } + + rate: { + limit: 1024 + timeout: 1000 + } + } + + # Processing tags + tags: [ + + # Loading tag from pulsar + { + name: tag-name-0 + type: { + source: pulsar + sink: client + } + service: "pulsar://localhost:6650" + admin: "http://localhost:8081" + options: { + # choose one of "topic", "topics", "topicsPattern" + topics: "topic1,topic2" + } + fields: [pulsar-field-0, pulsar-field-1, pulsar-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: { + field:pulsar-field-0 + # nebula 2.0 does not support int vid yet, so do not config policy. + # policy:hash + } + partition: 10 + batch: 1000 + interval.seconds: 10 + } + + # Loading from KAFKA + { + name: tag-name-1 + type: { + source: kafka + sink: client + } + service: "kafka.service.address" + topic: "topic-name" + fields: [kafka-field-0, kafka-field-1, kafka-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: kafka-field-0 + partition: 10 + batch: 10 + interval.seconds: 10 + } + ] + + # Processing edges + edges: [ + + # Loading tag from pulsar + { + name: edge-name-0 + type: { + source: pulsar + sink: client + } + service: "pulsar://localhost:6650" + admin: "http://localhost:8081" + options: { + # choose one of "topic", "topics", "topicsPattern" + topic: "topic1" + } + fields: [pulsar-field-0, pulsar-field-1, pulsar-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: { + field: pulsar-field-0 + } + target: { + field: pulsar-field-1 + } + ranking: pulsar-field-2 + partition: 10 + batch: 10 + interval.seconds: 10 + } + + # Loading from KAFKA + { + name: edge-name-1 + type: { + source: kafka + sink: client + } + service: "kafka.service.address" + topic: "topic-name" + fields: [kafka-field-0, kafka-field-1, kafka-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: kafka-field-0 + target: kafka-field-1 + partition: 10 + batch: 1000 + interval.seconds: 10 + } + ] +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/CheckPointHandler.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/CheckPointHandler.scala new file mode 100644 index 0000000..e3a4495 --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/CheckPointHandler.scala @@ -0,0 +1,41 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer + +import com.vesoft.nebula.tools.importer.config.{SchemaConfigEntry, SourceCategory} +import com.vesoft.nebula.tools.importer.utils.HDFSUtils +import org.apache.spark.TaskContext + +/** + * CheckPointHandler handle the checkpoint files for Neo4j and Janusgraph + */ +object CheckPointHandler { + + def checkSupportResume(value: SourceCategory.Value): Boolean = { + value match { + case SourceCategory.NEO4J => true + case SourceCategory.JANUS_GRAPH => true + case _ => false + } + } + + def getPathAndOffset(schemaConfig: SchemaConfigEntry, + breakPointCount: Long): Option[(String, Long)] = { + val partitionId = TaskContext.getPartitionId() + if (checkSupportResume(schemaConfig.dataSourceConfigEntry.category) && schemaConfig.checkPointPath.isDefined) { + val path = s"${schemaConfig.checkPointPath.get}/${schemaConfig.name}.${partitionId}" + val offset = breakPointCount + fetchOffset(path) + Some((path, offset)) + } else { + None + } + } + + def fetchOffset(path: String): Long = { + HDFSUtils.getContent(path).toLong + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/ErrorHandler.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/ErrorHandler.scala new file mode 100644 index 0000000..04b337a --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/ErrorHandler.scala @@ -0,0 +1,33 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer + +import org.apache.hadoop.conf.Configuration +import org.apache.hadoop.fs.{FileSystem, Path} +import scala.collection.mutable.ArrayBuffer + +object ErrorHandler { + def save(buffer: ArrayBuffer[String], path: String): Unit = { + val fileSystem = FileSystem.get(new Configuration()) + val errors = fileSystem.create(new Path(path)) + + try { + for (error <- buffer) { + errors.writeBytes(error) + errors.writeBytes("\n") + } + } finally { + errors.close() + fileSystem.close() + } + } + + def existError(path: String): Boolean = { + val fileSystem = FileSystem.get(new Configuration()) + fileSystem.exists(new Path(path)) + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/Exchange.scala new file mode 100644 index 0000000..202dddd --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/Exchange.scala @@ -0,0 +1,285 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer + +import org.apache.spark.sql.{DataFrame, SparkSession} +import java.io.File +import com.vesoft.nebula.tools.importer.config.{ + Configs, + DataSourceConfigEntry, + FileBaseSourceConfigEntry, + HBaseSourceConfigEntry, + HiveSourceConfigEntry, + JanusGraphSourceConfigEntry, + KafkaSourceConfigEntry, + MySQLSourceConfigEntry, + Neo4JSourceConfigEntry, + PulsarSourceConfigEntry, + SourceCategory +} +import com.vesoft.nebula.tools.importer.processor.{ + EdgeProcessor, + ReloadProcessor, + VerticesProcessor +} +import com.vesoft.nebula.tools.importer.reader.{ + CSVReader, + HBaseReader, + HiveReader, + JSONReader, + JanusGraphReader, + KafkaReader, + MySQLReader, + Neo4JReader, + ORCReader, + ParquetReader, + PulsarReader +} +import org.apache.log4j.Logger +import org.apache.spark.SparkConf + +final case class Argument(config: File = new File("application.conf"), + hive: Boolean = false, + directly: Boolean = false, + dry: Boolean = false, + reload: String = "") + +final case class TooManyErrorsException(private val message: String) extends Exception(message) + +/** + * SparkClientGenerator is a simple spark job used to write data into Nebula Graph parallel. + */ +object Exchange { + private[this] val LOG = Logger.getLogger(this.getClass) + + def main(args: Array[String]): Unit = { + val PROGRAM_NAME = "Nebula Graph Exchange" + val options = Configs.parser(args, PROGRAM_NAME) + val c: Argument = options match { + case Some(config) => config + case _ => + LOG.error("Argument parse failed") + sys.exit(-1) + } + + val configs = Configs.parse(c.config) + LOG.info(s"Config ${configs}") + + val session = SparkSession + .builder() + .appName(PROGRAM_NAME) + .config("spark.serializer", "org.apache.spark.serializer.KryoSerializer") + .config("spark.sql.shuffle.partitions", "1") + + for (key <- configs.sparkConfigEntry.map.keySet) { + session.config(key, configs.sparkConfigEntry.map(key)) + } + + val sparkConf = new SparkConf() + sparkConf.registerKryoClasses(Array(classOf[com.facebook.thrift.async.TAsyncClientManager])) + + // config hive for sparkSession + if (c.hive) { + if (configs.hiveConfigEntry.isEmpty) { + LOG.warn("you don't config hive source, so using hive tied with spark.") + } else { + val hiveConfig = configs.hiveConfigEntry.get + sparkConf.set("spark.sql.warehouse.dir", hiveConfig.waredir) + sparkConf + .set("javax.jdo.option.ConnectionURL", hiveConfig.connectionURL) + .set("javax.jdo.option.ConnectionDriverName", hiveConfig.connectionDriverName) + .set("javax.jdo.option.ConnectionUserName", hiveConfig.connectionUserName) + .set("javax.jdo.option.ConnectionPassword", hiveConfig.connectionPassWord) + } + session.enableHiveSupport() + } + + val spark = session.getOrCreate() + + // reload for failed import tasks + if (!c.reload.isEmpty) { + val batchSuccess = spark.sparkContext.longAccumulator(s"batchSuccess.reload") + val batchFailure = spark.sparkContext.longAccumulator(s"batchFailure.reload") + + val data = spark.read.text(c.reload) + val processor = new ReloadProcessor(data, configs, batchSuccess, batchFailure) + processor.process() + LOG.info(s"batchSuccess.reload: ${batchSuccess.value}") + LOG.info(s"batchFailure.reload: ${batchFailure.value}") + sys.exit(0) + } + + // import tags + if (configs.tagsConfig.nonEmpty) { + for (tagConfig <- configs.tagsConfig) { + LOG.info(s"Processing Tag ${tagConfig.name}") + + val fieldKeys = tagConfig.fields + LOG.info(s"field keys: ${fieldKeys.mkString(", ")}") + val nebulaKeys = tagConfig.nebulaFields + LOG.info(s"nebula keys: ${nebulaKeys.mkString(", ")}") + + val data = createDataSource(spark, tagConfig.dataSourceConfigEntry) + if (data.isDefined && !c.dry) { + val batchSuccess = + spark.sparkContext.longAccumulator(s"batchSuccess.${tagConfig.name}") + val batchFailure = + spark.sparkContext.longAccumulator(s"batchFailure.${tagConfig.name}") + + val processor = new VerticesProcessor( + repartition(data.get, tagConfig.partition, tagConfig.dataSourceConfigEntry.category), + tagConfig, + fieldKeys, + nebulaKeys, + configs, + batchSuccess, + batchFailure) + processor.process() + LOG.info(s"batchSuccess.${tagConfig.name}: ${batchSuccess.value}") + LOG.info(s"batchFailure.${tagConfig.name}: ${batchFailure.value}") + } + } + } else { + LOG.warn("Tag is not defined") + } + + // import edges + if (configs.edgesConfig.nonEmpty) { + for (edgeConfig <- configs.edgesConfig) { + LOG.info(s"Processing Edge ${edgeConfig.name}") + + val fieldKeys = edgeConfig.fields + LOG.info(s"field keys: ${fieldKeys.mkString(", ")}") + val nebulaKeys = edgeConfig.nebulaFields + LOG.info(s"nebula keys: ${nebulaKeys.mkString(", ")}") + val data = createDataSource(spark, edgeConfig.dataSourceConfigEntry) + if (data.isDefined && !c.dry) { + val batchSuccess = spark.sparkContext.longAccumulator(s"batchSuccess.${edgeConfig.name}") + val batchFailure = spark.sparkContext.longAccumulator(s"batchFailure.${edgeConfig.name}") + + val processor = new EdgeProcessor( + repartition(data.get, edgeConfig.partition, edgeConfig.dataSourceConfigEntry.category), + edgeConfig, + fieldKeys, + nebulaKeys, + configs, + batchSuccess, + batchFailure + ) + processor.process() + LOG.info(s"batchSuccess.${edgeConfig.name}: ${batchSuccess.value}") + LOG.info(s"batchFailure.${edgeConfig.name}: ${batchFailure.value}") + } + } + } else { + LOG.warn("Edge is not defined") + } + + // reimport for failed tags and edges + if (ErrorHandler.existError(configs.errorConfig.errorPath)) { + val batchSuccess = spark.sparkContext.longAccumulator(s"batchSuccess.reimport") + val batchFailure = spark.sparkContext.longAccumulator(s"batchFailure.reimport") + val data = spark.read.text() + val processor = new ReloadProcessor(data, configs, batchSuccess, batchFailure) + processor.process() + LOG.info(s"batchSuccess.reimport: ${batchSuccess.value}") + LOG.info(s"batchFailure.reimport: ${batchFailure.value}") + } + spark.close() + } + + /** + * Create data source for different data type. + * + * @param session The Spark Session. + * @param config The config. + * @return + */ + private[this] def createDataSource( + session: SparkSession, + config: DataSourceConfigEntry + ): Option[DataFrame] = { + config.category match { + case SourceCategory.PARQUET => + val parquetConfig = config.asInstanceOf[FileBaseSourceConfigEntry] + LOG.info(s"""Loading Parquet files from ${parquetConfig.path}""") + val reader = new ParquetReader(session, parquetConfig) + Some(reader.read()) + case SourceCategory.ORC => + val orcConfig = config.asInstanceOf[FileBaseSourceConfigEntry] + LOG.info(s"""Loading ORC files from ${orcConfig.path}""") + val reader = new ORCReader(session, orcConfig) + Some(reader.read()) + case SourceCategory.JSON => + val jsonConfig = config.asInstanceOf[FileBaseSourceConfigEntry] + LOG.info(s"""Loading JSON files from ${jsonConfig.path}""") + val reader = new JSONReader(session, jsonConfig) + Some(reader.read()) + case SourceCategory.CSV => + val csvConfig = config.asInstanceOf[FileBaseSourceConfigEntry] + LOG.info(s"""Loading CSV files from ${csvConfig.path}""") + val reader = + new CSVReader(session, csvConfig) + Some(reader.read()) + case SourceCategory.HIVE => + val hiveConfig = config.asInstanceOf[HiveSourceConfigEntry] + LOG.info(s"""Loading from Hive and exec ${hiveConfig.sentence}""") + val reader = new HiveReader(session, hiveConfig) + Some(reader.read()) + case SourceCategory.KAFKA => { + val kafkaConfig = config.asInstanceOf[KafkaSourceConfigEntry] + LOG.info(s"""Loading from Kafka ${kafkaConfig.server} and subscribe ${kafkaConfig.topic}""") + val reader = new KafkaReader(session, kafkaConfig) + Some(reader.read()) + } + case SourceCategory.NEO4J => + val neo4jConfig = config.asInstanceOf[Neo4JSourceConfigEntry] + LOG.info(s"Loading from neo4j config: ${neo4jConfig}") + val reader = new Neo4JReader(session, neo4jConfig) + Some(reader.read()) + case SourceCategory.MYSQL => + val mysqlConfig = config.asInstanceOf[MySQLSourceConfigEntry] + LOG.info(s"Loading from mysql config: ${mysqlConfig}") + val reader = new MySQLReader(session, mysqlConfig) + Some(reader.read()) + case SourceCategory.PULSAR => + val pulsarConfig = config.asInstanceOf[PulsarSourceConfigEntry] + LOG.info(s"Loading from pulsar config: ${pulsarConfig}") + val reader = new PulsarReader(session, pulsarConfig) + Some(reader.read()) + case SourceCategory.JANUS_GRAPH => + val janusGraphSourceConfigEntry = config.asInstanceOf[JanusGraphSourceConfigEntry] + val reader = new JanusGraphReader(session, janusGraphSourceConfigEntry) + Some(reader.read()) + case SourceCategory.HBASE => + val hbaseSourceConfigEntry = config.asInstanceOf[HBaseSourceConfigEntry] + val reader = new HBaseReader(session, hbaseSourceConfigEntry) + Some(reader.read()) + case _ => { + LOG.error(s"Data source ${config.category} not supported") + None + } + } + } + + /** + * Repartition the data frame using the specified partition number. + * + * @param frame + * @param partition + * @return + */ + private[this] def repartition(frame: DataFrame, + partition: Int, + sourceCategory: SourceCategory.Value): DataFrame = { + if (partition > 0 && !CheckPointHandler.checkSupportResume(sourceCategory)) { + frame.repartition(partition).toDF + } else { + frame + } + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/GraphProvider.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/GraphProvider.scala new file mode 100644 index 0000000..ab48520 --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/GraphProvider.scala @@ -0,0 +1,55 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer + +import com.google.common.net.HostAndPort +import com.vesoft.nebula.client.graph.NebulaPoolConfig +import com.vesoft.nebula.client.graph.data.{HostAddress, ResultSet} +import com.vesoft.nebula.client.graph.net.{NebulaPool, Session} +import com.vesoft.nebula.tools.importer.config.UserConfigEntry +import org.apache.log4j.Logger + +import scala.collection.JavaConverters._ +import scala.collection.mutable.ListBuffer + +/** + * + */ +class GraphProvider(addresses: List[HostAndPort]) extends AutoCloseable with Serializable { + private[this] lazy val LOG = Logger.getLogger(this.getClass) + + @transient val nebulaPoolConfig = new NebulaPoolConfig + @transient val pool: NebulaPool = new NebulaPool + val address = new ListBuffer[HostAddress]() + for (addr <- addresses) { + address.append(new HostAddress(addr.getHostText, addr.getPort)) + } + pool.init(address.asJava, nebulaPoolConfig) + + def getGraphClient(userConfigEntry: UserConfigEntry): Session = { + pool.getSession(userConfigEntry.user, userConfigEntry.password, true); + } + + def releaseGraphClient(session: Session): Unit = { + session.release() + } + + override def close(): Unit = { + pool.close() + } + + def switchSpace(session: Session, space: String): Boolean = { + val switchStatment = s"use $space" + LOG.info(s"switch space $space") + val result = submit(session, switchStatment) + result.isSucceeded + } + + def submit(session: Session, statement: String): ResultSet = { + session.execute(statement) + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/MetaProvider.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/MetaProvider.scala new file mode 100644 index 0000000..ea567c2 --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/MetaProvider.scala @@ -0,0 +1,95 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer + +import com.google.common.net.HostAndPort +import com.vesoft.nebula.client.graph.data.HostAddress +import com.vesoft.nebula.client.meta.MetaClient +import com.vesoft.nebula.meta.PropertyType +import com.vesoft.nebula.tools.importer.config.Type +import org.apache.log4j.Logger + +import scala.collection.JavaConverters._ +import scala.collection.mutable +import scala.collection.mutable.ListBuffer + +/** + * MetaProvider provide nebula graph meta query operations. + */ +class MetaProvider(addresses: List[HostAndPort]) extends AutoCloseable with Serializable { + private[this] lazy val LOG = Logger.getLogger(this.getClass) + + val address: ListBuffer[HostAddress] = new ListBuffer[HostAddress] + for (addr <- addresses) { + address.append(new HostAddress(addr.getHostText, addr.getPort)) + } + + private val metaClient = new MetaClient(address.asJava) + metaClient.connect() + + def getPartNumber(space: String): Unit = { + metaClient.getPartsAlloc(space).size() + } + + def getVidType(space: String): VidType.Value = { + val vidType = metaClient.getSpace(space).getProperties.getVid_type.getType + if (vidType == PropertyType.FIXED_STRING) { + return VidType.STRING + } + VidType.INT + } + + def getTagSchema(space: String, tag: String): Map[String, Integer] = { + val tagSchema = metaClient.getTag(space, tag) + val schema = new mutable.HashMap[String, Integer] + + val columns = tagSchema.getColumns + for (colDef <- columns.asScala) { + schema.put(new String(colDef.getName), colDef.getType.getType) + } + schema.toMap + } + + def getEdgeSchema(space: String, edge: String): Map[String, Integer] = { + val edgeSchema = metaClient.getEdge(space, edge) + val schema = new mutable.HashMap[String, Integer] + + val columns = edgeSchema.getColumns + for (colDef <- columns.asScala) { + schema.put(new String(colDef.getName), colDef.getType.getType) + } + schema.toMap + } + + def getLabelType(space: String, label: String): Type.Value = { + val tags = metaClient.getTags(space) + for (tag <- tags.asScala) { + if (new String(tag.getTag_name).equals(label)) { + return Type.VERTEX + } + } + val edges = metaClient.getEdges(space) + for (edge <- edges.asScala) { + if (new String(edge.getEdge_name).equals(label)) { + return Type.EDGE + } + } + null + } + + override def close(): Unit = { + metaClient.close() + } + +} + +object VidType extends Enumeration { + type Type = Value + + val STRING = Value("STRING") + val INT = Value("INT") +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/Configs.scala new file mode 100644 index 0000000..b9f37cf --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/Configs.scala @@ -0,0 +1,738 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.config + +import java.io.File +import java.nio.file.Files + +import com.google.common.net.HostAndPort +import com.vesoft.nebula.tools.importer.{Argument, KeyPolicy} +import com.typesafe.config.{Config, ConfigFactory} +import org.apache.log4j.Logger + +import scala.collection.JavaConverters._ +import scala.collection.mutable +import scala.collection.mutable.ListBuffer +import scala.util.control.Breaks._ + +object Type extends Enumeration { + type Type = Value + val VERTEX = Value("VERTEX") + val EDGE = Value("EDGE") +} + +/** + * DataBaseConfigEntry describe the nebula cluster's address and which space will be used. + * + * @param graphAddress + * @param space + */ +case class DataBaseConfigEntry(graphAddress: List[String], + space: String, + metaAddresses: List[String]) { + require(graphAddress.nonEmpty) + require(metaAddresses.nonEmpty) + require(space.trim.nonEmpty) + + override def toString: String = super.toString + + def getGraphAddress: List[HostAndPort] = { + val hostAndPorts = new ListBuffer[HostAndPort] + for (address <- graphAddress) { + hostAndPorts.append(HostAndPort.fromString(address)) + } + hostAndPorts.toList + } + + def getMetaAddress: List[HostAndPort] = { + val hostAndPorts = new ListBuffer[HostAndPort] + for (address <- metaAddresses) { + hostAndPorts.append(HostAndPort.fromString(address)) + } + hostAndPorts.toList + } +} + +/** + * UserConfigEntry is used when the client login the nebula graph service. + * + * @param user + * @param password + */ +case class UserConfigEntry(user: String, password: String) { + require(user.trim.nonEmpty && password.trim.nonEmpty) + + override def toString: String = super.toString +} + +/** + * ConnectionConfigEntry + * + * @param timeout + * @param retry + */ +case class ConnectionConfigEntry(timeout: Int, retry: Int) { + require(timeout > 0 && retry > 0) + + override def toString: String = super.toString +} + +/** + * ExecutionConfigEntry + * + * @param timeout + * @param retry + * @param interval + */ +case class ExecutionConfigEntry(timeout: Int, retry: Int, interval: Int) { + require(timeout > 0 && retry > 0 && interval > 0) + + override def toString: String = super.toString +} + +/** + * ErrorConfigEntry + * + * @param errorPath + * @param errorMaxSize + */ +case class ErrorConfigEntry(errorPath: String, errorMaxSize: Int) { + require(errorPath.trim.nonEmpty && errorMaxSize > 0) + + override def toString: String = super.toString +} + +/** + * RateConfigEntry + * + * @param limit + * @param timeout + */ +case class RateConfigEntry(limit: Int, timeout: Int) { + require(limit > 0 && timeout > 0) + + override def toString: String = super.toString +} + +/** + * + */ +object SparkConfigEntry { + def apply(config: Config): SparkConfigEntry = { + val map = mutable.Map[String, String]() + val sparkConfig = config.getObject("spark") + for (key <- sparkConfig.unwrapped().keySet().asScala) { + val sparkKey = s"spark.${key}" + if (config.getAnyRef(sparkKey).isInstanceOf[String]) { + val sparkValue = config.getString(sparkKey) + map += sparkKey -> sparkValue + } else { + for (subKey <- config.getObject(sparkKey).unwrapped().keySet().asScala) { + val key = s"${sparkKey}.${subKey}" + val sparkValue = config.getString(key) + map += key -> sparkValue + } + } + } + SparkConfigEntry(map.toMap) + } +} + +/** + * SparkConfigEntry support key-value pairs for spark session. + * + * @param map + */ +case class SparkConfigEntry(map: Map[String, String]) { + override def toString: String = { + "" + } +} + +case class HiveConfigEntry(waredir: String, + connectionURL: String, + connectionDriverName: String, + connectionUserName: String, + connectionPassWord: String) { + override def toString: String = + s"HiveConfigEntry:{" + + s"waredir=$waredir, " + + s"connectionURL=$connectionURL, " + + s"connectionDriverName=$connectionDriverName, " + + s"connectionUserName=$connectionUserName, " + + s"connectionPassWord=$connectionPassWord}" +} + +/** + * Configs + */ +case class Configs(databaseConfig: DataBaseConfigEntry, + userConfig: UserConfigEntry, + connectionConfig: ConnectionConfigEntry, + executionConfig: ExecutionConfigEntry, + errorConfig: ErrorConfigEntry, + rateConfig: RateConfigEntry, + sparkConfigEntry: SparkConfigEntry, + tagsConfig: List[TagConfigEntry], + edgesConfig: List[EdgeConfigEntry], + hiveConfigEntry: Option[HiveConfigEntry] = None) + +object Configs { + private[this] val LOG = Logger.getLogger(this.getClass) + + private[this] val DEFAULT_CONNECTION_TIMEOUT = 3000 + private[this] val DEFAULT_CONNECTION_RETRY = 3 + private[this] val DEFAULT_EXECUTION_RETRY = 3 + private[this] val DEFAULT_EXECUTION_TIMEOUT = 3000 + private[this] val DEFAULT_EXECUTION_INTERVAL = 3000 + private[this] val DEFAULT_ERROR_OUTPUT_PATH = "/tmp/nebula.writer.errors/" + private[this] val DEFAULT_ERROR_MAX_BATCH_SIZE = Int.MaxValue + private[this] val DEFAULT_RATE_LIMIT = 1024 + private[this] val DEFAULT_RATE_TIMEOUT = 100 + private[this] val DEFAULT_EDGE_RANKING = 0L + private[this] val DEFAULT_BATCH = 2 + private[this] val DEFAULT_PARTITION = -1 + private[this] val DEFAULT_CHECK_POINT_PATH = None + private[this] val DEFAULT_LOCAL_PATH = None + private[this] val DEFAULT_REMOTE_PATH = None + private[this] val DEFAULT_STREAM_INTERVAL = 30 + private[this] val DEFAULT_PARALLEL = 1 + + /** + * + * @param configPath + * @return + */ + def parse(configPath: File): Configs = { + if (!Files.exists(configPath.toPath)) { + throw new IllegalArgumentException(s"${configPath} not exist") + } + + val config = ConfigFactory.parseFile(configPath) + val nebulaConfig = config.getConfig("nebula") + val addresses = nebulaConfig.getStringList("address.graph").asScala.toList + val metaAddresses = nebulaConfig.getStringList("address.meta").asScala.toList + + val space = nebulaConfig.getString("space") + val databaseEntry = DataBaseConfigEntry(addresses, space, metaAddresses) + LOG.info(s"DataBase Config ${databaseEntry}") + + val user = nebulaConfig.getString("user") + val pswd = nebulaConfig.getString("pswd") + val userEntry = UserConfigEntry(user, pswd) + LOG.info(s"User Config ${userEntry}") + + val connectionConfig = getConfigOrNone(nebulaConfig, "connection") + val connectionTimeout = getOrElse(connectionConfig, "timeout", DEFAULT_CONNECTION_TIMEOUT) + val connectionRetry = getOrElse(connectionConfig, "retry", DEFAULT_CONNECTION_RETRY) + val connectionEntry = ConnectionConfigEntry(connectionTimeout, connectionRetry) + LOG.info(s"Connection Config ${connectionConfig}") + + val executionConfig = getConfigOrNone(nebulaConfig, "execution") + val executionTimeout = getOrElse(executionConfig, "timeout", DEFAULT_EXECUTION_TIMEOUT) + val executionRetry = getOrElse(executionConfig, "retry", DEFAULT_EXECUTION_RETRY) + val executionInterval = getOrElse(executionConfig, "interval", DEFAULT_EXECUTION_INTERVAL) + val executionEntry = ExecutionConfigEntry(executionTimeout, executionRetry, executionInterval) + LOG.info(s"Execution Config ${executionEntry}") + + val errorConfig = getConfigOrNone(nebulaConfig, "error") + val errorPath = getOrElse(errorConfig, "output", DEFAULT_ERROR_OUTPUT_PATH) + val errorMaxSize = getOrElse(errorConfig, "max", DEFAULT_ERROR_MAX_BATCH_SIZE) + val errorEntry = ErrorConfigEntry(errorPath, errorMaxSize) + + val rateConfig = getConfigOrNone(nebulaConfig, "rate") + val rateLimit = getOrElse(rateConfig, "limit", DEFAULT_RATE_LIMIT) + val rateTimeout = getOrElse(rateConfig, "timeout", DEFAULT_RATE_TIMEOUT) + val rateEntry = RateConfigEntry(rateLimit, rateTimeout) + + val sparkEntry = SparkConfigEntry(config) + + var hiveEntryOpt: Option[HiveConfigEntry] = None + if (config.hasPath("hive")) { + val waredir = config.getString("hive.waredir") + val connectionURL = config.getString("hive.connectionURL") + val connectionDriverName = config.getString("hive.connectionDriverName") + val connectionUserName = config.getString("hive.connectionUserName") + val connectionPassword = config.getString("hive.connectionPassword") + val hiveEntry = HiveConfigEntry(waredir, + connectionURL, + connectionDriverName, + connectionUserName, + connectionPassword) + hiveEntryOpt = Option(hiveEntry) + } + + val tags = mutable.ListBuffer[TagConfigEntry]() + val tagConfigs = getConfigsOrNone(config, "tags") + if (tagConfigs.isDefined) { + for (tagConfig <- tagConfigs.get.asScala) { + if (!tagConfig.hasPath("name") || + !tagConfig.hasPath("type.source") || + !tagConfig.hasPath("type.sink")) { + LOG.error("The `name` and `type` must be specified") + break() + } + + val tagName = tagConfig.getString("name") + val fields = tagConfig.getStringList("fields").asScala.toList + val nebulaFields = if (tagConfig.hasPath("nebula.fields")) { + tagConfig.getStringList("nebula.fields").asScala.toList + } else { + fields + } + + // You can specified the vertex field name via the config item `vertex` + // If you want to qualified the key policy, you can wrap them into a block. + val vertexField = if (tagConfig.hasPath("vertex.field")) { + tagConfig.getString("vertex.field") + } else { + tagConfig.getString("vertex") + } + + val policyOpt = if (tagConfig.hasPath("vertex.policy")) { + val policy = tagConfig.getString("vertex.policy").toLowerCase + Some(KeyPolicy.withName(policy)) + } else { + None + } + + val sourceCategory = toSourceCategory(tagConfig.getString("type.source")) + val sourceConfig = dataSourceConfig(sourceCategory, tagConfig, nebulaConfig) + LOG.info(s"Source Config ${sourceConfig}") + + val sinkCategory = toSinkCategory(tagConfig.getString("type.sink")) + val sinkConfig = dataSinkConfig(sinkCategory, nebulaConfig) + LOG.info(s"Sink Config ${sourceConfig}") + + val batch = getOrElse(tagConfig, "batch", DEFAULT_BATCH) + val checkPointPath = + if (tagConfig.hasPath("check_point_path")) Some(tagConfig.getString("check_point_path")) + else DEFAULT_CHECK_POINT_PATH + + val localPath = getOptOrElse(tagConfig, "local.path") + val remotePath = getOptOrElse(tagConfig, "remote.path") + + val partition = getOrElse(tagConfig, "partition", DEFAULT_PARTITION) + + LOG.info(s"name ${tagName} batch ${batch}") + val entry = TagConfigEntry(tagName, + sourceConfig, + sinkConfig, + fields, + nebulaFields, + vertexField, + policyOpt, + batch, + partition, + checkPointPath) + LOG.info(s"Tag Config: ${entry}") + tags += entry + } + } + + val edges = mutable.ListBuffer[EdgeConfigEntry]() + val edgeConfigs = getConfigsOrNone(config, "edges") + if (edgeConfigs.isDefined) { + for (edgeConfig <- edgeConfigs.get.asScala) { + if (!edgeConfig.hasPath("name") || + !edgeConfig.hasPath("type.source") || + !edgeConfig.hasPath("type.sink")) { + LOG.error("The `name` and `type`must be specified") + break() + } + + val edgeName = edgeConfig.getString("name") + val fields = edgeConfig.getStringList("fields").asScala.toList + val nebulaFields = if (edgeConfig.hasPath("nebula.fields")) { + edgeConfig.getStringList("nebula.fields").asScala.toList + } else { + fields + } + val isGeo = !edgeConfig.hasPath("source") && + edgeConfig.hasPath("latitude") && + edgeConfig.hasPath("longitude") + + val sourceCategory = toSourceCategory(edgeConfig.getString("type.source")) + val sourceConfig = dataSourceConfig(sourceCategory, edgeConfig, nebulaConfig) + LOG.info(s"Source Config ${sourceConfig}") + + val sinkCategory = toSinkCategory(edgeConfig.getString("type.sink")) + val sinkConfig = dataSinkConfig(sinkCategory, nebulaConfig) + LOG.info(s"Sink Config ${sourceConfig}") + + val sourceField = if (!isGeo) { + if (edgeConfig.hasPath("source.field")) { + edgeConfig.getString("source.field") + } else { + edgeConfig.getString("source") + } + } else { + throw new IllegalArgumentException("Source must be specified") + } + + val sourcePolicy = if (!isGeo) { + if (edgeConfig.hasPath("source.policy")) { + val policy = edgeConfig.getString("source.policy").toLowerCase + Some(KeyPolicy.withName(policy)) + } else { + None + } + } else { + None + } + + val targetField: String = if (edgeConfig.hasPath("target.field")) { + edgeConfig.getString("target.field") + } else { + edgeConfig.getString("target") + } + + val targetPolicy = if (edgeConfig.hasPath("target.policy")) { + val policy = edgeConfig.getString("target.policy").toLowerCase + Some(KeyPolicy.withName(policy)) + } else { + None + } + + val ranking = if (edgeConfig.hasPath("ranking")) { + Some(edgeConfig.getString("ranking")) + } else { + None + } + + val latitude = if (isGeo) { + Some(edgeConfig.getString("latitude")) + } else { + None + } + + val longitude = if (isGeo) { + Some(edgeConfig.getString("longitude")) + } else { + None + } + + val batch = getOrElse(edgeConfig, "batch", DEFAULT_BATCH) + val checkPointPath = + if (edgeConfig.hasPath("check_point_path")) Some(edgeConfig.getString("check_point_path")) + else DEFAULT_CHECK_POINT_PATH + + val partition = getOrElse(edgeConfig, "partition", DEFAULT_PARTITION) + + val localPath = getOptOrElse(edgeConfig, "path.local") + val remotePath = getOptOrElse(edgeConfig, "path.remote") + + val entry = EdgeConfigEntry( + edgeName, + sourceConfig, + sinkConfig, + fields, + nebulaFields, + sourceField, + sourcePolicy, + ranking, + targetField, + targetPolicy, + isGeo, + latitude, + longitude, + batch, + partition, + checkPointPath + ) + LOG.info(s"Edge Config: ${entry}") + edges += entry + } + } + + Configs(databaseEntry, + userEntry, + connectionEntry, + executionEntry, + errorEntry, + rateEntry, + sparkEntry, + tags.toList, + edges.toList, + hiveEntryOpt) + } + + /** + * Use to category name to category value mapping. + * + * @param category name + * @return + */ + private[this] def toSourceCategory(category: String): SourceCategory.Value = { + category.trim.toUpperCase match { + case "PARQUET" => SourceCategory.PARQUET + case "ORC" => SourceCategory.ORC + case "JSON" => SourceCategory.JSON + case "CSV" => SourceCategory.CSV + case "HIVE" => SourceCategory.HIVE + case "NEO4J" => SourceCategory.NEO4J + case "KAFKA" => SourceCategory.KAFKA + case "MYSQL" => SourceCategory.MYSQL + case "PULSAR" => SourceCategory.PULSAR + case "HBASE" => SourceCategory.HBASE + case _ => throw new IllegalArgumentException(s"${category} not support") + } + } + + /** + * Use to sink name to sink value mapping. + * + * @param category name + * @return + */ + private[this] def toSinkCategory(category: String): SinkCategory.Value = { + category.trim.toUpperCase match { + case "CLIENT" => SinkCategory.CLIENT + case "SST" => SinkCategory.SST + case _ => throw new IllegalArgumentException(s"${category} not support") + } + } + + /** + * Use to generate data source config according to category of source. + * + * @param category + * @param config + * @return + */ + private[this] def dataSourceConfig(category: SourceCategory.Value, + config: Config, + nebulaConfig: Config): DataSourceConfigEntry = { + category match { + case SourceCategory.PARQUET => + FileBaseSourceConfigEntry(SourceCategory.PARQUET, config.getString("path")) + case SourceCategory.ORC => + FileBaseSourceConfigEntry(SourceCategory.ORC, config.getString("path")) + case SourceCategory.JSON => + FileBaseSourceConfigEntry(SourceCategory.JSON, config.getString("path")) + case SourceCategory.CSV => + val separator = + if (config.hasPath("separator")) + config.getString("separator") + else "," + val header = + if (config.hasPath("header")) + config.getBoolean("header") + else + false + FileBaseSourceConfigEntry(SourceCategory.CSV, + config.getString("path"), + Some(separator), + Some(header)) + case SourceCategory.HIVE => + HiveSourceConfigEntry(SourceCategory.HIVE, config.getString("exec")) + case SourceCategory.NEO4J => + val name = config.getString("name") + val checkPointPath = + if (config.hasPath("check_point_path")) Some(config.getString("check_point_path")) + else DEFAULT_CHECK_POINT_PATH + val encryption = + if (config.hasPath("encryption")) config.getBoolean("encryption") else false + val parallel = + if (config.hasPath("partition")) config.getInt("partition") else DEFAULT_PARALLEL + if (parallel <= 0) + throw new IllegalArgumentException(s"Can't set neo4j ${name} partition<=0.") + val database = if (config.hasPath("database")) Some(config.getString("database")) else None + Neo4JSourceConfigEntry( + SourceCategory.NEO4J, + config.getString("exec"), + name, + config.getString("server"), + config.getString("user"), + config.getString("password"), + database, + encryption, + parallel, + checkPointPath + ) + case SourceCategory.JANUS_GRAPH => + JanusGraphSourceConfigEntry(SourceCategory.JANUS_GRAPH, "", false) // TODO + case SourceCategory.MYSQL => + MySQLSourceConfigEntry( + SourceCategory.MYSQL, + config.getString("host"), + config.getInt("port"), + config.getString("database"), + config.getString("table"), + config.getString("user"), + config.getString("password"), + getOrElse(config, "sentence", "") + ) + case SourceCategory.KAFKA => + val intervalSeconds = + if (config.hasPath("interval.seconds")) config.getInt("interval.seconds") + else DEFAULT_STREAM_INTERVAL + KafkaSourceConfigEntry(SourceCategory.KAFKA, + intervalSeconds, + config.getString("service"), + config.getString("topic")) + case SourceCategory.PULSAR => + val options = + config.getObject("options").unwrapped.asScala.map(x => x._1 -> x._2.toString).toMap + val intervalSeconds = + if (config.hasPath("interval.seconds")) config.getInt("interval.seconds") + else DEFAULT_STREAM_INTERVAL + PulsarSourceConfigEntry(SourceCategory.PULSAR, + intervalSeconds, + config.getString("service"), + config.getString("admin"), + options) + case SourceCategory.HBASE => + val fields: ListBuffer[String] = new ListBuffer[String] + fields.append(config.getStringList("fields").asScala: _*) + + if (config.hasPath("vertex")) { + fields.append(config.getString("vertex")) + } + if (config.hasPath("source.field")) { + fields.append(config.getString("source.field")) + } + if (config.hasPath("target.field")) { + fields.append(config.getString("target.field")) + } + + HBaseSourceConfigEntry(SourceCategory.HBASE, + config.getString("host"), + config.getString("port"), + config.getString("table"), + config.getString("columnFamily"), + fields.toSet.toList) + case _ => + throw new IllegalArgumentException("Unsupported data source") + } + } + + private[this] def dataSinkConfig(category: SinkCategory.Value, + nebulaConfig: Config): DataSinkConfigEntry = { + category match { + case SinkCategory.CLIENT => + NebulaSinkConfigEntry(SinkCategory.CLIENT, + nebulaConfig.getStringList("address.graph").asScala.toList) + case SinkCategory.SST => + FileBaseSinkConfigEntry(SinkCategory.SST, + nebulaConfig.getString("path.local"), + nebulaConfig.getString("path.remote")) + case _ => + throw new IllegalArgumentException("Unsupported data sink") + } + } + + /** + * Get the config list by the path. + * + * @param config The config. + * @param path The path of the config. + * @return + */ + private[this] def getConfigsOrNone(config: Config, + path: String): Option[java.util.List[_ <: Config]] = { + if (config.hasPath(path)) { + Some(config.getConfigList(path)) + } else { + None + } + } + + /** + * Get the config by the path. + * + * @param config + * @param path + * @return + */ + def getConfigOrNone(config: Config, path: String): Option[Config] = { + if (config.hasPath(path)) { + Some(config.getConfig(path)) + } else { + None + } + } + + /** + * Get the value from config by the path. If the path not exist, return the default value. + * + * @param config The config. + * @param path The path of the config. + * @param defaultValue The default value for the path. + * @return + */ + private[this] def getOrElse[T](config: Config, path: String, defaultValue: T): T = { + if (config.hasPath(path)) { + config.getAnyRef(path).asInstanceOf[T] + } else { + defaultValue + } + } + + private[this] def getOptOrElse(config: Config, path: String): Option[String] = { + if (config.hasPath(path)) { + Some(config.getString(path)) + } else { + None + } + } + + /** + * Get the value from config by the path which is optional. + * If the path not exist, return the default value. + * + * @param config + * @param path + * @param defaultValue + * @tparam T + * @return + */ + private[this] def getOrElse[T](config: Option[Config], path: String, defaultValue: T): T = { + if (config.isDefined && config.get.hasPath(path)) { + config.get.getAnyRef(path).asInstanceOf[T] + } else { + defaultValue + } + } + + /** + * Use to parse command line arguments. + * + * @param args + * @param programName + * @return Argument + */ + def parser(args: Array[String], programName: String): Option[Argument] = { + val parser = new scopt.OptionParser[Argument](programName) { + head(programName, "2.0.0") + + opt[File]('c', "config") + .required() + .valueName("") + .action((x, c) => c.copy(config = x)) + .text("config file") + + opt[Unit]('h', "hive") + .action((_, c) => c.copy(hive = true)) + .text("hive supported") + + opt[Unit]('d', "directly") + .action((_, c) => c.copy(directly = true)) + .text("directly mode") + + opt[Unit]('D', "dry") + .action((_, c) => c.copy(dry = true)) + .text("dry run") + + opt[String]('r', "reload") + .valueName("") + .action((x, c) => c.copy(reload = x)) + .text("reload path") + } + parser.parse(args, Argument()) + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SchemaConfigs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SchemaConfigs.scala new file mode 100644 index 0000000..33a964d --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SchemaConfigs.scala @@ -0,0 +1,145 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.config + +import com.vesoft.nebula.tools.importer.KeyPolicy + +/** + * SchemaConfigEntry is tag/edge super class use to save some basic parameter for importer. + */ +sealed trait SchemaConfigEntry { + + /** nebula tag or edge name */ + def name: String + + /** see{@link DataSourceConfigEntry}*/ + def dataSourceConfigEntry: DataSourceConfigEntry + + /** see{@link DataSinkConfigEntry}*/ + def dataSinkConfigEntry: DataSinkConfigEntry + + /** data source fields which are going to be import to nebula as properties */ + def fields: List[String] + + /** nebula properties which are going to fill value with data source value*/ + def nebulaFields: List[String] + + /** vertex or edge amount of one batch import */ + def batch: Int + + /** spark partition */ + def partition: Int + + /** check point path */ + def checkPointPath: Option[String] +} + +/** + * + * @param name + * @param dataSourceConfigEntry + * @param dataSinkConfigEntry + * @param fields + * @param nebulaFields + * @param vertexField + * @param vertexPolicy + * @param batch + * @param partition + * @param checkPointPath + */ +case class TagConfigEntry(override val name: String, + override val dataSourceConfigEntry: DataSourceConfigEntry, + override val dataSinkConfigEntry: DataSinkConfigEntry, + override val fields: List[String], + override val nebulaFields: List[String], + vertexField: String, + vertexPolicy: Option[KeyPolicy.Value], + override val batch: Int, + override val partition: Int, + override val checkPointPath: Option[String]) + extends SchemaConfigEntry { + require(name.trim.nonEmpty && vertexField.trim.nonEmpty && batch > 0) + + override def toString: String = { + s"Tag name: $name, " + + s"source: $dataSourceConfigEntry, " + + s"sink: $dataSinkConfigEntry, " + + s"vertex field: $vertexField, " + + s"vertex policy: $vertexPolicy, " + + s"batch: $batch, " + + s"partition: $partition." + } +} + +/** + * + * @param name + * @param dataSourceConfigEntry + * @param dataSinkConfigEntry + * @param fields + * @param nebulaFields + * @param sourceField + * @param sourcePolicy + * @param rankingField + * @param targetField + * @param targetPolicy + * @param isGeo + * @param latitude + * @param longitude + * @param batch + * @param partition + * @param checkPointPath + */ +case class EdgeConfigEntry(override val name: String, + override val dataSourceConfigEntry: DataSourceConfigEntry, + override val dataSinkConfigEntry: DataSinkConfigEntry, + override val fields: List[String], + override val nebulaFields: List[String], + sourceField: String, + sourcePolicy: Option[KeyPolicy.Value], + rankingField: Option[String], + targetField: String, + targetPolicy: Option[KeyPolicy.Value], + isGeo: Boolean, + latitude: Option[String], + longitude: Option[String], + override val batch: Int, + override val partition: Int, + override val checkPointPath: Option[String]) + extends SchemaConfigEntry { + require( + name.trim.nonEmpty && sourceField.trim.nonEmpty && + targetField.trim.nonEmpty && batch > 0) + + override def toString: String = { + if (isGeo) { + s"Edge name: $name, " + + s"source: $dataSourceConfigEntry, " + + s"sink: $dataSinkConfigEntry, " + + s"latitude: $latitude, " + + s"longitude: $longitude, " + + s"source field: $sourceField, " + + s"source policy: $sourcePolicy, " + + s"ranking: $rankingField, " + + s"target field: $targetField, " + + s"target policy: $targetPolicy, " + + s"batch: $batch, " + + s"partition: $partition." + } else { + s"Edge name: $name, " + + s"source: $dataSourceConfigEntry, " + + s"sink: $dataSinkConfigEntry, " + + s"source field: $sourceField, " + + s"source policy: $sourcePolicy, " + + s"ranking: $rankingField, " + + s"target field: $targetField, " + + s"target policy: $targetPolicy, " + + s"batch: $batch, " + + s"partition: $partition." + } + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SinkConfigs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SinkConfigs.scala new file mode 100644 index 0000000..3e8e093 --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SinkConfigs.scala @@ -0,0 +1,49 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.config + +/** + * SinkCategory is used to expression the writer's type. + * SST is not supported yet. + */ +object SinkCategory extends Enumeration { + type Type = Value + + val CLIENT = Value("CLIENT") + val SST = Value("SST") +} + +class SinkCategory + +/** + * DataSinkConfigEntry + */ +sealed trait DataSinkConfigEntry { + def category: SinkCategory.Value +} + +/** + * FileBaseSinkConfigEntry + */ +case class FileBaseSinkConfigEntry(override val category: SinkCategory.Value, + localPath: String, + remotePath: String) + extends DataSinkConfigEntry { + override def toString: String = { + s"File sink: from ${localPath} to ${remotePath}" + } +} + +/** + * NebulaSinkConfigEntry use to specified the nebula service's address. + */ +case class NebulaSinkConfigEntry(override val category: SinkCategory.Value, addresses: List[String]) + extends DataSinkConfigEntry { + override def toString: String = { + s"Nebula sink addresses: ${addresses.mkString("[", ", ", "]")}" + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SourceConfigs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SourceConfigs.scala new file mode 100644 index 0000000..6c51b09 --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SourceConfigs.scala @@ -0,0 +1,219 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.config + +import com.vesoft.nebula.tools.importer.utils.NebulaUtils + +/** + * Category use to explain the data source which the Spark application could reading. + */ +object SourceCategory extends Enumeration { + type Type = Value + + val PARQUET = Value("PARQUET") + val ORC = Value("ORC") + val JSON = Value("JSON") + val CSV = Value("CSV") + val TEXT = Value("TEXT") + + val HIVE = Value("HIVE") + val NEO4J = Value("NEO4J") + val JANUS_GRAPH = Value("JANUS GRAPH") + val MYSQL = Value("MYSQL") + val HBASE = Value("HBASE") + + val SOCKET = Value("SOCKET") + val KAFKA = Value("KAFKA") + val PULSAR = Value("PULSAR") +} + +class SourceCategory + +/** + * DataSourceConfigEntry + */ +sealed trait DataSourceConfigEntry { + def category: SourceCategory.Value +} + +sealed trait FileDataSourceConfigEntry extends DataSourceConfigEntry { + def path: String +} + +sealed trait ServerDataSourceConfigEntry extends DataSourceConfigEntry { + def sentence: String +} + +sealed trait StreamingDataSourceConfigEntry extends DataSourceConfigEntry { + def intervalSeconds: Int +} + +/** + * FileBaseSourceConfigEntry + * + * @param category + * @param path + * @param separator + * @param header + */ +case class FileBaseSourceConfigEntry(override val category: SourceCategory.Value, + override val path: String, + separator: Option[String] = None, + header: Option[Boolean] = None) + extends FileDataSourceConfigEntry { + override def toString: String = { + s"File source path: ${path}, separator: ${separator}, header: ${header}" + } +} + +/** + * HiveSourceConfigEntry + * + * @param sentence + */ +case class HiveSourceConfigEntry(override val category: SourceCategory.Value, + override val sentence: String) + extends ServerDataSourceConfigEntry { + require(sentence.trim.nonEmpty) + + override def toString: String = { + s"Hive source exec: ${sentence}" + } +} + +/** + * Neo4JSourceConfigEntry + * + * @param sentence + * @param name + * @param server + * @param user + * @param password + * @param database + * @param encryption + * @param parallel + * @param checkPointPath use save resume data dir path. + */ +case class Neo4JSourceConfigEntry(override val category: SourceCategory.Value, + override val sentence: String, + name: String, + server: String, + user: String, + password: String, + database: Option[String], + encryption: Boolean, + parallel: Int, + checkPointPath: Option[String]) + extends ServerDataSourceConfigEntry { + require(sentence.trim.nonEmpty && user.trim.nonEmpty && parallel > 0) + + override def toString: String = { + s"Neo4J source address: ${server}, user: ${user}, password: ${password}, encryption: ${encryption}," + + s" checkPointPath: ${checkPointPath}, exec: ${sentence}, parallel: ${parallel}, database: ${database}" + } +} + +case class JanusGraphSourceConfigEntry(override val category: SourceCategory.Value, + override val sentence: String, + isEdge: Boolean) + extends ServerDataSourceConfigEntry { + override def toString: String = { + s"Janus graph source" + } +} + +/** + * MySQLSourceConfigEntry + * + * @param host + * @param port + * @param database + * @param table + * @param user + * @param password + * @param sentence + * @return + */ +case class MySQLSourceConfigEntry(override val category: SourceCategory.Value, + host: String, + port: Int, + database: String, + table: String, + user: String, + password: String, + override val sentence: String) + extends ServerDataSourceConfigEntry { + require( + host.trim.length != 0 && port > 0 && database.trim.length > 0 && table.trim.length > 0 && user.trim.length > 0) + + override def toString: String = { + s"MySql source host: ${host}, port: ${port}, database: ${database}, table: ${table}, " + + s"user: ${user}, password: ${password}, sentence: ${sentence}" + } +} + +/** + * TODO: Support more config item about Kafka Consumer + * + * @param server + * @param topic + */ +case class KafkaSourceConfigEntry(override val category: SourceCategory.Value, + override val intervalSeconds: Int, + server: String, + topic: String) + extends StreamingDataSourceConfigEntry { + require(server.trim.nonEmpty && topic.trim.nonEmpty) + + override def toString: String = { + s"Kafka source server: ${server} topic:${topic}" + } +} + +/** + * PulsarSourceConfigEntry + * + * @param serviceUrl + * @param adminUrl use to get data schema. + * @param options + * @return + */ +case class PulsarSourceConfigEntry(override val category: SourceCategory.Value, + override val intervalSeconds: Int, + serviceUrl: String, + adminUrl: String, + options: Map[String, String]) + extends StreamingDataSourceConfigEntry { + require(serviceUrl.trim.nonEmpty && adminUrl.trim.nonEmpty && intervalSeconds >= 0) + require(options.keys.count(key => List("topic", "topics", "topicsPattern").contains(key)) == 1) + + override def toString: String = { + s"Pulsar source service url: ${serviceUrl} admin url: ${adminUrl} options: ${options}" + } +} + +/** + * HBaseSourceConfigEntry + * + */ +case class HBaseSourceConfigEntry(override val category: SourceCategory.Value, + host: String, + port: String, + table: String, + columnFamily: String, + fields: List[String]) + extends ServerDataSourceConfigEntry() { + + require(host.trim.length != 0 && port.trim.length != 0 && NebulaUtils + .isNumic(port.trim) && table.trim.length > 0 && table.trim.length > 0 && columnFamily.trim.length > 0) + + override val sentence: String = null + + override def toString: String = { + s"HBase source host: $host, port: $port, table: $table" + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/package.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/package.scala new file mode 100644 index 0000000..8ffcbd4 --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/package.scala @@ -0,0 +1,92 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools + +import com.google.common.base.Optional +import com.google.common.util.concurrent.ListenableFuture +import scala.collection.mutable.ListBuffer + +package object importer { + + type GraphSpaceID = Int + type PartitionID = Int + type TagID = Int + type EdgeType = Int + type SchemaID = (TagID, EdgeType) + type TagVersion = Long + type EdgeVersion = Long + type SchemaVersion = (TagVersion, EdgeVersion) + type VertexID = Long + type VertexIDSlice = String + type EdgeRank = Long + type PropertyNames = List[String] + type PropertyValues = List[Any] + type ProcessResult = ListBuffer[WriterResult] + type WriterResult = ListenableFuture[Optional[Integer]] + + case class Vertex(vertexID: VertexIDSlice, values: PropertyValues) { + + def propertyValues = values.mkString(", ") + + override def toString: String = { + s"Vertex ID: ${vertexID}, " + + s"Values: ${values.mkString(", ")}" + } + } + + case class Vertices(names: PropertyNames, + values: List[Vertex], + policy: Option[KeyPolicy.Value] = None) { + + def propertyNames: String = names.mkString(",") + + override def toString: String = { + s"Vertices: " + + s"Property Names: ${names.mkString(", ")}" + + s"Vertex Values: ${values.mkString(", ")} " + + s"with policy ${policy}" + } + } + + case class Edge(source: VertexIDSlice, + destination: VertexIDSlice, + ranking: Option[EdgeRank], + values: PropertyValues) { + + def this(source: VertexIDSlice, destination: VertexIDSlice, values: PropertyValues) = { + this(source, destination, None, values) + } + + def propertyValues: String = values.mkString(", ") + + override def toString: String = { + s"Edge: ${source}->${destination}@${ranking} values: ${propertyValues}" + } + } + + case class Edges(names: PropertyNames, + values: List[Edge], + sourcePolicy: Option[KeyPolicy.Value] = None, + targetPolicy: Option[KeyPolicy.Value] = None) { + def propertyNames: String = names.mkString(",") + + override def toString: String = { + "Edges:" + + s"Property Names: ${names.mkString(", ")}" + + s"with source policy ${sourcePolicy}" + + s"with target policy ${targetPolicy}" + } + } + + object KeyPolicy extends Enumeration { + type POLICY = Value + val HASH = Value("hash") + val UUID = Value("uuid") + } + + case class Offset(start: Long, size: Long) +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.scala new file mode 100644 index 0000000..03aa3db --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.scala @@ -0,0 +1,164 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.processor + +import com.google.common.geometry.{S2CellId, S2LatLng} +import com.vesoft.nebula.tools.importer.config.{ + Configs, + EdgeConfigEntry, + SinkCategory, + StreamingDataSourceConfigEntry +} +import com.vesoft.nebula.tools.importer.utils.NebulaUtils +import com.vesoft.nebula.tools.importer.{ + Edge, + Edges, + ErrorHandler, + GraphProvider, + MetaProvider, + VidType +} +import org.apache.log4j.Logger +import com.vesoft.nebula.tools.importer.writer.NebulaGraphClientWriter +import org.apache.commons.lang.StringEscapeUtils +import org.apache.spark.sql.streaming.Trigger +import org.apache.spark.sql.{DataFrame, Encoders} +import org.apache.spark.util.LongAccumulator + +import scala.collection.mutable.ArrayBuffer + +class EdgeProcessor(data: DataFrame, + edgeConfig: EdgeConfigEntry, + fieldKeys: List[String], + nebulaKeys: List[String], + config: Configs, + batchSuccess: LongAccumulator, + batchFailure: LongAccumulator) + extends Processor { + + @transient + private[this] lazy val LOG = Logger.getLogger(this.getClass) + + private[this] val DEFAULT_MIN_CELL_LEVEL = 10 + private[this] val DEFAULT_MAX_CELL_LEVEL = 18 + + private def processEachPartition(iterator: Iterator[Edge]): Unit = { + val graphProvider = new GraphProvider(config.databaseConfig.getGraphAddress) + + val writer = new NebulaGraphClientWriter(config.databaseConfig, + config.userConfig, + config.connectionConfig, + config.executionConfig.retry, + config.rateConfig, + edgeConfig, + graphProvider) + val errorBuffer = ArrayBuffer[String]() + + writer.prepare() + // batch write tags + iterator.grouped(edgeConfig.batch).foreach { edge => + val edges = Edges(nebulaKeys, edge.toList, edgeConfig.sourcePolicy, edgeConfig.targetPolicy) + val failStatement = writer.writeEdges(edges) + if (failStatement == null) { + batchSuccess.add(1) + } else { + errorBuffer.append(failStatement) + batchFailure.add(1) + } + + if (errorBuffer.nonEmpty) { + ErrorHandler.save(errorBuffer, s"${config.errorConfig.errorPath}/${edgeConfig.name}") + errorBuffer.clear() + } + } + writer.close() + } + + override def process(): Unit = { + + val address = config.databaseConfig.getMetaAddress + val space = config.databaseConfig.space + + val metaProvider = new MetaProvider(address) + val fieldTypeMap = NebulaUtils.getDataSourceFieldType(edgeConfig, space, metaProvider) + val isVidStringType = metaProvider.getVidType(space) == VidType.STRING + + if (edgeConfig.dataSinkConfigEntry.category == SinkCategory.SST) {} else { + val edgeFrame = data + .map { row => + var sourceField = if (!edgeConfig.isGeo) { + val sourceIndex = row.schema.fieldIndex(edgeConfig.sourceField) + row.get(sourceIndex).toString + } else { + val lat = row.getDouble(row.schema.fieldIndex(edgeConfig.latitude.get)) + val lng = row.getDouble(row.schema.fieldIndex(edgeConfig.longitude.get)) + indexCells(lat, lng).mkString(",") + } + + if (edgeConfig.sourcePolicy.isEmpty) { + // process string type vid + if (isVidStringType) { + if (StringEscapeUtils.escapeJava(sourceField).contains('\\')) { + sourceField = StringEscapeUtils.escapeJava(sourceField).mkString("\"", "", "\"") + } else { + sourceField = sourceField.mkString("\"", "", "\"") + } + } + } + + val targetIndex = row.schema.fieldIndex(edgeConfig.targetField) + var targetField = row.get(targetIndex).toString + if (edgeConfig.targetPolicy.isEmpty) { + // process string type vid + if (isVidStringType) { + if (StringEscapeUtils.escapeJava(targetField).contains('\\')) { + targetField = StringEscapeUtils.escapeJava(targetField).mkString("\"", "", "\"") + } else { + targetField = targetField.mkString("\"", "", "\"") + } + } + } + + val values = for { + property <- fieldKeys if property.trim.length != 0 + } yield extraValue(row, property, fieldTypeMap) + + if (edgeConfig.rankingField.isDefined) { + val index = row.schema.fieldIndex(edgeConfig.rankingField.get) + val ranking = row.get(index).toString + assert(NebulaUtils.isNumic(ranking), s"Not support non-Numeric type for ranking field") + + Edge(sourceField, targetField, Some(ranking.toLong), values) + } else { + Edge(sourceField, targetField, None, values) + } + }(Encoders.kryo[Edge]) + + // streaming write + if (data.isStreaming) { + val streamingDataSourceConfig = + edgeConfig.dataSourceConfigEntry.asInstanceOf[StreamingDataSourceConfigEntry] + edgeFrame.writeStream + .foreachBatch((edges, batchId) => { + LOG.info(s"${edgeConfig.name} edge start batch ${batchId}.") + edges.foreachPartition(processEachPartition _) + }) + .trigger(Trigger.ProcessingTime(s"${streamingDataSourceConfig.intervalSeconds} seconds")) + .start() + .awaitTermination() + } else + edgeFrame.foreachPartition(processEachPartition _) + } + } + + private[this] def indexCells(lat: Double, lng: Double): IndexedSeq[Long] = { + val coordinate = S2LatLng.fromDegrees(lat, lng) + val s2CellId = S2CellId.fromLatLng(coordinate) + for (index <- DEFAULT_MIN_CELL_LEVEL to DEFAULT_MAX_CELL_LEVEL) + yield s2CellId.parent(index).id() + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/Processor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/Processor.scala new file mode 100644 index 0000000..c04a909 --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/Processor.scala @@ -0,0 +1,77 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.processor + +import com.vesoft.nebula.meta.PropertyType +import com.vesoft.nebula.tools.importer.utils.HDFSUtils +import org.apache.commons.lang.StringEscapeUtils +import org.apache.spark.sql.Row +import org.apache.spark.sql.types.{IntegerType, LongType, StringType} + +/** + * processor is a converter. + * It is responsible for converting the dataframe row data into Nebula Graph's vertex or edge, + * and submit data to writer. + */ +trait Processor extends Serializable { + + /** + * process dataframe to vertices or edges + */ + def process(): Unit + + /** + * handle special types of attributes + * + * String type: add "" for attribute value, if value contains escape symbol,then keep it. + * + * Date type: add date() function for attribute value. + * eg: convert attribute value 2020-01-01 to date("2020-01-01") + * + * Time type: add time() function for attribute value. + * eg: convert attribute value 12:12:12:1111 to time("12:12:12:1111") + * + * DataTime type: add datetime() function for attribute value. + * eg: convert attribute value 2020-01-01T22:30:40 to datetime("2020-01-01T22:30:40") + */ + def extraValue(row: Row, + field: String, + fieldTypeMap: Map[String, Int], + toBytes: Boolean = false): Any = { + val index = row.schema.fieldIndex(field) + + if (row.isNullAt(index)) return null + + fieldTypeMap(field) match { + case PropertyType.STRING => { + val result = if (StringEscapeUtils.escapeJava(row.getString(index)).contains('\\')) { + StringEscapeUtils.escapeJava(row.get(index).toString).mkString("\"", "", "\"") + } else { + row.get(index).toString.mkString("\"", "", "\"") + } + if (toBytes) result.getBytes else result + } + case PropertyType.DATE => "date(\"" + row.get(index) + "\")" + case PropertyType.DATETIME => "datatime(\"" + row.get(index) + "\")" + case PropertyType.TIME => "time(\"" + row.get(index) + "\")" + case _ => row.get(index) + } + } + + def fetchOffset(path: String): Long = { + HDFSUtils.getContent(path).toLong + } + + def getLong(row: Row, field: String): Long = { + val index = row.schema.fieldIndex(field) + row.schema.fields(index).dataType match { + case LongType => row.getLong(index) + case IntegerType => row.getInt(index).toLong + case StringType => row.getString(index).toLong + } + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/ReloadProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/ReloadProcessor.scala new file mode 100644 index 0000000..a7f3fc3 --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/ReloadProcessor.scala @@ -0,0 +1,50 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.processor + +import com.vesoft.nebula.tools.importer.{ErrorHandler, GraphProvider} +import com.vesoft.nebula.tools.importer.config.Configs +import org.apache.spark.sql.{DataFrame, Row} +import org.apache.spark.util.LongAccumulator + +import scala.collection.mutable.ArrayBuffer + +class ReloadProcessor(data: DataFrame, + config: Configs, + batchSuccess: LongAccumulator, + batchFailure: LongAccumulator) + extends Processor { + + override def process(): Unit = { + data.foreachPartition(processEachPartition(_)) + } + + private def processEachPartition(iterator: Iterator[Row]): Unit = { + val graphProvider = new GraphProvider(config.databaseConfig.getGraphAddress) + val session = graphProvider.getGraphClient(config.userConfig) + if (session == null) { + throw new IllegalArgumentException("connect to graph failed.") + } + + val errorBuffer = ArrayBuffer[String]() + + iterator.foreach(row => { + val exec = row.getString(0) + val result = session.execute(exec) + if (result == null || !result.isSucceeded) { + errorBuffer.append(exec) + batchFailure.add(1) + } else { + batchSuccess.add(1) + } + if (errorBuffer.nonEmpty) { + ErrorHandler.save(errorBuffer, s"${config.errorConfig.errorPath}/reload") + errorBuffer.clear() + } + }) + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.scala new file mode 100644 index 0000000..b72e906 --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.scala @@ -0,0 +1,145 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.processor + +import com.vesoft.nebula.tools.importer.config.{ + Configs, + SinkCategory, + StreamingDataSourceConfigEntry, + TagConfigEntry +} +import com.vesoft.nebula.tools.importer.utils.{NebulaUtils} +import com.vesoft.nebula.tools.importer.{ + ErrorHandler, + GraphProvider, + MetaProvider, + Vertex, + Vertices, + VidType +} +import org.apache.log4j.Logger +import com.vesoft.nebula.tools.importer.writer.{NebulaGraphClientWriter} +import org.apache.commons.lang.StringEscapeUtils +import org.apache.spark.sql.streaming.Trigger +import org.apache.spark.sql.{DataFrame, Encoders} +import org.apache.spark.util.LongAccumulator + +import scala.collection.mutable.ArrayBuffer + +/** + * + * @param data + * @param tagConfig + * @param fieldKeys + * @param nebulaKeys + * @param config + * @param batchSuccess + * @param batchFailure + */ +class VerticesProcessor(data: DataFrame, + tagConfig: TagConfigEntry, + fieldKeys: List[String], + nebulaKeys: List[String], + config: Configs, + batchSuccess: LongAccumulator, + batchFailure: LongAccumulator) + extends Processor { + + @transient + private[this] lazy val LOG = Logger.getLogger(this.getClass) + + private def processEachPartition(iterator: Iterator[Vertex]): Unit = { + val graphProvider = new GraphProvider(config.databaseConfig.getGraphAddress) + + val writer = new NebulaGraphClientWriter(config.databaseConfig, + config.userConfig, + config.connectionConfig, + config.executionConfig.retry, + config.rateConfig, + tagConfig, + graphProvider) + + val errorBuffer = ArrayBuffer[String]() + + writer.prepare() + // batch write tags + iterator.grouped(tagConfig.batch).foreach { vertex => + val vertices = Vertices(nebulaKeys, vertex.toList, tagConfig.vertexPolicy) + val failStatement = writer.writeVertices(vertices) + if (failStatement == null) { + batchSuccess.add(1) + } else { + errorBuffer.append(failStatement) + batchFailure.add(1) + } + + if (errorBuffer.nonEmpty) { + ErrorHandler.save(errorBuffer, s"${config.errorConfig.errorPath}/${tagConfig.name}") + errorBuffer.clear() + } + } + + writer.close() + graphProvider.close() + } + + override def process(): Unit = { + + val address = config.databaseConfig.getMetaAddress + val space = config.databaseConfig.space + + val metaProvider = new MetaProvider(address) + val fieldTypeMap = NebulaUtils.getDataSourceFieldType(tagConfig, space, metaProvider) + val isVidStringType = metaProvider.getVidType(space) == VidType.STRING + + if (tagConfig.dataSinkConfigEntry.category == SinkCategory.SST) {} else { + val vertices = data + .map { row => + val vertexID = { + val index = row.schema.fieldIndex(tagConfig.vertexField) + if (tagConfig.vertexPolicy.isEmpty) { + // process string type vid + if (isVidStringType) { + val value = row.get(index).toString + if (StringEscapeUtils.escapeJava(value).contains('\\')) { + StringEscapeUtils.escapeJava(value).mkString("\"", "", "\"") + } else { + value.mkString("\"", "", "\"") + } + } else { + // process int type vid + assert(NebulaUtils.isNumic(row.get(index).toString)) + row.get(index).toString + } + } else { + row.get(index).toString + } + } + + val values = for { + property <- fieldKeys if property.trim.length != 0 + } yield extraValue(row, property, fieldTypeMap) + Vertex(vertexID, values) + }(Encoders.kryo[Vertex]) + + // streaming write + if (data.isStreaming) { + val streamingDataSourceConfig = + tagConfig.dataSourceConfigEntry.asInstanceOf[StreamingDataSourceConfigEntry] + vertices.writeStream + .foreachBatch((vertexSet, batchId) => { + LOG.info(s"${tagConfig.name} tag start batch ${batchId}.") + vertexSet.foreachPartition(processEachPartition _) + }) + .trigger(Trigger.ProcessingTime(s"${streamingDataSourceConfig.intervalSeconds} seconds")) + .start() + .awaitTermination() + } else + vertices.foreachPartition(processEachPartition _) + } + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/FileBaseReader.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/FileBaseReader.scala new file mode 100644 index 0000000..06ac879 --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/FileBaseReader.scala @@ -0,0 +1,115 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.reader + +import com.vesoft.nebula.tools.importer.config.FileBaseSourceConfigEntry +import org.apache.spark.sql.catalyst.encoders.RowEncoder +import org.apache.spark.sql.types.StructType +import org.apache.spark.sql.{DataFrame, Row, SparkSession} + +/** + * The FileBaseReader is the abstract class for HDFS file reader. + * + * @param session + * @param path + */ +abstract class FileBaseReader(val session: SparkSession, val path: String) extends Reader { + + require(path.trim.nonEmpty) + + override def close(): Unit = { + session.close() + } +} + +/** + * The ParquetReader extend the FileBaseReader and support read parquet file from HDFS. + * + * @param session + * @param parquetConfig + */ +class ParquetReader(override val session: SparkSession, parquetConfig: FileBaseSourceConfigEntry) + extends FileBaseReader(session, parquetConfig.path) { + + override def read(): DataFrame = { + session.read.parquet(path) + } +} + +/** + * The ORCReader extend the FileBaseReader and support read orc file from HDFS. + * + * @param session + * @param orcConfig + */ +class ORCReader(override val session: SparkSession, orcConfig: FileBaseSourceConfigEntry) + extends FileBaseReader(session, orcConfig.path) { + + override def read(): DataFrame = { + session.read.orc(path) + } +} + +/** + * The JSONReader extend the FileBaseReader and support read json file from HDFS. + * + * @param session + * @param jsonConfig + */ +class JSONReader(override val session: SparkSession, jsonConfig: FileBaseSourceConfigEntry) + extends FileBaseReader(session, jsonConfig.path) { + + override def read(): DataFrame = { + session.read.json(path) + } +} + +/** + * The CSVReader extend the FileBaseReader and support read csv file from HDFS. + * All types of the structure are StringType. + * + * @param session + * @param csvConfig + */ +class CSVReader(override val session: SparkSession, csvConfig: FileBaseSourceConfigEntry) + extends FileBaseReader(session, csvConfig.path) { + + override def read(): DataFrame = { + session.read + .option("delimiter", csvConfig.separator.get) + .option("header", csvConfig.header.get) + .option("inferSchema", true) + .csv(path) + } +} + +/** + * The CustomReader extend the FileBaseReader and support read text file from HDFS. + * Transformation is a function convert a line into Row. + * The structure of the row should be specified. + * + * @param session + * @param customConfig + * @param transformation + * @param structType + */ +abstract class CustomReader(override val session: SparkSession, + customConfig: FileBaseSourceConfigEntry, + transformation: String => Row, + filter: Row => Boolean, + structType: StructType) + extends FileBaseReader(session, customConfig.path) { + + override def read(): DataFrame = { + val encoder = RowEncoder.apply(structType) + session.read + .text(path) + .filter(!_.getString(0).isEmpty) + .map(row => transformation(row.getString(0)))(encoder) + .filter(filter) + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/Reader.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/Reader.scala new file mode 100644 index 0000000..3fae084 --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/Reader.scala @@ -0,0 +1,64 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.reader + +import com.vesoft.nebula.tools.importer.Offset +import com.vesoft.nebula.tools.importer.utils.HDFSUtils +import org.apache.spark.sql.{DataFrame, SparkSession} + +/** + * The Reader is used for create a DataFrame from the source. Such as Hive or HDFS. + */ +trait Reader extends Serializable { + def session: SparkSession + + def read(): DataFrame + + def close(): Unit +} + +trait CheckPointSupport extends Serializable { + + def getOffsets(totalCount: Long, + parallel: Int, + checkPointPath: Option[String], + checkPointNamePrefix: String): List[Offset] = { + if (totalCount <= 0) + throw new RuntimeException(s"${checkPointNamePrefix}: return data count<=0") + + val batchSizes = List.fill((totalCount % parallel).toInt)(totalCount / parallel + 1) ::: List + .fill((parallel - totalCount % parallel).toInt)(totalCount / parallel) + + val startOffsets = batchSizes.scanLeft(0L)(_ + _).init + + val checkPointOffsets = checkPointPath match { + case Some(path) => + val files = Range(0, parallel).map(i => s"${path}/${checkPointNamePrefix}.${i}").toList + if (files.forall(HDFSUtils.exists)) + files.map(HDFSUtils.getContent(_).trim.toLong).sorted + else startOffsets + case _ => startOffsets + } + + if (checkPointOffsets.zip(startOffsets).exists(x => x._1 < x._2)) + throw new RuntimeException( + s"Check Point file maybe previous. Please delete ${checkPointPath}/${checkPointNamePrefix}.* file") + + val eachPartitionLimit = { + batchSizes + .zip(startOffsets.zip(checkPointOffsets)) + .map(x => { + x._1 - (x._2._2 - x._2._1) + }) + } + val offsets = checkPointOffsets.zip(eachPartitionLimit).map(x => Offset(x._1, x._2)) + if (offsets.exists(_.size < 0L)) + throw new RuntimeException( + s"Check point file maybe broken. Please delete ${checkPointPath}/${checkPointNamePrefix}.* file") + offsets + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/ServerBaseReader.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/ServerBaseReader.scala new file mode 100644 index 0000000..71fe14a --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/ServerBaseReader.scala @@ -0,0 +1,249 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.reader + +import com.google.common.collect.Maps +import com.vesoft.nebula.tools.importer.config._ +import com.vesoft.nebula.tools.importer.utils.HDFSUtils +import org.apache.hadoop.hbase.HBaseConfiguration +import org.apache.hadoop.hbase.client.Result +import org.apache.hadoop.hbase.io.ImmutableBytesWritable +import org.apache.hadoop.hbase.mapreduce.TableInputFormat +import org.apache.hadoop.hbase.util.Bytes +import org.apache.log4j.Logger +import org.apache.spark.TaskContext +import org.apache.spark.rdd.RDD +import org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema +import org.apache.spark.sql.types.{DataTypes, StructType} +import org.apache.spark.sql.{DataFrame, Row, SparkSession} +import org.apache.tinkerpop.gremlin.process.computer.clustering.peerpressure.{ + ClusterCountMapReduce, + PeerPressureVertexProgram +} +import org.apache.tinkerpop.gremlin.spark.process.computer.SparkGraphComputer +import org.apache.tinkerpop.gremlin.spark.structure.io.PersistedOutputRDD +import org.apache.tinkerpop.gremlin.structure.util.GraphFactory +import org.neo4j.driver.{AuthTokens, GraphDatabase} +import org.neo4j.spark.dataframe.CypherTypes +import org.neo4j.spark.utils.Neo4jSessionAwareIterator +import org.neo4j.spark.{Executor, Neo4jConfig} +import scala.collection.JavaConverters._ +import scala.collection.mutable.ListBuffer + +/** + * ServerBaseReader is the abstract class of + * It include a spark session and a sentence which will sent to service. + * @param session + * @param sentence + */ +abstract class ServerBaseReader(override val session: SparkSession, val sentence: String) + extends Reader { + + override def close(): Unit = { + session.close() + } +} + +/** + * HiveReader extends the @{link ServerBaseReader}. + * The HiveReader reading data from Apache Hive via sentence. + * @param session + * @param hiveConfig + */ +class HiveReader(override val session: SparkSession, hiveConfig: HiveSourceConfigEntry) + extends ServerBaseReader(session, hiveConfig.sentence) { + override def read(): DataFrame = { + session.sql(sentence) + } +} + +/** + * The MySQLReader extends the ServerBaseReader. + * The MySQLReader reading data from MySQL via sentence. + * + * @param session + * @param mysqlConfig + */ +class MySQLReader(override val session: SparkSession, mysqlConfig: MySQLSourceConfigEntry) + extends ServerBaseReader(session, mysqlConfig.sentence) { + override def read(): DataFrame = { + val url = + s"jdbc:mysql://${mysqlConfig.host}:${mysqlConfig.port}/${mysqlConfig.database}?useUnicode=true&characterEncoding=utf-8" + session.read + .format("jdbc") + .option("url", url) + .option("dbtable", mysqlConfig.table) + .option("user", mysqlConfig.user) + .option("password", mysqlConfig.password) + .load() + } +} + +/** + * Neo4JReader extends the ServerBaseReader + * this reader support checkpoint by sacrificing performance + * @param session + * @param neo4jConfig + */ +class Neo4JReader(override val session: SparkSession, neo4jConfig: Neo4JSourceConfigEntry) + extends ServerBaseReader(session, neo4jConfig.sentence) + with CheckPointSupport { + + @transient lazy private val LOG = Logger.getLogger(this.getClass) + + override def read(): DataFrame = { + if (!neo4jConfig.sentence.toUpperCase.contains("ORDER")) + LOG.warn( + "We strongly suggest the cypher sentence must use `order by` clause.\n" + + "Because the `skip` clause in partition no guarantees are made on the order of the result unless the query specifies the ORDER BY clause") + val totalCount: Long = { + val returnIndex = neo4jConfig.sentence.toUpperCase.lastIndexOf("RETURN") + "RETURN".length + val countSentence = neo4jConfig.sentence.substring(0, returnIndex) + " count(*)" + val driver = + GraphDatabase.driver(s"${neo4jConfig.server}", + AuthTokens.basic(neo4jConfig.user, neo4jConfig.password)) + val neo4JSession = driver.session() + neo4JSession.run(countSentence).single().get(0).asLong() + } + + val offsets = + getOffsets(totalCount, neo4jConfig.parallel, neo4jConfig.checkPointPath, neo4jConfig.name) + LOG.info(s"${neo4jConfig.name} offsets: ${offsets.mkString(",")}") + if (offsets.forall(_.size == 0L)) { + LOG.warn(s"${neo4jConfig.name} already write done from check point.") + return session.createDataFrame(session.sparkContext.emptyRDD[Row], new StructType()) + } + + val config = Neo4jConfig(neo4jConfig.server, + neo4jConfig.user, + Some(neo4jConfig.password), + neo4jConfig.database, + neo4jConfig.encryption) + + val rdd = session.sparkContext + .parallelize(offsets, offsets.size) + .flatMap(offset => { + if (neo4jConfig.checkPointPath.isDefined) { + val path = + s"${neo4jConfig.checkPointPath.get}/${neo4jConfig.name}.${TaskContext.getPartitionId()}" + HDFSUtils.saveContent(path, offset.start.toString) + } + val query = s"${neo4jConfig.sentence} SKIP ${offset.start} LIMIT ${offset.size}" + val result = new Neo4jSessionAwareIterator(config, query, Maps.newHashMap(), false) + val fields = if (result.hasNext) result.peek().keys().asScala else List() + val schema = + if (result.hasNext) + StructType( + fields + .map(k => (k, result.peek().get(k).`type`())) + .map(keyType => CypherTypes.field(keyType))) + else new StructType() + result.map(record => { + val row = new Array[Any](record.keys().size()) + for (i <- row.indices) + row.update(i, Executor.convert(record.get(i).asObject())) + new GenericRowWithSchema(values = row, schema).asInstanceOf[Row] + }) + }) + + if (rdd.isEmpty()) + throw new RuntimeException( + "Please check your cypher sentence. because use it search nothing!") + val schema = rdd.repartition(1).first().schema + session.createDataFrame(rdd, schema) + } +} + +/** + * JanusGraphReader extends the link ServerBaseReader + * @param session + * @param janusGraphConfig + */ +class JanusGraphReader(override val session: SparkSession, + janusGraphConfig: JanusGraphSourceConfigEntry) + extends ServerBaseReader(session, "") + with CheckPointSupport { + + override def read(): DataFrame = { + val graph = GraphFactory.open("conf/hadoop/hadoop-gryo.properties") + graph.configuration().setProperty("gremlin.hadoop.graphWriter", classOf[PersistedOutputRDD]) + graph.configuration().setProperty("gremlin.spark.persistContext", true) + + val result = graph + .compute(classOf[SparkGraphComputer]) + .program(PeerPressureVertexProgram.build().create(graph)) + .mapReduce(ClusterCountMapReduce.build().memoryKey("clusterCount").create()) + .submit() + .get() + + if (janusGraphConfig.isEdge) { + result.graph().edges() + } else { + result.graph().variables().asMap() + } + null + } +} + +/** + * + * @param session + * @param nebulaConfig + */ +class NebulaReader(override val session: SparkSession, nebulaConfig: ServerDataSourceConfigEntry) + extends ServerBaseReader(session, nebulaConfig.sentence) { + override def read(): DataFrame = ??? +} + +/** + * HBaseReader extends [[ServerBaseReader]] + * + */ +class HBaseReader(override val session: SparkSession, hbaseConfig: HBaseSourceConfigEntry) + extends ServerBaseReader(session, null) { + + private[this] val LOG = Logger.getLogger(this.getClass) + + override def read(): DataFrame = { + val cf = hbaseConfig.columnFamily + val scanConf = HBaseConfiguration.create() + scanConf.set("hbase.zookeeper.quorum", hbaseConfig.host) + scanConf.set("hbase.zookeeper.property.clientPort", hbaseConfig.port) + scanConf.set(TableInputFormat.INPUT_TABLE, hbaseConfig.table) + hbaseConfig.fields.filter(field => !field.equalsIgnoreCase("rowkey")) + scanConf.set(TableInputFormat.SCAN_COLUMNS, + hbaseConfig.fields + .filter(field => !field.equalsIgnoreCase("rowkey")) + .map(field => s"$cf:$field") + .mkString(" ")) + val fields = hbaseConfig.fields + + val hbaseRDD: RDD[(ImmutableBytesWritable, Result)] = session.sparkContext.newAPIHadoopRDD( + scanConf, + classOf[TableInputFormat], + classOf[ImmutableBytesWritable], + classOf[Result]) + + val rowRDD = hbaseRDD.map(row => { + val values: ListBuffer[String] = new ListBuffer[String] + val result: Result = row._2 + + for (i <- fields.indices) { + if (fields(i).equalsIgnoreCase("rowkey")) { + values += Bytes.toString(result.getRow) + } else { + values += Bytes.toString(result.getValue(Bytes.toBytes(cf), Bytes.toBytes(fields(i)))) + } + } + Row.fromSeq(values.toList) + }) + val schema = StructType( + fields.map(field => DataTypes.createStructField(field, DataTypes.StringType, true))) + val dataFrame = session.createDataFrame(rowRDD, schema) + dataFrame + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/StreamingBaseReader.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/StreamingBaseReader.scala new file mode 100644 index 0000000..55177f5 --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/StreamingBaseReader.scala @@ -0,0 +1,62 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.reader + +import com.vesoft.nebula.tools.importer.config.{ + KafkaSourceConfigEntry, + PulsarSourceConfigEntry +} +import org.apache.spark.sql.{DataFrame, SparkSession} + +/** + * Spark Streaming + * + * @param session + */ +abstract class StreamingBaseReader(override val session: SparkSession) extends Reader { + + override def close(): Unit = { + session.close() + } +} + +/** + * + * @param session + * @param kafkaConfig + */ +class KafkaReader(override val session: SparkSession, kafkaConfig: KafkaSourceConfigEntry) + extends StreamingBaseReader(session) { + + require(kafkaConfig.server.trim.nonEmpty && kafkaConfig.topic.trim.nonEmpty) + + override def read(): DataFrame = { + session.readStream + .format("kafka") + .option("kafka.bootstrap.servers", kafkaConfig.server) + .option("subscribe", kafkaConfig.topic) + .load() + } +} + +/** + * + * @param session + * @param pulsarConfig + */ +class PulsarReader(override val session: SparkSession, pulsarConfig: PulsarSourceConfigEntry) + extends StreamingBaseReader(session) { + + override def read(): DataFrame = { + session.readStream + .format("pulsar") + .option("service.url", pulsarConfig.serviceUrl) + .option("admin.url", pulsarConfig.adminUrl) + .options(pulsarConfig.options) + .load() + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/HDFSUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/HDFSUtils.scala new file mode 100644 index 0000000..b6a6ae2 --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/HDFSUtils.scala @@ -0,0 +1,67 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.utils + +import java.nio.charset.Charset +import org.apache.hadoop.conf.Configuration +import org.apache.hadoop.fs.{FileSystem, Path} +import scala.io.Source + +object HDFSUtils { + + def getFileSystem(): FileSystem = + FileSystem.get(new Configuration()) + + def list(path: String): List[String] = { + val system = getFileSystem() + try { + system.listStatus(new Path(path)).map(_.getPath.getName).toList + } finally { + system.close() + } + } + + def exists(path: String): Boolean = { + val system = getFileSystem() + try { + system.exists(new Path(path)) + } finally { + system.close() + } + } + + def getContent(path: String): String = { + val system = getFileSystem() + val inputStream = system.open(new Path(path)) + try { + Source.fromInputStream(inputStream).mkString + } finally { + system.close() + } + } + + def saveContent(path: String, + content: String, + charset: Charset = Charset.defaultCharset()): Unit = { + val system = getFileSystem() + val outputStream = system.create(new Path(path)) + try { + outputStream.write(content.getBytes(charset)) + } finally { + outputStream.close() + } + } + + def upload(localPath: String, remotePath: String): Unit = { + val system = getFileSystem() + try { + system.copyFromLocalFile(new Path(localPath), new Path(remotePath)) + } finally { + system.close() + } + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/KafkaUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/KafkaUtils.scala new file mode 100644 index 0000000..cd019bf --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/KafkaUtils.scala @@ -0,0 +1,15 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.utils + +import com.vesoft.nebula.tools.importer.{Edge, Vertex} + +object KafkaUtils { + + def writeVertices(vertices: Vertex*): Unit = {} + def writeEdge(edges: Edge*): Unit = {} +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/NebulaUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/NebulaUtils.scala new file mode 100644 index 0000000..b1cff5b --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/NebulaUtils.scala @@ -0,0 +1,94 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.utils + +import com.vesoft.nebula.meta.{PropertyType} +import com.vesoft.nebula.tools.importer.MetaProvider +import com.vesoft.nebula.tools.importer.config.{ + EdgeConfigEntry, + SchemaConfigEntry, + TagConfigEntry, + Type +} +import org.apache.log4j.Logger +import org.apache.spark.sql.types.DataType +import org.apache.spark.sql.types.DataTypes.{ + BooleanType, + DoubleType, + FloatType, + IntegerType, + LongType, + StringType +} +import scala.collection.JavaConversions.seqAsJavaList +import scala.collection.mutable + +object NebulaUtils { + private[this] val LOG = Logger.getLogger(this.getClass) + + def getDataSourceFieldType(sourceConfig: SchemaConfigEntry, + space: String, + metaProvider: MetaProvider): Map[String, Int] = { + val nebulaFields = sourceConfig.nebulaFields + val sourceFields = sourceConfig.fields + val label = sourceConfig.name + + var nebulaSchemaMap: Map[String, Integer] = null + val dataType: Type.Value = metaProvider.getLabelType(space, label) + if (dataType == null) { + throw new IllegalArgumentException(s"label $label does not exist.") + } + if (dataType == Type.VERTEX) { + nebulaSchemaMap = metaProvider.getTagSchema(space, label) + } else { + nebulaSchemaMap = metaProvider.getEdgeSchema(space, label) + } + + val sourceSchemaMap: mutable.Map[String, Int] = mutable.HashMap[String, Int]() + for (i <- nebulaFields.indices) { + sourceSchemaMap.put(sourceFields.get(i), nebulaSchemaMap(nebulaFields.get(i))) + } + // todo String vid and Int vid + if (dataType == Type.VERTEX) { + sourceSchemaMap.put(sourceConfig.asInstanceOf[TagConfigEntry].vertexField, + PropertyType.STRING) + } else { + sourceSchemaMap.put(sourceConfig.asInstanceOf[EdgeConfigEntry].sourceField, + PropertyType.STRING) + sourceSchemaMap.put(sourceConfig.asInstanceOf[EdgeConfigEntry].targetField, + PropertyType.STRING) + } + sourceSchemaMap.toMap + } + + def getDataType(clazz: Class[_]): DataType = { + if (classOf[java.lang.Boolean] == clazz) return BooleanType + else if (classOf[java.lang.Long] == clazz || classOf[java.lang.Integer] == clazz) + return LongType + else if (classOf[java.lang.Double] == clazz || classOf[java.lang.Float] == clazz) + return DoubleType + StringType + } + + def getDataFrameValue(value: String, dataType: DataType): Any = { + dataType match { + case LongType => value.toLong + case IntegerType => value.toInt + case BooleanType => value.toBoolean + case DoubleType => value.toDouble + case FloatType => value.toFloat + case _ => value + } + } + + def isNumic(str: String): Boolean = { + for (char <- str.toCharArray) { + if (!Character.isDigit(char)) return false + } + true + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/FileBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/FileBaseWriter.scala new file mode 100644 index 0000000..28cbbe9 --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/FileBaseWriter.scala @@ -0,0 +1,56 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.writer + +import org.rocksdb.{ + EnvOptions, + Options, + RocksDB, + SstFileWriter +} +import org.slf4j.LoggerFactory + +/** + * + * @param path + */ +class NebulaSSTWriter(path: String) extends Writer { + require(path.trim.size != 0) + + private val LOG = LoggerFactory.getLogger(getClass) + + try { + RocksDB.loadLibrary() + LOG.info("Loading RocksDB successfully") + } catch { + case _: Exception => + LOG.error("Can't load RocksDB library!") + } + + // TODO More Config ... + val options = new Options() + .setCreateIfMissing(true) + + val env = new EnvOptions() + var writer: SstFileWriter = _ + + override def prepare(): Unit = { + writer = new SstFileWriter(env, options) + writer.open(path) + } + + def write(key: Array[Byte], value: Array[Byte]): Unit = { + writer.put(key, value) + } + + override def close(): Unit = { + writer.finish() + writer.close() + options.close() + env.close() + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.scala new file mode 100644 index 0000000..a1e923f --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.scala @@ -0,0 +1,242 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.writer + +import java.util.concurrent.{CountDownLatch, TimeUnit} +import com.google.common.base.Optional +import com.google.common.util.concurrent.{FutureCallback, RateLimiter} +import com.vesoft.nebula.graph.ErrorCode +import com.vesoft.nebula.tools.importer.config.{ + ConnectionConfigEntry, + DataBaseConfigEntry, + RateConfigEntry, + SchemaConfigEntry, + Type, + UserConfigEntry +} +import com.vesoft.nebula.tools.importer.utils.{HDFSUtils, NebulaUtils} +import com.vesoft.nebula.tools.importer.{ + Edges, + GraphProvider, + KeyPolicy, + TooManyErrorsException, + Vertices +} +import org.apache.log4j.Logger +import org.apache.spark.util.LongAccumulator +import scala.collection.JavaConverters._ + +abstract class ServerBaseWriter extends Writer { + private[this] val BATCH_INSERT_TEMPLATE = "INSERT %s %s(%s) VALUES %s" + private[this] val INSERT_VALUE_TEMPLATE = "%s: (%s)" + private[this] val INSERT_VALUE_TEMPLATE_WITH_POLICY = "%s(\"%s\"): (%s)" + private[this] val ENDPOINT_TEMPLATE = "%s(\"%s\")" + private[this] val EDGE_VALUE_WITHOUT_RANKING_TEMPLATE = "%s->%s: (%s)" + private[this] val EDGE_VALUE_TEMPLATE = "%s->%s@%d: (%s)" + + def toExecuteSentence(name: String, vertices: Vertices): String = { + BATCH_INSERT_TEMPLATE.format( + Type.VERTEX.toString, + name, + vertices.propertyNames, + vertices.values + .map { vertex => + // TODO Check + if (vertices.policy.isEmpty) { + INSERT_VALUE_TEMPLATE.format(vertex.vertexID, vertex.propertyValues) + } else { + vertices.policy.get match { + case KeyPolicy.HASH => + INSERT_VALUE_TEMPLATE_WITH_POLICY + .format(KeyPolicy.HASH.toString, vertex.vertexID, vertex.propertyValues) + case KeyPolicy.UUID => + INSERT_VALUE_TEMPLATE_WITH_POLICY + .format(KeyPolicy.UUID.toString, vertex.vertexID, vertex.propertyValues) + case _ => + throw new IllegalArgumentException("Not Support") + } + } + } + .mkString(", ") + ) + } + + def toExecuteSentence(name: String, edges: Edges): String = { + val values = edges.values + .map { edge => + (for (element <- edge.source.split(",")) + yield { + // TODO Check and Test + val source = edges.sourcePolicy match { + case Some(KeyPolicy.HASH) => + ENDPOINT_TEMPLATE.format(KeyPolicy.HASH.toString, element) + case Some(KeyPolicy.UUID) => + ENDPOINT_TEMPLATE.format(KeyPolicy.UUID.toString, element) + case None => + element + } + + val target = edges.targetPolicy match { + case Some(KeyPolicy.HASH) => + ENDPOINT_TEMPLATE.format(KeyPolicy.HASH.toString, edge.destination) + case Some(KeyPolicy.UUID) => + ENDPOINT_TEMPLATE.format(KeyPolicy.UUID.toString, edge.destination) + case None => + edge.destination + } + + if (edge.ranking.isEmpty) + EDGE_VALUE_WITHOUT_RANKING_TEMPLATE + .format(source, target, edge.propertyValues) + else + EDGE_VALUE_TEMPLATE.format(source, target, edge.ranking.get, edge.propertyValues) + }).mkString(", ") + + } + .mkString(", ") + BATCH_INSERT_TEMPLATE.format(Type.EDGE.toString, name, edges.propertyNames, values) + } + + def writeVertices(vertices: Vertices): String + + def writeEdges(edges: Edges): String +} + +/** + * + */ +class NebulaGraphClientWriter(dataBaseConfigEntry: DataBaseConfigEntry, + userConfigEntry: UserConfigEntry, + connectionConfigEntry: ConnectionConfigEntry, + executionRetry: Int, + rateConfig: RateConfigEntry, + config: SchemaConfigEntry, + graphProvider: GraphProvider) + extends ServerBaseWriter { + private val LOG = Logger.getLogger(this.getClass) + + require( + dataBaseConfigEntry.getGraphAddress.nonEmpty + && dataBaseConfigEntry.getMetaAddress.nonEmpty + && dataBaseConfigEntry.space.trim.nonEmpty) + require(userConfigEntry.user.trim.nonEmpty && userConfigEntry.password.trim.nonEmpty) + require(connectionConfigEntry.timeout > 0 && connectionConfigEntry.retry > 0) + require(executionRetry > 0) + + val session = graphProvider.getGraphClient(userConfigEntry) + val rateLimiter = RateLimiter.create(rateConfig.limit) + + def prepare(): Unit = { + val switchResult = graphProvider.switchSpace(session, dataBaseConfigEntry.space) + if (!switchResult) { + this.close() + throw new RuntimeException("Switch Failed") + } + + LOG.info(s"Connection to ${dataBaseConfigEntry.metaAddresses}") + } + + override def writeVertices(vertices: Vertices): String = { + val sentence = toExecuteSentence(config.name, vertices) + LOG.info(sentence) + if (rateLimiter.tryAcquire(rateConfig.timeout, TimeUnit.MILLISECONDS)) { + val result = graphProvider.submit(session, sentence) + if (result.isSucceeded) { + return null + } + LOG.error(s"write vertex failed with statement $sentence. ${result.getErrorMessage}") + } else { + LOG.error(s"write vertex failed because write speed is too fast") + } + sentence + } + + override def writeEdges(edges: Edges): String = { + val sentence = toExecuteSentence(config.name, edges) + LOG.info(sentence) + if (rateLimiter.tryAcquire(rateConfig.timeout, TimeUnit.MILLISECONDS)) { + val result = graphProvider.submit(session, sentence) + if (result.isSucceeded) { + return null + } + LOG.error(s"write edge failed with statement $sentence. ${result.getErrorMessage}") + } else { + LOG.error(s"write vertex failed because write speed is too fast") + } + sentence + } + + override def close(): Unit = { + graphProvider.releaseGraphClient(session) + } +} + +class NebulaWriterCallback(latch: CountDownLatch, + batchSuccess: LongAccumulator, + batchFailure: LongAccumulator, + pathAndOffset: Option[(String, Long)]) + extends FutureCallback[java.util.List[Optional[Integer]]] { + + private[this] lazy val LOG = Logger.getLogger(this.getClass) + + private[this] val DEFAULT_ERROR_TIMES = 16 + + override def onSuccess(results: java.util.List[Optional[Integer]]): Unit = { + if (pathAndOffset.isDefined) { + if (results.asScala.forall(_.get() == ErrorCode.SUCCEEDED)) + HDFSUtils.saveContent(pathAndOffset.get._1, pathAndOffset.get._2.toString) + else + throw new RuntimeException( + s"Some error code: ${results.asScala.filter(_.get() != ErrorCode.SUCCEEDED).head} appear") + } + for (result <- results.asScala) { + latch.countDown() + if (result.get() == ErrorCode.SUCCEEDED) { + batchSuccess.add(1) + } else { + LOG.error(s"batch insert error with code ${result.get()}, batch size is ${results.size()}") + batchFailure.add(1) + } + } + } + + override def onFailure(t: Throwable): Unit = { + latch.countDown() + if (batchFailure.value > DEFAULT_ERROR_TIMES) { + throw TooManyErrorsException("too many errors") + } else { + batchFailure.add(1) + } + + if (pathAndOffset.isDefined) { + throw new RuntimeException(s"Some error appear") + } + } +} + +/** + * + * @param addresses + * @param space + */ +class NebulaStorageClientWriter(addresses: List[(String, Int)], space: String) + extends ServerBaseWriter { + + require(addresses.size != 0) + + def this(host: String, port: Int, space: String) = { + this(List(host -> port), space) + } + + override def prepare(): Unit = {} + + override def writeVertices(vertices: Vertices): String = ??? + + override def writeEdges(edges: Edges): String = ??? + + override def close(): Unit = {} +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/Writer.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/Writer.scala new file mode 100644 index 0000000..9ea5783 --- /dev/null +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/Writer.scala @@ -0,0 +1,17 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.writer + +/** + * + */ +trait Writer extends Serializable { + + def prepare(): Unit + + def close() +} diff --git a/nebula-exchange/src/test/scala/mock/MockConfigs.scala b/nebula-exchange/src/test/scala/mock/MockConfigs.scala new file mode 100644 index 0000000..5b7edb5 --- /dev/null +++ b/nebula-exchange/src/test/scala/mock/MockConfigs.scala @@ -0,0 +1,50 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package mock + +import com.vesoft.nebula.tools.importer.config._ +import com.vesoft.nebula.tools.importer.test.mock.{MockGraphDataEdge, MockGraphDataVertex} + +import scala.util.Random + +object MockConfigs { + + val port: Int = 9000 + Random.nextInt(1000) + val metaPort: Int = 9000 + Random.nextInt(1000) + + val dataBaseConfig: DataBaseConfigEntry = + DataBaseConfigEntry(List("127.0.0.1:" + port), "test", List("127.0.0.1" + metaPort)) + + val userConfig: UserConfigEntry = UserConfigEntry("user", "password") + + val connectionConfig: ConnectionConfigEntry = ConnectionConfigEntry(1000, 1) + + val executionConfig: ExecutionConfigEntry = ExecutionConfigEntry(1000, 1, 1) + + val errorConfig: ErrorConfigEntry = ErrorConfigEntry("/tmp/", 100) + + val rateConfig: RateConfigEntry = RateConfigEntry(100, 100) + + val sparkConfigEntry: SparkConfigEntry = SparkConfigEntry(Map[String, String]()) + + val tagsConfig = List(new MockGraphDataVertex().tagConfig) + + val edgesConfig = List(new MockGraphDataEdge().edgeConfig) + + val configs: Configs = Configs( + dataBaseConfig, + userConfig, + connectionConfig, + executionConfig, + errorConfig, + rateConfig, + sparkConfigEntry, + tagsConfig, + edgesConfig + ) + +} diff --git a/nebula-exchange/src/test/scala/mock/MockGraphData.scala b/nebula-exchange/src/test/scala/mock/MockGraphData.scala new file mode 100644 index 0000000..f8a96e4 --- /dev/null +++ b/nebula-exchange/src/test/scala/mock/MockGraphData.scala @@ -0,0 +1,213 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.test.mock + +import com.typesafe.config.impl.ConfigImpl.fromAnyRef +import com.vesoft.nebula.tools.importer.KeyPolicy +import com.vesoft.nebula.tools.importer.config.{ + EdgeConfigEntry, + FileBaseSourceConfigEntry, + NebulaSinkConfigEntry, + SinkCategory, + SourceCategory, + TagConfigEntry +} +import org.apache.spark.sql.{DataFrame, SparkSession} + +import scala.collection.immutable + +object Spark { + private val master = "local[1]" + private val appName = "exchange_testing" + val sparkSession: SparkSession = + new SparkSession.Builder().appName(appName).master(master).getOrCreate() + sparkSession.sparkContext.setLogLevel("warn") +} + +object MockGraphData { + + import Spark.sparkSession.implicits._ + + private val numberVertex = 5 + private val numberEdgeDegree = 1 + + val policyList = List(Some(KeyPolicy.HASH), Some(KeyPolicy.UUID), None) + val dataSourceConfig: FileBaseSourceConfigEntry = + FileBaseSourceConfigEntry(SourceCategory.TEXT, "") + val dataSinkConfig: NebulaSinkConfigEntry = NebulaSinkConfigEntry(SinkCategory.CLIENT, List("")) + + private def genRow(id: Long) = (id, id.toString, id + 0.01, id % 2 == 0) + + val vertexTypeName = "tagA" + + val edgeTypeName = "edgeAA" + + val propertyFieldName = List("idInt", "idString", "tDouble", "tBoolean") + + val vertexFieldName: List[String] = propertyFieldName + + val edgeFieldName: List[String] = List("from.idInt", "to.idInt") ::: vertexFieldName + + val vertexIdFieldName = "idInt" + + val edgeRankFieldName = "idInt" + + val edgeFromFieldName = "from.idInt" + + val edgeToFieldName = "to.idInt" + + val vertexData: Seq[(Long, String, Double, Boolean)] = + Seq(for (ids <- Range(0, numberVertex)) yield genRow(ids)).flatMap(_.toList) + + val vertexDataIdString: Seq[(String, String, Double, Boolean)] = + vertexData.map(x => (x._1.toString, x._2, x._3, x._4)) + + val edgeData: Seq[(Long, Long, Long, String, Double, Boolean)] = { + val fromVertexId = Range(0, numberVertex).map(_.toLong).toList + var toVertexId = Range(0, numberVertex).map(_.toLong).toList + var id = numberVertex + for (_ <- Range(0, numberEdgeDegree)) yield { + toVertexId = toVertexId.last :: toVertexId.init + for (ids <- Range(0, numberVertex)) yield { + val property = genRow(id) + id += 1 + (fromVertexId(ids), toVertexId(ids), property._1, property._2, property._3, property._4) + } + } + }.flatMap(_.toList).toList + + private val edgeDataIdString00: Seq[(Long, Long, Long, String, Double, Boolean)] = edgeData + private val edgeDataIdString01: Seq[(Long, String, Long, String, Double, Boolean)] = + edgeData.map(x => (x._1, x._2.toString, x._3, x._4, x._5, x._6)) + private val edgeDataIdString10: Seq[(String, Long, Long, String, Double, Boolean)] = + edgeData.map(x => (x._1.toString, x._2, x._3, x._4, x._5, x._6)) + private val edgeDataIdString11: Seq[(String, String, Long, String, Double, Boolean)] = + edgeData.map(x => (x._1.toString, x._2.toString, x._3, x._4, x._5, x._6)) + + def vertexDataFrame: DataFrame = vertexData.toDF(vertexFieldName: _*) + + def vertexDataFrame(vertex: Option[KeyPolicy.Value]): DataFrame = + if (vertex.isEmpty) vertexDataFrame else vertexDataIdString.toDF(vertexFieldName: _*) + + def edgeDataFrame: DataFrame = edgeData.toDF(edgeFieldName: _*) + + def edgeDataFrame(source: Option[KeyPolicy.Value], target: Option[KeyPolicy.Value]): DataFrame = { + { + if (source.isEmpty) { + if (target.isEmpty) edgeDataIdString00.toDF() + else edgeDataIdString01.toDF() + } else { + if (target.isEmpty) edgeDataIdString10.toDF() + else edgeDataIdString11.toDF() + } + }.toDF(edgeFieldName: _*) + } + + private def getVertexIDTemplateFromKeyPolicy(keyPolicy: Option[KeyPolicy.Value]) = + keyPolicy match { + case Some(KeyPolicy.HASH) => "hash(\"%d\")" + case Some(KeyPolicy.UUID) => "uuid(\"%d\")" + case _ => "%d" + } + + def createInsertVertexSentence(vertexPolicy: Option[KeyPolicy.Value]): String = { + val vertexIdTemplate = getVertexIDTemplateFromKeyPolicy(vertexPolicy) + val s = if (vertexPolicy.isEmpty) "" else "\"" + + s"INSERT VERTEX ${vertexTypeName}(idInt,idString,tDouble,tBoolean) VALUES " + + s"${vertexIdTemplate.format(0)}: (${s}0${s}, ${'"'}0${'"'}, 0.01, true), " + + s"${vertexIdTemplate.format(1)}: (${s}1${s}, ${'"'}1${'"'}, 1.01, false), " + + s"${vertexIdTemplate.format(2)}: (${s}2${s}, ${'"'}2${'"'}, 2.01, true), " + + s"${vertexIdTemplate.format(3)}: (${s}3${s}, ${'"'}3${'"'}, 3.01, false), " + + s"${vertexIdTemplate.format(4)}: (${s}4${s}, ${'"'}4${'"'}, 4.01, true)" + } + + def createInsertEdgeSentence(fromVertexPolicy: Option[KeyPolicy.Value], + toVertexPolicy: Option[KeyPolicy.Value], + hasRank: Boolean): String = { + val from = getVertexIDTemplateFromKeyPolicy(fromVertexPolicy) + val to = getVertexIDTemplateFromKeyPolicy(toVertexPolicy) + val rankList = for (i <- Range(5, 10)) yield if (hasRank) s"@${i}" else "" + + s"INSERT EDGE ${edgeTypeName}(idInt,idString,tDouble,tBoolean) VALUES " + + s"${from.format(0)}->${to.format(4)}${rankList(0)}: (5, ${'"'}5${'"'}, 5.01, false), " + + s"${from.format(1)}->${to.format(0)}${rankList(1)}: (6, ${'"'}6${'"'}, 6.01, true), " + + s"${from.format(2)}->${to.format(1)}${rankList(2)}: (7, ${'"'}7${'"'}, 7.01, false), " + + s"${from.format(3)}->${to.format(2)}${rankList(3)}: (8, ${'"'}8${'"'}, 8.01, true), " + + s"${from.format(4)}->${to.format(3)}${rankList(4)}: (9, ${'"'}9${'"'}, 9.01, false)" + } +} + +class MockGraphDataVertex(vertexPolicy: Option[KeyPolicy.Value] = None) { + + val vertexDataFrame: DataFrame = MockGraphData.vertexDataFrame(vertexPolicy) + val tagConfig: TagConfigEntry = { + val fields = MockGraphData.propertyFieldName + .map(property => { + (property, fromAnyRef(property, "")) + }) + .toMap + + // TODO fields + TagConfigEntry( + MockGraphData.vertexTypeName, + MockGraphData.dataSourceConfig, + MockGraphData.dataSinkConfig, + Nil, + Nil, + MockGraphData.vertexIdFieldName, + vertexPolicy, + MockGraphData.vertexData.size, + 1, + None + ) + } + + val insertVertexSentence: String = MockGraphData.createInsertVertexSentence(vertexPolicy) + +} + +class MockGraphDataEdge(edgeSourcePolicy: Option[KeyPolicy.Value] = None, + edgeTargetPolicy: Option[KeyPolicy.Value] = None, + rank: Boolean = false) { + + val edgeDataFrame: DataFrame = + MockGraphData.edgeDataFrame(edgeSourcePolicy, edgeTargetPolicy) + + val edgeConfig: EdgeConfigEntry = { + val fields = MockGraphData.propertyFieldName + .map(property => { + (property, fromAnyRef(property, "")) + }) + .toMap + val rankingField = if (rank) Some(MockGraphData.edgeRankFieldName) else None + + // TODO fields + EdgeConfigEntry( + MockGraphData.edgeTypeName, + MockGraphData.dataSourceConfig, + MockGraphData.dataSinkConfig, + Nil, + Nil, + MockGraphData.edgeFromFieldName, + edgeSourcePolicy, + rankingField, + MockGraphData.edgeToFieldName, + edgeTargetPolicy, + isGeo = false, + None, + None, + MockGraphData.edgeData.size, + 1, + None + ) + } + + val insertEdgeSentence: String = + MockGraphData.createInsertEdgeSentence(edgeSourcePolicy, edgeTargetPolicy, rank) + +} diff --git a/nebula-exchange/src/test/scala/mock/MockQueryProcessor.scala b/nebula-exchange/src/test/scala/mock/MockQueryProcessor.scala new file mode 100644 index 0000000..84a819a --- /dev/null +++ b/nebula-exchange/src/test/scala/mock/MockQueryProcessor.scala @@ -0,0 +1,63 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.tools.importer.test.mock + +import com.vesoft.nebula.graph.{AuthResponse, ErrorCode, ExecutionResponse, GraphService} +import mock.MockConfigs +import org.apache.log4j.Logger + +class MockQueryProcessor extends GraphService.Iface { + private[this] val LOG = Logger.getLogger(this.getClass) + + var queryStatement: Array[Byte] = null + var countDownLatchFailOfInsert: Int = -1 + var countDownLatchFailOfSentence: Int = -1 + + def resetLatch(): Unit = { + resetLatchInsert() + resetLatchSentence() + } + + def resetLatchInsert(): Unit = countDownLatchFailOfInsert = -1 + def resetLatchSentence(): Unit = countDownLatchFailOfSentence = -1 + + override def authenticate(username: Array[Byte], + password: Array[Byte]): AuthResponse = { + LOG.info(s"Get login user: ${username}, password: ${password}") + if (MockConfigs.userConfig.user == username && MockConfigs.userConfig.password == password) + new AuthResponse(ErrorCode.SUCCEEDED, "SUCCEEDED".getBytes(), 1) + else + new AuthResponse(ErrorCode.E_BAD_USERNAME_PASSWORD, "BAD USERNAME OR PASSWORD".getBytes(), 1) + } + override def signout(sessionId: Long): Unit = {} + override def execute(sessionId: Long, stmt: Array[Byte]): ExecutionResponse = { + queryStatement = stmt + if (queryStatement.contains("INSERT")) { + if (countDownLatchFailOfInsert == 0) { + LOG.info(s"mock server got statement: ${queryStatement}, return error") + new ExecutionResponse(ErrorCode.E_SYNTAX_ERROR, 1) + } else { + if (countDownLatchFailOfInsert > 0) + countDownLatchFailOfInsert -= 1 + LOG.info(s"mock server got statement: ${queryStatement}, return success") + new ExecutionResponse(ErrorCode.SUCCEEDED, 1); + } + } else { + if (countDownLatchFailOfSentence == 0) { + LOG.info(s"mock server got statement: ${queryStatement}, return error") + new ExecutionResponse(ErrorCode.E_SYNTAX_ERROR, 1) + } else { + if (countDownLatchFailOfSentence > 0) + countDownLatchFailOfSentence -= 1 + LOG.info(s"mock server got statement: ${queryStatement}, return success") + new ExecutionResponse(ErrorCode.SUCCEEDED, 1); + } + } + } + + override def executeJson(sessionId: Long, stmt: Array[Byte]): Array[Byte] = ??? +} diff --git a/nebula-exchange/src/test/scala/mock/MockQueryServer.java b/nebula-exchange/src/test/scala/mock/MockQueryServer.java new file mode 100644 index 0000000..52679ac --- /dev/null +++ b/nebula-exchange/src/test/scala/mock/MockQueryServer.java @@ -0,0 +1,117 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package mock; + +import com.facebook.thrift.TProcessor; +import com.facebook.thrift.TProcessorFactory; +import com.facebook.thrift.protocol.TProtocol; +import com.facebook.thrift.server.TRpcConnectionContext; +import com.facebook.thrift.server.TServer; +import com.facebook.thrift.transport.TFramedTransport; +import com.facebook.thrift.transport.TServerSocket; +import com.facebook.thrift.transport.TTransport; +import com.facebook.thrift.transport.TTransportException; +import com.vesoft.nebula.graph.GraphService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class MockQueryServer extends Thread { + private static final Logger LOGGER = LoggerFactory.getLogger(MockQueryServer.class); + private final TServer server; + + public MockQueryServer(GraphService.Iface mockProcessor, final int port) { + TProcessor processor = new GraphService.Processor(mockProcessor); + TProcessorFactory factory = new TProcessorFactory(processor); + TServerSocket serverSocket = null; + + try { + serverSocket = new TServerSocket(port); + } catch (TTransportException e) { + e.printStackTrace(); + } + + server = new TServer(factory, serverSocket, new TFramedTransport.Factory(10000000)) { + public void serve() { + LOGGER.info("TServer start " + port); + try { + serverTransport_.listen(); + } catch (TTransportException ttx) { + LOGGER.error("Error occurred during listening.", ttx); + return; + } + + TTransport client = null; + TProcessor processor; + TTransport inputTransport = null; + TTransport outputTransport = null; + TProtocol inputProtocol; + TProtocol outputProtocol; + while (true) { + try { + client = serverTransport_.accept(); + if (client != null) { + processor = processorFactory_.getProcessor(client); + + inputTransport = inputTransportFactory_.getTransport(client); + inputProtocol = inputProtocolFactory_.getProtocol(inputTransport); + outputTransport = outputTransportFactory_.getTransport(client); + outputProtocol = outputProtocolFactory_.getProtocol(outputTransport); + + TRpcConnectionContext serverCtx = new TRpcConnectionContext(client, + inputProtocol, outputProtocol); + try { + while (processor.process(inputProtocol, outputProtocol, serverCtx)) ; + } catch (TTransportException e) { + } + } + } catch (Exception x) { + LOGGER.error("Error occurred during processing of message.", x); + } finally { + if (client != null) { + client.close(); + } + + if (inputTransport != null) { + inputTransport.close(); + } + + if (outputTransport != null) { + outputTransport.close(); + } + } + } + } + }; + } + + public void run() { + startServer(); + } + + public void startServer() { + server.serve(); + synchronized (server) { + server.notify(); + } + } + + public void waitUntilStarted() { + synchronized (server) { + try { + server.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public void stopServer() { + server.stop(); + this.stop(); + } +} diff --git a/nebula-exchange/target/classes.timestamp b/nebula-exchange/target/classes.timestamp new file mode 100644 index 0000000..945c9b4 --- /dev/null +++ b/nebula-exchange/target/classes.timestamp @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/nebula-exchange/target/classes/application.conf b/nebula-exchange/target/classes/application.conf new file mode 100644 index 0000000..61bfa28 --- /dev/null +++ b/nebula-exchange/target/classes/application.conf @@ -0,0 +1,129 @@ +{ + # Spark relation config + spark: { + app: { + name: Nebula Exchange 2.0 + } + + driver: { + cores: 1 + maxResultSize: 1G + } + + executor: { + memory:1G + } + + cores:{ + max: 16 + } + } + + # Nebula Graph relation config + nebula: { + address:{ + graph:["127.0.0.1:3699"] + meta:["127.0.0.1:45500"] + } + user: user + pswd: password + space: test + + connection { + timeout: 3000 + retry: 3 + } + + execution { + retry: 3 + } + + error: { + max: 32 + # failed import job will be recorded in output path + output: /tmp/errors + } + + rate: { + limit: 1024 + timeout: 1000 + } + } + + # Processing tags + tags: [ + + # Loading tag from HDFS and data type is parquet + { + name: tag-name-0 + type: { + source: parquet + sink: client + } + path: hdfs tag path 0 + fields: [parquet-field-0, parquet-field-1, parquet-field-2] + nebula.fields: [nebula-field-0 nebula-field-1 nebula-field-2] + vertex: hive-field-0 + batch: 256 + partition: 32 + } + + # Loading tag from HDFS and data type is csv + { + name: tag-name-2 + type: { + source: csv + sink: client + } + path: hdfs tag path 2 + fields: [csv-field-0, csv-field-1, csv-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: hive-field-0 + separator: "," + header: true + batch: 256 + partition: 32 + } + + # Loading tag from HDFS and data type is csv + { + name: tag-name-2 + type: { + source: csv + sink: client + } + path: hdfs tag path 2 + fields: [csv-field-0, csv-field-1, csv-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: hive-field-0 + separator: "," + header: true + batch: 256 + partition: 32 + } + ] + + # Processing edges + edges: [ + # Loading tag from HDFS and data type is json + { + name: edge-name-0 + type: { + source: json + sink: client + } + path: hdfs edge path 0 + fields: [json-field-0, json-field-1, json-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: { + field: hive-field-0 + } + target: { + field: hive-field-1 + } + ranking: hive-field-2 + batch: 256 + partition: 32 + } + ] +} diff --git a/nebula-exchange/target/classes/server_application.conf b/nebula-exchange/target/classes/server_application.conf new file mode 100644 index 0000000..8e6118b --- /dev/null +++ b/nebula-exchange/target/classes/server_application.conf @@ -0,0 +1,183 @@ +{ + # Spark relation config + spark: { + driver: { + cores: 1 + maxResultSize: 1G + } + + cores { + max: 16 + } + } + + # if the hive is in the same cluster with spark, you can ignore this hive configure + hive: { + waredir: "hdfs://HOSTNAME:9000/apps/svr/hive-0.13.1-cdh5.3.2/warehouse/" + connectionURL: "jdbc:mysql://your_ip:3306/hive_spark?characterEncoding=UTF-8" + connectionDriverName: "com.mysql.jdbc.Driver" + connectionUserName: "user" + connectionPassword: "password" + } + + # Nebula Graph relation config + nebula: { + address:{ + graph:["127.0.0.1:3699"] + meta:["127.0.0.1:45500"] + } + user: user + pswd: password + space: test + + connection { + timeout: 3000 + retry: 3 + } + + execution { + retry: 3 + } + + error: { + max: 32 + # failed import job will be recorded in output path + output: /tmp/errors + } + + rate: { + limit: 1024 + timeout: 1000 + } + } + + # Processing tags + tags: [ + # Loading from Hive + { + name: tag-name-1 + type: { + source: hive + sink: client + } + exec: "select hive-field0, hive-field1, hive-field2 from database.table" + fields: [hive-field-0, hive-field-1, hive-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: { + field: hive-field-0 + # nebula 2.0 does not support int vid yet, so do not config policy. + # policy: "hash" + } + vertex: hive-field-0 + batch: 256 + partition: 32 + } + + # Loading tag from neo4j + { + name: tag-name-0 + type: { + source: neo4j + sink: client + } + server: "bolt://127.0.0.1:7687" + user: neo4j + password: neo4j + exec: "match (n:label) return n.neo4j-field-0 as neo4j-field-0, n.neo4j-field-1 as neo4j-field-1 order by (n.neo4j-field-0)" + fields: [neo4j-field-0, neo4j-field-1] + nebula.fields: [nebula-field-0, nebula-field-1] + vertex: { + field:neo4j-field-0 + # nebula 2.0 does not support int vid yet, so do not config policy. + # policy:uuid + } + partition: 10 + batch: 1000 + check_point_path: /tmp/test + } + + # Loading from HBase, if fields or vertex contains rowkey, please configure it as rowkey. + { + name: hbase-table-name + type: { + source: hbase + sink: client + } + host:127.0.0.1 + port:2181 + table:hbase-table + columnFamily:hbase-table-cloumnfamily + fields: [hbase-column-0, hbase-column-1] + nebula.fields: [nebula-field-0, nebula-field-1] + vertex: rowkey + partition: 10 + batch: 1000 + } + ] + + # Processing edges + edges: [ + # Loading from Hive + { + name: edge-name-1 + type: { + source: hive + sink: client + } + exec: "select hive-field0, hive-field1, hive-field2 from database.table" + fields: [ hive-field-0, hive-field-1, hive-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: hive-field-0 + target: hive-field-1 + batch: 256 + partition: 32 + } + + # Loading from neo4j + { + name: edge-name-0 + type: { + source: neo4j + sink: client + } + server: "bolt://127.0.0.1:7687" + user: neo4j + password: neo4j + exec: "match (a:vertex_label)-[r:edge_label]->(b:vertex_label) return a.neo4j-source-field, b.neo4j-target-field, r.neo4j-field-0 as neo4j-field-0, r.neo4j-field-1 as neo4j-field-1 order by id(r)" + fields: [neo4j-field-0, neo4j-field-1] + nebula.fields: [nebula-field-0, nebula-field-1] + source: { + field: a.neo4j-source-field + } + target: { + field: b.neo4j-target-field + } + partition: 10 + batch: 1000 + check_point_path: /tmp/test + } + + # Loading from hbase + { + name: hbase-table-name + type: { + source: hbase + sink: client + } + host:127.0.0.1 + port:2181 + table:hbase-table + columnFamily:hbase-table-cloumnfamily + fields: [hbase-column-0, hbase-column-1] + nebula.fields:[nebula-field-0, nebula-field-1] + source: { + field: hbase-column-k + } + target: { + field: hbase-column-h + } + partition: 10 + batch: 1000 + } + ] +} diff --git a/nebula-exchange/target/classes/stream_application.conf b/nebula-exchange/target/classes/stream_application.conf new file mode 100644 index 0000000..ab0a201 --- /dev/null +++ b/nebula-exchange/target/classes/stream_application.conf @@ -0,0 +1,143 @@ +{ + # Spark relation config + spark: { + app: { + name: Spark Writer + } + + driver: { + cores: 1 + maxResultSize: 1G + } + + cores { + max: 16 + } + } + + # Nebula Graph relation config + nebula: { + address:{ + graph:["127.0.0.1:3699"] + meta:["127.0.0.1:45500"] + } + user: user + pswd: password + space: test + + connection { + timeout: 3000 + retry: 3 + } + + execution { + retry: 3 + } + + error: { + max: 32 + # failed import job will be recorded in output path + output: /tmp/errors + } + + rate: { + limit: 1024 + timeout: 1000 + } + } + + # Processing tags + tags: [ + + # Loading tag from pulsar + { + name: tag-name-0 + type: { + source: pulsar + sink: client + } + service: "pulsar://localhost:6650" + admin: "http://localhost:8081" + options: { + # choose one of "topic", "topics", "topicsPattern" + topics: "topic1,topic2" + } + fields: [pulsar-field-0, pulsar-field-1, pulsar-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: { + field:pulsar-field-0 + # nebula 2.0 does not support int vid yet, so do not config policy. + # policy:hash + } + partition: 10 + batch: 1000 + interval.seconds: 10 + } + + # Loading from KAFKA + { + name: tag-name-1 + type: { + source: kafka + sink: client + } + service: "kafka.service.address" + topic: "topic-name" + fields: [kafka-field-0, kafka-field-1, kafka-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: kafka-field-0 + partition: 10 + batch: 10 + interval.seconds: 10 + } + ] + + # Processing edges + edges: [ + + # Loading tag from pulsar + { + name: edge-name-0 + type: { + source: pulsar + sink: client + } + service: "pulsar://localhost:6650" + admin: "http://localhost:8081" + options: { + # choose one of "topic", "topics", "topicsPattern" + topic: "topic1" + } + fields: [pulsar-field-0, pulsar-field-1, pulsar-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: { + field: pulsar-field-0 + } + target: { + field: pulsar-field-1 + } + ranking: pulsar-field-2 + partition: 10 + batch: 10 + interval.seconds: 10 + } + + # Loading from KAFKA + { + name: edge-name-1 + type: { + source: kafka + sink: client + } + service: "kafka.service.address" + topic: "topic-name" + fields: [kafka-field-0, kafka-field-1, kafka-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: kafka-field-0 + target: kafka-field-1 + partition: 10 + batch: 1000 + interval.seconds: 10 + } + ] +} diff --git a/nebula-exchange/target/classes/test_application.conf b/nebula-exchange/target/classes/test_application.conf new file mode 100644 index 0000000..652de01 --- /dev/null +++ b/nebula-exchange/target/classes/test_application.conf @@ -0,0 +1,109 @@ +{ + # Spark relation config + spark: { + + + driver: { + cores: 1 + maxResultSize: 1G + } + + cores { + max: 16 + } + } + + # Nebula Graph relation config + nebula: { + address:{ + graph:["192.168.8.172:3799"] + meta:["192.168.8.172:45509"] + } + user: user + pswd: password + space: exchange + + connection { + timeout: 3000 + retry: 3 + } + + execution { + retry: 3 + } + + error: { + max: 32 + # failed import job will be recorded in output path + output: /tmp/errors + } + + rate: { + limit: 1024 + timeout: 1000 + } + } + + # Processing tags + tags: [ + + # Loading tag from HDFS and data type is csv + { + name: person + type: { + source: csv + sink: client + } + path: "hdfs://192.168.8.171:9000/ldbc/tags/person.csv" + fields: [firstName] + nebula.fields: [first_name] + vertex: firstName + separator: "|" + header: true + batch: 256 + partition: 32 + } + + # Loading tag from neo4j + { + name: person1 + type: { + source: neo4j + sink: client + } + server: "bolt://192.168.8.164:7687" + user: neo4j + password: nebula + exec: "match (n:team) return n.name as name" + fields: [name] + nebula.fields: [name] + vertex: { + field:name + # nebula 2.0 does not support int vid yet, so do not config policy. + # policy:uuid + } + partition: 10 + batch: 1000 + check_point_path: /tmp/test + } + ] + + edges:[ + { + name: knows1 + type: { + source: csv + sink: client + } + path: "hdfs://192.168.8.171:9000/ldbc/edges/person_knows_person.csv" + fields: [creationDate] + nebula.fields: [timep] + source: Person.id1 + target: Person.id2 + separator: "|" + header: true + batch: 256 + partition: 32 + } + ] +} diff --git a/nebula-exchange/target/maven-archiver/pom.properties b/nebula-exchange/target/maven-archiver/pom.properties new file mode 100644 index 0000000..c0c4f12 --- /dev/null +++ b/nebula-exchange/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Wed Dec 09 18:46:41 CST 2020 +version=2.0.0 +groupId=com.vesoft +artifactId=nebula-exchange diff --git a/nebula-exchange/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/nebula-exchange/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..e69de29 diff --git a/nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst new file mode 100644 index 0000000..ea46e29 --- /dev/null +++ b/nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst @@ -0,0 +1,2 @@ +mock/MockQueryServer.class +mock/MockQueryServer$1.class diff --git a/nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst new file mode 100644 index 0000000..0734639 --- /dev/null +++ b/nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst @@ -0,0 +1 @@ +/Users/nicole/workspace/nebula/nebula-spark-utils/nebula-exchange/src/test/scala/mock/MockQueryServer.java diff --git a/nebula-exchange/target/site/scaladocs/com/package.html b/nebula-exchange/target/site/scaladocs/com/package.html new file mode 100644 index 0000000..2ef3274 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/package.html @@ -0,0 +1,118 @@ + + + + com - nebula-exchange 2.0.0 API - com + + + + + + + + + + + + + + + +
+ Package + +

com

+ + Permalink + + +
+ +

+ + + package + + + com + +

+ +
+ + +
+
+ + +
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + + + +
+

Value Members

+
  1. + + +

    + + + package + + + vesoft + +

    + + Permalink + + + +
+
+ + + + +
+ +
+ + +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/package.html new file mode 100644 index 0000000..52d0317 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/package.html @@ -0,0 +1,118 @@ + + + + nebula - nebula-exchange 2.0.0 API - com.vesoft.nebula + + + + + + + + + + + + + + + +
+ Package +

com.vesoft

+

nebula

+ + Permalink + + +
+ +

+ + + package + + + nebula + +

+ +
+ + +
+
+ + +
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + + + +
+

Value Members

+
  1. + + +

    + + + package + + + tools + +

    + + Permalink + + + +
+
+ + + + +
+ +
+ + +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Argument.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Argument.html new file mode 100644 index 0000000..3cf4620 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Argument.html @@ -0,0 +1,544 @@ + + + + Argument - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.Argument + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer

+

Argument

Related Doc: + package importer +

+ + Permalink + + +
+ +

+ + final + case class + + + Argument(config: File = new File("application.conf"), hive: Boolean = false, directly: Boolean = false, dry: Boolean = false, reload: String = "") extends Product with Serializable + +

+ +
+ Linear Supertypes +
Serializable, Serializable, Product, Equals, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. Argument
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + Argument(config: File = new File("application.conf"), hive: Boolean = false, directly: Boolean = false, dry: Boolean = false, reload: String = "") + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + val + + + config: File + +

    + + Permalink + + + +
  7. + + +

    + + + val + + + directly: Boolean + +

    + + Permalink + + + +
  8. + + +

    + + + val + + + dry: Boolean + +

    + + Permalink + + + +
  9. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  10. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  11. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + + val + + + hive: Boolean + +

    + + Permalink + + + +
  13. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  14. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + + val + + + reload: String + +

    + + Permalink + + + +
  18. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/CheckPointHandler$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/CheckPointHandler$.html new file mode 100644 index 0000000..ce1b1a5 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/CheckPointHandler$.html @@ -0,0 +1,534 @@ + + + + CheckPointHandler - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.CheckPointHandler + + + + + + + + + + + + + + + +
+ Object +

com.vesoft.nebula.tools.importer

+

CheckPointHandler

Related Doc: + package importer +

+ + Permalink + + +
+ +

+ + + object + + + CheckPointHandler + +

+ +

CheckPointHandler handle the checkpoint files for Neo4j and Janusgraph +

+ Linear Supertypes +
AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. CheckPointHandler
  2. AnyRef
  3. Any
  4. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + checkSupportResume(value: config.SourceCategory.Value): Boolean + +

    + + Permalink + + + +
  6. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + fetchOffset(path: String): Long + +

    + + Permalink + + + +
  10. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  11. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + + def + + + getPathAndOffset(schemaConfig: SchemaConfigEntry, breakPointCount: Long): Option[(String, Long)] + +

    + + Permalink + + + +
  13. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  14. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  15. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  20. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/ErrorHandler$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/ErrorHandler$.html new file mode 100644 index 0000000..143aa13 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/ErrorHandler$.html @@ -0,0 +1,516 @@ + + + + ErrorHandler - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.ErrorHandler + + + + + + + + + + + + + + + +
+ Object +

com.vesoft.nebula.tools.importer

+

ErrorHandler

Related Doc: + package importer +

+ + Permalink + + +
+ +

+ + + object + + + ErrorHandler + +

+ +
+ Linear Supertypes +
AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. ErrorHandler
  2. AnyRef
  3. Any
  4. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + existError(path: String): Boolean + +

    + + Permalink + + + +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + save(buffer: ArrayBuffer[String], path: String): Unit + +

    + + Permalink + + + +
  17. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  19. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Exchange$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Exchange$.html new file mode 100644 index 0000000..98b6319 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Exchange$.html @@ -0,0 +1,500 @@ + + + + Exchange - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.Exchange + + + + + + + + + + + + + + + +
+ Object +

com.vesoft.nebula.tools.importer

+

Exchange

Related Doc: + package importer +

+ + Permalink + + +
+ +

+ + + object + + + Exchange + +

+ +

SparkClientGenerator is a simple spark job used to write data into Nebula Graph parallel. +

+ Linear Supertypes +
AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. Exchange
  2. AnyRef
  3. Any
  4. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + + def + + + main(args: Array[String]): Unit + +

    + + Permalink + + + +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  18. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/GraphProvider.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/GraphProvider.html new file mode 100644 index 0000000..2fc9025 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/GraphProvider.html @@ -0,0 +1,644 @@ + + + + GraphProvider - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.GraphProvider + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer

+

GraphProvider

Related Doc: + package importer +

+ + Permalink + + +
+ +

+ + + class + + + GraphProvider extends AutoCloseable with Serializable + +

+ +
+ Linear Supertypes +
Serializable, Serializable, AutoCloseable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. GraphProvider
  2. Serializable
  3. Serializable
  4. AutoCloseable
  5. AnyRef
  6. Any
  7. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + GraphProvider(addresses: scala.List[HostAndPort]) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + + val + + + address: ListBuffer[HostAddress] + +

    + + Permalink + + + +
  5. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  6. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  7. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    GraphProvider → AutoCloseable
    +
  8. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  9. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  11. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + + def + + + getGraphClient(userConfigEntry: UserConfigEntry): Session + +

    + + Permalink + + + +
  13. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  14. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  15. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + val + + + nebulaPoolConfig: NebulaPoolConfig + +

    + + Permalink + + + +
  17. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + + val + + + pool: NebulaPool + +

    + + Permalink + + + +
  20. + + +

    + + + def + + + releaseGraphClient(session: Session): Unit + +

    + + Permalink + + + +
  21. + + +

    + + + def + + + submit(session: Session, statement: String): ResultSet + +

    + + Permalink + + + +
  22. + + +

    + + + def + + + switchSpace(session: Session, space: String): Boolean + +

    + + Permalink + + + +
  23. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  24. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  25. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  26. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  27. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AutoCloseable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/MetaProvider.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/MetaProvider.html new file mode 100644 index 0000000..c07934a --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/MetaProvider.html @@ -0,0 +1,628 @@ + + + + MetaProvider - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.MetaProvider + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer

+

MetaProvider

Related Doc: + package importer +

+ + Permalink + + +
+ +

+ + + class + + + MetaProvider extends AutoCloseable with Serializable + +

+ +

MetaProvider provide nebula graph meta query operations. +

+ Linear Supertypes +
Serializable, Serializable, AutoCloseable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. MetaProvider
  2. Serializable
  3. Serializable
  4. AutoCloseable
  5. AnyRef
  6. Any
  7. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + MetaProvider(addresses: scala.List[HostAndPort]) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + + val + + + address: ListBuffer[HostAddress] + +

    + + Permalink + + + +
  5. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  6. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  7. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    MetaProvider → AutoCloseable
    +
  8. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  9. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  11. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + + def + + + getEdgeSchema(space: String, edge: String): scala.Predef.Map[String, Integer] + +

    + + Permalink + + + +
  13. + + +

    + + + def + + + getLabelType(space: String, label: String): config.Type.Value + +

    + + Permalink + + + +
  14. + + +

    + + + def + + + getPartNumber(space: String): Unit + +

    + + Permalink + + + +
  15. + + +

    + + + def + + + getTagSchema(space: String, tag: String): scala.Predef.Map[String, Integer] + +

    + + Permalink + + + +
  16. + + +

    + + + def + + + getVidType(space: String): VidType.Value + +

    + + Permalink + + + +
  17. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  18. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  19. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  21. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  22. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  23. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  24. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  25. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  26. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AutoCloseable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/TooManyErrorsException.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/TooManyErrorsException.html new file mode 100644 index 0000000..d9c1023 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/TooManyErrorsException.html @@ -0,0 +1,684 @@ + + + + TooManyErrorsException - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.TooManyErrorsException + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer

+

TooManyErrorsException

Related Doc: + package importer +

+ + Permalink + + +
+ +

+ + final + case class + + + TooManyErrorsException(message: String) extends Exception with Product with Serializable + +

+ +
+ Linear Supertypes +
Serializable, Product, Equals, Exception, Throwable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. TooManyErrorsException
  2. Serializable
  3. Product
  4. Equals
  5. Exception
  6. Throwable
  7. Serializable
  8. AnyRef
  9. Any
  10. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + TooManyErrorsException(message: String) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + addSuppressed(arg0: Throwable): Unit + +

    + + Permalink + + +
    Definition Classes
    Throwable
    +
  5. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  6. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + fillInStackTrace(): Throwable + +

    + + Permalink + + +
    Definition Classes
    Throwable
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + + def + + + getCause(): Throwable + +

    + + Permalink + + +
    Definition Classes
    Throwable
    +
  11. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + + def + + + getLocalizedMessage(): String + +

    + + Permalink + + +
    Definition Classes
    Throwable
    +
  13. + + +

    + + + def + + + getMessage(): String + +

    + + Permalink + + +
    Definition Classes
    Throwable
    +
  14. + + +

    + + + def + + + getStackTrace(): Array[StackTraceElement] + +

    + + Permalink + + +
    Definition Classes
    Throwable
    +
  15. + + +

    + + final + def + + + getSuppressed(): Array[Throwable] + +

    + + Permalink + + +
    Definition Classes
    Throwable
    +
  16. + + +

    + + + def + + + initCause(arg0: Throwable): Throwable + +

    + + Permalink + + +
    Definition Classes
    Throwable
    +
  17. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  18. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  21. + + +

    + + + def + + + printStackTrace(arg0: PrintWriter): Unit + +

    + + Permalink + + +
    Definition Classes
    Throwable
    +
  22. + + +

    + + + def + + + printStackTrace(arg0: PrintStream): Unit + +

    + + Permalink + + +
    Definition Classes
    Throwable
    +
  23. + + +

    + + + def + + + printStackTrace(): Unit + +

    + + Permalink + + +
    Definition Classes
    Throwable
    +
  24. + + +

    + + + def + + + setStackTrace(arg0: Array[StackTraceElement]): Unit + +

    + + Permalink + + +
    Definition Classes
    Throwable
    +
  25. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  26. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    Throwable → AnyRef → Any
    +
  27. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  28. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  29. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from Exception

+
+

Inherited from Throwable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/VidType$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/VidType$.html new file mode 100644 index 0000000..c8fba7d --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/VidType$.html @@ -0,0 +1,786 @@ + + + + VidType - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.VidType + + + + + + + + + + + + + + + +
+ Object +

com.vesoft.nebula.tools.importer

+

VidType

Related Doc: + package importer +

+ + Permalink + + +
+ +

+ + + object + + + VidType extends Enumeration + +

+ +
+ Linear Supertypes +
Enumeration, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. VidType
  2. Enumeration
  3. Serializable
  4. Serializable
  5. AnyRef
  6. Any
  7. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + +
+

Type Members

+
  1. + + +

    + + + type + + + Type = Value + +

    + + Permalink + + + +
  2. + + +

    + + + class + + + Val extends Value with Serializable + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    Annotations
    + @SerialVersionUID() + +
    +
  3. + + +

    + + abstract + class + + + Value extends Ordered[Value] with Serializable + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    Annotations
    + @SerialVersionUID() + +
    +
  4. + + +

    + + + class + + + ValueSet extends AbstractSet[Value] with SortedSet[Value] with SortedSetLike[Value, ValueSet] with Serializable + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
+
+ + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + + val + + + INT: Value + +

    + + Permalink + + + +
  5. + + +

    + + + val + + + STRING: Value + +

    + + Permalink + + + +
  6. + + +

    + + final + def + + + Value(i: Int, name: String): Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  7. + + +

    + + final + def + + + Value(name: String): Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  8. + + +

    + + final + def + + + Value(i: Int): Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  9. + + +

    + + final + def + + + Value: Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  10. + + +

    + + final + def + + + apply(x: Int): Value + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
  11. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  13. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  15. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  16. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  17. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  18. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  19. + + +

    + + final + def + + + maxId: Int + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
  20. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  21. + + +

    + + + var + + + nextId: Int + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  22. + + +

    + + + var + + + nextName: Iterator[String] + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  23. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  24. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  25. + + +

    + + + def + + + readResolve(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  26. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  27. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    Enumeration → AnyRef → Any
    +
  28. + + +

    + + + def + + + values: ValueSet + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
  29. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  30. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  31. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  32. + + +

    + + final + def + + + withName(s: String): Value + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
+
+ + + + +
+ +
+
+

Inherited from Enumeration

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs$.html new file mode 100644 index 0000000..03d13b2 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs$.html @@ -0,0 +1,540 @@ + + + + Configs - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.Configs + + + + + + + + + + + + + + + + + +

+ + + object + + + Configs extends Serializable + +

+ +
+ Linear Supertypes +
Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. Configs
  2. Serializable
  3. Serializable
  4. AnyRef
  5. Any
  6. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + getConfigOrNone(config: Config, path: String): Option[Config] + +

    + + Permalink + + +

    Get the config by the path.

    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + parse(configPath: File): Configs + +

    + + Permalink + + +

    +
  17. + + +

    + + + def + + + parser(args: Array[String], programName: String): Option[Argument] + +

    + + Permalink + + +

    Use to parse command line arguments.

    Use to parse command line arguments. +

    returns

    Argument

    +
  18. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  20. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs.html new file mode 100644 index 0000000..6957086 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs.html @@ -0,0 +1,632 @@ + + + + Configs - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.Configs + + + + + + + + + + + + + + + + + +

+ + + case class + + + Configs(databaseConfig: DataBaseConfigEntry, userConfig: UserConfigEntry, connectionConfig: ConnectionConfigEntry, executionConfig: ExecutionConfigEntry, errorConfig: ErrorConfigEntry, rateConfig: RateConfigEntry, sparkConfigEntry: SparkConfigEntry, tagsConfig: scala.List[TagConfigEntry], edgesConfig: scala.List[EdgeConfigEntry], hiveConfigEntry: Option[HiveConfigEntry] = None) extends Product with Serializable + +

+ +

Configs +

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. Configs
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + Configs(databaseConfig: DataBaseConfigEntry, userConfig: UserConfigEntry, connectionConfig: ConnectionConfigEntry, executionConfig: ExecutionConfigEntry, errorConfig: ErrorConfigEntry, rateConfig: RateConfigEntry, sparkConfigEntry: SparkConfigEntry, tagsConfig: scala.List[TagConfigEntry], edgesConfig: scala.List[EdgeConfigEntry], hiveConfigEntry: Option[HiveConfigEntry] = None) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + val + + + connectionConfig: ConnectionConfigEntry + +

    + + Permalink + + + +
  7. + + +

    + + + val + + + databaseConfig: DataBaseConfigEntry + +

    + + Permalink + + + +
  8. + + +

    + + + val + + + edgesConfig: scala.List[EdgeConfigEntry] + +

    + + Permalink + + + +
  9. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  10. + + +

    + + + val + + + errorConfig: ErrorConfigEntry + +

    + + Permalink + + + +
  11. + + +

    + + + val + + + executionConfig: ExecutionConfigEntry + +

    + + Permalink + + + +
  12. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  13. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  14. + + +

    + + + val + + + hiveConfigEntry: Option[HiveConfigEntry] + +

    + + Permalink + + + +
  15. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  16. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + + val + + + rateConfig: RateConfigEntry + +

    + + Permalink + + + +
  20. + + +

    + + + val + + + sparkConfigEntry: SparkConfigEntry + +

    + + Permalink + + + +
  21. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  22. + + +

    + + + val + + + tagsConfig: scala.List[TagConfigEntry] + +

    + + Permalink + + + +
  23. + + +

    + + + val + + + userConfig: UserConfigEntry + +

    + + Permalink + + + +
  24. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  25. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  26. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ConnectionConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ConnectionConfigEntry.html new file mode 100644 index 0000000..8504231 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ConnectionConfigEntry.html @@ -0,0 +1,511 @@ + + + + ConnectionConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.ConnectionConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

ConnectionConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + ConnectionConfigEntry(timeout: Int, retry: Int) extends Product with Serializable + +

+ +

ConnectionConfigEntry +

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. ConnectionConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + ConnectionConfigEntry(timeout: Int, retry: Int) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  8. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  10. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  11. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  12. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + + val + + + retry: Int + +

    + + Permalink + + + +
  14. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + + val + + + timeout: Int + +

    + + Permalink + + + +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    ConnectionConfigEntry → AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataBaseConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataBaseConfigEntry.html new file mode 100644 index 0000000..18fc83e --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataBaseConfigEntry.html @@ -0,0 +1,562 @@ + + + + DataBaseConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.DataBaseConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

DataBaseConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + DataBaseConfigEntry(graphAddress: scala.List[String], space: String, metaAddresses: scala.List[String]) extends Product with Serializable + +

+ +

DataBaseConfigEntry describe the nebula cluster's address and which space will be used. +

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. DataBaseConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + DataBaseConfigEntry(graphAddress: scala.List[String], space: String, metaAddresses: scala.List[String]) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  8. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + getGraphAddress: scala.List[HostAndPort] + +

    + + Permalink + + + +
  10. + + +

    + + + def + + + getMetaAddress: scala.List[HostAndPort] + +

    + + Permalink + + + +
  11. + + +

    + + + val + + + graphAddress: scala.List[String] + +

    + + Permalink + + + +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + + val + + + metaAddresses: scala.List[String] + +

    + + Permalink + + + +
  14. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + + val + + + space: String + +

    + + Permalink + + + +
  18. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    DataBaseConfigEntry → AnyRef → Any
    +
  20. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSinkConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSinkConfigEntry.html new file mode 100644 index 0000000..0d8dadb --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSinkConfigEntry.html @@ -0,0 +1,506 @@ + + + + DataSinkConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.DataSinkConfigEntry + + + + + + + + + + + + + + + +
+ Trait +

com.vesoft.nebula.tools.importer.config

+

DataSinkConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + sealed + trait + + + DataSinkConfigEntry extends AnyRef + +

+ +

DataSinkConfigEntry +

+ Linear Supertypes +
AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. DataSinkConfigEntry
  2. AnyRef
  3. Any
  4. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + +
+

Abstract Value Members

+
  1. + + +

    + + abstract + def + + + category: SinkCategory.Value + +

    + + Permalink + + + +
+
+ +
+

Concrete Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSourceConfigEntry.html new file mode 100644 index 0000000..d9c8f8c --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSourceConfigEntry.html @@ -0,0 +1,506 @@ + + + + DataSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.DataSourceConfigEntry + + + + + + + + + + + + + + + +
+ Trait +

com.vesoft.nebula.tools.importer.config

+

DataSourceConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + sealed + trait + + + DataSourceConfigEntry extends AnyRef + +

+ + + + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. DataSourceConfigEntry
  2. AnyRef
  3. Any
  4. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + +
+

Abstract Value Members

+
  1. + + +

    + + abstract + def + + + category: SourceCategory.Value + +

    + + Permalink + + + +
+
+ +
+

Concrete Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/EdgeConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/EdgeConfigEntry.html new file mode 100644 index 0000000..d26d69d --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/EdgeConfigEntry.html @@ -0,0 +1,750 @@ + + + + EdgeConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.EdgeConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

EdgeConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + EdgeConfigEntry(name: String, dataSourceConfigEntry: DataSourceConfigEntry, dataSinkConfigEntry: DataSinkConfigEntry, fields: scala.List[String], nebulaFields: scala.List[String], sourceField: String, sourcePolicy: Option[KeyPolicy.Value], rankingField: Option[String], targetField: String, targetPolicy: Option[KeyPolicy.Value], isGeo: Boolean, latitude: Option[String], longitude: Option[String], batch: Int, partition: Int, checkPointPath: Option[String]) extends SchemaConfigEntry with Product with Serializable + +

+ +
+ Linear Supertypes +
Serializable, Serializable, Product, Equals, SchemaConfigEntry, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. EdgeConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. SchemaConfigEntry
  7. AnyRef
  8. Any
  9. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + EdgeConfigEntry(name: String, dataSourceConfigEntry: DataSourceConfigEntry, dataSinkConfigEntry: DataSinkConfigEntry, fields: scala.List[String], nebulaFields: scala.List[String], sourceField: String, sourcePolicy: Option[KeyPolicy.Value], rankingField: Option[String], targetField: String, targetPolicy: Option[KeyPolicy.Value], isGeo: Boolean, latitude: Option[String], longitude: Option[String], batch: Int, partition: Int, checkPointPath: Option[String]) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + val + + + batch: Int + +

    + + Permalink + + +

    vertex or edge amount of one batch import

    vertex or edge amount of one batch import

    Definition Classes
    EdgeConfigEntrySchemaConfigEntry
    +
  6. + + +

    + + + val + + + checkPointPath: Option[String] + +

    + + Permalink + + +

    check point path

    check point path

    Definition Classes
    EdgeConfigEntrySchemaConfigEntry
    +
  7. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  8. + + +

    + + + val + + + dataSinkConfigEntry: DataSinkConfigEntry + +

    + + Permalink + + +

    seeDataSinkConfigEntry

    +
  9. + + +

    + + + val + + + dataSourceConfigEntry: DataSourceConfigEntry + +

    + + Permalink + + +

    seeDataSourceConfigEntry

    +
  10. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  11. + + +

    + + + val + + + fields: scala.List[String] + +

    + + Permalink + + +

    data source fields which are going to be import to nebula as properties

    data source fields which are going to be import to nebula as properties

    Definition Classes
    EdgeConfigEntrySchemaConfigEntry
    +
  12. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  13. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  14. + + +

    + + + val + + + isGeo: Boolean + +

    + + Permalink + + + +
  15. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  16. + + +

    + + + val + + + latitude: Option[String] + +

    + + Permalink + + + +
  17. + + +

    + + + val + + + longitude: Option[String] + +

    + + Permalink + + + +
  18. + + +

    + + + val + + + name: String + +

    + + Permalink + + +

    nebula tag or edge name

    nebula tag or edge name

    Definition Classes
    EdgeConfigEntrySchemaConfigEntry
    +
  19. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + val + + + nebulaFields: scala.List[String] + +

    + + Permalink + + +

    nebula properties which are going to fill value with data source value

    nebula properties which are going to fill value with data source value

    Definition Classes
    EdgeConfigEntrySchemaConfigEntry
    +
  21. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  22. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  23. + + +

    + + + val + + + partition: Int + +

    + + Permalink + + +

    spark partition

    spark partition

    Definition Classes
    EdgeConfigEntrySchemaConfigEntry
    +
  24. + + +

    + + + val + + + rankingField: Option[String] + +

    + + Permalink + + + +
  25. + + +

    + + + val + + + sourceField: String + +

    + + Permalink + + + +
  26. + + +

    + + + val + + + sourcePolicy: Option[KeyPolicy.Value] + +

    + + Permalink + + + +
  27. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  28. + + +

    + + + val + + + targetField: String + +

    + + Permalink + + + +
  29. + + +

    + + + val + + + targetPolicy: Option[KeyPolicy.Value] + +

    + + Permalink + + + +
  30. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    EdgeConfigEntry → AnyRef → Any
    +
  31. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  32. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  33. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from SchemaConfigEntry

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ErrorConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ErrorConfigEntry.html new file mode 100644 index 0000000..bdc2203 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ErrorConfigEntry.html @@ -0,0 +1,511 @@ + + + + ErrorConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.ErrorConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

ErrorConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + ErrorConfigEntry(errorPath: String, errorMaxSize: Int) extends Product with Serializable + +

+ +

ErrorConfigEntry +

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. ErrorConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + ErrorConfigEntry(errorPath: String, errorMaxSize: Int) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + val + + + errorMaxSize: Int + +

    + + Permalink + + + +
  8. + + +

    + + + val + + + errorPath: String + +

    + + Permalink + + + +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    ErrorConfigEntry → AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ExecutionConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ExecutionConfigEntry.html new file mode 100644 index 0000000..1595d37 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ExecutionConfigEntry.html @@ -0,0 +1,528 @@ + + + + ExecutionConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.ExecutionConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

ExecutionConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + ExecutionConfigEntry(timeout: Int, retry: Int, interval: Int) extends Product with Serializable + +

+ +

ExecutionConfigEntry +

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. ExecutionConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + ExecutionConfigEntry(timeout: Int, retry: Int, interval: Int) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  8. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + val + + + interval: Int + +

    + + Permalink + + + +
  10. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  11. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  12. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + + val + + + retry: Int + +

    + + Permalink + + + +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + val + + + timeout: Int + +

    + + Permalink + + + +
  17. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    ExecutionConfigEntry → AnyRef → Any
    +
  18. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSinkConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSinkConfigEntry.html new file mode 100644 index 0000000..549493f --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSinkConfigEntry.html @@ -0,0 +1,530 @@ + + + + FileBaseSinkConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.FileBaseSinkConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

FileBaseSinkConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + FileBaseSinkConfigEntry(category: SinkCategory.Value, localPath: String, remotePath: String) extends DataSinkConfigEntry with Product with Serializable + +

+ +

FileBaseSinkConfigEntry +

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, DataSinkConfigEntry, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. FileBaseSinkConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. DataSinkConfigEntry
  7. AnyRef
  8. Any
  9. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + FileBaseSinkConfigEntry(category: SinkCategory.Value, localPath: String, remotePath: String) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + val + + + category: SinkCategory.Value + +

    + + Permalink + + + +
  6. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  11. + + +

    + + + val + + + localPath: String + +

    + + Permalink + + + +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + + val + + + remotePath: String + +

    + + Permalink + + + +
  16. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    FileBaseSinkConfigEntry → AnyRef → Any
    +
  18. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from DataSinkConfigEntry

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSourceConfigEntry.html new file mode 100644 index 0000000..73fc8aa --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSourceConfigEntry.html @@ -0,0 +1,549 @@ + + + + FileBaseSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.FileBaseSourceConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

FileBaseSourceConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + FileBaseSourceConfigEntry(category: SourceCategory.Value, path: String, separator: Option[String] = None, header: Option[Boolean] = None) extends FileDataSourceConfigEntry with Product with Serializable + +

+ +

FileBaseSourceConfigEntry +

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, FileDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. FileBaseSourceConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. FileDataSourceConfigEntry
  7. DataSourceConfigEntry
  8. AnyRef
  9. Any
  10. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + FileBaseSourceConfigEntry(category: SourceCategory.Value, path: String, separator: Option[String] = None, header: Option[Boolean] = None) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + val + + + category: SourceCategory.Value + +

    + + Permalink + + + +
  6. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + val + + + header: Option[Boolean] + +

    + + Permalink + + + +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + + val + + + path: String + +

    + + Permalink + + + +
  16. + + +

    + + + val + + + separator: Option[String] + +

    + + Permalink + + + +
  17. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    FileBaseSourceConfigEntry → AnyRef → Any
    +
  19. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from FileDataSourceConfigEntry

+
+

Inherited from DataSourceConfigEntry

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileDataSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileDataSourceConfigEntry.html new file mode 100644 index 0000000..59b062f --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileDataSourceConfigEntry.html @@ -0,0 +1,524 @@ + + + + FileDataSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.FileDataSourceConfigEntry + + + + + + + + + + + + + + + +
+ Trait +

com.vesoft.nebula.tools.importer.config

+

FileDataSourceConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + sealed + trait + + + FileDataSourceConfigEntry extends DataSourceConfigEntry + +

+ +
+ Linear Supertypes + +
+ Known Subclasses + +
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. FileDataSourceConfigEntry
  2. DataSourceConfigEntry
  3. AnyRef
  4. Any
  5. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + +
+

Abstract Value Members

+
  1. + + +

    + + abstract + def + + + category: SourceCategory.Value + +

    + + Permalink + + +
    Definition Classes
    DataSourceConfigEntry
    +
  2. + + +

    + + abstract + def + + + path: String + +

    + + Permalink + + + +
+
+ +
+

Concrete Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from DataSourceConfigEntry

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HBaseSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HBaseSourceConfigEntry.html new file mode 100644 index 0000000..ed0228c --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HBaseSourceConfigEntry.html @@ -0,0 +1,599 @@ + + + + HBaseSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.HBaseSourceConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

HBaseSourceConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + HBaseSourceConfigEntry(category: SourceCategory.Value, host: String, port: String, table: String, columnFamily: String, fields: scala.List[String]) extends ServerDataSourceConfigEntry with Product with Serializable + +

+ +

HBaseSourceConfigEntry

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, ServerDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. HBaseSourceConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. ServerDataSourceConfigEntry
  7. DataSourceConfigEntry
  8. AnyRef
  9. Any
  10. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + HBaseSourceConfigEntry(category: SourceCategory.Value, host: String, port: String, table: String, columnFamily: String, fields: scala.List[String]) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + val + + + category: SourceCategory.Value + +

    + + Permalink + + + +
  6. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  7. + + +

    + + + val + + + columnFamily: String + +

    + + Permalink + + + +
  8. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  9. + + +

    + + + val + + + fields: scala.List[String] + +

    + + Permalink + + + +
  10. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  11. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + + val + + + host: String + +

    + + Permalink + + + +
  13. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  14. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + + val + + + port: String + +

    + + Permalink + + + +
  18. + + +

    + + + val + + + sentence: String + +

    + + Permalink + + + +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + val + + + table: String + +

    + + Permalink + + + +
  21. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    HBaseSourceConfigEntry → AnyRef → Any
    +
  22. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  24. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from ServerDataSourceConfigEntry

+
+

Inherited from DataSourceConfigEntry

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveConfigEntry.html new file mode 100644 index 0000000..772fce6 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveConfigEntry.html @@ -0,0 +1,561 @@ + + + + HiveConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.HiveConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

HiveConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + HiveConfigEntry(waredir: String, connectionURL: String, connectionDriverName: String, connectionUserName: String, connectionPassWord: String) extends Product with Serializable + +

+ +
+ Linear Supertypes +
Serializable, Serializable, Product, Equals, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. HiveConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + HiveConfigEntry(waredir: String, connectionURL: String, connectionDriverName: String, connectionUserName: String, connectionPassWord: String) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + val + + + connectionDriverName: String + +

    + + Permalink + + + +
  7. + + +

    + + + val + + + connectionPassWord: String + +

    + + Permalink + + + +
  8. + + +

    + + + val + + + connectionURL: String + +

    + + Permalink + + + +
  9. + + +

    + + + val + + + connectionUserName: String + +

    + + Permalink + + + +
  10. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  11. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  12. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  13. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  14. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    HiveConfigEntry → AnyRef → Any
    +
  19. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + + val + + + waredir: String + +

    + + Permalink + + + +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveSourceConfigEntry.html new file mode 100644 index 0000000..111b4d6 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveSourceConfigEntry.html @@ -0,0 +1,515 @@ + + + + HiveSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.HiveSourceConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

HiveSourceConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + HiveSourceConfigEntry(category: SourceCategory.Value, sentence: String) extends ServerDataSourceConfigEntry with Product with Serializable + +

+ +

HiveSourceConfigEntry +

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, ServerDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. HiveSourceConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. ServerDataSourceConfigEntry
  7. DataSourceConfigEntry
  8. AnyRef
  9. Any
  10. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + HiveSourceConfigEntry(category: SourceCategory.Value, sentence: String) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + val + + + category: SourceCategory.Value + +

    + + Permalink + + + +
  6. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  11. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  12. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + + val + + + sentence: String + +

    + + Permalink + + + +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    HiveSourceConfigEntry → AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from ServerDataSourceConfigEntry

+
+

Inherited from DataSourceConfigEntry

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/JanusGraphSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/JanusGraphSourceConfigEntry.html new file mode 100644 index 0000000..780bcec --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/JanusGraphSourceConfigEntry.html @@ -0,0 +1,531 @@ + + + + JanusGraphSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.JanusGraphSourceConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

JanusGraphSourceConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + JanusGraphSourceConfigEntry(category: SourceCategory.Value, sentence: String, isEdge: Boolean) extends ServerDataSourceConfigEntry with Product with Serializable + +

+ +
+ Linear Supertypes +
Serializable, Serializable, Product, Equals, ServerDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. JanusGraphSourceConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. ServerDataSourceConfigEntry
  7. DataSourceConfigEntry
  8. AnyRef
  9. Any
  10. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + JanusGraphSourceConfigEntry(category: SourceCategory.Value, sentence: String, isEdge: Boolean) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + val + + + category: SourceCategory.Value + +

    + + Permalink + + + +
  6. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + val + + + isEdge: Boolean + +

    + + Permalink + + + +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + + val + + + sentence: String + +

    + + Permalink + + + +
  16. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    JanusGraphSourceConfigEntry → AnyRef → Any
    +
  18. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from ServerDataSourceConfigEntry

+
+

Inherited from DataSourceConfigEntry

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/KafkaSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/KafkaSourceConfigEntry.html new file mode 100644 index 0000000..8d53b17 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/KafkaSourceConfigEntry.html @@ -0,0 +1,549 @@ + + + + KafkaSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.KafkaSourceConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

KafkaSourceConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + KafkaSourceConfigEntry(category: SourceCategory.Value, intervalSeconds: Int, server: String, topic: String) extends StreamingDataSourceConfigEntry with Product with Serializable + +

+ +

TODO: Support more config item about Kafka Consumer +

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, StreamingDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. KafkaSourceConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. StreamingDataSourceConfigEntry
  7. DataSourceConfigEntry
  8. AnyRef
  9. Any
  10. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + KafkaSourceConfigEntry(category: SourceCategory.Value, intervalSeconds: Int, server: String, topic: String) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + val + + + category: SourceCategory.Value + +

    + + Permalink + + + +
  6. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + val + + + intervalSeconds: Int + +

    + + Permalink + + + +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + + val + + + server: String + +

    + + Permalink + + + +
  16. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    KafkaSourceConfigEntry → AnyRef → Any
    +
  18. + + +

    + + + val + + + topic: String + +

    + + Permalink + + + +
  19. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from StreamingDataSourceConfigEntry

+
+

Inherited from DataSourceConfigEntry

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/MySQLSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/MySQLSourceConfigEntry.html new file mode 100644 index 0000000..9f4d4c7 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/MySQLSourceConfigEntry.html @@ -0,0 +1,617 @@ + + + + MySQLSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.MySQLSourceConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

MySQLSourceConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + MySQLSourceConfigEntry(category: SourceCategory.Value, host: String, port: Int, database: String, table: String, user: String, password: String, sentence: String) extends ServerDataSourceConfigEntry with Product with Serializable + +

+ +

MySQLSourceConfigEntry +

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, ServerDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. MySQLSourceConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. ServerDataSourceConfigEntry
  7. DataSourceConfigEntry
  8. AnyRef
  9. Any
  10. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + MySQLSourceConfigEntry(category: SourceCategory.Value, host: String, port: Int, database: String, table: String, user: String, password: String, sentence: String) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + val + + + category: SourceCategory.Value + +

    + + Permalink + + + +
  6. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  7. + + +

    + + + val + + + database: String + +

    + + Permalink + + + +
  8. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + val + + + host: String + +

    + + Permalink + + + +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + val + + + password: String + +

    + + Permalink + + + +
  17. + + +

    + + + val + + + port: Int + +

    + + Permalink + + + +
  18. + + +

    + + + val + + + sentence: String + +

    + + Permalink + + + +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + val + + + table: String + +

    + + Permalink + + + +
  21. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    MySQLSourceConfigEntry → AnyRef → Any
    +
  22. + + +

    + + + val + + + user: String + +

    + + Permalink + + + +
  23. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  24. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  25. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from ServerDataSourceConfigEntry

+
+

Inherited from DataSourceConfigEntry

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/NebulaSinkConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/NebulaSinkConfigEntry.html new file mode 100644 index 0000000..2cf075c --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/NebulaSinkConfigEntry.html @@ -0,0 +1,513 @@ + + + + NebulaSinkConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.NebulaSinkConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

NebulaSinkConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + NebulaSinkConfigEntry(category: SinkCategory.Value, addresses: scala.List[String]) extends DataSinkConfigEntry with Product with Serializable + +

+ +

NebulaSinkConfigEntry use to specified the nebula service's address. +

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, DataSinkConfigEntry, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. NebulaSinkConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. DataSinkConfigEntry
  7. AnyRef
  8. Any
  9. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + NebulaSinkConfigEntry(category: SinkCategory.Value, addresses: scala.List[String]) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + + val + + + addresses: scala.List[String] + +

    + + Permalink + + + +
  5. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  6. + + +

    + + + val + + + category: SinkCategory.Value + +

    + + Permalink + + + +
  7. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  8. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    NebulaSinkConfigEntry → AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from DataSinkConfigEntry

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Neo4JSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Neo4JSourceConfigEntry.html new file mode 100644 index 0000000..25b8647 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Neo4JSourceConfigEntry.html @@ -0,0 +1,651 @@ + + + + Neo4JSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.Neo4JSourceConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

Neo4JSourceConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + Neo4JSourceConfigEntry(category: SourceCategory.Value, sentence: String, name: String, server: String, user: String, password: String, database: Option[String], encryption: Boolean, parallel: Int, checkPointPath: Option[String]) extends ServerDataSourceConfigEntry with Product with Serializable + +

+ +

Neo4JSourceConfigEntry +

checkPointPath

use save resume data dir path.

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, ServerDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. Neo4JSourceConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. ServerDataSourceConfigEntry
  7. DataSourceConfigEntry
  8. AnyRef
  9. Any
  10. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + Neo4JSourceConfigEntry(category: SourceCategory.Value, sentence: String, name: String, server: String, user: String, password: String, database: Option[String], encryption: Boolean, parallel: Int, checkPointPath: Option[String]) + +

    + + Permalink + + +

    checkPointPath

    use save resume data dir path.

    +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + val + + + category: SourceCategory.Value + +

    + + Permalink + + + +
  6. + + +

    + + + val + + + checkPointPath: Option[String] + +

    + + Permalink + + +

    use save resume data dir path.

    +
  7. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  8. + + +

    + + + val + + + database: Option[String] + +

    + + Permalink + + + +
  9. + + +

    + + + val + + + encryption: Boolean + +

    + + Permalink + + + +
  10. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  11. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  12. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  13. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  14. + + +

    + + + val + + + name: String + +

    + + Permalink + + + +
  15. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + + val + + + parallel: Int + +

    + + Permalink + + + +
  19. + + +

    + + + val + + + password: String + +

    + + Permalink + + + +
  20. + + +

    + + + val + + + sentence: String + +

    + + Permalink + + + +
  21. + + +

    + + + val + + + server: String + +

    + + Permalink + + + +
  22. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  23. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    Neo4JSourceConfigEntry → AnyRef → Any
    +
  24. + + +

    + + + val + + + user: String + +

    + + Permalink + + + +
  25. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  26. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  27. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from ServerDataSourceConfigEntry

+
+

Inherited from DataSourceConfigEntry

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/PulsarSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/PulsarSourceConfigEntry.html new file mode 100644 index 0000000..8c40c35 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/PulsarSourceConfigEntry.html @@ -0,0 +1,566 @@ + + + + PulsarSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.PulsarSourceConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

PulsarSourceConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + PulsarSourceConfigEntry(category: SourceCategory.Value, intervalSeconds: Int, serviceUrl: String, adminUrl: String, options: scala.Predef.Map[String, String]) extends StreamingDataSourceConfigEntry with Product with Serializable + +

+ +

PulsarSourceConfigEntry +

adminUrl

use to get data schema.

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, StreamingDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. PulsarSourceConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. StreamingDataSourceConfigEntry
  7. DataSourceConfigEntry
  8. AnyRef
  9. Any
  10. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + PulsarSourceConfigEntry(category: SourceCategory.Value, intervalSeconds: Int, serviceUrl: String, adminUrl: String, options: scala.Predef.Map[String, String]) + +

    + + Permalink + + +

    adminUrl

    use to get data schema.

    +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + + val + + + adminUrl: String + +

    + + Permalink + + +

    use to get data schema.

    +
  5. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  6. + + +

    + + + val + + + category: SourceCategory.Value + +

    + + Permalink + + + +
  7. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  8. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + val + + + intervalSeconds: Int + +

    + + Permalink + + + +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + val + + + options: scala.Predef.Map[String, String] + +

    + + Permalink + + + +
  17. + + +

    + + + val + + + serviceUrl: String + +

    + + Permalink + + + +
  18. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    PulsarSourceConfigEntry → AnyRef → Any
    +
  20. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from StreamingDataSourceConfigEntry

+
+

Inherited from DataSourceConfigEntry

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/RateConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/RateConfigEntry.html new file mode 100644 index 0000000..b2c4895 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/RateConfigEntry.html @@ -0,0 +1,511 @@ + + + + RateConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.RateConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

RateConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + RateConfigEntry(limit: Int, timeout: Int) extends Product with Serializable + +

+ +

RateConfigEntry +

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. RateConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + RateConfigEntry(limit: Int, timeout: Int) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  8. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  10. + + +

    + + + val + + + limit: Int + +

    + + Permalink + + + +
  11. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  12. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + + val + + + timeout: Int + +

    + + Permalink + + + +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    RateConfigEntry → AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SchemaConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SchemaConfigEntry.html new file mode 100644 index 0000000..480bef8 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SchemaConfigEntry.html @@ -0,0 +1,625 @@ + + + + SchemaConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.SchemaConfigEntry + + + + + + + + + + + + + + + +
+ Trait +

com.vesoft.nebula.tools.importer.config

+

SchemaConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + sealed + trait + + + SchemaConfigEntry extends AnyRef + +

+ +

SchemaConfigEntry is tag/edge super class use to save some basic parameter for importer. +

+ Linear Supertypes +
AnyRef, Any
+
+ Known Subclasses + +
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. SchemaConfigEntry
  2. AnyRef
  3. Any
  4. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + +
+

Abstract Value Members

+
  1. + + +

    + + abstract + def + + + batch: Int + +

    + + Permalink + + +

    vertex or edge amount of one batch import

    +
  2. + + +

    + + abstract + def + + + checkPointPath: Option[String] + +

    + + Permalink + + +

    check point path

    +
  3. + + +

    + + abstract + def + + + dataSinkConfigEntry: DataSinkConfigEntry + +

    + + Permalink + + +

    seeDataSinkConfigEntry

    +
  4. + + +

    + + abstract + def + + + dataSourceConfigEntry: DataSourceConfigEntry + +

    + + Permalink + + +

    seeDataSourceConfigEntry

    +
  5. + + +

    + + abstract + def + + + fields: scala.List[String] + +

    + + Permalink + + +

    data source fields which are going to be import to nebula as properties

    +
  6. + + +

    + + abstract + def + + + name: String + +

    + + Permalink + + +

    nebula tag or edge name

    +
  7. + + +

    + + abstract + def + + + nebulaFields: scala.List[String] + +

    + + Permalink + + +

    nebula properties which are going to fill value with data source value

    +
  8. + + +

    + + abstract + def + + + partition: Int + +

    + + Permalink + + +

    spark partition

    +
+
+ +
+

Concrete Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ServerDataSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ServerDataSourceConfigEntry.html new file mode 100644 index 0000000..c7a2d42 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ServerDataSourceConfigEntry.html @@ -0,0 +1,524 @@ + + + + ServerDataSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.ServerDataSourceConfigEntry + + + + + + + + + + + + + + + +
+ Trait +

com.vesoft.nebula.tools.importer.config

+

ServerDataSourceConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + sealed + trait + + + ServerDataSourceConfigEntry extends DataSourceConfigEntry + +

+ + + + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. ServerDataSourceConfigEntry
  2. DataSourceConfigEntry
  3. AnyRef
  4. Any
  5. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + +
+

Abstract Value Members

+
  1. + + +

    + + abstract + def + + + category: SourceCategory.Value + +

    + + Permalink + + +
    Definition Classes
    DataSourceConfigEntry
    +
  2. + + +

    + + abstract + def + + + sentence: String + +

    + + Permalink + + + +
+
+ +
+

Concrete Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from DataSourceConfigEntry

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory$.html new file mode 100644 index 0000000..bb3098b --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory$.html @@ -0,0 +1,790 @@ + + + + SinkCategory - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.SinkCategory + + + + + + + + + + + + + + + + + +

+ + + object + + + SinkCategory extends Enumeration + +

+ +

SinkCategory is used to expression the writer's type. +SST is not supported yet. +

+ Linear Supertypes +
Enumeration, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. SinkCategory
  2. Enumeration
  3. Serializable
  4. Serializable
  5. AnyRef
  6. Any
  7. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + +
+

Type Members

+
  1. + + +

    + + + type + + + Type = Value + +

    + + Permalink + + + +
  2. + + +

    + + + class + + + Val extends Value with Serializable + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    Annotations
    + @SerialVersionUID() + +
    +
  3. + + +

    + + abstract + class + + + Value extends Ordered[Value] with Serializable + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    Annotations
    + @SerialVersionUID() + +
    +
  4. + + +

    + + + class + + + ValueSet extends AbstractSet[Value] with SortedSet[Value] with SortedSetLike[Value, ValueSet] with Serializable + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
+
+ + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + + val + + + CLIENT: Value + +

    + + Permalink + + + +
  5. + + +

    + + + val + + + SST: Value + +

    + + Permalink + + + +
  6. + + +

    + + final + def + + + Value(i: Int, name: String): Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  7. + + +

    + + final + def + + + Value(name: String): Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  8. + + +

    + + final + def + + + Value(i: Int): Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  9. + + +

    + + final + def + + + Value: Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  10. + + +

    + + final + def + + + apply(x: Int): Value + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
  11. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  13. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  15. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  16. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  17. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  18. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  19. + + +

    + + final + def + + + maxId: Int + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
  20. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  21. + + +

    + + + var + + + nextId: Int + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  22. + + +

    + + + var + + + nextName: Iterator[String] + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  23. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  24. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  25. + + +

    + + + def + + + readResolve(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  26. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  27. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    Enumeration → AnyRef → Any
    +
  28. + + +

    + + + def + + + values: ValueSet + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
  29. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  30. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  31. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  32. + + +

    + + final + def + + + withName(s: String): Value + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
+
+ + + + +
+ +
+
+

Inherited from Enumeration

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory.html new file mode 100644 index 0000000..75eadab --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory.html @@ -0,0 +1,504 @@ + + + + SinkCategory - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.SinkCategory + + + + + + + + + + + + + + + + + +

+ + + class + + + SinkCategory extends AnyRef + +

+ +
+ Linear Supertypes +
AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. SinkCategory
  2. AnyRef
  3. Any
  4. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + SinkCategory() + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory$.html new file mode 100644 index 0000000..3d0b6ff --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory$.html @@ -0,0 +1,976 @@ + + + + SourceCategory - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.SourceCategory + + + + + + + + + + + + + + + + + +

+ + + object + + + SourceCategory extends Enumeration + +

+ +

Category use to explain the data source which the Spark application could reading. +

+ Linear Supertypes +
Enumeration, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. SourceCategory
  2. Enumeration
  3. Serializable
  4. Serializable
  5. AnyRef
  6. Any
  7. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + +
+

Type Members

+
  1. + + +

    + + + type + + + Type = Value + +

    + + Permalink + + + +
  2. + + +

    + + + class + + + Val extends Value with Serializable + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    Annotations
    + @SerialVersionUID() + +
    +
  3. + + +

    + + abstract + class + + + Value extends Ordered[Value] with Serializable + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    Annotations
    + @SerialVersionUID() + +
    +
  4. + + +

    + + + class + + + ValueSet extends AbstractSet[Value] with SortedSet[Value] with SortedSetLike[Value, ValueSet] with Serializable + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
+
+ + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + + val + + + CSV: Value + +

    + + Permalink + + + +
  5. + + +

    + + + val + + + HBASE: Value + +

    + + Permalink + + + +
  6. + + +

    + + + val + + + HIVE: Value + +

    + + Permalink + + + +
  7. + + +

    + + + val + + + JANUS_GRAPH: Value + +

    + + Permalink + + + +
  8. + + +

    + + + val + + + JSON: Value + +

    + + Permalink + + + +
  9. + + +

    + + + val + + + KAFKA: Value + +

    + + Permalink + + + +
  10. + + +

    + + + val + + + MYSQL: Value + +

    + + Permalink + + + +
  11. + + +

    + + + val + + + NEO4J: Value + +

    + + Permalink + + + +
  12. + + +

    + + + val + + + ORC: Value + +

    + + Permalink + + + +
  13. + + +

    + + + val + + + PARQUET: Value + +

    + + Permalink + + + +
  14. + + +

    + + + val + + + PULSAR: Value + +

    + + Permalink + + + +
  15. + + +

    + + + val + + + SOCKET: Value + +

    + + Permalink + + + +
  16. + + +

    + + + val + + + TEXT: Value + +

    + + Permalink + + + +
  17. + + +

    + + final + def + + + Value(i: Int, name: String): Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  18. + + +

    + + final + def + + + Value(name: String): Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  19. + + +

    + + final + def + + + Value(i: Int): Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  20. + + +

    + + final + def + + + Value: Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  21. + + +

    + + final + def + + + apply(x: Int): Value + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
  22. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  23. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  24. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  25. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  26. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  27. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  28. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  29. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  30. + + +

    + + final + def + + + maxId: Int + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
  31. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  32. + + +

    + + + var + + + nextId: Int + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  33. + + +

    + + + var + + + nextName: Iterator[String] + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  34. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  35. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  36. + + +

    + + + def + + + readResolve(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  37. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  38. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    Enumeration → AnyRef → Any
    +
  39. + + +

    + + + def + + + values: ValueSet + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
  40. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  41. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  42. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  43. + + +

    + + final + def + + + withName(s: String): Value + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
+
+ + + + +
+ +
+
+

Inherited from Enumeration

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory.html new file mode 100644 index 0000000..4b092c0 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory.html @@ -0,0 +1,504 @@ + + + + SourceCategory - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.SourceCategory + + + + + + + + + + + + + + + + + +

+ + + class + + + SourceCategory extends AnyRef + +

+ +
+ Linear Supertypes +
AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. SourceCategory
  2. AnyRef
  3. Any
  4. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + SourceCategory() + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry$.html new file mode 100644 index 0000000..eff2a11 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry$.html @@ -0,0 +1,505 @@ + + + + SparkConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.SparkConfigEntry + + + + + + + + + + + + + + + + + +

+ + + object + + + SparkConfigEntry extends Serializable + +

+ +
+ Linear Supertypes +
Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. SparkConfigEntry
  2. Serializable
  3. Serializable
  4. AnyRef
  5. Any
  6. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + + def + + + apply(config: Config): SparkConfigEntry + +

    + + Permalink + + + +
  5. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  6. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  18. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry.html new file mode 100644 index 0000000..e25615d --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry.html @@ -0,0 +1,496 @@ + + + + SparkConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.SparkConfigEntry + + + + + + + + + + + + + + + + + +

+ + + case class + + + SparkConfigEntry(map: scala.Predef.Map[String, String]) extends Product with Serializable + +

+ +

SparkConfigEntry support key-value pairs for spark session. +

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. SparkConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + SparkConfigEntry(map: scala.Predef.Map[String, String]) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  8. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  10. + + +

    + + + val + + + map: scala.Predef.Map[String, String] + +

    + + Permalink + + + +
  11. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  12. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    SparkConfigEntry → AnyRef → Any
    +
  16. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  17. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/StreamingDataSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/StreamingDataSourceConfigEntry.html new file mode 100644 index 0000000..b0093ad --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/StreamingDataSourceConfigEntry.html @@ -0,0 +1,524 @@ + + + + StreamingDataSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.StreamingDataSourceConfigEntry + + + + + + + + + + + + + + + +
+ Trait +

com.vesoft.nebula.tools.importer.config

+

StreamingDataSourceConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + sealed + trait + + + StreamingDataSourceConfigEntry extends DataSourceConfigEntry + +

+ +
+ Linear Supertypes + +
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. StreamingDataSourceConfigEntry
  2. DataSourceConfigEntry
  3. AnyRef
  4. Any
  5. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + +
+

Abstract Value Members

+
  1. + + +

    + + abstract + def + + + category: SourceCategory.Value + +

    + + Permalink + + +
    Definition Classes
    DataSourceConfigEntry
    +
  2. + + +

    + + abstract + def + + + intervalSeconds: Int + +

    + + Permalink + + + +
+
+ +
+

Concrete Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from DataSourceConfigEntry

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/TagConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/TagConfigEntry.html new file mode 100644 index 0000000..4aa24e1 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/TagConfigEntry.html @@ -0,0 +1,648 @@ + + + + TagConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.TagConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

TagConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + TagConfigEntry(name: String, dataSourceConfigEntry: DataSourceConfigEntry, dataSinkConfigEntry: DataSinkConfigEntry, fields: scala.List[String], nebulaFields: scala.List[String], vertexField: String, vertexPolicy: Option[KeyPolicy.Value], batch: Int, partition: Int, checkPointPath: Option[String]) extends SchemaConfigEntry with Product with Serializable + +

+ +
+ Linear Supertypes +
Serializable, Serializable, Product, Equals, SchemaConfigEntry, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. TagConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. SchemaConfigEntry
  7. AnyRef
  8. Any
  9. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + TagConfigEntry(name: String, dataSourceConfigEntry: DataSourceConfigEntry, dataSinkConfigEntry: DataSinkConfigEntry, fields: scala.List[String], nebulaFields: scala.List[String], vertexField: String, vertexPolicy: Option[KeyPolicy.Value], batch: Int, partition: Int, checkPointPath: Option[String]) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + val + + + batch: Int + +

    + + Permalink + + +

    vertex or edge amount of one batch import

    vertex or edge amount of one batch import

    Definition Classes
    TagConfigEntrySchemaConfigEntry
    +
  6. + + +

    + + + val + + + checkPointPath: Option[String] + +

    + + Permalink + + +

    check point path

    check point path

    Definition Classes
    TagConfigEntrySchemaConfigEntry
    +
  7. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  8. + + +

    + + + val + + + dataSinkConfigEntry: DataSinkConfigEntry + +

    + + Permalink + + +

    seeDataSinkConfigEntry

    +
  9. + + +

    + + + val + + + dataSourceConfigEntry: DataSourceConfigEntry + +

    + + Permalink + + +

    seeDataSourceConfigEntry

    +
  10. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  11. + + +

    + + + val + + + fields: scala.List[String] + +

    + + Permalink + + +

    data source fields which are going to be import to nebula as properties

    data source fields which are going to be import to nebula as properties

    Definition Classes
    TagConfigEntrySchemaConfigEntry
    +
  12. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  13. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  14. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  15. + + +

    + + + val + + + name: String + +

    + + Permalink + + +

    nebula tag or edge name

    nebula tag or edge name

    Definition Classes
    TagConfigEntrySchemaConfigEntry
    +
  16. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + + val + + + nebulaFields: scala.List[String] + +

    + + Permalink + + +

    nebula properties which are going to fill value with data source value

    nebula properties which are going to fill value with data source value

    Definition Classes
    TagConfigEntrySchemaConfigEntry
    +
  18. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + val + + + partition: Int + +

    + + Permalink + + +

    spark partition

    spark partition

    Definition Classes
    TagConfigEntrySchemaConfigEntry
    +
  21. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  22. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    TagConfigEntry → AnyRef → Any
    +
  23. + + +

    + + + val + + + vertexField: String + +

    + + Permalink + + + +
  24. + + +

    + + + val + + + vertexPolicy: Option[KeyPolicy.Value] + +

    + + Permalink + + + +
  25. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  26. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  27. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from SchemaConfigEntry

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Type$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Type$.html new file mode 100644 index 0000000..4514358 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Type$.html @@ -0,0 +1,786 @@ + + + + Type - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.Type + + + + + + + + + + + + + + + +
+ Object +

com.vesoft.nebula.tools.importer.config

+

Type

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + object + + + Type extends Enumeration + +

+ +
+ Linear Supertypes +
Enumeration, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. Type
  2. Enumeration
  3. Serializable
  4. Serializable
  5. AnyRef
  6. Any
  7. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + +
+

Type Members

+
  1. + + +

    + + + type + + + Type = Value + +

    + + Permalink + + + +
  2. + + +

    + + + class + + + Val extends Value with Serializable + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    Annotations
    + @SerialVersionUID() + +
    +
  3. + + +

    + + abstract + class + + + Value extends Ordered[Value] with Serializable + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    Annotations
    + @SerialVersionUID() + +
    +
  4. + + +

    + + + class + + + ValueSet extends AbstractSet[Value] with SortedSet[Value] with SortedSetLike[Value, ValueSet] with Serializable + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
+
+ + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + + val + + + EDGE: Value + +

    + + Permalink + + + +
  5. + + +

    + + + val + + + VERTEX: Value + +

    + + Permalink + + + +
  6. + + +

    + + final + def + + + Value(i: Int, name: String): Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  7. + + +

    + + final + def + + + Value(name: String): Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  8. + + +

    + + final + def + + + Value(i: Int): Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  9. + + +

    + + final + def + + + Value: Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  10. + + +

    + + final + def + + + apply(x: Int): Value + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
  11. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  13. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  15. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  16. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  17. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  18. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  19. + + +

    + + final + def + + + maxId: Int + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
  20. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  21. + + +

    + + + var + + + nextId: Int + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  22. + + +

    + + + var + + + nextName: Iterator[String] + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  23. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  24. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  25. + + +

    + + + def + + + readResolve(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  26. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  27. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    Enumeration → AnyRef → Any
    +
  28. + + +

    + + + def + + + values: ValueSet + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
  29. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  30. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  31. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  32. + + +

    + + final + def + + + withName(s: String): Value + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
+
+ + + + +
+ +
+
+

Inherited from Enumeration

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/UserConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/UserConfigEntry.html new file mode 100644 index 0000000..17fb308 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/UserConfigEntry.html @@ -0,0 +1,511 @@ + + + + UserConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.UserConfigEntry + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.config

+

UserConfigEntry

Related Doc: + package config +

+ + Permalink + + +
+ +

+ + + case class + + + UserConfigEntry(user: String, password: String) extends Product with Serializable + +

+ +

UserConfigEntry is used when the client login the nebula graph service. +

+ Linear Supertypes +
Serializable, Serializable, Product, Equals, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. UserConfigEntry
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + UserConfigEntry(user: String, password: String) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  8. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  10. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  11. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  12. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + + val + + + password: String + +

    + + Permalink + + + +
  14. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    UserConfigEntry → AnyRef → Any
    +
  16. + + +

    + + + val + + + user: String + +

    + + Permalink + + + +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/package.html new file mode 100644 index 0000000..b693879 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/package.html @@ -0,0 +1,700 @@ + + + + config - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config + + + + + + + + + + + + + + + +
+ Package +

com.vesoft.nebula.tools.importer

+

config

+ + Permalink + + +
+ +

+ + + package + + + config + +

+ +
+ + +
+
+ + +
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + +
+

Type Members

+
  1. + + +

    + + + case class + + + Configs(databaseConfig: DataBaseConfigEntry, userConfig: UserConfigEntry, connectionConfig: ConnectionConfigEntry, executionConfig: ExecutionConfigEntry, errorConfig: ErrorConfigEntry, rateConfig: RateConfigEntry, sparkConfigEntry: SparkConfigEntry, tagsConfig: scala.List[TagConfigEntry], edgesConfig: scala.List[EdgeConfigEntry], hiveConfigEntry: Option[HiveConfigEntry] = None) extends Product with Serializable + +

    + + Permalink + + +

    Configs +

    +
  2. + + +

    + + + case class + + + ConnectionConfigEntry(timeout: Int, retry: Int) extends Product with Serializable + +

    + + Permalink + + +

    ConnectionConfigEntry +

    +
  3. + + +

    + + + case class + + + DataBaseConfigEntry(graphAddress: scala.List[String], space: String, metaAddresses: scala.List[String]) extends Product with Serializable + +

    + + Permalink + + +

    DataBaseConfigEntry describe the nebula cluster's address and which space will be used.

    +
  4. + + +

    + + sealed + trait + + + DataSinkConfigEntry extends AnyRef + +

    + + Permalink + + +

    DataSinkConfigEntry +

    +
  5. + + +

    + + sealed + trait + + + DataSourceConfigEntry extends AnyRef + +

    + + Permalink + + +

    DataSourceConfigEntry +

    +
  6. + + +

    + + + case class + + + EdgeConfigEntry(name: String, dataSourceConfigEntry: DataSourceConfigEntry, dataSinkConfigEntry: DataSinkConfigEntry, fields: scala.List[String], nebulaFields: scala.List[String], sourceField: String, sourcePolicy: Option[KeyPolicy.Value], rankingField: Option[String], targetField: String, targetPolicy: Option[KeyPolicy.Value], isGeo: Boolean, latitude: Option[String], longitude: Option[String], batch: Int, partition: Int, checkPointPath: Option[String]) extends SchemaConfigEntry with Product with Serializable + +

    + + Permalink + + +

    +
  7. + + +

    + + + case class + + + ErrorConfigEntry(errorPath: String, errorMaxSize: Int) extends Product with Serializable + +

    + + Permalink + + +

    ErrorConfigEntry +

    +
  8. + + +

    + + + case class + + + ExecutionConfigEntry(timeout: Int, retry: Int, interval: Int) extends Product with Serializable + +

    + + Permalink + + +

    ExecutionConfigEntry +

    +
  9. + + +

    + + + case class + + + FileBaseSinkConfigEntry(category: SinkCategory.Value, localPath: String, remotePath: String) extends DataSinkConfigEntry with Product with Serializable + +

    + + Permalink + + +

    FileBaseSinkConfigEntry +

    +
  10. + + +

    + + + case class + + + FileBaseSourceConfigEntry(category: SourceCategory.Value, path: String, separator: Option[String] = None, header: Option[Boolean] = None) extends FileDataSourceConfigEntry with Product with Serializable + +

    + + Permalink + + +

    FileBaseSourceConfigEntry +

    +
  11. + + +

    + + sealed + trait + + + FileDataSourceConfigEntry extends DataSourceConfigEntry + +

    + + Permalink + + + +
  12. + + +

    + + + case class + + + HBaseSourceConfigEntry(category: SourceCategory.Value, host: String, port: String, table: String, columnFamily: String, fields: scala.List[String]) extends ServerDataSourceConfigEntry with Product with Serializable + +

    + + Permalink + + +

    HBaseSourceConfigEntry

    +
  13. + + +

    + + + case class + + + HiveConfigEntry(waredir: String, connectionURL: String, connectionDriverName: String, connectionUserName: String, connectionPassWord: String) extends Product with Serializable + +

    + + Permalink + + + +
  14. + + +

    + + + case class + + + HiveSourceConfigEntry(category: SourceCategory.Value, sentence: String) extends ServerDataSourceConfigEntry with Product with Serializable + +

    + + Permalink + + +

    HiveSourceConfigEntry +

    +
  15. + + +

    + + + case class + + + JanusGraphSourceConfigEntry(category: SourceCategory.Value, sentence: String, isEdge: Boolean) extends ServerDataSourceConfigEntry with Product with Serializable + +

    + + Permalink + + + +
  16. + + +

    + + + case class + + + KafkaSourceConfigEntry(category: SourceCategory.Value, intervalSeconds: Int, server: String, topic: String) extends StreamingDataSourceConfigEntry with Product with Serializable + +

    + + Permalink + + +

    TODO: Support more config item about Kafka Consumer +

    +
  17. + + +

    + + + case class + + + MySQLSourceConfigEntry(category: SourceCategory.Value, host: String, port: Int, database: String, table: String, user: String, password: String, sentence: String) extends ServerDataSourceConfigEntry with Product with Serializable + +

    + + Permalink + + +

    MySQLSourceConfigEntry +

    +
  18. + + +

    + + + case class + + + NebulaSinkConfigEntry(category: SinkCategory.Value, addresses: scala.List[String]) extends DataSinkConfigEntry with Product with Serializable + +

    + + Permalink + + +

    NebulaSinkConfigEntry use to specified the nebula service's address.

    +
  19. + + +

    + + + case class + + + Neo4JSourceConfigEntry(category: SourceCategory.Value, sentence: String, name: String, server: String, user: String, password: String, database: Option[String], encryption: Boolean, parallel: Int, checkPointPath: Option[String]) extends ServerDataSourceConfigEntry with Product with Serializable + +

    + + Permalink + + +

    Neo4JSourceConfigEntry +

    Neo4JSourceConfigEntry +

    checkPointPath

    use save resume data dir path.

    +
  20. + + +

    + + + case class + + + PulsarSourceConfigEntry(category: SourceCategory.Value, intervalSeconds: Int, serviceUrl: String, adminUrl: String, options: scala.Predef.Map[String, String]) extends StreamingDataSourceConfigEntry with Product with Serializable + +

    + + Permalink + + +

    PulsarSourceConfigEntry +

    PulsarSourceConfigEntry +

    adminUrl

    use to get data schema.

    +
  21. + + +

    + + + case class + + + RateConfigEntry(limit: Int, timeout: Int) extends Product with Serializable + +

    + + Permalink + + +

    RateConfigEntry +

    +
  22. + + +

    + + sealed + trait + + + SchemaConfigEntry extends AnyRef + +

    + + Permalink + + +

    SchemaConfigEntry is tag/edge super class use to save some basic parameter for importer.

    +
  23. + + +

    + + sealed + trait + + + ServerDataSourceConfigEntry extends DataSourceConfigEntry + +

    + + Permalink + + + +
  24. + + +

    + + + class + + + SinkCategory extends AnyRef + +

    + + Permalink + + + +
  25. + + +

    + + + class + + + SourceCategory extends AnyRef + +

    + + Permalink + + + +
  26. + + +

    + + + case class + + + SparkConfigEntry(map: scala.Predef.Map[String, String]) extends Product with Serializable + +

    + + Permalink + + +

    SparkConfigEntry support key-value pairs for spark session.

    +
  27. + + +

    + + sealed + trait + + + StreamingDataSourceConfigEntry extends DataSourceConfigEntry + +

    + + Permalink + + + +
  28. + + +

    + + + case class + + + TagConfigEntry(name: String, dataSourceConfigEntry: DataSourceConfigEntry, dataSinkConfigEntry: DataSinkConfigEntry, fields: scala.List[String], nebulaFields: scala.List[String], vertexField: String, vertexPolicy: Option[KeyPolicy.Value], batch: Int, partition: Int, checkPointPath: Option[String]) extends SchemaConfigEntry with Product with Serializable + +

    + + Permalink + + +

    +
  29. + + +

    + + + case class + + + UserConfigEntry(user: String, password: String) extends Product with Serializable + +

    + + Permalink + + +

    UserConfigEntry is used when the client login the nebula graph service.

    +
+
+ + + +
+

Value Members

+
  1. + + +

    + + + object + + + Configs extends Serializable + +

    + + Permalink + + + +
  2. + + +

    + + + object + + + SinkCategory extends Enumeration + +

    + + Permalink + + +

    SinkCategory is used to expression the writer's type.

    SinkCategory is used to expression the writer's type. +SST is not supported yet. +

    +
  3. + + +

    + + + object + + + SourceCategory extends Enumeration + +

    + + Permalink + + +

    Category use to explain the data source which the Spark application could reading.

    +
  4. + + +

    + + + object + + + SparkConfigEntry extends Serializable + +

    + + Permalink + + +

    +
  5. + + +

    + + + object + + + Type extends Enumeration + +

    + + Permalink + + + +
+
+ + + + +
+ +
+ + +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edge.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edge.html new file mode 100644 index 0000000..cf3c80b --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edge.html @@ -0,0 +1,578 @@ + + + + Edge - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.Edge + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer

+

Edge

Related Doc: + package importer +

+ + Permalink + + +
+ +

+ + + case class + + + Edge(source: VertexIDSlice, destination: VertexIDSlice, ranking: Option[EdgeRank], values: PropertyValues) extends Product with Serializable + +

+ +
+ Linear Supertypes +
Serializable, Serializable, Product, Equals, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. Edge
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + Edge(source: VertexIDSlice, destination: VertexIDSlice, values: PropertyValues) + +

    + + Permalink + + + +
  2. + + +

    + + + new + + + Edge(source: VertexIDSlice, destination: VertexIDSlice, ranking: Option[EdgeRank], values: PropertyValues) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + val + + + destination: VertexIDSlice + +

    + + Permalink + + + +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  11. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  12. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + + def + + + propertyValues: String + +

    + + Permalink + + + +
  15. + + +

    + + + val + + + ranking: Option[EdgeRank] + +

    + + Permalink + + + +
  16. + + +

    + + + val + + + source: VertexIDSlice + +

    + + Permalink + + + +
  17. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    Edge → AnyRef → Any
    +
  19. + + +

    + + + val + + + values: PropertyValues + +

    + + Permalink + + + +
  20. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edges.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edges.html new file mode 100644 index 0000000..b78bb5f --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edges.html @@ -0,0 +1,561 @@ + + + + Edges - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.Edges + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer

+

Edges

Related Doc: + package importer +

+ + Permalink + + +
+ +

+ + + case class + + + Edges(names: PropertyNames, values: scala.List[Edge], sourcePolicy: Option[KeyPolicy.Value] = None, targetPolicy: Option[KeyPolicy.Value] = None) extends Product with Serializable + +

+ +
+ Linear Supertypes +
Serializable, Serializable, Product, Equals, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. Edges
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + Edges(names: PropertyNames, values: scala.List[Edge], sourcePolicy: Option[KeyPolicy.Value] = None, targetPolicy: Option[KeyPolicy.Value] = None) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  8. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  10. + + +

    + + + val + + + names: PropertyNames + +

    + + Permalink + + + +
  11. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  12. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + + def + + + propertyNames: String + +

    + + Permalink + + + +
  15. + + +

    + + + val + + + sourcePolicy: Option[KeyPolicy.Value] + +

    + + Permalink + + + +
  16. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + + val + + + targetPolicy: Option[KeyPolicy.Value] + +

    + + Permalink + + + +
  18. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    Edges → AnyRef → Any
    +
  19. + + +

    + + + val + + + values: scala.List[Edge] + +

    + + Permalink + + + +
  20. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$KeyPolicy$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$KeyPolicy$.html new file mode 100644 index 0000000..e50aaad --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$KeyPolicy$.html @@ -0,0 +1,786 @@ + + + + KeyPolicy - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.KeyPolicy + + + + + + + + + + + + + + + +
+ Object +

com.vesoft.nebula.tools.importer

+

KeyPolicy

Related Doc: + package importer +

+ + Permalink + + +
+ +

+ + + object + + + KeyPolicy extends Enumeration + +

+ +
+ Linear Supertypes +
Enumeration, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. KeyPolicy
  2. Enumeration
  3. Serializable
  4. Serializable
  5. AnyRef
  6. Any
  7. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + +
+

Type Members

+
  1. + + +

    + + + type + + + POLICY = Value + +

    + + Permalink + + + +
  2. + + +

    + + + class + + + Val extends Value with Serializable + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    Annotations
    + @SerialVersionUID() + +
    +
  3. + + +

    + + abstract + class + + + Value extends Ordered[Value] with Serializable + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    Annotations
    + @SerialVersionUID() + +
    +
  4. + + +

    + + + class + + + ValueSet extends AbstractSet[Value] with SortedSet[Value] with SortedSetLike[Value, ValueSet] with Serializable + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
+
+ + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + + val + + + HASH: Value + +

    + + Permalink + + + +
  5. + + +

    + + + val + + + UUID: Value + +

    + + Permalink + + + +
  6. + + +

    + + final + def + + + Value(i: Int, name: String): Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  7. + + +

    + + final + def + + + Value(name: String): Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  8. + + +

    + + final + def + + + Value(i: Int): Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  9. + + +

    + + final + def + + + Value: Value + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  10. + + +

    + + final + def + + + apply(x: Int): Value + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
  11. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  13. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  15. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  16. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  17. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  18. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  19. + + +

    + + final + def + + + maxId: Int + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
  20. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  21. + + +

    + + + var + + + nextId: Int + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  22. + + +

    + + + var + + + nextName: Iterator[String] + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  23. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  24. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  25. + + +

    + + + def + + + readResolve(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected
    Definition Classes
    Enumeration
    +
  26. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  27. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    Enumeration → AnyRef → Any
    +
  28. + + +

    + + + def + + + values: ValueSet + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
  29. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  30. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  31. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  32. + + +

    + + final + def + + + withName(s: String): Value + +

    + + Permalink + + +
    Definition Classes
    Enumeration
    +
+
+ + + + +
+ +
+
+

Inherited from Enumeration

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Offset.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Offset.html new file mode 100644 index 0000000..64cfd56 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Offset.html @@ -0,0 +1,493 @@ + + + + Offset - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.Offset + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer

+

Offset

Related Doc: + package importer +

+ + Permalink + + +
+ +

+ + + case class + + + Offset(start: Long, size: Long) extends Product with Serializable + +

+ +
+ Linear Supertypes +
Serializable, Serializable, Product, Equals, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. Offset
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + Offset(start: Long, size: Long) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  8. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  10. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  11. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  12. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + + val + + + size: Long + +

    + + Permalink + + + +
  14. + + +

    + + + val + + + start: Long + +

    + + Permalink + + + +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  17. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertex.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertex.html new file mode 100644 index 0000000..0f53ecb --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertex.html @@ -0,0 +1,527 @@ + + + + Vertex - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.Vertex + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer

+

Vertex

Related Doc: + package importer +

+ + Permalink + + +
+ +

+ + + case class + + + Vertex(vertexID: VertexIDSlice, values: PropertyValues) extends Product with Serializable + +

+ +
+ Linear Supertypes +
Serializable, Serializable, Product, Equals, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. Vertex
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + Vertex(vertexID: VertexIDSlice, values: PropertyValues) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  8. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  10. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  11. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  12. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + + def + + + propertyValues: String + +

    + + Permalink + + + +
  14. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    Vertex → AnyRef → Any
    +
  16. + + +

    + + + val + + + values: PropertyValues + +

    + + Permalink + + + +
  17. + + +

    + + + val + + + vertexID: VertexIDSlice + +

    + + Permalink + + + +
  18. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertices.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertices.html new file mode 100644 index 0000000..5f5ef6b --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertices.html @@ -0,0 +1,544 @@ + + + + Vertices - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.Vertices + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer

+

Vertices

Related Doc: + package importer +

+ + Permalink + + +
+ +

+ + + case class + + + Vertices(names: PropertyNames, values: scala.List[Vertex], policy: Option[KeyPolicy.Value] = None) extends Product with Serializable + +

+ +
+ Linear Supertypes +
Serializable, Serializable, Product, Equals, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. Vertices
  2. Serializable
  3. Serializable
  4. Product
  5. Equals
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + Vertices(names: PropertyNames, values: scala.List[Vertex], policy: Option[KeyPolicy.Value] = None) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  8. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  10. + + +

    + + + val + + + names: PropertyNames + +

    + + Permalink + + + +
  11. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  12. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + + val + + + policy: Option[KeyPolicy.Value] + +

    + + Permalink + + + +
  15. + + +

    + + + def + + + propertyNames: String + +

    + + Permalink + + + +
  16. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    Vertices → AnyRef → Any
    +
  18. + + +

    + + + val + + + values: scala.List[Vertex] + +

    + + Permalink + + + +
  19. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from Product

+
+

Inherited from Equals

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package.html new file mode 100644 index 0000000..e784aa3 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package.html @@ -0,0 +1,709 @@ + + + + importer - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer + + + + + + + + + + + + + + + +
+ Package +

com.vesoft.nebula.tools

+

importer

+ + Permalink + + +
+ +

+ + + package + + + importer + +

+ +
+ Linear Supertypes +
AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. importer
  2. AnyRef
  3. Any
  4. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + +
+

Type Members

+
  1. + + +

    + + final + case class + + + Argument(config: File = new File("application.conf"), hive: Boolean = false, directly: Boolean = false, dry: Boolean = false, reload: String = "") extends Product with Serializable + +

    + + Permalink + + + +
  2. + + +

    + + + case class + + + Edge(source: VertexIDSlice, destination: VertexIDSlice, ranking: Option[EdgeRank], values: PropertyValues) extends Product with Serializable + +

    + + Permalink + + + +
  3. + + +

    + + + type + + + EdgeRank = Long + +

    + + Permalink + + + +
  4. + + +

    + + + type + + + EdgeType = Int + +

    + + Permalink + + + +
  5. + + +

    + + + type + + + EdgeVersion = Long + +

    + + Permalink + + + +
  6. + + +

    + + + case class + + + Edges(names: PropertyNames, values: scala.List[Edge], sourcePolicy: Option[KeyPolicy.Value] = None, targetPolicy: Option[KeyPolicy.Value] = None) extends Product with Serializable + +

    + + Permalink + + + +
  7. + + +

    + + + class + + + GraphProvider extends AutoCloseable with Serializable + +

    + + Permalink + + +

    +
  8. + + +

    + + + type + + + GraphSpaceID = Int + +

    + + Permalink + + + +
  9. + + +

    + + + class + + + MetaProvider extends AutoCloseable with Serializable + +

    + + Permalink + + +

    MetaProvider provide nebula graph meta query operations.

    +
  10. + + +

    + + + case class + + + Offset(start: Long, size: Long) extends Product with Serializable + +

    + + Permalink + + + +
  11. + + +

    + + + type + + + PartitionID = Int + +

    + + Permalink + + + +
  12. + + +

    + + + type + + + ProcessResult = ListBuffer[WriterResult] + +

    + + Permalink + + + +
  13. + + +

    + + + type + + + PropertyNames = scala.collection.immutable.List[String] + +

    + + Permalink + + + +
  14. + + +

    + + + type + + + PropertyValues = scala.collection.immutable.List[Any] + +

    + + Permalink + + + +
  15. + + +

    + + + type + + + SchemaID = (TagID, EdgeType) + +

    + + Permalink + + + +
  16. + + +

    + + + type + + + SchemaVersion = (TagVersion, EdgeVersion) + +

    + + Permalink + + + +
  17. + + +

    + + + type + + + TagID = Int + +

    + + Permalink + + + +
  18. + + +

    + + + type + + + TagVersion = Long + +

    + + Permalink + + + +
  19. + + +

    + + final + case class + + + TooManyErrorsException(message: String) extends Exception with Product with Serializable + +

    + + Permalink + + + +
  20. + + +

    + + + case class + + + Vertex(vertexID: VertexIDSlice, values: PropertyValues) extends Product with Serializable + +

    + + Permalink + + + +
  21. + + +

    + + + type + + + VertexID = Long + +

    + + Permalink + + + +
  22. + + +

    + + + type + + + VertexIDSlice = String + +

    + + Permalink + + + +
  23. + + +

    + + + case class + + + Vertices(names: PropertyNames, values: scala.List[Vertex], policy: Option[KeyPolicy.Value] = None) extends Product with Serializable + +

    + + Permalink + + + +
  24. + + +

    + + + type + + + WriterResult = ListenableFuture[Optional[Integer]] + +

    + + Permalink + + + +
+
+ + + +
+

Value Members

+
  1. + + +

    + + + object + + + CheckPointHandler + +

    + + Permalink + + +

    CheckPointHandler handle the checkpoint files for Neo4j and Janusgraph +

    +
  2. + + +

    + + + object + + + ErrorHandler + +

    + + Permalink + + + +
  3. + + +

    + + + object + + + Exchange + +

    + + Permalink + + +

    SparkClientGenerator is a simple spark job used to write data into Nebula Graph parallel.

    +
  4. + + +

    + + + object + + + KeyPolicy extends Enumeration + +

    + + Permalink + + + +
  5. + + +

    + + + object + + + VidType extends Enumeration + +

    + + Permalink + + + +
  6. + + +

    + + + package + + + config + +

    + + Permalink + + + +
  7. + + +

    + + + package + + + processor + +

    + + Permalink + + + +
  8. + + +

    + + + package + + + reader + +

    + + Permalink + + + +
  9. + + +

    + + + package + + + utils + +

    + + Permalink + + + +
  10. + + +

    + + + package + + + writer + +

    + + Permalink + + + +
+
+ + + + +
+ +
+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.html new file mode 100644 index 0000000..e1e2959 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.html @@ -0,0 +1,582 @@ + + + + EdgeProcessor - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.processor.EdgeProcessor + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.processor

+

EdgeProcessor

Related Doc: + package processor +

+ + Permalink + + +
+ +

+ + + class + + + EdgeProcessor extends Processor + +

+ +
+ Linear Supertypes +
Processor, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. EdgeProcessor
  2. Processor
  3. Serializable
  4. Serializable
  5. AnyRef
  6. Any
  7. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + EdgeProcessor(data: DataFrame, edgeConfig: EdgeConfigEntry, fieldKeys: scala.List[String], nebulaKeys: scala.List[String], config: Configs, batchSuccess: LongAccumulator, batchFailure: LongAccumulator) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + extraValue(row: org.apache.spark.sql.Row, field: String, fieldTypeMap: scala.Predef.Map[String, Int], toBytes: Boolean = false): Any + +

    + + Permalink + + +

    handle special types of attributes

    handle special types of attributes

    String type: add "" for attribute value, if value contains escape symbol,then keep it.

    Date type: add date() function for attribute value. +eg: convert attribute value 2020-01-01 to date("2020-01-01")

    Time type: add time() function for attribute value. +eg: convert attribute value 12:12:12:1111 to time("12:12:12:1111")

    DataTime type: add datetime() function for attribute value. +eg: convert attribute value 2020-01-01T22:30:40 to datetime("2020-01-01T22:30:40") +

    Definition Classes
    Processor
    +
  9. + + +

    + + + def + + + fetchOffset(path: String): Long + +

    + + Permalink + + +
    Definition Classes
    Processor
    +
  10. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  11. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + + def + + + getLong(row: org.apache.spark.sql.Row, field: String): Long + +

    + + Permalink + + +
    Definition Classes
    Processor
    +
  13. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  14. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  15. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + + def + + + process(): Unit + +

    + + Permalink + + +

    process dataframe to vertices or edges +

    process dataframe to vertices or edges +

    Definition Classes
    EdgeProcessorProcessor
    +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  21. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Processor

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/Processor.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/Processor.html new file mode 100644 index 0000000..110d7f7 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/Processor.html @@ -0,0 +1,568 @@ + + + + Processor - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.processor.Processor + + + + + + + + + + + + + + + +
+ Trait +

com.vesoft.nebula.tools.importer.processor

+

Processor

Related Doc: + package processor +

+ + Permalink + + +
+ +

+ + + trait + + + Processor extends Serializable + +

+ +

processor is a converter. +It is responsible for converting the dataframe row data into Nebula Graph's vertex or edge, +and submit data to writer. +

+ Linear Supertypes +
Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. Processor
  2. Serializable
  3. Serializable
  4. AnyRef
  5. Any
  6. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + +
+

Abstract Value Members

+
  1. + + +

    + + abstract + def + + + process(): Unit + +

    + + Permalink + + +

    process dataframe to vertices or edges +

    +
+
+ +
+

Concrete Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + extraValue(row: org.apache.spark.sql.Row, field: String, fieldTypeMap: scala.Predef.Map[String, Int], toBytes: Boolean = false): Any + +

    + + Permalink + + +

    handle special types of attributes

    handle special types of attributes

    String type: add "" for attribute value, if value contains escape symbol,then keep it.

    Date type: add date() function for attribute value. +eg: convert attribute value 2020-01-01 to date("2020-01-01")

    Time type: add time() function for attribute value. +eg: convert attribute value 12:12:12:1111 to time("12:12:12:1111")

    DataTime type: add datetime() function for attribute value. +eg: convert attribute value 2020-01-01T22:30:40 to datetime("2020-01-01T22:30:40") +

    +
  9. + + +

    + + + def + + + fetchOffset(path: String): Long + +

    + + Permalink + + + +
  10. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  11. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + + def + + + getLong(row: org.apache.spark.sql.Row, field: String): Long + +

    + + Permalink + + + +
  13. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  14. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  15. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  20. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/ReloadProcessor.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/ReloadProcessor.html new file mode 100644 index 0000000..7048cd8 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/ReloadProcessor.html @@ -0,0 +1,582 @@ + + + + ReloadProcessor - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.processor.ReloadProcessor + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.processor

+

ReloadProcessor

Related Doc: + package processor +

+ + Permalink + + +
+ +

+ + + class + + + ReloadProcessor extends Processor + +

+ +
+ Linear Supertypes +
Processor, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. ReloadProcessor
  2. Processor
  3. Serializable
  4. Serializable
  5. AnyRef
  6. Any
  7. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + ReloadProcessor(data: DataFrame, config: Configs, batchSuccess: LongAccumulator, batchFailure: LongAccumulator) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + extraValue(row: org.apache.spark.sql.Row, field: String, fieldTypeMap: scala.Predef.Map[String, Int], toBytes: Boolean = false): Any + +

    + + Permalink + + +

    handle special types of attributes

    handle special types of attributes

    String type: add "" for attribute value, if value contains escape symbol,then keep it.

    Date type: add date() function for attribute value. +eg: convert attribute value 2020-01-01 to date("2020-01-01")

    Time type: add time() function for attribute value. +eg: convert attribute value 12:12:12:1111 to time("12:12:12:1111")

    DataTime type: add datetime() function for attribute value. +eg: convert attribute value 2020-01-01T22:30:40 to datetime("2020-01-01T22:30:40") +

    Definition Classes
    Processor
    +
  9. + + +

    + + + def + + + fetchOffset(path: String): Long + +

    + + Permalink + + +
    Definition Classes
    Processor
    +
  10. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  11. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + + def + + + getLong(row: org.apache.spark.sql.Row, field: String): Long + +

    + + Permalink + + +
    Definition Classes
    Processor
    +
  13. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  14. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  15. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + + def + + + process(): Unit + +

    + + Permalink + + +

    process dataframe to vertices or edges +

    process dataframe to vertices or edges +

    Definition Classes
    ReloadProcessorProcessor
    +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  21. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Processor

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.html new file mode 100644 index 0000000..f318e66 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.html @@ -0,0 +1,582 @@ + + + + VerticesProcessor - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.processor.VerticesProcessor + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.processor

+

VerticesProcessor

Related Doc: + package processor +

+ + Permalink + + +
+ +

+ + + class + + + VerticesProcessor extends Processor + +

+ +
+ Linear Supertypes +
Processor, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. VerticesProcessor
  2. Processor
  3. Serializable
  4. Serializable
  5. AnyRef
  6. Any
  7. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + VerticesProcessor(data: DataFrame, tagConfig: TagConfigEntry, fieldKeys: scala.List[String], nebulaKeys: scala.List[String], config: Configs, batchSuccess: LongAccumulator, batchFailure: LongAccumulator) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + extraValue(row: org.apache.spark.sql.Row, field: String, fieldTypeMap: scala.Predef.Map[String, Int], toBytes: Boolean = false): Any + +

    + + Permalink + + +

    handle special types of attributes

    handle special types of attributes

    String type: add "" for attribute value, if value contains escape symbol,then keep it.

    Date type: add date() function for attribute value. +eg: convert attribute value 2020-01-01 to date("2020-01-01")

    Time type: add time() function for attribute value. +eg: convert attribute value 12:12:12:1111 to time("12:12:12:1111")

    DataTime type: add datetime() function for attribute value. +eg: convert attribute value 2020-01-01T22:30:40 to datetime("2020-01-01T22:30:40") +

    Definition Classes
    Processor
    +
  9. + + +

    + + + def + + + fetchOffset(path: String): Long + +

    + + Permalink + + +
    Definition Classes
    Processor
    +
  10. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  11. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + + def + + + getLong(row: org.apache.spark.sql.Row, field: String): Long + +

    + + Permalink + + +
    Definition Classes
    Processor
    +
  13. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  14. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  15. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + + def + + + process(): Unit + +

    + + Permalink + + +

    process dataframe to vertices or edges +

    process dataframe to vertices or edges +

    Definition Classes
    VerticesProcessorProcessor
    +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  21. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Processor

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/package.html new file mode 100644 index 0000000..44f07b4 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/package.html @@ -0,0 +1,172 @@ + + + + processor - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.processor + + + + + + + + + + + + + + + +
+ Package +

com.vesoft.nebula.tools.importer

+

processor

+ + Permalink + + +
+ +

+ + + package + + + processor + +

+ +
+ + +
+
+ + +
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + +
+

Type Members

+
  1. + + +

    + + + class + + + EdgeProcessor extends Processor + +

    + + Permalink + + + +
  2. + + +

    + + + trait + + + Processor extends Serializable + +

    + + Permalink + + +

    processor is a converter.

    processor is a converter. +It is responsible for converting the dataframe row data into Nebula Graph's vertex or edge, +and submit data to writer. +

    +
  3. + + +

    + + + class + + + ReloadProcessor extends Processor + +

    + + Permalink + + + +
  4. + + +

    + + + class + + + VerticesProcessor extends Processor + +

    + + Permalink + + +

    +
+
+ + + + + + + + +
+ +
+ + +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CSVReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CSVReader.html new file mode 100644 index 0000000..cc0d17d --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CSVReader.html @@ -0,0 +1,580 @@ + + + + CSVReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.CSVReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

CSVReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + + class + + + CSVReader extends FileBaseReader + +

+ +

The CSVReader extend the FileBaseReader and support read csv file from HDFS. +All types of the structure are StringType. +

+ Linear Supertypes +
FileBaseReader, Reader, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. CSVReader
  2. FileBaseReader
  3. Reader
  4. Serializable
  5. Serializable
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + CSVReader(session: SparkSession, csvConfig: FileBaseSourceConfigEntry) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    FileBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + val + + + path: String + +

    + + Permalink + + +
    Definition Classes
    FileBaseReader
    +
  17. + + +

    + + + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    CSVReaderReader
    +
  18. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    CSVReaderFileBaseReaderReader
    +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  21. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from FileBaseReader

+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CheckPointSupport.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CheckPointSupport.html new file mode 100644 index 0000000..8576dc9 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CheckPointSupport.html @@ -0,0 +1,506 @@ + + + + CheckPointSupport - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.CheckPointSupport + + + + + + + + + + + + + + + +
+ Trait +

com.vesoft.nebula.tools.importer.reader

+

CheckPointSupport

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + + trait + + + CheckPointSupport extends Serializable + +

+ +
+ Linear Supertypes +
Serializable, Serializable, AnyRef, Any
+
+ Known Subclasses + +
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. CheckPointSupport
  2. Serializable
  3. Serializable
  4. AnyRef
  5. Any
  6. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + getOffsets(totalCount: Long, parallel: Int, checkPointPath: Option[String], checkPointNamePrefix: String): scala.List[Offset] + +

    + + Permalink + + + +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  18. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CustomReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CustomReader.html new file mode 100644 index 0000000..0e894b4 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CustomReader.html @@ -0,0 +1,581 @@ + + + + CustomReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.CustomReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

CustomReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + abstract + class + + + CustomReader extends FileBaseReader + +

+ +

The CustomReader extend the FileBaseReader and support read text file from HDFS. +Transformation is a function convert a line into Row. +The structure of the row should be specified. +

+ Linear Supertypes +
FileBaseReader, Reader, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. CustomReader
  2. FileBaseReader
  3. Reader
  4. Serializable
  5. Serializable
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + CustomReader(session: SparkSession, customConfig: FileBaseSourceConfigEntry, transformation: (String) ⇒ org.apache.spark.sql.Row, filter: (org.apache.spark.sql.Row) ⇒ Boolean, structType: StructType) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    FileBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + val + + + path: String + +

    + + Permalink + + +
    Definition Classes
    FileBaseReader
    +
  17. + + +

    + + + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    CustomReaderReader
    +
  18. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    CustomReaderFileBaseReaderReader
    +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  21. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from FileBaseReader

+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/FileBaseReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/FileBaseReader.html new file mode 100644 index 0000000..eab3944 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/FileBaseReader.html @@ -0,0 +1,583 @@ + + + + FileBaseReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.FileBaseReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

FileBaseReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + abstract + class + + + FileBaseReader extends Reader + +

+ +

The FileBaseReader is the abstract class for HDFS file reader. +

+ Linear Supertypes +
Reader, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. FileBaseReader
  2. Reader
  3. Serializable
  4. Serializable
  5. AnyRef
  6. Any
  7. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + FileBaseReader(session: SparkSession, path: String) + +

    + + Permalink + + + +
+
+ + + +
+

Abstract Value Members

+
  1. + + +

    + + abstract + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    Reader
    +
+
+ +
+

Concrete Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    FileBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + val + + + path: String + +

    + + Permalink + + + +
  17. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    FileBaseReaderReader
    +
  18. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  20. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HBaseReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HBaseReader.html new file mode 100644 index 0000000..eba5e1c --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HBaseReader.html @@ -0,0 +1,578 @@ + + + + HBaseReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.HBaseReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

HBaseReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + + class + + + HBaseReader extends ServerBaseReader + +

+ +

HBaseReader extends ServerBaseReader

+ Linear Supertypes +
ServerBaseReader, Reader, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. HBaseReader
  2. ServerBaseReader
  3. Reader
  4. Serializable
  5. Serializable
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + HBaseReader(session: SparkSession, hbaseConfig: HBaseSourceConfigEntry) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    ServerBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    HBaseReaderReader
    +
  17. + + +

    + + + val + + + sentence: String + +

    + + Permalink + + +
    Definition Classes
    ServerBaseReader
    +
  18. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    HBaseReaderServerBaseReaderReader
    +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  21. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from ServerBaseReader

+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HiveReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HiveReader.html new file mode 100644 index 0000000..19061a6 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HiveReader.html @@ -0,0 +1,579 @@ + + + + HiveReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.HiveReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

HiveReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + + class + + + HiveReader extends ServerBaseReader + +

+ +

HiveReader extends the @{link ServerBaseReader}. +The HiveReader reading data from Apache Hive via sentence.

+ Linear Supertypes +
ServerBaseReader, Reader, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. HiveReader
  2. ServerBaseReader
  3. Reader
  4. Serializable
  5. Serializable
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + HiveReader(session: SparkSession, hiveConfig: HiveSourceConfigEntry) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    ServerBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    HiveReaderReader
    +
  17. + + +

    + + + val + + + sentence: String + +

    + + Permalink + + +
    Definition Classes
    ServerBaseReader
    +
  18. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    HiveReaderServerBaseReaderReader
    +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  21. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from ServerBaseReader

+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JSONReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JSONReader.html new file mode 100644 index 0000000..70fc6bb --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JSONReader.html @@ -0,0 +1,579 @@ + + + + JSONReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.JSONReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

JSONReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + + class + + + JSONReader extends FileBaseReader + +

+ +

The JSONReader extend the FileBaseReader and support read json file from HDFS. +

+ Linear Supertypes +
FileBaseReader, Reader, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. JSONReader
  2. FileBaseReader
  3. Reader
  4. Serializable
  5. Serializable
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + JSONReader(session: SparkSession, jsonConfig: FileBaseSourceConfigEntry) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    FileBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + val + + + path: String + +

    + + Permalink + + +
    Definition Classes
    FileBaseReader
    +
  17. + + +

    + + + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    JSONReaderReader
    +
  18. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    JSONReaderFileBaseReaderReader
    +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  21. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from FileBaseReader

+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JanusGraphReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JanusGraphReader.html new file mode 100644 index 0000000..e020cbd --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JanusGraphReader.html @@ -0,0 +1,597 @@ + + + + JanusGraphReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.JanusGraphReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

JanusGraphReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + + class + + + JanusGraphReader extends ServerBaseReader with CheckPointSupport + +

+ +

JanusGraphReader extends the link ServerBaseReader

+ Linear Supertypes +
CheckPointSupport, ServerBaseReader, Reader, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. JanusGraphReader
  2. CheckPointSupport
  3. ServerBaseReader
  4. Reader
  5. Serializable
  6. Serializable
  7. AnyRef
  8. Any
  9. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + JanusGraphReader(session: SparkSession, janusGraphConfig: JanusGraphSourceConfigEntry) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    ServerBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + getOffsets(totalCount: Long, parallel: Int, checkPointPath: Option[String], checkPointNamePrefix: String): scala.List[Offset] + +

    + + Permalink + + +
    Definition Classes
    CheckPointSupport
    +
  12. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  13. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  14. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    JanusGraphReaderReader
    +
  18. + + +

    + + + val + + + sentence: String + +

    + + Permalink + + +
    Definition Classes
    ServerBaseReader
    +
  19. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    JanusGraphReaderServerBaseReaderReader
    +
  20. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  21. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  22. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  24. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from CheckPointSupport

+
+

Inherited from ServerBaseReader

+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/KafkaReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/KafkaReader.html new file mode 100644 index 0000000..57d5c27 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/KafkaReader.html @@ -0,0 +1,561 @@ + + + + KafkaReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.KafkaReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

KafkaReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + + class + + + KafkaReader extends StreamingBaseReader + +

+ +
+ Linear Supertypes +
StreamingBaseReader, Reader, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. KafkaReader
  2. StreamingBaseReader
  3. Reader
  4. Serializable
  5. Serializable
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + KafkaReader(session: SparkSession, kafkaConfig: KafkaSourceConfigEntry) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    StreamingBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    KafkaReaderReader
    +
  17. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    KafkaReaderStreamingBaseReaderReader
    +
  18. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  20. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from StreamingBaseReader

+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/MySQLReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/MySQLReader.html new file mode 100644 index 0000000..7c0b6de --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/MySQLReader.html @@ -0,0 +1,580 @@ + + + + MySQLReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.MySQLReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

MySQLReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + + class + + + MySQLReader extends ServerBaseReader + +

+ +

The MySQLReader extends the ServerBaseReader. +The MySQLReader reading data from MySQL via sentence. +

+ Linear Supertypes +
ServerBaseReader, Reader, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. MySQLReader
  2. ServerBaseReader
  3. Reader
  4. Serializable
  5. Serializable
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + MySQLReader(session: SparkSession, mysqlConfig: MySQLSourceConfigEntry) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    ServerBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    MySQLReaderReader
    +
  17. + + +

    + + + val + + + sentence: String + +

    + + Permalink + + +
    Definition Classes
    ServerBaseReader
    +
  18. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    MySQLReaderServerBaseReaderReader
    +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  21. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from ServerBaseReader

+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/NebulaReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/NebulaReader.html new file mode 100644 index 0000000..05e7cdd --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/NebulaReader.html @@ -0,0 +1,578 @@ + + + + NebulaReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.NebulaReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

NebulaReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + + class + + + NebulaReader extends ServerBaseReader + +

+ +
+ Linear Supertypes +
ServerBaseReader, Reader, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. NebulaReader
  2. ServerBaseReader
  3. Reader
  4. Serializable
  5. Serializable
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + NebulaReader(session: SparkSession, nebulaConfig: ServerDataSourceConfigEntry) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    ServerBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    NebulaReaderReader
    +
  17. + + +

    + + + val + + + sentence: String + +

    + + Permalink + + +
    Definition Classes
    ServerBaseReader
    +
  18. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    NebulaReaderServerBaseReaderReader
    +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  21. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from ServerBaseReader

+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Neo4JReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Neo4JReader.html new file mode 100644 index 0000000..c7d3101 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Neo4JReader.html @@ -0,0 +1,598 @@ + + + + Neo4JReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.Neo4JReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

Neo4JReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + + class + + + Neo4JReader extends ServerBaseReader with CheckPointSupport + +

+ +

Neo4JReader extends the ServerBaseReader +this reader support checkpoint by sacrificing performance

+ Linear Supertypes +
CheckPointSupport, ServerBaseReader, Reader, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. Neo4JReader
  2. CheckPointSupport
  3. ServerBaseReader
  4. Reader
  5. Serializable
  6. Serializable
  7. AnyRef
  8. Any
  9. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + Neo4JReader(session: SparkSession, neo4jConfig: Neo4JSourceConfigEntry) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    ServerBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + getOffsets(totalCount: Long, parallel: Int, checkPointPath: Option[String], checkPointNamePrefix: String): scala.List[Offset] + +

    + + Permalink + + +
    Definition Classes
    CheckPointSupport
    +
  12. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  13. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  14. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    Neo4JReaderReader
    +
  18. + + +

    + + + val + + + sentence: String + +

    + + Permalink + + +
    Definition Classes
    ServerBaseReader
    +
  19. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    Neo4JReaderServerBaseReaderReader
    +
  20. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  21. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  22. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  24. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from CheckPointSupport

+
+

Inherited from ServerBaseReader

+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ORCReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ORCReader.html new file mode 100644 index 0000000..3e0aa3b --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ORCReader.html @@ -0,0 +1,579 @@ + + + + ORCReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.ORCReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

ORCReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + + class + + + ORCReader extends FileBaseReader + +

+ +

The ORCReader extend the FileBaseReader and support read orc file from HDFS. +

+ Linear Supertypes +
FileBaseReader, Reader, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. ORCReader
  2. FileBaseReader
  3. Reader
  4. Serializable
  5. Serializable
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + ORCReader(session: SparkSession, orcConfig: FileBaseSourceConfigEntry) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    FileBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + val + + + path: String + +

    + + Permalink + + +
    Definition Classes
    FileBaseReader
    +
  17. + + +

    + + + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    ORCReaderReader
    +
  18. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    ORCReaderFileBaseReaderReader
    +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  21. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from FileBaseReader

+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ParquetReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ParquetReader.html new file mode 100644 index 0000000..3ca9f40 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ParquetReader.html @@ -0,0 +1,579 @@ + + + + ParquetReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.ParquetReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

ParquetReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + + class + + + ParquetReader extends FileBaseReader + +

+ +

The ParquetReader extend the FileBaseReader and support read parquet file from HDFS. +

+ Linear Supertypes +
FileBaseReader, Reader, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. ParquetReader
  2. FileBaseReader
  3. Reader
  4. Serializable
  5. Serializable
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + ParquetReader(session: SparkSession, parquetConfig: FileBaseSourceConfigEntry) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    FileBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + val + + + path: String + +

    + + Permalink + + +
    Definition Classes
    FileBaseReader
    +
  17. + + +

    + + + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    ParquetReaderReader
    +
  18. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    ParquetReaderFileBaseReaderReader
    +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  21. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from FileBaseReader

+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/PulsarReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/PulsarReader.html new file mode 100644 index 0000000..b903cc9 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/PulsarReader.html @@ -0,0 +1,561 @@ + + + + PulsarReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.PulsarReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

PulsarReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + + class + + + PulsarReader extends StreamingBaseReader + +

+ +
+ Linear Supertypes +
StreamingBaseReader, Reader, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. PulsarReader
  2. StreamingBaseReader
  3. Reader
  4. Serializable
  5. Serializable
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + PulsarReader(session: SparkSession, pulsarConfig: PulsarSourceConfigEntry) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    StreamingBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    PulsarReaderReader
    +
  17. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    PulsarReaderStreamingBaseReaderReader
    +
  18. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  20. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from StreamingBaseReader

+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Reader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Reader.html new file mode 100644 index 0000000..89e021f --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Reader.html @@ -0,0 +1,544 @@ + + + + Reader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.Reader + + + + + + + + + + + + + + + +
+ Trait +

com.vesoft.nebula.tools.importer.reader

+

Reader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + + trait + + + Reader extends Serializable + +

+ +

The Reader is used for create a DataFrame from the source. Such as Hive or HDFS. +

+ Linear Supertypes +
Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. Reader
  2. Serializable
  3. Serializable
  4. AnyRef
  5. Any
  6. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + +
+

Abstract Value Members

+
  1. + + +

    + + abstract + def + + + close(): Unit + +

    + + Permalink + + + +
  2. + + +

    + + abstract + def + + + read(): DataFrame + +

    + + Permalink + + + +
  3. + + +

    + + abstract + def + + + session: SparkSession + +

    + + Permalink + + + +
+
+ +
+

Concrete Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ServerBaseReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ServerBaseReader.html new file mode 100644 index 0000000..d4e39fc --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ServerBaseReader.html @@ -0,0 +1,583 @@ + + + + ServerBaseReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.ServerBaseReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

ServerBaseReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + abstract + class + + + ServerBaseReader extends Reader + +

+ +

ServerBaseReader is the abstract class of +It include a spark session and a sentence which will sent to service.

+ Linear Supertypes +
Reader, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. ServerBaseReader
  2. Reader
  3. Serializable
  4. Serializable
  5. AnyRef
  6. Any
  7. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + ServerBaseReader(session: SparkSession, sentence: String) + +

    + + Permalink + + + +
+
+ + + +
+

Abstract Value Members

+
  1. + + +

    + + abstract + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    Reader
    +
+
+ +
+

Concrete Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    ServerBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + val + + + sentence: String + +

    + + Permalink + + + +
  17. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    ServerBaseReaderReader
    +
  18. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  20. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/StreamingBaseReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/StreamingBaseReader.html new file mode 100644 index 0000000..6382ee1 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/StreamingBaseReader.html @@ -0,0 +1,566 @@ + + + + StreamingBaseReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.StreamingBaseReader + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.reader

+

StreamingBaseReader

Related Doc: + package reader +

+ + Permalink + + +
+ +

+ + abstract + class + + + StreamingBaseReader extends Reader + +

+ +

Spark Streaming +

+ Linear Supertypes +
Reader, Serializable, Serializable, AnyRef, Any
+
+ Known Subclasses + +
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. StreamingBaseReader
  2. Reader
  3. Serializable
  4. Serializable
  5. AnyRef
  6. Any
  7. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + StreamingBaseReader(session: SparkSession) + +

    + + Permalink + + + +
+
+ + + +
+

Abstract Value Members

+
  1. + + +

    + + abstract + def + + + read(): DataFrame + +

    + + Permalink + + +
    Definition Classes
    Reader
    +
+
+ +
+

Concrete Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    StreamingBaseReaderReader
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + val + + + session: SparkSession + +

    + + Permalink + + +
    Definition Classes
    StreamingBaseReaderReader
    +
  17. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  19. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Reader

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/package.html new file mode 100644 index 0000000..7b3f8d4 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/package.html @@ -0,0 +1,419 @@ + + + + reader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader + + + + + + + + + + + + + + + +
+ Package +

com.vesoft.nebula.tools.importer

+

reader

+ + Permalink + + +
+ +

+ + + package + + + reader + +

+ +
+ + +
+
+ + +
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + +
+

Type Members

+
  1. + + +

    + + + class + + + CSVReader extends FileBaseReader + +

    + + Permalink + + +

    The CSVReader extend the FileBaseReader and support read csv file from HDFS.

    The CSVReader extend the FileBaseReader and support read csv file from HDFS. +All types of the structure are StringType. +

    +
  2. + + +

    + + + trait + + + CheckPointSupport extends Serializable + +

    + + Permalink + + + +
  3. + + +

    + + abstract + class + + + CustomReader extends FileBaseReader + +

    + + Permalink + + +

    The CustomReader extend the FileBaseReader and support read text file from HDFS.

    The CustomReader extend the FileBaseReader and support read text file from HDFS. +Transformation is a function convert a line into Row. +The structure of the row should be specified. +

    +
  4. + + +

    + + abstract + class + + + FileBaseReader extends Reader + +

    + + Permalink + + +

    The FileBaseReader is the abstract class for HDFS file reader.

    +
  5. + + +

    + + + class + + + HBaseReader extends ServerBaseReader + +

    + + Permalink + + +

    HBaseReader extends ServerBaseReader

    +
  6. + + +

    + + + class + + + HiveReader extends ServerBaseReader + +

    + + Permalink + + +

    HiveReader extends the @{link ServerBaseReader}.

    HiveReader extends the @{link ServerBaseReader}. +The HiveReader reading data from Apache Hive via sentence.

    +
  7. + + +

    + + + class + + + JSONReader extends FileBaseReader + +

    + + Permalink + + +

    The JSONReader extend the FileBaseReader and support read json file from HDFS.

    +
  8. + + +

    + + + class + + + JanusGraphReader extends ServerBaseReader with CheckPointSupport + +

    + + Permalink + + +

    JanusGraphReader extends the link ServerBaseReader

    +
  9. + + +

    + + + class + + + KafkaReader extends StreamingBaseReader + +

    + + Permalink + + +

    +
  10. + + +

    + + + class + + + MySQLReader extends ServerBaseReader + +

    + + Permalink + + +

    The MySQLReader extends the ServerBaseReader.

    The MySQLReader extends the ServerBaseReader. +The MySQLReader reading data from MySQL via sentence. +

    +
  11. + + +

    + + + class + + + NebulaReader extends ServerBaseReader + +

    + + Permalink + + +

    +
  12. + + +

    + + + class + + + Neo4JReader extends ServerBaseReader with CheckPointSupport + +

    + + Permalink + + +

    Neo4JReader extends the ServerBaseReader +this reader support checkpoint by sacrificing performance

    +
  13. + + +

    + + + class + + + ORCReader extends FileBaseReader + +

    + + Permalink + + +

    The ORCReader extend the FileBaseReader and support read orc file from HDFS.

    +
  14. + + +

    + + + class + + + ParquetReader extends FileBaseReader + +

    + + Permalink + + +

    The ParquetReader extend the FileBaseReader and support read parquet file from HDFS.

    +
  15. + + +

    + + + class + + + PulsarReader extends StreamingBaseReader + +

    + + Permalink + + +

    +
  16. + + +

    + + + trait + + + Reader extends Serializable + +

    + + Permalink + + +

    The Reader is used for create a DataFrame from the source.

    The Reader is used for create a DataFrame from the source. Such as Hive or HDFS. +

    +
  17. + + +

    + + abstract + class + + + ServerBaseReader extends Reader + +

    + + Permalink + + +

    ServerBaseReader is the abstract class of +It include a spark session and a sentence which will sent to service.

    +
  18. + + +

    + + abstract + class + + + StreamingBaseReader extends Reader + +

    + + Permalink + + +

    Spark Streaming +

    +
+
+ + + + + + + + +
+ +
+ + +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/HDFSUtils$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/HDFSUtils$.html new file mode 100644 index 0000000..91399b5 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/HDFSUtils$.html @@ -0,0 +1,584 @@ + + + + HDFSUtils - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.utils.HDFSUtils + + + + + + + + + + + + + + + +
+ Object +

com.vesoft.nebula.tools.importer.utils

+

HDFSUtils

Related Doc: + package utils +

+ + Permalink + + +
+ +

+ + + object + + + HDFSUtils + +

+ +
+ Linear Supertypes +
AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. HDFSUtils
  2. AnyRef
  3. Any
  4. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + exists(path: String): Boolean + +

    + + Permalink + + + +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + getContent(path: String): String + +

    + + Permalink + + + +
  12. + + +

    + + + def + + + getFileSystem(): FileSystem + +

    + + Permalink + + + +
  13. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  14. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  15. + + +

    + + + def + + + list(path: String): scala.List[String] + +

    + + Permalink + + + +
  16. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + + def + + + saveContent(path: String, content: String, charset: Charset = Charset.defaultCharset()): Unit + +

    + + Permalink + + + +
  20. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  21. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  22. + + +

    + + + def + + + upload(localPath: String, remotePath: String): Unit + +

    + + Permalink + + + +
  23. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  24. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  25. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/KafkaUtils$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/KafkaUtils$.html new file mode 100644 index 0000000..6223ae3 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/KafkaUtils$.html @@ -0,0 +1,516 @@ + + + + KafkaUtils - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.utils.KafkaUtils + + + + + + + + + + + + + + + +
+ Object +

com.vesoft.nebula.tools.importer.utils

+

KafkaUtils

Related Doc: + package utils +

+ + Permalink + + +
+ +

+ + + object + + + KafkaUtils + +

+ +
+ Linear Supertypes +
AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. KafkaUtils
  2. AnyRef
  3. Any
  4. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + + def + + + writeEdge(edges: Edge*): Unit + +

    + + Permalink + + + +
  21. + + +

    + + + def + + + writeVertices(vertices: Vertex*): Unit + +

    + + Permalink + + + +
+
+ + + + +
+ +
+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/NebulaUtils$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/NebulaUtils$.html new file mode 100644 index 0000000..a432852 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/NebulaUtils$.html @@ -0,0 +1,550 @@ + + + + NebulaUtils - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.utils.NebulaUtils + + + + + + + + + + + + + + + +
+ Object +

com.vesoft.nebula.tools.importer.utils

+

NebulaUtils

Related Doc: + package utils +

+ + Permalink + + +
+ +

+ + + object + + + NebulaUtils + +

+ +
+ Linear Supertypes +
AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. NebulaUtils
  2. AnyRef
  3. Any
  4. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + getDataFrameValue(value: String, dataType: DataType): Any + +

    + + Permalink + + + +
  11. + + +

    + + + def + + + getDataSourceFieldType(sourceConfig: SchemaConfigEntry, space: String, metaProvider: MetaProvider): scala.Predef.Map[String, Int] + +

    + + Permalink + + + +
  12. + + +

    + + + def + + + getDataType(clazz: Class[_]): DataType + +

    + + Permalink + + + +
  13. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  14. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  15. + + +

    + + + def + + + isNumic(str: String): Boolean + +

    + + Permalink + + + +
  16. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  21. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/package.html new file mode 100644 index 0000000..70dddda --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/package.html @@ -0,0 +1,152 @@ + + + + utils - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.utils + + + + + + + + + + + + + + + +
+ Package +

com.vesoft.nebula.tools.importer

+

utils

+ + Permalink + + +
+ +

+ + + package + + + utils + +

+ +
+ + +
+
+ + +
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + + + +
+

Value Members

+
  1. + + +

    + + + object + + + HDFSUtils + +

    + + Permalink + + + +
  2. + + +

    + + + object + + + KafkaUtils + +

    + + Permalink + + + +
  3. + + +

    + + + object + + + NebulaUtils + +

    + + Permalink + + + +
+
+ + + + +
+ +
+ + +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaGraphClientWriter.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaGraphClientWriter.html new file mode 100644 index 0000000..9b0ba02 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaGraphClientWriter.html @@ -0,0 +1,646 @@ + + + + NebulaGraphClientWriter - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.writer.NebulaGraphClientWriter + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.writer

+

NebulaGraphClientWriter

Related Doc: + package writer +

+ + Permalink + + +
+ +

+ + + class + + + NebulaGraphClientWriter extends ServerBaseWriter + +

+ +
+ Linear Supertypes +
ServerBaseWriter, Writer, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. NebulaGraphClientWriter
  2. ServerBaseWriter
  3. Writer
  4. Serializable
  5. Serializable
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + NebulaGraphClientWriter(dataBaseConfigEntry: DataBaseConfigEntry, userConfigEntry: UserConfigEntry, connectionConfigEntry: ConnectionConfigEntry, executionRetry: Int, rateConfig: RateConfigEntry, config: SchemaConfigEntry, graphProvider: GraphProvider) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    NebulaGraphClientWriterWriter
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + prepare(): Unit + +

    + + Permalink + + +
    Definition Classes
    NebulaGraphClientWriterWriter
    +
  17. + + +

    + + + val + + + rateLimiter: RateLimiter + +

    + + Permalink + + + +
  18. + + +

    + + + val + + + session: Session + +

    + + Permalink + + + +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + def + + + toExecuteSentence(name: String, edges: Edges): String + +

    + + Permalink + + +
    Definition Classes
    ServerBaseWriter
    +
  21. + + +

    + + + def + + + toExecuteSentence(name: String, vertices: Vertices): String + +

    + + Permalink + + +
    Definition Classes
    ServerBaseWriter
    +
  22. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  23. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  24. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  25. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  26. + + +

    + + + def + + + writeEdges(edges: Edges): String + +

    + + Permalink + + + +
  27. + + +

    + + + def + + + writeVertices(vertices: Vertices): String + +

    + + Permalink + + + +
+
+ + + + +
+ +
+
+

Inherited from ServerBaseWriter

+
+

Inherited from Writer

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaSSTWriter.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaSSTWriter.html new file mode 100644 index 0000000..62c34ea --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaSSTWriter.html @@ -0,0 +1,610 @@ + + + + NebulaSSTWriter - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.writer.NebulaSSTWriter + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.writer

+

NebulaSSTWriter

Related Doc: + package writer +

+ + Permalink + + +
+ +

+ + + class + + + NebulaSSTWriter extends Writer + +

+ +
+ Linear Supertypes +
Writer, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. NebulaSSTWriter
  2. Writer
  3. Serializable
  4. Serializable
  5. AnyRef
  6. Any
  7. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + NebulaSSTWriter(path: String) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    NebulaSSTWriterWriter
    +
  7. + + +

    + + + val + + + env: EnvOptions + +

    + + Permalink + + + +
  8. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  9. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  11. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  13. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  14. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  17. + + +

    + + + val + + + options: Options + +

    + + Permalink + + + +
  18. + + +

    + + + def + + + prepare(): Unit + +

    + + Permalink + + +
    Definition Classes
    NebulaSSTWriterWriter
    +
  19. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  20. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  21. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  24. + + +

    + + + def + + + write(key: Array[Byte], value: Array[Byte]): Unit + +

    + + Permalink + + + +
  25. + + +

    + + + var + + + writer: SstFileWriter + +

    + + Permalink + + + +
+
+ + + + +
+ +
+
+

Inherited from Writer

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaStorageClientWriter.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaStorageClientWriter.html new file mode 100644 index 0000000..44a2e96 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaStorageClientWriter.html @@ -0,0 +1,629 @@ + + + + NebulaStorageClientWriter - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.writer.NebulaStorageClientWriter + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.writer

+

NebulaStorageClientWriter

Related Doc: + package writer +

+ + Permalink + + +
+ +

+ + + class + + + NebulaStorageClientWriter extends ServerBaseWriter + +

+ +
+ Linear Supertypes +
ServerBaseWriter, Writer, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. NebulaStorageClientWriter
  2. ServerBaseWriter
  3. Writer
  4. Serializable
  5. Serializable
  6. AnyRef
  7. Any
  8. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + NebulaStorageClientWriter(host: String, port: Int, space: String) + +

    + + Permalink + + + +
  2. + + +

    + + + new + + + NebulaStorageClientWriter(addresses: scala.List[(String, Int)], space: String) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    NebulaStorageClientWriterWriter
    +
  7. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  8. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  9. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  10. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  12. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  13. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + prepare(): Unit + +

    + + Permalink + + +
    Definition Classes
    NebulaStorageClientWriterWriter
    +
  17. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + + def + + + toExecuteSentence(name: String, edges: Edges): String + +

    + + Permalink + + +
    Definition Classes
    ServerBaseWriter
    +
  19. + + +

    + + + def + + + toExecuteSentence(name: String, vertices: Vertices): String + +

    + + Permalink + + +
    Definition Classes
    ServerBaseWriter
    +
  20. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  21. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  22. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  23. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  24. + + +

    + + + def + + + writeEdges(edges: Edges): String + +

    + + Permalink + + + +
  25. + + +

    + + + def + + + writeVertices(vertices: Vertices): String + +

    + + Permalink + + + +
+
+ + + + +
+ +
+
+

Inherited from ServerBaseWriter

+
+

Inherited from Writer

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaWriterCallback.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaWriterCallback.html new file mode 100644 index 0000000..96ebbc7 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaWriterCallback.html @@ -0,0 +1,538 @@ + + + + NebulaWriterCallback - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.writer.NebulaWriterCallback + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.writer

+

NebulaWriterCallback

Related Doc: + package writer +

+ + Permalink + + +
+ +

+ + + class + + + NebulaWriterCallback extends FutureCallback[java.util.List[Optional[Integer]]] + +

+ +
+ Linear Supertypes +
FutureCallback[java.util.List[Optional[Integer]]], AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. NebulaWriterCallback
  2. FutureCallback
  3. AnyRef
  4. Any
  5. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + NebulaWriterCallback(latch: CountDownLatch, batchSuccess: LongAccumulator, batchFailure: LongAccumulator, pathAndOffset: Option[(String, Long)]) + +

    + + Permalink + + + +
+
+ + + + + +
+

Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + + def + + + onFailure(t: Throwable): Unit + +

    + + Permalink + + +
    Definition Classes
    NebulaWriterCallback → FutureCallback
    +
  16. + + +

    + + + def + + + onSuccess(results: java.util.List[Optional[Integer]]): Unit + +

    + + Permalink + + +
    Definition Classes
    NebulaWriterCallback → FutureCallback
    +
  17. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  18. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  19. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from FutureCallback[java.util.List[Optional[Integer]]]

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.html new file mode 100644 index 0000000..22804b7 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.html @@ -0,0 +1,616 @@ + + + + ServerBaseWriter - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.writer.ServerBaseWriter + + + + + + + + + + + + + + + +
+ Class +

com.vesoft.nebula.tools.importer.writer

+

ServerBaseWriter

Related Doc: + package writer +

+ + Permalink + + +
+ +

+ + abstract + class + + + ServerBaseWriter extends Writer + +

+ +
+ Linear Supertypes +
Writer, Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. ServerBaseWriter
  2. Writer
  3. Serializable
  4. Serializable
  5. AnyRef
  6. Any
  7. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+
+

Instance Constructors

+
  1. + + +

    + + + new + + + ServerBaseWriter() + +

    + + Permalink + + + +
+
+ + + +
+

Abstract Value Members

+
  1. + + +

    + + abstract + def + + + close(): Unit + +

    + + Permalink + + +
    Definition Classes
    Writer
    +
  2. + + +

    + + abstract + def + + + prepare(): Unit + +

    + + Permalink + + +
    Definition Classes
    Writer
    +
  3. + + +

    + + abstract + def + + + writeEdges(edges: Edges): String + +

    + + Permalink + + + +
  4. + + +

    + + abstract + def + + + writeVertices(vertices: Vertices): String + +

    + + Permalink + + + +
+
+ +
+

Concrete Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + toExecuteSentence(name: String, edges: Edges): String + +

    + + Permalink + + + +
  17. + + +

    + + + def + + + toExecuteSentence(name: String, vertices: Vertices): String + +

    + + Permalink + + + +
  18. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  19. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  20. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  21. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Writer

+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/Writer.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/Writer.html new file mode 100644 index 0000000..a97d214 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/Writer.html @@ -0,0 +1,526 @@ + + + + Writer - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.writer.Writer + + + + + + + + + + + + + + + +
+ Trait +

com.vesoft.nebula.tools.importer.writer

+

Writer

Related Doc: + package writer +

+ + Permalink + + +
+ +

+ + + trait + + + Writer extends Serializable + +

+ +
+ Linear Supertypes +
Serializable, Serializable, AnyRef, Any
+
+ + +
+
+
+ Ordering +
    + +
  1. Alphabetic
  2. +
  3. By Inheritance
  4. +
+
+
+ Inherited
+
+
    +
  1. Writer
  2. Serializable
  3. Serializable
  4. AnyRef
  5. Any
  6. +
+
+ +
    +
  1. Hide All
  2. +
  3. Show All
  4. +
+
+
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + +
+

Abstract Value Members

+
  1. + + +

    + + abstract + def + + + close(): Unit + +

    + + Permalink + + + +
  2. + + +

    + + abstract + def + + + prepare(): Unit + +

    + + Permalink + + + +
+
+ +
+

Concrete Value Members

+
  1. + + +

    + + final + def + + + !=(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  2. + + +

    + + final + def + + + ##(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  3. + + +

    + + final + def + + + ==(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  4. + + +

    + + final + def + + + asInstanceOf[T0]: T0 + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  5. + + +

    + + + def + + + clone(): AnyRef + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  6. + + +

    + + final + def + + + eq(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  7. + + +

    + + + def + + + equals(arg0: Any): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  8. + + +

    + + + def + + + finalize(): Unit + +

    + + Permalink + + +
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + classOf[java.lang.Throwable] + ) + +
    +
  9. + + +

    + + final + def + + + getClass(): Class[_] + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  10. + + +

    + + + def + + + hashCode(): Int + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  11. + + +

    + + final + def + + + isInstanceOf[T0]: Boolean + +

    + + Permalink + + +
    Definition Classes
    Any
    +
  12. + + +

    + + final + def + + + ne(arg0: AnyRef): Boolean + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  13. + + +

    + + final + def + + + notify(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  14. + + +

    + + final + def + + + notifyAll(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  15. + + +

    + + final + def + + + synchronized[T0](arg0: ⇒ T0): T0 + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    +
  16. + + +

    + + + def + + + toString(): String + +

    + + Permalink + + +
    Definition Classes
    AnyRef → Any
    +
  17. + + +

    + + final + def + + + wait(): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  18. + + +

    + + final + def + + + wait(arg0: Long, arg1: Int): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
  19. + + +

    + + final + def + + + wait(arg0: Long): Unit + +

    + + Permalink + + +
    Definition Classes
    AnyRef
    Annotations
    + @throws( + + ... + ) + +
    +
+
+ + + + +
+ +
+
+

Inherited from Serializable

+
+

Inherited from Serializable

+
+

Inherited from AnyRef

+
+

Inherited from Any

+
+ +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/package.html new file mode 100644 index 0000000..e53d1fa --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/package.html @@ -0,0 +1,203 @@ + + + + writer - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.writer + + + + + + + + + + + + + + + +
+ Package +

com.vesoft.nebula.tools.importer

+

writer

+ + Permalink + + +
+ +

+ + + package + + + writer + +

+ +
+ + +
+
+ + +
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + +
+

Type Members

+
  1. + + +

    + + + class + + + NebulaGraphClientWriter extends ServerBaseWriter + +

    + + Permalink + + +

    +
  2. + + +

    + + + class + + + NebulaSSTWriter extends Writer + +

    + + Permalink + + +

    +
  3. + + +

    + + + class + + + NebulaStorageClientWriter extends ServerBaseWriter + +

    + + Permalink + + +

    +
  4. + + +

    + + + class + + + NebulaWriterCallback extends FutureCallback[java.util.List[Optional[Integer]]] + +

    + + Permalink + + + +
  5. + + +

    + + abstract + class + + + ServerBaseWriter extends Writer + +

    + + Permalink + + + +
  6. + + +

    + + + trait + + + Writer extends Serializable + +

    + + Permalink + + +

    +
+
+ + + + + + + + +
+ +
+ + +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/package.html new file mode 100644 index 0000000..2511f7f --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/package.html @@ -0,0 +1,118 @@ + + + + tools - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools + + + + + + + + + + + + + + + +
+ Package +

com.vesoft.nebula

+

tools

+ + Permalink + + +
+ +

+ + + package + + + tools + +

+ +
+ + +
+
+ + +
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + + + +
+

Value Members

+
  1. + + +

    + + + package + + + importer + +

    + + Permalink + + + +
+
+ + + + +
+ +
+ + +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/package.html new file mode 100644 index 0000000..b7cbd41 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/com/vesoft/package.html @@ -0,0 +1,118 @@ + + + + vesoft - nebula-exchange 2.0.0 API - com.vesoft + + + + + + + + + + + + + + + +
+ Package +

com

+

vesoft

+ + Permalink + + +
+ +

+ + + package + + + vesoft + +

+ +
+ + +
+
+ + +
+ Visibility +
  1. Public
  2. All
+
+
+ +
+
+ + + + + + +
+

Value Members

+
  1. + + +

    + + + package + + + nebula + +

    + + Permalink + + + +
+
+ + + + +
+ +
+ + +
+ +
+
+

Ungrouped

+ +
+
+ +
+ +
+ + + + + + diff --git a/nebula-exchange/target/site/scaladocs/index.html b/nebula-exchange/target/site/scaladocs/index.html new file mode 100644 index 0000000..9775439 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index.html @@ -0,0 +1,80 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + + + + + + +
+ class icon + trait icon + trait icon + trait icon +
+
+
+
+
+
#ABCDEFGHIJKLMNOPQRSTUVWXYZdeprecated
+
+
+ +
    +
    1. + com +
        +
        1. + com.vesoft +
            +
            1. + com.vesoft.nebula +
                +
                1. + com.vesoft.nebula.tools +
                    +
                    1. + com.vesoft.nebula.tools.importer +
                      1. (case class)Argument
                      2. (object)
                        CheckPointHandler
                      3. (case class)Edge
                      4. (case class)Edges
                      5. (object)
                        ErrorHandler
                      6. (object)
                        Exchange
                      7. (class)GraphProvider
                      8. (object)
                        KeyPolicy
                      9. (class)MetaProvider
                      10. (case class)Offset
                      11. (case class)TooManyErrorsException
                      12. (case class)Vertex
                      13. (case class)Vertices
                      14. (object)
                        VidType
                      +
                      1. + com.vesoft.nebula.tools.importer.config +
                        1. (object)(case class)Configs
                        2. (case class)ConnectionConfigEntry
                        3. (case class)DataBaseConfigEntry
                        4. (trait)DataSinkConfigEntry
                        5. (trait)DataSourceConfigEntry
                        6. (case class)EdgeConfigEntry
                        7. (case class)ErrorConfigEntry
                        8. (case class)ExecutionConfigEntry
                        9. (case class)FileBaseSinkConfigEntry
                        10. (case class)FileBaseSourceConfigEntry
                        11. (trait)FileDataSourceConfigEntry
                        12. (case class)HBaseSourceConfigEntry
                        13. (case class)HiveConfigEntry
                        14. (case class)HiveSourceConfigEntry
                        15. (case class)JanusGraphSourceConfigEntry
                        16. (case class)KafkaSourceConfigEntry
                        17. (case class)MySQLSourceConfigEntry
                        18. (case class)NebulaSinkConfigEntry
                        19. (case class)Neo4JSourceConfigEntry
                        20. (case class)PulsarSourceConfigEntry
                        21. (case class)RateConfigEntry
                        22. (trait)SchemaConfigEntry
                        23. (trait)ServerDataSourceConfigEntry
                        24. (object)(class)SinkCategory
                        25. (object)(class)SourceCategory
                        26. (object)(case class)SparkConfigEntry
                        27. (trait)StreamingDataSourceConfigEntry
                        28. (case class)TagConfigEntry
                        29. (object)
                          Type
                        30. (case class)UserConfigEntry
                        +
                        +
                      2. + com.vesoft.nebula.tools.importer.processor +
                        1. (class)EdgeProcessor
                        2. (trait)Processor
                        3. (class)ReloadProcessor
                        4. (class)VerticesProcessor
                        +
                        +
                      3. + com.vesoft.nebula.tools.importer.reader +
                        1. (trait)CheckPointSupport
                        2. (class)CSVReader
                        3. (class)CustomReader
                        4. (class)FileBaseReader
                        5. (class)HBaseReader
                        6. (class)HiveReader
                        7. (class)JanusGraphReader
                        8. (class)JSONReader
                        9. (class)KafkaReader
                        10. (class)MySQLReader
                        11. (class)NebulaReader
                        12. (class)Neo4JReader
                        13. (class)ORCReader
                        14. (class)ParquetReader
                        15. (class)PulsarReader
                        16. (trait)Reader
                        17. (class)ServerBaseReader
                        18. (class)StreamingBaseReader
                        +
                        +
                      4. + com.vesoft.nebula.tools.importer.utils +
                        1. (object)
                          HDFSUtils
                        2. (object)
                          KafkaUtils
                        3. (object)
                          NebulaUtils
                        +
                        +
                      5. + com.vesoft.nebula.tools.importer.writer +
                        1. (class)NebulaGraphClientWriter
                        2. (class)NebulaSSTWriter
                        3. (class)NebulaStorageClientWriter
                        4. (class)NebulaWriterCallback
                        5. (class)ServerBaseWriter
                        6. (trait)Writer
                        +
                        +
                      +
                    +
                  +
                +
              +
            +
            +
            +
            + +
            + + diff --git a/nebula-exchange/target/site/scaladocs/index.js b/nebula-exchange/target/site/scaladocs/index.js new file mode 100644 index 0000000..e8cf3e3 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index.js @@ -0,0 +1 @@ +Index.PACKAGES = {"com.vesoft.nebula" : [], "com.vesoft.nebula.tools.importer.reader" : [{"trait" : "com\/vesoft\/nebula\/tools\/importer\/reader\/CheckPointSupport.html", "name" : "com.vesoft.nebula.tools.importer.reader.CheckPointSupport"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/CSVReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.CSVReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/CustomReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.CustomReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/FileBaseReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.FileBaseReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/HBaseReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.HBaseReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/HiveReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.HiveReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/JanusGraphReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.JanusGraphReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/JSONReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.JSONReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/KafkaReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.KafkaReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/MySQLReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.MySQLReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/NebulaReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.NebulaReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/Neo4JReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.Neo4JReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/ORCReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.ORCReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/ParquetReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.ParquetReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/PulsarReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.PulsarReader"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/reader\/Reader.html", "name" : "com.vesoft.nebula.tools.importer.reader.Reader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/ServerBaseReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.ServerBaseReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/StreamingBaseReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.StreamingBaseReader"}], "com.vesoft.nebula.tools.importer.utils" : [{"object" : "com\/vesoft\/nebula\/tools\/importer\/utils\/HDFSUtils$.html", "name" : "com.vesoft.nebula.tools.importer.utils.HDFSUtils"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/utils\/KafkaUtils$.html", "name" : "com.vesoft.nebula.tools.importer.utils.KafkaUtils"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/utils\/NebulaUtils$.html", "name" : "com.vesoft.nebula.tools.importer.utils.NebulaUtils"}], "com.vesoft.nebula.tools" : [], "com.vesoft.nebula.tools.importer.writer" : [{"class" : "com\/vesoft\/nebula\/tools\/importer\/writer\/NebulaGraphClientWriter.html", "name" : "com.vesoft.nebula.tools.importer.writer.NebulaGraphClientWriter"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/writer\/NebulaSSTWriter.html", "name" : "com.vesoft.nebula.tools.importer.writer.NebulaSSTWriter"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/writer\/NebulaStorageClientWriter.html", "name" : "com.vesoft.nebula.tools.importer.writer.NebulaStorageClientWriter"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/writer\/NebulaWriterCallback.html", "name" : "com.vesoft.nebula.tools.importer.writer.NebulaWriterCallback"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/writer\/ServerBaseWriter.html", "name" : "com.vesoft.nebula.tools.importer.writer.ServerBaseWriter"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/writer\/Writer.html", "name" : "com.vesoft.nebula.tools.importer.writer.Writer"}], "com.vesoft" : [], "com.vesoft.nebula.tools.importer.config" : [{"object" : "com\/vesoft\/nebula\/tools\/importer\/config\/Configs$.html", "case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/Configs.html", "name" : "com.vesoft.nebula.tools.importer.config.Configs"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/ConnectionConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.ConnectionConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/DataBaseConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.DataBaseConfigEntry"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/config\/DataSinkConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.DataSinkConfigEntry"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/config\/DataSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.DataSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/EdgeConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.EdgeConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/ErrorConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.ErrorConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/ExecutionConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.ExecutionConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/FileBaseSinkConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.FileBaseSinkConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/FileBaseSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.FileBaseSourceConfigEntry"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/config\/FileDataSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.FileDataSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/HBaseSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.HBaseSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/HiveConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.HiveConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/HiveSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.HiveSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/JanusGraphSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.JanusGraphSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/KafkaSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.KafkaSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/MySQLSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.MySQLSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/NebulaSinkConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.NebulaSinkConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/Neo4JSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.Neo4JSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/PulsarSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.PulsarSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/RateConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.RateConfigEntry"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/config\/SchemaConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.SchemaConfigEntry"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/config\/ServerDataSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.ServerDataSourceConfigEntry"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/config\/SinkCategory.html", "object" : "com\/vesoft\/nebula\/tools\/importer\/config\/SinkCategory$.html", "name" : "com.vesoft.nebula.tools.importer.config.SinkCategory"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/config\/SourceCategory.html", "object" : "com\/vesoft\/nebula\/tools\/importer\/config\/SourceCategory$.html", "name" : "com.vesoft.nebula.tools.importer.config.SourceCategory"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/SparkConfigEntry.html", "object" : "com\/vesoft\/nebula\/tools\/importer\/config\/SparkConfigEntry$.html", "name" : "com.vesoft.nebula.tools.importer.config.SparkConfigEntry"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/config\/StreamingDataSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.StreamingDataSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/TagConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.TagConfigEntry"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/config\/Type$.html", "name" : "com.vesoft.nebula.tools.importer.config.Type"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/UserConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.UserConfigEntry"}], "com.vesoft.nebula.tools.importer.processor" : [{"class" : "com\/vesoft\/nebula\/tools\/importer\/processor\/EdgeProcessor.html", "name" : "com.vesoft.nebula.tools.importer.processor.EdgeProcessor"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/processor\/Processor.html", "name" : "com.vesoft.nebula.tools.importer.processor.Processor"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/processor\/ReloadProcessor.html", "name" : "com.vesoft.nebula.tools.importer.processor.ReloadProcessor"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/processor\/VerticesProcessor.html", "name" : "com.vesoft.nebula.tools.importer.processor.VerticesProcessor"}], "com.vesoft.nebula.tools.importer" : [{"case class" : "com\/vesoft\/nebula\/tools\/importer\/Argument.html", "name" : "com.vesoft.nebula.tools.importer.Argument"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/CheckPointHandler$.html", "name" : "com.vesoft.nebula.tools.importer.CheckPointHandler"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/package$$Edge.html", "name" : "com.vesoft.nebula.tools.importer.Edge"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/package$$Edges.html", "name" : "com.vesoft.nebula.tools.importer.Edges"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/ErrorHandler$.html", "name" : "com.vesoft.nebula.tools.importer.ErrorHandler"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/Exchange$.html", "name" : "com.vesoft.nebula.tools.importer.Exchange"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/GraphProvider.html", "name" : "com.vesoft.nebula.tools.importer.GraphProvider"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/package$$KeyPolicy$.html", "name" : "com.vesoft.nebula.tools.importer.KeyPolicy"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/MetaProvider.html", "name" : "com.vesoft.nebula.tools.importer.MetaProvider"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/package$$Offset.html", "name" : "com.vesoft.nebula.tools.importer.Offset"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/TooManyErrorsException.html", "name" : "com.vesoft.nebula.tools.importer.TooManyErrorsException"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/package$$Vertex.html", "name" : "com.vesoft.nebula.tools.importer.Vertex"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/package$$Vertices.html", "name" : "com.vesoft.nebula.tools.importer.Vertices"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/VidType$.html", "name" : "com.vesoft.nebula.tools.importer.VidType"}], "com" : []}; \ No newline at end of file diff --git a/nebula-exchange/target/site/scaladocs/index/index-a.html b/nebula-exchange/target/site/scaladocs/index/index-a.html new file mode 100644 index 0000000..0d07f2a --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-a.html @@ -0,0 +1,29 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            Argument
            + +
            +
            address
            + +
            +
            addresses
            + +
            +
            adminUrl
            + +
            +
            apply
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-b.html b/nebula-exchange/target/site/scaladocs/index/index-b.html new file mode 100644 index 0000000..ac6eeec --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-b.html @@ -0,0 +1,17 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            batch
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-c.html b/nebula-exchange/target/site/scaladocs/index/index-c.html new file mode 100644 index 0000000..d1bae90 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-c.html @@ -0,0 +1,74 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            CLIENT
            + +
            +
            CSV
            + +
            +
            CSVReader
            + +
            +
            CheckPointHandler
            + +
            +
            CheckPointSupport
            + +
            +
            Configs
            + +
            +
            ConnectionConfigEntry
            + +
            +
            CustomReader
            + +
            +
            category
            + +
            +
            checkPointPath
            + +
            +
            checkSupportResume
            + +
            +
            close
            + +
            +
            columnFamily
            + +
            +
            com
            + +
            +
            config
            + +
            +
            connectionConfig
            + +
            +
            connectionDriverName
            + +
            +
            connectionPassWord
            + +
            +
            connectionURL
            + +
            +
            connectionUserName
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-d.html b/nebula-exchange/target/site/scaladocs/index/index-d.html new file mode 100644 index 0000000..332ea9d --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-d.html @@ -0,0 +1,44 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            DataBaseConfigEntry
            + +
            +
            DataSinkConfigEntry
            + +
            +
            DataSourceConfigEntry
            + +
            +
            dataSinkConfigEntry
            + +
            +
            dataSourceConfigEntry
            + +
            +
            database
            + +
            +
            databaseConfig
            + +
            +
            destination
            + +
            +
            directly
            + +
            +
            dry
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-e.html b/nebula-exchange/target/site/scaladocs/index/index-e.html new file mode 100644 index 0000000..a966b4b --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-e.html @@ -0,0 +1,80 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            EDGE
            + +
            +
            Edge
            + +
            +
            EdgeConfigEntry
            + +
            +
            EdgeProcessor
            + +
            +
            EdgeRank
            + +
            +
            EdgeType
            + +
            +
            EdgeVersion
            + +
            +
            Edges
            + +
            +
            ErrorConfigEntry
            + +
            +
            ErrorHandler
            + +
            +
            Exchange
            + +
            +
            ExecutionConfigEntry
            + +
            +
            edgesConfig
            + +
            +
            encryption
            + +
            +
            env
            + +
            +
            errorConfig
            + +
            +
            errorMaxSize
            + +
            +
            errorPath
            + +
            +
            executionConfig
            + +
            +
            existError
            + +
            +
            exists
            + +
            +
            extraValue
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-f.html b/nebula-exchange/target/site/scaladocs/index/index-f.html new file mode 100644 index 0000000..df34a36 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-f.html @@ -0,0 +1,32 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            FileBaseReader
            + +
            +
            FileBaseSinkConfigEntry
            + +
            +
            FileBaseSourceConfigEntry
            + +
            +
            FileDataSourceConfigEntry
            + +
            +
            fetchOffset
            + +
            +
            fields
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-g.html b/nebula-exchange/target/site/scaladocs/index/index-g.html new file mode 100644 index 0000000..537d637 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-g.html @@ -0,0 +1,74 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            GraphProvider
            + +
            +
            GraphSpaceID
            + +
            +
            getConfigOrNone
            + +
            +
            getContent
            + +
            +
            getDataFrameValue
            + +
            +
            getDataSourceFieldType
            + +
            +
            getDataType
            + +
            +
            getEdgeSchema
            + +
            +
            getFileSystem
            + +
            +
            getGraphAddress
            + +
            +
            getGraphClient
            + +
            +
            getLabelType
            + +
            +
            getLong
            + +
            +
            getMetaAddress
            + +
            +
            getOffsets
            + +
            +
            getPartNumber
            + +
            +
            getPathAndOffset
            + +
            +
            getTagSchema
            + +
            +
            getVidType
            + +
            +
            graphAddress
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-h.html b/nebula-exchange/target/site/scaladocs/index/index-h.html new file mode 100644 index 0000000..769af3b --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-h.html @@ -0,0 +1,53 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            HASH
            + +
            +
            HBASE
            + +
            +
            HBaseReader
            + +
            +
            HBaseSourceConfigEntry
            + +
            +
            HDFSUtils
            + +
            +
            HIVE
            + +
            +
            HiveConfigEntry
            + +
            +
            HiveReader
            + +
            +
            HiveSourceConfigEntry
            + +
            +
            header
            + +
            +
            hive
            + +
            +
            hiveConfigEntry
            + +
            +
            host
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-i.html b/nebula-exchange/target/site/scaladocs/index/index-i.html new file mode 100644 index 0000000..0249970 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-i.html @@ -0,0 +1,35 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            INT
            + +
            +
            importer
            + +
            +
            interval
            + +
            +
            intervalSeconds
            + +
            +
            isEdge
            + +
            +
            isGeo
            + +
            +
            isNumic
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-j.html b/nebula-exchange/target/site/scaladocs/index/index-j.html new file mode 100644 index 0000000..a786d08 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-j.html @@ -0,0 +1,29 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            JANUS_GRAPH
            + +
            +
            JSON
            + +
            +
            JSONReader
            + +
            +
            JanusGraphReader
            + +
            +
            JanusGraphSourceConfigEntry
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-k.html b/nebula-exchange/target/site/scaladocs/index/index-k.html new file mode 100644 index 0000000..a8f0ccf --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-k.html @@ -0,0 +1,29 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            KAFKA
            + +
            +
            KafkaReader
            + +
            +
            KafkaSourceConfigEntry
            + +
            +
            KafkaUtils
            + +
            +
            KeyPolicy
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-l.html b/nebula-exchange/target/site/scaladocs/index/index-l.html new file mode 100644 index 0000000..6ecf261 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-l.html @@ -0,0 +1,29 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            latitude
            + +
            +
            limit
            + +
            +
            list
            + +
            +
            localPath
            + +
            +
            longitude
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-m.html b/nebula-exchange/target/site/scaladocs/index/index-m.html new file mode 100644 index 0000000..70ac5bd --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-m.html @@ -0,0 +1,35 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            MYSQL
            + +
            +
            MetaProvider
            + +
            +
            MySQLReader
            + +
            +
            MySQLSourceConfigEntry
            + +
            +
            main
            + +
            +
            map
            + +
            +
            metaAddresses
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-n.html b/nebula-exchange/target/site/scaladocs/index/index-n.html new file mode 100644 index 0000000..a8c5fd5 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-n.html @@ -0,0 +1,59 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            NEO4J
            + +
            +
            NebulaGraphClientWriter
            + +
            +
            NebulaReader
            + +
            +
            NebulaSSTWriter
            + +
            +
            NebulaSinkConfigEntry
            + +
            +
            NebulaStorageClientWriter
            + +
            +
            NebulaUtils
            + +
            +
            NebulaWriterCallback
            + +
            +
            Neo4JReader
            + +
            +
            Neo4JSourceConfigEntry
            + +
            +
            name
            + +
            +
            names
            + +
            +
            nebula
            + +
            +
            nebulaFields
            + +
            +
            nebulaPoolConfig
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-o.html b/nebula-exchange/target/site/scaladocs/index/index-o.html new file mode 100644 index 0000000..b3cbeec --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-o.html @@ -0,0 +1,32 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            ORC
            + +
            +
            ORCReader
            + +
            +
            Offset
            + +
            +
            onFailure
            + +
            +
            onSuccess
            + +
            +
            options
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-p.html b/nebula-exchange/target/site/scaladocs/index/index-p.html new file mode 100644 index 0000000..497d775 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-p.html @@ -0,0 +1,89 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            PARQUET
            + +
            +
            POLICY
            + +
            +
            PULSAR
            + +
            +
            ParquetReader
            + +
            +
            PartitionID
            + +
            +
            ProcessResult
            + +
            +
            Processor
            + +
            +
            PropertyNames
            + +
            +
            PropertyValues
            + +
            +
            PulsarReader
            + +
            +
            PulsarSourceConfigEntry
            + +
            +
            parallel
            + +
            +
            parse
            + +
            +
            parser
            + +
            +
            partition
            + +
            +
            password
            + +
            +
            path
            + +
            +
            policy
            + +
            +
            pool
            + +
            +
            port
            + +
            +
            prepare
            + +
            +
            process
            + +
            +
            processor
            + +
            +
            propertyNames
            + +
            +
            propertyValues
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-r.html b/nebula-exchange/target/site/scaladocs/index/index-r.html new file mode 100644 index 0000000..f9972f9 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-r.html @@ -0,0 +1,53 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            RateConfigEntry
            + +
            +
            Reader
            + +
            +
            ReloadProcessor
            + +
            +
            ranking
            + +
            +
            rankingField
            + +
            +
            rateConfig
            + +
            +
            rateLimiter
            + +
            +
            read
            + +
            +
            reader
            + +
            +
            releaseGraphClient
            + +
            +
            reload
            + +
            +
            remotePath
            + +
            +
            retry
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-s.html b/nebula-exchange/target/site/scaladocs/index/index-s.html new file mode 100644 index 0000000..c320fa6 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-s.html @@ -0,0 +1,104 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            SOCKET
            + +
            +
            SST
            + +
            +
            STRING
            + +
            +
            SchemaConfigEntry
            + +
            +
            SchemaID
            + +
            +
            SchemaVersion
            + +
            +
            ServerBaseReader
            + +
            +
            ServerBaseWriter
            + +
            +
            ServerDataSourceConfigEntry
            + +
            +
            SinkCategory
            + +
            +
            SourceCategory
            + +
            +
            SparkConfigEntry
            + +
            +
            StreamingBaseReader
            + +
            +
            StreamingDataSourceConfigEntry
            + +
            +
            save
            + +
            +
            saveContent
            + +
            +
            sentence
            + +
            +
            separator
            + +
            +
            server
            + +
            +
            serviceUrl
            + +
            +
            session
            + +
            +
            size
            + +
            +
            source
            + +
            +
            sourceField
            + +
            +
            sourcePolicy
            + +
            +
            space
            + +
            +
            sparkConfigEntry
            + +
            +
            start
            + +
            +
            submit
            + +
            +
            switchSpace
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-t.html b/nebula-exchange/target/site/scaladocs/index/index-t.html new file mode 100644 index 0000000..cb5b6eb --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-t.html @@ -0,0 +1,59 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            TEXT
            + +
            +
            TagConfigEntry
            + +
            +
            TagID
            + +
            +
            TagVersion
            + +
            +
            TooManyErrorsException
            + +
            +
            Type
            + +
            +
            table
            + +
            +
            tagsConfig
            + +
            +
            targetField
            + +
            +
            targetPolicy
            + +
            +
            timeout
            + +
            +
            toExecuteSentence
            + +
            +
            toString
            + +
            +
            tools
            + +
            +
            topic
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-u.html b/nebula-exchange/target/site/scaladocs/index/index-u.html new file mode 100644 index 0000000..7c15e50 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-u.html @@ -0,0 +1,32 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            UUID
            + +
            +
            UserConfigEntry
            + +
            +
            upload
            + +
            +
            user
            + +
            +
            userConfig
            + +
            +
            utils
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-v.html b/nebula-exchange/target/site/scaladocs/index/index-v.html new file mode 100644 index 0000000..1c1dbe9 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-v.html @@ -0,0 +1,50 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            VERTEX
            + +
            +
            Vertex
            + +
            +
            VertexID
            + +
            +
            VertexIDSlice
            + +
            +
            Vertices
            + +
            +
            VerticesProcessor
            + +
            +
            VidType
            + +
            +
            values
            + +
            +
            vertexField
            + +
            +
            vertexID
            + +
            +
            vertexPolicy
            + +
            +
            vesoft
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/index/index-w.html b/nebula-exchange/target/site/scaladocs/index/index-w.html new file mode 100644 index 0000000..634b9b7 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/index/index-w.html @@ -0,0 +1,38 @@ + + + + nebula-exchange 2.0.0 API + + + + + + + + +
            +
            Writer
            + +
            +
            WriterResult
            + +
            +
            waredir
            + +
            +
            write
            + +
            +
            writeEdge
            + +
            +
            writeEdges
            + +
            +
            writeVertices
            + +
            +
            writer
            + +
            + diff --git a/nebula-exchange/target/site/scaladocs/lib/arrow-down.png b/nebula-exchange/target/site/scaladocs/lib/arrow-down.png new file mode 100644 index 0000000000000000000000000000000000000000..7229603ae5b30ce0e0bd09863543b260085c8f2d GIT binary patch literal 6232 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 literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/class_big.png b/nebula-exchange/target/site/scaladocs/lib/class_big.png new file mode 100644 index 0000000000000000000000000000000000000000..cb1f638a585c50456f57b73c4d043c75762ff9a5 GIT binary patch literal 7516 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
            }cgT+sFDw4uMOU<91Pe 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 U==iC&s{jB107*qoM6N<$f-P8sEdT%j literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/constructorsbg.gif b/nebula-exchange/target/site/scaladocs/lib/constructorsbg.gif new file mode 100644 index 0000000000000000000000000000000000000000..2e3f5ea53025f68e2636f9c65e5115a3aa1bb581 GIT binary patch literal 1206 zcmZ?wbhEHbWMq(GIKseSZEam&UmqG8YHx4v?(P;76XWUWX=!Qc=j$685$WvY?CR?3 zAK)Jt7-V8%YG!5@8yjnDYwPIXsHUnK9v&VQ9TgWB=jiAd5*+O9?QL#hZftDKfCLo( zb4U0FD7Yk+Bm!w0`-+0ZZE`@j@w*YQzUa=n7J9^3ax%w4}1^R}1 z1|ToN6#Dw&SDKp(S6y5Zl!|aKR)dQ}DhpEegHnt0ON)|Ify$LZRuxz|7o{eaQ#zd*q`*i^wcF*!32#0RVQ^|kWMD=taQOHTE4u~h<^pqH7MVr61% z;AY@x;B0E?uBO)VrJ|N z)az`3RWB$hI zxnujbty?y4+PGo;y0vRouUffc`Ld-;7B5=3VE(+hb7s$)Ib-^?sZ%CTnmD1queYbW ztFxoMt+l1Osj;EHuC}JSsEZKEj1-MDKQ~FE;c4QDl#HG zEHorIC@{d^&)3J>%hSW%&DF)($Qx)!_Hn5)9TB4Am2f&=-p_kccyqPBfKGwUE!WRLZeY z&9_xAcF-<$)~j$)tu;5Sb~kMFG;Z}V?)EY6_cxj1Z!#mmbas&G!VuHNfk6*)|04m# ze}c|Msfi`2DGKG8B^e6tp1uJLIt)MnasUIXxWbl9$+AdMQ_qW!P0lP*Igu!GM1jSD HgTWdAVsJLn literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/defbg-blue.gif b/nebula-exchange/target/site/scaladocs/lib/defbg-blue.gif new file mode 100644 index 0000000000000000000000000000000000000000..69038337a793be5ec04430183980b7e393113ea1 GIT binary patch literal 1544 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 availableWidth) + { + // resize diagram + var height = diagramHeight / diagramWidth * availableWidth; + $(".diagram svg", this).width(availableWidth); + $(".diagram svg", this).height(height); + + // register click event on whole div + $(".diagram", this).click(function() { + diagrams.popup($(this)); + }); + $(".diagram", this).addClass("magnifying"); + } + else + { + // restore full size of diagram + $(".diagram svg", this).width(diagramWidth); + $(".diagram svg", this).height(diagramHeight); + // don't show custom cursor any more + $(".diagram", this).removeClass("magnifying"); + } + }); +}; + +/** + * Shows or hides a diagram depending on its current state. + */ +diagrams.toggle = function(container, dontAnimate) +{ + // change class of link + $(".diagram-link", container).toggleClass("open"); + // get element to show / hide + var div = $(".diagram", container); + if (div.is(':visible')) + { + $(".diagram-help", container).hide(); + div.unbind("click"); + div.removeClass("magnifying"); + div.slideUp(100); + } + else + { + diagrams.resize(); + if(dontAnimate) + div.show(); + else + div.slideDown(100); + $(".diagram-help", container).show(); + } +}; + +/** + * Opens a popup containing a copy of a diagram. + */ +diagrams.windows = {}; +diagrams.popup = function(diagram) +{ + var id = diagram.attr("id"); + if(!diagrams.windows[id] || diagrams.windows[id].closed) { + var title = $(".symbol .name", $("#signature")).text(); + // cloning from parent window to popup somehow doesn't work in IE + // therefore include the SVG as a string into the HTML + var svgIE = jQuery.browser.msie ? $("
            ").append(diagram.data("svg")).html() : ""; + var html = '' + + '\n' + + '\n' + + '\n' + + ' \n' + + ' ' + title + '\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' Close this window\n' + + ' ' + svgIE + '\n' + + ' \n' + + ''; + + var padding = 30; + var screenHeight = screen.availHeight; + var screenWidth = screen.availWidth; + var w = Math.min(screenWidth, diagram.data("width") + 2 * padding); + var h = Math.min(screenHeight, diagram.data("height") + 2 * padding); + var left = (screenWidth - w) / 2; + var top = (screenHeight - h) / 2; + var parameters = "height=" + h + ", width=" + w + ", left=" + left + ", top=" + top + ", scrollbars=yes, location=no, resizable=yes"; + var win = window.open("about:blank", "_blank", parameters); + win.document.open(); + win.document.write(html); + win.document.close(); + diagrams.windows[id] = win; + } + win.focus(); +}; + +/** + * This method is called from within the popup when a node is clicked. + */ +diagrams.redirectFromPopup = function(url) +{ + window.location = url; +}; + +/** + * Helper method that adds a class to a SVG element. + */ +diagrams.addClass = function(svgElem, newClass) { + newClass = newClass || "over"; + var classes = svgElem.attr("class"); + if ($.inArray(newClass, classes.split(/\s+/)) == -1) { + classes += (classes ? ' ' : '') + newClass; + svgElem.attr("class", classes); + } +}; + +/** + * Helper method that removes a class from a SVG element. + */ +diagrams.removeClass = function(svgElem, oldClass) { + oldClass = oldClass || "over"; + var classes = svgElem.attr("class"); + classes = $.grep(classes.split(/\s+/), function(n, i) { return n != oldClass; }).join(' '); + svgElem.attr("class", classes); +}; + diff --git a/nebula-exchange/target/site/scaladocs/lib/filter_box_left.png b/nebula-exchange/target/site/scaladocs/lib/filter_box_left.png new file mode 100644 index 0000000000000000000000000000000000000000..0e8c893315e7955b02474d3a544b9145aafb15b2 GIT binary patch literal 1692 zcmaJ?Yfuws6pg$rSOqBp3YKM~RV;Zz60;aJAs|tLX#yHS2bN@k3}iRiY$T*bRAg#9 zU=@FeD54a{@j+EkDTq>D1*#y5=}<;1FQtW2QWQm;)^1R+Kd|4-?)R8;&OP^jcW1wn zMQxbxvc!c#q0E;=h~?zGh0nhVLI8<$M9qZi_hoVG}vq!iJ%!WPy#m5Py=;ZL5vtw zxJE~4Fch#U!ikuX5P+o9Hz{a!GqR}RZJEe|F-)+I!J;#5DNO^V(*K8QwKHe~AxGZ% zomJQnouNY*a>RfcaTR%SNmN@X9TbWqFoEIG7?w6&MOg|)V1^V-2ZSm(fD~3~P}_bA zFO@=z7d?GMc8_g2)3)ShrtuM!>~@@N>+T&8M1C!960tDa)O{gFy2(fA zz3T<_SYuv{D)_EL=f;)y69e-Ky4|eHMud}d&8tpKdJXw|FA8wVks>d2E7RxJTpy%k& zkln?LUfbzg^RAqmv%e%NGORQBAW}-Td|p~VHijo;X8zsZ($X^6+uM6!J#g~Lon3o| z%yy6Q#l8#XZjX=8POAt4(SV9rv74$vZ!mQ7Ih=6>K^_l|jA(PbOJZ)7%FntjLr%)i zy2~xr+}{#jYpUxb&qZ$DoK;v{eCMdMAN4_|-e@%T^!4>EHE#RNqt*9tQPEOmTwHcp z8SUCPVvxz@I`!(h*bT?;AMpB?9IRY;6SepD?GM%LqlKtmzwpwk1RTGYUvT)Ehf9tw zE33A9!v5+(_aFQ91qB5O)j2tiU0q!X$!!raxvG}Ir~D;ZJ#daH$(+?g#+>uOcV@q9( zNA}J$hYc4tg?PB^X-m33JSql-TX}6aoBK0{#?8YKde>dG#XG8NY8+x>{FmgFM?ny@ z_lvcz0)e1s=k?TwO*EQAcHQALZe00KpIDBLpO!mctE_}kbiwl%FJKIFot&Jc+$f_8 z8oG+eBKkEqH`A|N(9~bzE0=fty7^4!Zl}xsijNe>*2c%iZiL<2FV|eD)ojQO;0pxH zS6iOl-NNi$#aFwY%o;pr{{mUu^Fwjf3l}ad*ZyPVIVyrIkPEX+>TMxn15Nd zav-ZrQP;=Um;C7y>q90w(zLCoZdruVQ63j}ETaFVxBMUOjizep$G*PA6TE6m?$RPx zmv)7uBXiNdkmBLz_4cmubG5#W6mXxF8k^TF<8E1SsNetIhE~5hP876f;&u1}p9{AC Ng(NIW{GBLa@4p#{lvn@& literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/filter_box_left2.gif b/nebula-exchange/target/site/scaladocs/lib/filter_box_left2.gif new file mode 100644 index 0000000000000000000000000000000000000000..b9b49076a6410112fd18b370bc661154bbab8f80 GIT binary patch literal 1462 zcmZ?wbhEHb6k!lyxN5?1>C&aRxVRrbe!P11>f*(Vt*xySCr_wV1o zw{PEm|Ni~!*RS{P-TU(8%b!1gZrr%>`t|GF+}z{Gk3W6-^z7NQ8#ZiMzkdCvPoHkz zz8w`6_44J*J9qAsmzV$k{ky2BXxFY?A3l8e`}gm(Y13k3V}U0q$LPMun}Zr!h6zgDka?cw3^9}E}>0mc8^5xxNmE{P?HK-$K>q98Fj zJGDe1DK$Ma&sORE?)^#%nJKnP;ikR@z6H*y8JQkcMXAA6ej&+K*~ykEO7?aNHWgMC zxdpkYC5Z|ZxjA{oRu#5Ni7EL>sa8NXNLXJ<0j#7X+g8aDB%uJZ(>cE=Rl!uxKsVXI z%s|1+P|wiV#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$nd zN=gc>^!0&3rdMvPmtT~wZ)j<02{OaTNEfI=x41H|B(Xv_uUHvof=g;~a#3bMNoIbY z0?5R~r2NtnTP2`NAzsKWfE$}vtOxdvUUGh}ennz|zM-B0$V)JVzP|XC=H|jx7ncO3 zBHWAB;NpiyW)Z+ZoqU2Pda%GTJ1y;^Qsfi`|MIrh5Ij~R+$jC3rFV4s>P;d@5 zRq#zr&ddYx!Rmc|tvvIJOA_;vQ$1a5m4GJbWoD*WS(v-I7@E3Rm|B{e7#g}7IJr4n zI=dQ~nOmATIhq)m!1TK0Czs}?=9R$orXciM;?xUD3b_S9n_W_iGRsm^+=}vZ6~JD$ z%Eav!Go0o@^`_uv@OxBG5|NZ^* z``6DO-@kqR^7+%p5AWZ-ee?R&%NNg|J$>@{(ZdJ#@7=v~`_|1H*RNf@a{1E53+K6ZM9qnzcEzM1h4fS=kHPuy>73F26CB;RB1^Ico zIoVm68R==MDalER3Gs2UG0{A;Cd`0selzKHgrQ9`0_gF3wJl4)%7oHr7^_ z7UpKACdNjp{}N?qO7E-ATK8?BP}HFfhW0S{OOhO#noZi%b`dsS#`djvo JU&f9M)&NKAH`@RJ literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/filter_box_right.png b/nebula-exchange/target/site/scaladocs/lib/filter_box_right.png new file mode 100644 index 0000000000000000000000000000000000000000..f127e35b48d39bd048fea2a8e98dd68fb5984601 GIT binary patch literal 1803 zcmaJ?c~BEq9F7=in$dz{RRT&}Q31^f1hNu^kf2c$5rQC;nkCsl%&~E^K%iDsP^4;s zswhfSj9LVxBU)6zD?lRSRqKIq)Yc0{2E>ZW2!(D?uz!@knceq(Z@%yQojaQsDVaZp zOd%5pgfXH8f+&3d8h<8|obmV5KZquLbH{{nSTv%<(jgQkgej0Dm@3jj$#4`5DKb_y z!65{~NI)fx!{Wq?K{=wOLkDXImTC>)(Bk;*gGa;^fHH1aSc^j6qbRR--e3MjkMr3*u+TH3OgyKrl5A z_!v~2IFcHUpfEL%&ZNni943{+qO<%1f`Wo(Q`t-wlfh&&SZo?A2=r%zOeXcy0&s7r zLJ39*B0l-TEgq19VS13kNKa3vr~A_pG?~HTa=8u-Hk*bcXod_O1{rBO!?ZyK0c?xf@&7}$+99+7i-JGL z`=7!FX@(wVM8O6m6_w+SQ%-ZZ(u3hB3}FZ=MG(zk6(ds+3^Al2dTMxdAXN;>RXT?~ zfESBFk8}4R1{IF>v}ciN9$6Oq1WO31itrb>~t_Df!-{X?fQ9 zk?JIIN5%8rmh<<$$;Z4(?)U8LzyE69^LhEC^74BlLIs86fWskY8r;Bf?!pZ-sdfFG zEUlZ1QX2`TCJv^u=h4T(yzAE>!Qz2IB=t^oLm+|jIi3Ru3nRw?Px8I}cliAP zxNQ*#m&E)SH+#mh%F2yao6Xkw8-V6)4t36KX3*(``t0_0ZE$d~tfsu&FJkiLdb5+FCcW+59F?F=Jatd;7)5j{%KNS2af>G#LE5-o6b>Of(&?uQwr?bo>feF3Stxw*8it|Y@&xNo0JVq&5uUvsI*eDvs*oLqZ)TAJqc z6~I)8L|y6{3u!c?$z-z3XxuejBa;zcwzXYsPxIenwMM*XZN0H+)~s2Ef|G@QF3<8? zd>>4;+3oI^KXi2kbiI4WwwTS+e0+UHC#G*NDmvHDu>5sk?j4Hn5;CMv5U*Xo?#`N? z%k=jjnVXxdswQrEIjUv<_!U=02Q!~Od!`~rJgFZ8@lIrZPu`e&t!W`}d!{lag{0wl zEZTJWSyIiJGu%7nN2+t$+SFssH7#TI7e-A+Z{51J*7jswQ)Do#R&^ z+d>XWN-c-;EsvPptIr*D*;!Pyzq-1}{-V}z(rD`{pNt#d0cRJtl_j4%Qd3p+mq+f^ zSWiEgq?J z35ki5t#tIyzEifoic2?XlvuDZ6_~zP>KC?sg-@-|lHY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C z$yM3OmMKd1b_zBXRu#Dgxv3?I3Kh9IdBs*0wn~X9`AMl(KsHENUr7P1q$Jx`$q^)> z0J76LzbI9~RL?*+*}%*|!OT$4(AdP>++0V&$iUD*-@r)U&`8(N+{)O<%D_MY3Y37h z6{VzE1-ZCE?E>;_l`=|73as??%gf94%8m8%i_-NCEiElUW*8ai0#)c1SLT%@R_Nvx zE5l51Ni9w;$}A|!%+FH*nV6WAUs__T1av9H3%LbwWAlpjz~0eI&d=4aNG#Ad)H48i z38v837r)ZnT)67ulAu(Cd$Af^98y`3svneEoL^d$oC;K~46>@g%DE^tu_V7JBtJg~ z7K#BG`6c$o&6x?pHz^PXs=oo!a#3DsBObD2IKumbD1#;jC zKQ#}S+KYh6n(_a?zkh!J`uXGgx36D5fBN|0{kyksUcY(?%$rZ2Jbv`>!To!8@7%t1 z^TzdSSFc>Ybn(LZb7#+-K6UcM@nc7i96ogL!2W%E_w3%abI0~=Teoc9v~k1wb!*qG zUbS+?@?}exEMBy5!Tfo1=ggipbH?;(Q>RRxG;umQ)5GYU2RQu zRb@qaS!qdeQDH%TUT#iyR%S+eT53viQer}UTx?8qRAfYWSZGLaP+)++pRbR%m#2rj zo2!enlcR&Zovn?vm8FHbnW>4f5im>X>FQ`}X=xV%Qmue&kg&dz0$52&wylyQNJ0T*r*nQ$s)DJWfo`&anSp|t zp`M|!iMhGCj)IYap@F`Ek-njkuA#Y=v5}R5fdUjL0c|TvNwW%aaf8|g1^l#~=$ z>Fbx5m+O@q>*W`v>l<2HT7t|lGSUUA&@HaaD@m--%_~-hnc$LIoLrPyP?DLSrvNfB zF)6>a#8wIDQivCF3*g4)73+b$qnDhYt6z~=pl_&W0P+${p|3A~rMbCq)x{-2sR;LC zHMlsWvLIDID784hv?w_hs9YIjRe_arQEFmIeo;t%ehw@Y12XbU@{2R_3lyA#O%;3- zlQZ)`e6V_7Un|eN;*!L?t5 zX6BYAPL3ueiaKZd} zbLY&SHFL)FX;Y_6o-}bne_wA;cUNaeds}Nub5mnOeO+x$bya0Wd0A;maZzDGeqL@) zc2;IadRl5qa#CVKd|YfybW~(Scvxsia8O`?zn`yFMfdYiVkztEs9eD=8|-%gM?}OG!$Ii;0Q|3keGF^YQX;2gptZlbs@FmYn}yD2~erzFfAE6%X5*J>dm-YQn*FG@2pU+&rzrw7-v$x*ez4<+USbC|VJu9>x`~~1WHKzao literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/filterboxbg.gif b/nebula-exchange/target/site/scaladocs/lib/filterboxbg.gif new file mode 100644 index 0000000000000000000000000000000000000000..ae2f85823bbbd77d85a28d8348bfd75a1ec626ba GIT binary patch literal 1366 zcmaJ>d0^927|&$j+)$KD(Vht+jHR17kQ|Xk~>-G7(u~=+)csLf1#pCg4G#U&J1%shPBA!%LkH;I2 z#Q-f73I+oHOga+^12g3F`2nN9zdw;s)9KX6$Vez04h4f=k2jS{`~1FiCX-OrU@#aR zj;2yc5GN9eh9hAxhK7dXaj>aIB9TBKkVqu_e!s`#Nv4u1Ku)Kj9HV5UsKr$eJ4l5D z-^wbtNKze)0=F`4EN??Hd-ftQOWTlUvkP;HcBY+O+AA@Qy~~@Z-VVx2BUOvwN;l!= zM2=BN*v)nFGU2u%BrUWu1hBPb6oE$}N{0=p);3@*rd^O2*sRBN6jqMG;It~H;$H-2Ig?S|0ygt^@t4Gz{oyTp)+ATXZA1F zw+o6Ow+kX{Z#2U$l45zyAH};|L>(_HBu_DQ4jTd#^ejsg6&9z%V0M_yRFSl4tHPt5El;t`Es*7WICCjA`bIm!qS}SlOi0oh_b}d6YC4qxSOD5Rdx!^hV z#<+CuT#PxnC`bm?4)$LMom~RmqnYDv3!L%BXL!)<5@_qZk-z@@Zk3iy3q&o^Ix_2n0zAN=goPd@(W!w=pceDB?N-X3`C%{LCb zzJK4|*Is>P&+eCBdhvzlpL_P1T~F_PYR8lP+n;#+u}8N(^6*0sK5+ki_ug~&U3YHX za>wnr-FnN-n{T>t(+wN1zwX*=uHJCf`o1gIU2*wkmtNA_&!Ej)h%7(taaFHsux!+vQ;i5tQD4W zv&o2qE2YzH_B}#`-nO=9mf!3Ja$e73rto#dFaKXdXHZg3R;GHY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C$yM3OmMKd1b_zBX zRu#Dgxv3?I3Kh9IdBs*0wn~X9`AMl(KsHENUr7P1q$Jx`$q^)>0J76LzbI9~RL?*+ z*}%*|!OT$4(AdP>++0V&$iUD*-@r)U&`8(N+{)O<%D_MY3Y37h6{VzE1-ZCE?E>;_ zl`=|73as??%gf94%8m8%i_-NCEiElUW*8ai0#)c1SLT%@R_NvxE5l51Ni9w;$}A|! z%+FH*nV6WAUs__T1av9H3%LbwWAlpjz~0eI&d=4aNG#Ad)H48i38v837r)ZnT)67u zlAu(Cd$Af^98y`3svneEoL^d$oC;K~46>@g%DE^tu_V7JBtJg~7K#BG`6c$o&6x?nx#i>^x=oo!a#3DsBObD2IKumbD1#;jCKQ#}S+KYh6n(_a? zzkh!J`uXGgx36D5fBN|0{kyksUcY+z;`y_uPaZ#d_~8D%yLWEix_RUJwX0VyU%GhV z{JFDdPMZ`!zF{kpYlR z+RD .pre { + display: block; + position: absolute; + top: 0; + left: 0; + height: 23px; + width: 21px; + background: url("filter_box_left.png"); +} + +#textfilter > .input { + display: block; + position: absolute; + top: 0; + right: 20px; + left: 20px; +} + +#textfilter > .input > input { + height: 20px; + padding: 1px; + font-weight: bold; + color: #000000; + background: #ffffff url("filterboxbarbg.png") repeat-x bottom left; + width: 100%; +} + +#textfilter > .post { + display: block; + position: absolute; + top: 0; + right: 0; + height: 23px; + width: 21px; + background: url("filter_box_right.png"); +} + +/*#textfilter { + position: relative; + display: block; + height: 20px; + margin-bottom: 5px; +} + +#textfilter > .pre { + display: block; + position: absolute; + top: 0; + left: 0; + height: 20px; + width: 20px; + background: url("filter_box_left.png"); +} + +#textfilter > .input { + display: block; + position: absolute; + top: 0; + right: 20px; + left: 20px; +} + +#textfilter > .input > input { + height: 16px; + padding: 2px; + font-weight: bold; + color: darkblue; + background-color: white; + width: 100%; +} + +#textfilter > .post { + display: block; + position: absolute; + top: 0; + right: 0; + height: 20px; + width: 20px; + background: url("filter_box_right.png"); +}*/ + +#focusfilter { + position: relative; + text-align: center; + display: block; + padding: 5px; + background-color: #fffebd; /* light yellow*/ + text-shadow: #ffffff 0 1px 0; +} + +#focusfilter .focuscoll { + font-weight: bold; + text-shadow: #ffffff 0 1px 0; +} + +#focusfilter img { + bottom: -2px; + position: relative; +} + +#kindfilter { + position: relative; + display: block; + padding: 5px; +/* background-color: #999;*/ + text-align: center; +} + +#kindfilter > a { + color: black; +/* text-decoration: underline;*/ + text-shadow: #ffffff 0 1px 0; + +} + +#kindfilter > a:hover { + color: #4C4C4C; + text-decoration: none; + text-shadow: #ffffff 0 1px 0; +} + +#letters { + position: relative; + text-align: center; + padding-bottom: 5px; + border:1px solid #bbbbbb; + border-top:0; + border-left:0; + border-right:0; +} + +#letters > a, #letters > span { +/* font-family: monospace;*/ + color: #858484; + font-weight: bold; + font-size: 8pt; + text-shadow: #ffffff 0 1px 0; + padding-right: 2px; +} + +#letters > span { + color: #bbb; +} + +#tpl { + display: block; + position: fixed; + overflow: auto; + right: 0; + left: 0; + bottom: 0; + top: 5px; + position: absolute; + display: block; +} + +#tpl .packhide { + display: block; + float: right; + font-weight: normal; + color: white; +} + +#tpl .packfocus { + display: block; + float: right; + font-weight: normal; + color: white; +} + +#tpl .packages > ol { + background-color: #dadfe6; + /*margin-bottom: 5px;*/ +} + +/*#tpl .packages > ol > li { + margin-bottom: 1px; +}*/ + +#tpl .packages > li > a { + padding: 0px 5px; +} + +#tpl .packages > li > a.tplshow { + display: block; + color: white; + font-weight: bold; + display: block; + text-shadow: #000000 0 1px 0; +} + +#tpl ol > li.pack { + padding: 3px 5px; + background: url("packagesbg.gif"); + background-repeat:repeat-x; + min-height: 14px; + background-color: #6e808e; +} + +#tpl ol > li { + display: block; +} + +#tpl .templates > li { + padding-left: 5px; + min-height: 18px; +} + +#tpl ol > li .icon { + padding-right: 5px; + bottom: -2px; + position: relative; +} + +#tpl .templates div.placeholder { + padding-right: 5px; + width: 13px; + display: inline-block; +} + +#tpl .templates span.tplLink { + padding-left: 5px; +} + +#content { + border-left-width: 1px; + border-left-color: black; + border-left-style: white; + right: 0px; + left: 0px; + bottom: 0px; + top: 0px; + position: fixed; + margin-left: 300px; + display: block; + -webkit-overflow-scrolling: touch; +} + +#content > iframe { + display: block; + height: 100%; + width: 100%; +} + +.ui-layout-pane { + background: #FFF; + overflow: auto; +} + +.ui-layout-resizer { + background-image:url('filterbg.gif'); + background-repeat:repeat-x; + background-color: #ededee; /* light gray */ + border:1px solid #bbbbbb; + border-top:0; + border-bottom:0; + border-left: 0; +} + +.ui-layout-toggler { + background: #AAA; +} \ No newline at end of file diff --git a/nebula-exchange/target/site/scaladocs/lib/index.js b/nebula-exchange/target/site/scaladocs/lib/index.js new file mode 100644 index 0000000..cf81f7f --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/lib/index.js @@ -0,0 +1,577 @@ +// © 2009–2010 EPFL/LAMP +// code by Gilles Dubochet with contributions by Johannes Rudolph, "spiros" and Marcin Kubala + +var topLevelTemplates = undefined; +var topLevelPackages = undefined; + +var scheduler = undefined; + +var kindFilterState = undefined; +var focusFilterState = undefined; + +var title = $(document).attr('title'); + +var lastFragment = ""; + +$(document).ready(function() { + $('body').layout({ + west__size: '20%', + center__maskContents: true + }); + $('#browser').layout({ + center__paneSelector: ".ui-west-center" + //,center__initClosed:true + ,north__paneSelector: ".ui-west-north" + }); + $('iframe').bind("load", function(){ + try { + var subtitle = $(this).contents().find('title').text(); + $(document).attr('title', (title ? title + " - " : "") + subtitle); + } catch (e) { + // Chrome doesn't allow reading the iframe's contents when + // used on the local file system. + } + setUrlFragmentFromFrameSrc(); + }); + + // workaround for IE's iframe sizing lack of smartness + if($.browser.msie) { + function fixIFrame() { + $('iframe').height($(window).height() ) + } + $('iframe').bind("load",fixIFrame) + $('iframe').bind("resize",fixIFrame) + } + + scheduler = new Scheduler(); + scheduler.addLabel("init", 1); + scheduler.addLabel("focus", 2); + scheduler.addLabel("filter", 4); + + prepareEntityList(); + + configureTextFilter(); + configureKindFilter(); + configureEntityList(); + + setFrameSrcFromUrlFragment(); + + // If the url fragment changes, adjust the src of iframe "template". + $(window).bind('hashchange', function() { + if(lastFragment != window.location.hash) { + lastFragment = window.location.hash; + setFrameSrcFromUrlFragment(); + } + }); +}); + +// Set the iframe's src according to the fragment of the current url. +// fragment = "#scala.Either" => iframe url = "scala/Either.html" +// fragment = "#scala.Either@isRight:Boolean" => iframe url = "scala/Either.html#isRight:Boolean" +// fragment = "#scalaz.iteratee.package@>@>[E,A]=scalaz.iteratee.package.Iteratee[E,A]" => iframe url = "scalaz/iteratee/package.html#>@>[E,A]=scalaz.iteratee.package.Iteratee[E,A]" +function setFrameSrcFromUrlFragment() { + + function extractLoc(fragment) { + var loc = fragment.split('@')[0].replace(/\./g, "/"); + if (loc.indexOf(".html") < 0) { + loc += ".html"; + } + return loc; + } + + function extractMemberSig(fragment) { + var splitIdx = fragment.indexOf('@'); + if (splitIdx < 0) { + return; + } + return fragment.substr(splitIdx + 1); + } + + var fragment = location.hash.slice(1); + if (fragment) { + var locWithMemeberSig = extractLoc(fragment); + var memberSig = extractMemberSig(fragment); + if (memberSig) { + locWithMemeberSig += "#" + memberSig; + } + frames["template"].location.replace(location.protocol + locWithMemeberSig); + } else { + console.log("empty fragment detected"); + frames["template"].location.replace("package.html"); + } +} + +// Set the url fragment according to the src of the iframe "template". +// iframe url = "scala/Either.html" => url fragment = "#scala.Either" +// iframe url = "scala/Either.html#isRight:Boolean" => url fragment = "#scala.Either@isRight:Boolean" +// iframe url = "scalaz/iteratee/package.html#>@>[E,A]=scalaz.iteratee.package.Iteratee[E,A]" => fragment = "#scalaz.iteratee.package@>@>[E,A]=scalaz.iteratee.package.Iteratee[E,A]" +function setUrlFragmentFromFrameSrc() { + try { + var commonLength = location.pathname.lastIndexOf("/"); + var frameLocation = frames["template"].location; + var relativePath = frameLocation.pathname.slice(commonLength + 1); + + if(!relativePath || frameLocation.pathname.indexOf("/") < 0) + return; + + // Add #, remove ".html" and replace "/" with "." + fragment = "#" + relativePath.replace(/\.html$/, "").replace(/\//g, "."); + + // Add the frame's hash after an @ + if(frameLocation.hash) fragment += ("@" + frameLocation.hash.slice(1)); + + // Use replace to not add history items + lastFragment = fragment; + location.replace(fragment); + } + catch(e) { + // Chrome doesn't allow reading the iframe's location when + // used on the local file system. + } +} + +var Index = {}; + +(function (ns) { + function openLink(t, type) { + var href; + if (type == 'object') { + href = t['object']; + } else { + href = t['class'] || t['trait'] || t['case class'] || t['type']; + } + return [ + '' + ].join(''); + } + + function createPackageHeader(pack) { + return [ + '
          1. ', + 'focushide', + '', + pack, + '
          2. ' + ].join(''); + }; + + function createListItem(template) { + var inner = ''; + + + if (template.object) { + inner += openLink(template, 'object'); + } + + if (template['class'] || template['trait'] || template['case class'] || template['type']) { + inner += (inner == '') ? + '
            ' : ''; + inner += openLink(template, template['trait'] ? 'trait' : template['type'] ? 'type' : 'class'); + } else { + inner += '
            '; + } + + return [ + '
          3. ', + inner, + '', + template.name.replace(/^.*\./, ''), + '
          4. ' + ].join(''); + } + + + ns.createPackageTree = function (pack, matched, focused) { + var html = $.map(matched, function (child, i) { + return createListItem(child); + }).join(''); + + var header; + if (focused && pack == focused) { + header = ''; + } else { + header = createPackageHeader(pack); + } + + return [ + '
              ', + header, + '
                ', + html, + '
            ' + ].join(''); + } + + ns.keys = function (obj) { + var result = []; + var key; + for (key in obj) { + result.push(key); + } + return result; + } + + var hiddenPackages = {}; + + function subPackages(pack) { + return $.grep($('#tpl ol.packages'), function (element, index) { + var pack = $('li.pack > .tplshow', element).text(); + return pack.indexOf(pack + '.') == 0; + }); + } + + ns.hidePackage = function (ol) { + var selected = $('li.pack > .tplshow', ol).text(); + hiddenPackages[selected] = true; + + $('ol.templates', ol).hide(); + + $.each(subPackages(selected), function (index, element) { + $(element).hide(); + }); + } + + ns.showPackage = function (ol, state) { + var selected = $('li.pack > .tplshow', ol).text(); + hiddenPackages[selected] = false; + + $('ol.templates', ol).show(); + + $.each(subPackages(selected), function (index, element) { + $(element).show(); + + // When the filter is in "packs" state, + // we don't want to show the `.templates` + var key = $('li.pack > .tplshow', element).text(); + if (hiddenPackages[key] || state == 'packs') { + $('ol.templates', element).hide(); + } + }); + } + +})(Index); + +function configureEntityList() { + kindFilterSync(); + configureHideFilter(); + configureFocusFilter(); + textFilter(); +} + +/* Updates the list of entities (i.e. the content of the #tpl element) from the raw form generated by Scaladoc to a + form suitable for display. In particular, it adds class and object etc. icons, and it configures links to open in + the right frame. Furthermore, it sets the two reference top-level entities lists (topLevelTemplates and + topLevelPackages) to serve as reference for resetting the list when needed. + Be advised: this function should only be called once, on page load. */ +function prepareEntityList() { + var classIcon = $("#library > img.class"); + var traitIcon = $("#library > img.trait"); + var typeIcon = $("#library > img.type"); + var objectIcon = $("#library > img.object"); + var packageIcon = $("#library > img.package"); + + $('#tpl li.pack > a.tplshow').attr("target", "template"); + $('#tpl li.pack').each(function () { + $("span.class", this).each(function() { $(this).replaceWith(classIcon.clone()); }); + $("span.trait", this).each(function() { $(this).replaceWith(traitIcon.clone()); }); + $("span.type", this).each(function() { $(this).replaceWith(typeIcon.clone()); }); + $("span.object", this).each(function() { $(this).replaceWith(objectIcon.clone()); }); + $("span.package", this).each(function() { $(this).replaceWith(packageIcon.clone()); }); + }); + $('#tpl li.pack') + .prepend("hide") + .prepend("focus"); +} + +/* Handles all key presses while scrolling around with keyboard shortcuts in left panel */ +function keyboardScrolldownLeftPane() { + scheduler.add("init", function() { + $("#textfilter input").blur(); + var $items = $("#tpl li"); + $items.first().addClass('selected'); + + $(window).bind("keydown", function(e) { + var $old = $items.filter('.selected'), + $new; + + switch ( e.keyCode ) { + + case 9: // tab + $old.removeClass('selected'); + break; + + case 13: // enter + $old.removeClass('selected'); + var $url = $old.children().filter('a:last').attr('href'); + $("#template").attr("src",$url); + break; + + case 27: // escape + $old.removeClass('selected'); + $(window).unbind(e); + $("#textfilter input").focus(); + + break; + + case 38: // up + $new = $old.prev(); + + if (!$new.length) { + $new = $old.parent().prev(); + } + + if ($new.is('ol') && $new.children(':last').is('ol')) { + $new = $new.children().children(':last'); + } else if ($new.is('ol')) { + $new = $new.children(':last'); + } + + break; + + case 40: // down + $new = $old.next(); + if (!$new.length) { + $new = $old.parent().parent().next(); + } + if ($new.is('ol')) { + $new = $new.children(':first'); + } + break; + } + + if ($new.is('li')) { + $old.removeClass('selected'); + $new.addClass('selected'); + } else if (e.keyCode == 38) { + $(window).unbind(e); + $("#textfilter input").focus(); + } + }); + }); +} + +/* Configures the text filter */ +function configureTextFilter() { + scheduler.add("init", function() { + $("#textfilter").append(""); + var input = $("#textfilter input"); + resizeFilterBlock(); + input.bind('keyup', function(event) { + if (event.keyCode == 27) { // escape + input.attr("value", ""); + } + if (event.keyCode == 40) { // down arrow + $(window).unbind("keydown"); + keyboardScrolldownLeftPane(); + return false; + } + textFilter(); + }); + input.bind('keydown', function(event) { + if (event.keyCode == 9) { // tab + $("#template").contents().find("#mbrsel-input").focus(); + input.attr("value", ""); + return false; + } + textFilter(); + }); + input.focus(function(event) { input.select(); }); + }); + scheduler.add("init", function() { + $("#textfilter > .post").click(function(){ + $("#textfilter input").attr("value", ""); + textFilter(); + }); + }); +} + +function compilePattern(query) { + var escaped = query.replace(/([\.\*\+\?\|\(\)\[\]\\])/g, '\\$1'); + + if (query.toLowerCase() != query) { + // Regexp that matches CamelCase subbits: "BiSe" is + // "[a-z]*Bi[a-z]*Se" and matches "BitSet", "ABitSet", ... + return new RegExp(escaped.replace(/([A-Z])/g,"[a-z]*$1")); + } + else { // if query is all lower case make a normal case insensitive search + return new RegExp(escaped, "i"); + } +} + +// Filters all focused templates and packages. This function should be made less-blocking. +// @param query The string of the query +function textFilter() { + var query = $("#textfilter input").attr("value") || ''; + var queryRegExp = compilePattern(query); + + // if we are filtering on types, then we have to display types + // ("display packages only" is not possible when filtering) + if (query !== "") { + kindFilter("all"); + } + + // Three things trigger a reload of the left pane list: + // typeof textFilter.lastQuery === "undefined" <-- first load, there is nothing yet in the left pane + // textFilter.lastQuery !== query <-- the filter text has changed + // focusFilterState != null <-- a package has been "focused" + if ((typeof textFilter.lastQuery === "undefined") || (textFilter.lastQuery !== query) || (focusFilterState != null)) { + + textFilter.lastQuery = query; + + scheduler.clear("filter"); + + $('#tpl').html(''); + + var index = 0; + + var searchLoop = function () { + var packages = Index.keys(Index.PACKAGES).sort(); + + while (packages[index]) { + var pack = packages[index]; + var children = Index.PACKAGES[pack]; + index++; + + if (focusFilterState) { + if (pack == focusFilterState || + pack.indexOf(focusFilterState + '.') == 0) { + ; + } else { + continue; + } + } + + var matched = $.grep(children, function (child, i) { + return queryRegExp.test(child.name); + }); + + if (matched.length > 0) { + $('#tpl').append(Index.createPackageTree(pack, matched, + focusFilterState)); + scheduler.add('filter', searchLoop); + return; + } + } + + $('#tpl a.packfocus').click(function () { + focusFilter($(this).parent().parent()); + }); + configureHideFilter(); + }; + + scheduler.add('filter', searchLoop); + } +} + +/* Configures the hide tool by adding the hide link to all packages. */ +function configureHideFilter() { + $('#tpl li.pack a.packhide').click(function () { + var packhide = $(this) + var action = packhide.text(); + + var ol = $(this).parent().parent(); + + if (action == "hide") { + Index.hidePackage(ol); + packhide.text("show"); + } + else { + Index.showPackage(ol, kindFilterState); + packhide.text("hide"); + } + return false; + }); +} + +/* Configures the focus tool by adding the focus bar in the filter box (initially hidden), and by adding the focus + link to all packages. */ +function configureFocusFilter() { + scheduler.add("init", function() { + focusFilterState = null; + if ($("#focusfilter").length == 0) { + $("#filter").append("
            focused on
            "); + $("#focusfilter > .focusremove").click(function(event) { + textFilter(); + + $("#focusfilter").hide(); + $("#kindfilter").show(); + resizeFilterBlock(); + focusFilterState = null; + }); + $("#focusfilter").hide(); + resizeFilterBlock(); + } + }); + scheduler.add("init", function() { + $('#tpl li.pack a.packfocus').click(function () { + focusFilter($(this).parent()); + return false; + }); + }); +} + +/* Focuses the entity index on a specific package. To do so, it will copy the sub-templates and sub-packages of the + focuses package into the top-level templates and packages position of the index. The original top-level + @param package The
          5. element that corresponds to the package in the entity index */ +function focusFilter(package) { + scheduler.clear("filter"); + + var currentFocus = $('li.pack > .tplshow', package).text(); + $("#focusfilter > .focuscoll").empty(); + $("#focusfilter > .focuscoll").append(currentFocus); + + $("#focusfilter").show(); + $("#kindfilter").hide(); + resizeFilterBlock(); + focusFilterState = currentFocus; + kindFilterSync(); + + textFilter(); +} + +function configureKindFilter() { + scheduler.add("init", function() { + kindFilterState = "all"; + $("#filter").append(""); + $("#kindfilter > a").click(function(event) { kindFilter("packs"); }); + resizeFilterBlock(); + }); +} + +function kindFilter(kind) { + if (kind == "packs") { + kindFilterState = "packs"; + kindFilterSync(); + $("#kindfilter > a").replaceWith("display all entities"); + $("#kindfilter > a").click(function(event) { kindFilter("all"); }); + } + else { + kindFilterState = "all"; + kindFilterSync(); + $("#kindfilter > a").replaceWith("display packages only"); + $("#kindfilter > a").click(function(event) { kindFilter("packs"); }); + } +} + +/* Applies the kind filter. */ +function kindFilterSync() { + if (kindFilterState == "all" || focusFilterState != null) { + $("#tpl a.packhide").text('hide'); + $("#tpl ol.templates").show(); + } else { + $("#tpl a.packhide").text('show'); + $("#tpl ol.templates").hide(); + } +} + +function resizeFilterBlock() { + $("#tpl").css("top", $("#filter").outerHeight(true)); +} diff --git a/nebula-exchange/target/site/scaladocs/lib/jquery-ui.js b/nebula-exchange/target/site/scaladocs/lib/jquery-ui.js new file mode 100644 index 0000000..faab0cf --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/lib/jquery-ui.js @@ -0,0 +1,6 @@ +/*! jQuery UI - v1.9.0 - 2012-10-05 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.slider.js, jquery.ui.sortable.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js +* Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */ + +(function(e,t){function i(t,n){var r,i,o,u=t.nodeName.toLowerCase();return"area"===u?(r=t.parentNode,i=r.name,!t.href||!i||r.nodeName.toLowerCase()!=="map"?!1:(o=e("img[usemap=#"+i+"]")[0],!!o&&s(o))):(/input|select|textarea|button|object/.test(u)?!t.disabled:"a"===u?t.href||n:n)&&s(t)}function s(t){return!e(t).parents().andSelf().filter(function(){return e.css(this,"visibility")==="hidden"||e.expr.filters.hidden(this)}).length}var n=0,r=/^ui-id-\d+$/;e.ui=e.ui||{};if(e.ui.version)return;e.extend(e.ui,{version:"1.9.0",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({_focus:e.fn.focus,focus:function(t,n){return typeof t=="number"?this.each(function(){var r=this;setTimeout(function(){e(r).focus(),n&&n.call(r)},t)}):this._focus.apply(this,arguments)},scrollParent:function(){var t;return e.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?t=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):t=this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(n){if(n!==t)return this.css("zIndex",n);if(this.length){var r=e(this[0]),i,s;while(r.length&&r[0]!==document){i=r.css("position");if(i==="absolute"||i==="relative"||i==="fixed"){s=parseInt(r.css("zIndex"),10);if(!isNaN(s)&&s!==0)return s}r=r.parent()}}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++n)})},removeUniqueId:function(){return this.each(function(){r.test(this.id)&&e(this).removeAttr("id")})}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(n,r){function u(t,n,r,s){return e.each(i,function(){n-=parseFloat(e.css(t,"padding"+this))||0,r&&(n-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(n-=parseFloat(e.css(t,"margin"+this))||0)}),n}var i=r==="Width"?["Left","Right"]:["Top","Bottom"],s=r.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+r]=function(n){return n===t?o["inner"+r].call(this):this.each(function(){e(this).css(s,u(this,n)+"px")})},e.fn["outer"+r]=function(t,n){return typeof t!="number"?o["outer"+r].call(this,t):this.each(function(){e(this).css(s,u(this,t,!0,n)+"px")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(n){return!!e.data(n,t)}}):function(t,n,r){return!!e.data(t,r[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),r=isNaN(n);return(r||n>=0)&&i(t,!r)}}),e(function(){var t=document.body,n=t.appendChild(n=document.createElement("div"));n.offsetHeight,e.extend(n.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),e.support.minHeight=n.offsetHeight===100,e.support.selectstart="onselectstart"in n,t.removeChild(n).style.display="none"}),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,n,r){var i,s=e.ui[t].prototype;for(i in r)s.plugins[i]=s.plugins[i]||[],s.plugins[i].push([n,r[i]])},call:function(e,t,n){var r,i=e.plugins[t];if(!i||!e.element[0].parentNode||e.element[0].parentNode.nodeType===11)return;for(r=0;r0?!0:(t[r]=1,i=t[r]>0,t[r]=0,i)},isOverAxis:function(e,t,n){return e>t&&e",options:{disabled:!1,create:null},_createWidget:function(t,r){r=e(r||this.defaultElement||this)[0],this.element=e(r),this.uuid=n++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),r!==this&&(e.data(r,this.widgetName,this),e.data(r,this.widgetFullName,this),this._on({remove:"destroy"}),this.document=e(r.style?r.ownerDocument:r.document||r),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(n,r){var i=n,s,o,u;if(arguments.length===0)return e.widget.extend({},this.options);if(typeof n=="string"){i={},s=n.split("."),n=s.shift();if(s.length){o=i[n]=e.widget.extend({},this.options[n]);for(u=0;u=9||!!t.button?this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted):this._mouseUp(t)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(e){return this.mouseDelayMet},_mouseStart:function(e){},_mouseDrag:function(e){},_mouseStop:function(e){},_mouseCapture:function(e){return!0}})})(jQuery);(function(e,t){function h(e,t,n){return[parseInt(e[0],10)*(l.test(e[0])?t/100:1),parseInt(e[1],10)*(l.test(e[1])?n/100:1)]}function p(t,n){return parseInt(e.css(t,n),10)||0}e.ui=e.ui||{};var n,r=Math.max,i=Math.abs,s=Math.round,o=/left|center|right/,u=/top|center|bottom/,a=/[\+\-]\d+%?/,f=/^\w+/,l=/%$/,c=e.fn.position;e.position={scrollbarWidth:function(){if(n!==t)return n;var r,i,s=e("
            "),o=s.children()[0];return e("body").append(s),r=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,r===i&&(i=s[0].clientWidth),s.remove(),n=r-i},getScrollInfo:function(t){var n=t.isWindow?"":t.element.css("overflow-x"),r=t.isWindow?"":t.element.css("overflow-y"),i=n==="scroll"||n==="auto"&&t.width0?"right":"center",vertical:u<0?"top":o>0?"bottom":"middle"};lr(i(o),i(u))?h.important="horizontal":h.important="vertical",t.using.call(this,e,h)}),a.offset(e.extend(C,{using:u}))})},e.ui.position={fit:{left:function(e,t){var n=t.within,i=n.isWindow?n.scrollLeft:n.offset.left,s=n.width,o=e.left-t.collisionPosition.marginLeft,u=i-o,a=o+t.collisionWidth-s-i,f;t.collisionWidth>s?u>0&&a<=0?(f=e.left+u+t.collisionWidth-s-i,e.left+=u-f):a>0&&u<=0?e.left=i:u>a?e.left=i+s-t.collisionWidth:e.left=i:u>0?e.left+=u:a>0?e.left-=a:e.left=r(e.left-o,e.left)},top:function(e,t){var n=t.within,i=n.isWindow?n.scrollTop:n.offset.top,s=t.within.height,o=e.top-t.collisionPosition.marginTop,u=i-o,a=o+t.collisionHeight-s-i,f;t.collisionHeight>s?u>0&&a<=0?(f=e.top+u+t.collisionHeight-s-i,e.top+=u-f):a>0&&u<=0?e.top=i:u>a?e.top=i+s-t.collisionHeight:e.top=i:u>0?e.top+=u:a>0?e.top-=a:e.top=r(e.top-o,e.top)}},flip:{left:function(e,t){var n=t.within,r=n.offset.left+n.scrollLeft,s=n.width,o=n.isWindow?n.scrollLeft:n.offset.left,u=e.left-t.collisionPosition.marginLeft,a=u-o,f=u+t.collisionWidth-s-o,l=t.my[0]==="left"?-t.elemWidth:t.my[0]==="right"?t.elemWidth:0,c=t.at[0]==="left"?t.targetWidth:t.at[0]==="right"?-t.targetWidth:0,h=-2*t.offset[0],p,d;if(a<0){p=e.left+l+c+h+t.collisionWidth-s-r;if(p<0||p0){d=e.left-t.collisionPosition.marginLeft+l+c+h-o;if(d>0||i(d)a&&(v<0||v0&&(d=e.top-t.collisionPosition.marginTop+c+h+p-o,e.top+c+h+p>f&&(d>0||i(d)10&&i<11,t.innerHTML="",n.removeChild(t)}(),e.uiBackCompat!==!1&&function(e){var n=e.fn.position;e.fn.position=function(r){if(!r||!r.offset)return n.call(this,r);var i=r.offset.split(" "),s=r.at.split(" ");return i.length===1&&(i[1]=i[0]),/^\d/.test(i[0])&&(i[0]="+"+i[0]),/^\d/.test(i[1])&&(i[1]="+"+i[1]),s.length===1&&(/left|center|right/.test(s[0])?s[1]="center":(s[1]=s[0],s[0]="center")),n.call(this,e.extend(r,{at:s[0]+i[0]+" "+s[1]+i[1],offset:t}))}}(jQuery)})(jQuery);(function(e,t){var n=0,r={},i={};r.height=r.paddingTop=r.paddingBottom=r.borderTopWidth=r.borderBottomWidth="hide",i.height=i.paddingTop=i.paddingBottom=i.borderTopWidth=i.borderBottomWidth="show",e.widget("ui.accordion",{version:"1.9.0",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var t=this.accordionId="ui-accordion-"+(this.element.attr("id")||++n),r=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset"),this.headers=this.element.find(r.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this._hoverable(this.headers),this._focusable(this.headers),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").hide(),!r.collapsible&&r.active===!1&&(r.active=0),r.active<0&&(r.active+=this.headers.length),this.active=this._findActive(r.active).addClass("ui-accordion-header-active ui-state-active").toggleClass("ui-corner-all ui-corner-top"),this.active.next().addClass("ui-accordion-content-active").show(),this._createIcons(),this.originalHeight=this.element[0].style.height,this.refresh(),this.element.attr("role","tablist"),this.headers.attr("role","tab").each(function(n){var r=e(this),i=r.attr("id"),s=r.next(),o=s.attr("id");i||(i=t+"-header-"+n,r.attr("id",i)),o||(o=t+"-panel-"+n,s.attr("id",o)),r.attr("aria-controls",o),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false",tabIndex:-1}).next().attr({"aria-expanded":"false","aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true",tabIndex:0}).next().attr({"aria-expanded":"true","aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._on(this.headers,{keydown:"_keydown"}),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._setupEvents(r.event)},_getCreateEventData:function(){return{header:this.active,content:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),e=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this.options.heightStyle!=="content"&&(this.element.css("height",this.originalHeight),e.css("height",""))},_setOption:function(e,t){if(e==="active"){this._activate(t);return}e==="event"&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),e==="collapsible"&&!t&&this.options.active===!1&&this._activate(0),e==="icons"&&(this._destroyIcons(),t&&this._createIcons()),e==="disabled"&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)},_keydown:function(t){if(t.altKey||t.ctrlKey)return;var n=e.ui.keyCode,r=this.headers.length,i=this.headers.index(t.target),s=!1;switch(t.keyCode){case n.RIGHT:case n.DOWN:s=this.headers[(i+1)%r];break;case n.LEFT:case n.UP:s=this.headers[(i-1+r)%r];break;case n.SPACE:case n.ENTER:this._eventHandler(t);break;case n.HOME:s=this.headers[0];break;case n.END:s=this.headers[r-1]}s&&(e(t.target).attr("tabIndex",-1),e(s).attr("tabIndex",0),s.focus(),t.preventDefault())},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t,n,r=this.options.heightStyle,i=this.element.parent();this.element.css("height",this.originalHeight),r==="fill"?(e.support.minHeight||(n=i.css("overflow"),i.css("overflow","hidden")),t=i.height(),this.element.siblings(":visible").each(function(){var n=e(this),r=n.css("position");if(r==="absolute"||r==="fixed")return;t-=n.outerHeight(!0)}),n&&i.css("overflow",n),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):r==="auto"&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).height("").height())}).height(t)),r!=="content"&&this.element.height(this.element.height())},_activate:function(t){var n=this._findActive(t)[0];if(n===this.active[0])return;n=n||this.active[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return typeof t=="number"?this.headers.eq(t):e()},_setupEvents:function(t){var n={};if(!t)return;e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._on(this.headers,n)},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i[0]===r[0],o=s&&n.collapsible,u=o?e():i.next(),a=r.next(),f={oldHeader:r,oldPanel:a,newHeader:o?e():i,newPanel:u};t.preventDefault();if(s&&!n.collapsible||this._trigger("beforeActivate",t,f)===!1)return;n.active=o?!1:this.headers.index(i),this.active=s?e():i,this._toggle(f),r.removeClass("ui-accordion-header-active ui-state-active"),n.icons&&r.children(".ui-accordion-header-icon").removeClass(n.icons.activeHeader).addClass(n.icons.header),s||(i.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),n.icons&&i.children(".ui-accordion-header-icon").removeClass(n.icons.header).addClass(n.icons.activeHeader),i.next().addClass("ui-accordion-content-active"))},_toggle:function(t){var n=t.newPanel,r=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=n,this.prevHide=r,this.options.animate?this._animate(n,r,t):(r.hide(),n.show(),this._toggleComplete(t)),r.attr({"aria-expanded":"false","aria-hidden":"true"}),r.prev().attr("aria-selected","false"),n.length&&r.length?r.prev().attr("tabIndex",-1):n.length&&this.headers.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),n.attr({"aria-expanded":"true","aria-hidden":"false"}).prev().attr({"aria-selected":"true",tabIndex:0})},_animate:function(e,t,n){var s,o,u,a=this,f=0,l=e.length&&(!t.length||e.index()",options:{appendTo:"body",autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},pending:0,_create:function(){var t,n,r;this.isMultiLine=this._isMultiLine(),this.valueMethod=this.element[this.element.is("input,textarea")?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on({keydown:function(i){if(this.element.prop("readOnly")){t=!0,r=!0,n=!0;return}t=!1,r=!1,n=!1;var s=e.ui.keyCode;switch(i.keyCode){case s.PAGE_UP:t=!0,this._move("previousPage",i);break;case s.PAGE_DOWN:t=!0,this._move("nextPage",i);break;case s.UP:t=!0,this._keyEvent("previous",i);break;case s.DOWN:t=!0,this._keyEvent("next",i);break;case s.ENTER:case s.NUMPAD_ENTER:this.menu.active&&(t=!0,i.preventDefault(),this.menu.select(i));break;case s.TAB:this.menu.active&&this.menu.select(i);break;case s.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(i),i.preventDefault());break;default:n=!0,this._searchTimeout(i)}},keypress:function(r){if(t){t=!1,r.preventDefault();return}if(n)return;var i=e.ui.keyCode;switch(r.keyCode){case i.PAGE_UP:this._move("previousPage",r);break;case i.PAGE_DOWN:this._move("nextPage",r);break;case i.UP:this._keyEvent("previous",r);break;case i.DOWN:this._keyEvent("next",r)}},input:function(e){if(r){r=!1,e.preventDefault();return}this._searchTimeout(e)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}clearTimeout(this.searching),this.close(e),this._change(e)}}),this._initSource(),this.menu=e("
          6. "+(o[0]>0&&I==o[1]-1?'
            ':""):""),F+=U}B+=F}return B+=x+($.browser.msie&&parseInt($.browser.version,10)<7&&!e.inline?'':""),e._keyEvent=!1,B},_generateMonthYearHeader:function(e,t,n,r,i,s,o,u){var a=this._get(e,"changeMonth"),f=this._get(e,"changeYear"),l=this._get(e,"showMonthAfterYear"),c='
            ',h="";if(s||!a)h+=''+o[t]+"";else{var p=r&&r.getFullYear()==n,d=i&&i.getFullYear()==n;h+='"}l||(c+=h+(s||!a||!f?" ":""));if(!e.yearshtml){e.yearshtml="";if(s||!f)c+=''+n+"";else{var m=this._get(e,"yearRange").split(":"),g=(new Date).getFullYear(),y=function(e){var t=e.match(/c[+-].*/)?n+parseInt(e.substring(1),10):e.match(/[+-].*/)?g+parseInt(e,10):parseInt(e,10);return isNaN(t)?g:t},b=y(m[0]),w=Math.max(b,y(m[1]||""));b=r?Math.max(b,r.getFullYear()):b,w=i?Math.min(w,i.getFullYear()):w,e.yearshtml+='",c+=e.yearshtml,e.yearshtml=null}}return c+=this._get(e,"yearSuffix"),l&&(c+=(s||!a||!f?" ":"")+h),c+="
            ",c},_adjustInstDate:function(e,t,n){var r=e.drawYear+(n=="Y"?t:0),i=e.drawMonth+(n=="M"?t:0),s=Math.min(e.selectedDay,this._getDaysInMonth(r,i))+(n=="D"?t:0),o=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(r,i,s)));e.selectedDay=o.getDate(),e.drawMonth=e.selectedMonth=o.getMonth(),e.drawYear=e.selectedYear=o.getFullYear(),(n=="M"||n=="Y")&&this._notifyChange(e)},_restrictMinMax:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max"),i=n&&tr?r:i,i},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return t==null?[1,1]:typeof t=="number"?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return(new Date(e,t,1)).getDay()},_canAdjustMonth:function(e,t,n,r){var i=this._getNumberOfMonths(e),s=this._daylightSavingAdjust(new Date(n,r+(t<0?t:i[0]*i[1]),1));return t<0&&s.setDate(this._getDaysInMonth(s.getFullYear(),s.getMonth())),this._isInRange(e,s)},_isInRange:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max");return(!n||t.getTime()>=n.getTime())&&(!r||t.getTime()<=r.getTime())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t=typeof t!="string"?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,n,r){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var i=t?typeof t=="object"?t:this._daylightSavingAdjust(new Date(r,n,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),i,this._getFormatConfig(e))}}),$.fn.datepicker=function(e){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find(document.body).append($.datepicker.dpDiv),$.datepicker.initialized=!0);var t=Array.prototype.slice.call(arguments,1);return typeof e!="string"||e!="isDisabled"&&e!="getDate"&&e!="widget"?e=="option"&&arguments.length==2&&typeof arguments[1]=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t)):this.each(function(){typeof e=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this].concat(t)):$.datepicker._attachDatepicker(this,e)}):$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t))},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.9.0",window["DP_jQuery_"+dpuuid]=$})(jQuery);(function(e,t){var n="ui-dialog ui-widget ui-widget-content ui-corner-all ",r={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};e.widget("ui.dialog",{version:"1.9.0",options:{autoOpen:!0,buttons:{},closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:!1,maxWidth:!1,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var n=e(this).css(t).offset().top;n<0&&e(this).css("top",t.top-n)}},resizable:!0,show:null,stack:!0,title:"",width:300,zIndex:1e3},_create:function(){this.originalTitle=this.element.attr("title"),typeof this.originalTitle!="string"&&(this.originalTitle=""),this.oldPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.options.title=this.options.title||this.originalTitle;var t=this,r=this.options,i=r.title||" ",s=(this.uiDialog=e("
            ")).addClass(n+r.dialogClass).css({display:"none",outline:0,zIndex:r.zIndex}).attr("tabIndex",-1).keydown(function(n){r.closeOnEscape&&!n.isDefaultPrevented()&&n.keyCode&&n.keyCode===e.ui.keyCode.ESCAPE&&(t.close(n),n.preventDefault())}).mousedown(function(e){t.moveToTop(!1,e)}).appendTo("body"),o=this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(s),u=(this.uiDialogTitlebar=e("
            ")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(s),a=e("").addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").click(function(e){e.preventDefault(),t.close(e)}).appendTo(u),f=(this.uiDialogTitlebarCloseText=e("")).addClass("ui-icon ui-icon-closethick").text(r.closeText).appendTo(a),l=e("").uniqueId().addClass("ui-dialog-title").html(i).prependTo(u),c=(this.uiDialogButtonPane=e("
            ")).addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),h=(this.uiButtonSet=e("
            ")).addClass("ui-dialog-buttonset").appendTo(c);s.attr({role:"dialog","aria-labelledby":l.attr("id")}),u.find("*").add(u).disableSelection(),this._hoverable(a),this._focusable(a),r.draggable&&e.fn.draggable&&this._makeDraggable(),r.resizable&&e.fn.resizable&&this._makeResizable(),this._createButtons(r.buttons),this._isOpen=!1,e.fn.bgiframe&&s.bgiframe(),this._on(s,{keydown:function(t){if(!r.modal||t.keyCode!==e.ui.keyCode.TAB)return;var n=e(":tabbable",s),i=n.filter(":first"),o=n.filter(":last");if(t.target===o[0]&&!t.shiftKey)return i.focus(1),!1;if(t.target===i[0]&&t.shiftKey)return o.focus(1),!1}})},_init:function(){this.options.autoOpen&&this.open()},_destroy:function(){var e,t=this.oldPosition;this.overlay&&this.overlay.destroy(),this.uiDialog.hide(),this.element.removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"),this.uiDialog.remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},close:function(t){var n=this,r,i;if(!this._isOpen)return;if(!1===this._trigger("beforeClose",t))return;return this._isOpen=!1,this.overlay&&this.overlay.destroy(),this.options.hide?this.uiDialog.hide(this.options.hide,function(){n._trigger("close",t)}):(this.uiDialog.hide(),this._trigger("close",t)),e.ui.dialog.overlay.resize(),this.options.modal&&(r=0,e(".ui-dialog").each(function(){this!==n.uiDialog[0]&&(i=e(this).css("z-index"),isNaN(i)||(r=Math.max(r,i)))}),e.ui.dialog.maxZ=r),this},isOpen:function(){return this._isOpen},moveToTop:function(t,n){var r=this.options,i;return r.modal&&!t||!r.stack&&!r.modal?this._trigger("focus",n):(r.zIndex>e.ui.dialog.maxZ&&(e.ui.dialog.maxZ=r.zIndex),this.overlay&&(e.ui.dialog.maxZ+=1,e.ui.dialog.overlay.maxZ=e.ui.dialog.maxZ,this.overlay.$el.css("z-index",e.ui.dialog.overlay.maxZ)),i={scrollTop:this.element.scrollTop(),scrollLeft:this.element.scrollLeft()},e.ui.dialog.maxZ+=1,this.uiDialog.css("z-index",e.ui.dialog.maxZ),this.element.attr(i),this._trigger("focus",n),this)},open:function(){if(this._isOpen)return;var t,n=this.options,r=this.uiDialog;return this._size(),this._position(n.position),r.show(n.show),this.overlay=n.modal?new e.ui.dialog.overlay(this):null,this.moveToTop(!0),t=this.element.find(":tabbable"),t.length||(t=this.uiDialogButtonPane.find(":tabbable"),t.length||(t=r)),t.eq(0).focus(),this._isOpen=!0,this._trigger("open"),this},_createButtons:function(t){var n,r,i=this,s=!1;this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),typeof t=="object"&&t!==null&&e.each(t,function(){return!(s=!0)}),s?(e.each(t,function(t,n){n=e.isFunction(n)?{click:n,text:t}:n;var r=e("
            ').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var n=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,n.cursorAt&&this._adjustOffsetFromHelper(n.cursorAt),n.containment&&this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,n){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute");if(!n){var r=this._uiHash();if(this._trigger("drag",t,r)===!1)return this._mouseUp({}),!1;this.position=r.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";return e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var n=!1;e.ui.ddmanager&&!this.options.dropBehaviour&&(n=e.ui.ddmanager.drop(this,t)),this.dropped&&(n=this.dropped,this.dropped=!1);var r=this.element[0],i=!1;while(r&&(r=r.parentNode))r==document&&(i=!0);if(!i&&this.options.helper==="original")return!1;if(this.options.revert=="invalid"&&!n||this.options.revert=="valid"&&n||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,n)){var s=this;e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){s._trigger("stop",t)!==!1&&s._clear()})}else this._trigger("stop",t)!==!1&&this._clear();return!1},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){var n=!this.options.handle||!e(this.options.handle,this.element).length?!0:!1;return e(this.options.handle,this.element).find("*").andSelf().each(function(){this==t.target&&(n=!0)}),n},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t])):n.helper=="clone"?this.element.clone().removeAttr("id"):this.element;return r.parents("body").length||r.appendTo(n.appendTo=="parent"?this.element[0].parentNode:n.appendTo),r[0]!=this.element[0]&&!/(fixed|absolute)/.test(r.css("position"))&&r.css("position","absolute"),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&e.browser.msie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t=this.options;t.containment=="parent"&&(t.containment=this.helper[0].parentNode);if(t.containment=="document"||t.containment=="window")this.containment=[t.containment=="document"?0:e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t.containment=="document"?0:e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(t.containment=="document"?0:e(window).scrollLeft())+e(t.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(t.containment=="document"?0:e(window).scrollTop())+(e(t.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(t.containment)&&t.containment.constructor!=Array){var n=e(t.containment),r=n[0];if(!r)return;var i=n.offset(),s=e(r).css("overflow")!="hidden";this.containment=[(parseInt(e(r).css("borderLeftWidth"),10)||0)+(parseInt(e(r).css("paddingLeft"),10)||0),(parseInt(e(r).css("borderTopWidth"),10)||0)+(parseInt(e(r).css("paddingTop"),10)||0),(s?Math.max(r.scrollWidth,r.offsetWidth):r.offsetWidth)-(parseInt(e(r).css("borderLeftWidth"),10)||0)-(parseInt(e(r).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(s?Math.max(r.scrollHeight,r.offsetHeight):r.offsetHeight)-(parseInt(e(r).css("borderTopWidth"),10)||0)-(parseInt(e(r).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=n}else t.containment.constructor==Array&&(this.containment=t.containment)},_convertPositionTo:function(t,n){n||(n=this.position);var r=t=="absolute"?1:-1,i=this.options,s=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(s[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():o?0:s.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():o?0:s.scrollLeft())*r}},_generatePosition:function(t){var n=this.options,r=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,i=/(html|body)/i.test(r[0].tagName),s=t.pageX,o=t.pageY;if(this.originalPosition){var u;if(this.containment){if(this.relative_container){var a=this.relative_container.offset();u=[this.containment[0]+a.left,this.containment[1]+a.top,this.containment[2]+a.left,this.containment[3]+a.top]}else u=this.containment;t.pageX-this.offset.click.leftu[2]&&(s=u[2]+this.offset.click.left),t.pageY-this.offset.click.top>u[3]&&(o=u[3]+this.offset.click.top)}if(n.grid){var f=n.grid[1]?this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1]:this.originalPageY;o=u?f-this.offset.click.topu[3]?f-this.offset.click.topu[2]?l-this.offset.click.left=0;l--){var c=r.snapElements[l].left,h=c+r.snapElements[l].width,p=r.snapElements[l].top,d=p+r.snapElements[l].height;if(!(c-s=l&&o<=c||u>=l&&u<=c||oc)&&(i>=a&&i<=f||s>=a&&s<=f||if);default:return!1}},e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,n){var r=e.ui.ddmanager.droppables[t.options.scope]||[],i=n?n.type:null,s=(t.currentItem||t.element).find(":data(droppable)").andSelf();e:for(var o=0;oe?0:r.max")[0],c,h=t.each;l.style.cssText="background-color:rgba(1,1,1,.5)",f.rgba=l.style.backgroundColor.indexOf("rgba")>-1,h(u,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),o.fn=t.extend(o.prototype,{parse:function(r,i,s,a){if(r===n)return this._rgba=[null,null,null,null],this;if(r.jquery||r.nodeType)r=t(r).css(i),i=n;var f=this,l=t.type(r),v=this._rgba=[],m;i!==n&&(r=[r,i,s,a],l="array");if(l==="string")return this.parse(d(r)||c._default);if(l==="array")return h(u.rgba.props,function(e,t){v[t.idx]=p(r[t.idx],t)}),this;if(l==="object")return r instanceof o?h(u,function(e,t){r[t.cache]&&(f[t.cache]=r[t.cache].slice())}):h(u,function(t,n){var i=n.cache;h(n.props,function(e,t){if(!f[i]&&n.to){if(e==="alpha"||r[e]==null)return;f[i]=n.to(f._rgba)}f[i][t.idx]=p(r[e],t,!0)}),f[i]&&e.inArray(null,f[i].slice(0,3))<0&&(f[i][3]=1,n.from&&(f._rgba=n.from(f[i])))}),this},is:function(e){var t=o(e),n=!0,r=this;return h(u,function(e,i){var s,o=t[i.cache];return o&&(s=r[i.cache]||i.to&&i.to(r._rgba)||[],h(i.props,function(e,t){if(o[t.idx]!=null)return n=o[t.idx]===s[t.idx],n})),n}),n},_space:function(){var e=[],t=this;return h(u,function(n,r){t[r.cache]&&e.push(n)}),e.pop()},transition:function(e,t){var n=o(e),r=n._space(),i=u[r],s=this.alpha()===0?o("transparent"):this,f=s[i.cache]||i.to(s._rgba),l=f.slice();return n=n[i.cache],h(i.props,function(e,r){var i=r.idx,s=f[i],o=n[i],u=a[r.type]||{};if(o===null)return;s===null?l[i]=o:(u.mod&&(o-s>u.mod/2?s+=u.mod:s-o>u.mod/2&&(s-=u.mod)),l[i]=p((o-s)*t+s,r))}),this[r](l)},blend:function(e){if(this._rgba[3]===1)return this;var n=this._rgba.slice(),r=n.pop(),i=o(e)._rgba;return o(t.map(n,function(e,t){return(1-r)*i[t]+r*e}))},toRgbaString:function(){var e="rgba(",n=t.map(this._rgba,function(e,t){return e==null?t>2?1:0:e});return n[3]===1&&(n.pop(),e="rgb("),e+n.join()+")"},toHslaString:function(){var e="hsla(",n=t.map(this.hsla(),function(e,t){return e==null&&(e=t>2?1:0),t&&t<3&&(e=Math.round(e*100)+"%"),e});return n[3]===1&&(n.pop(),e="hsl("),e+n.join()+")"},toHexString:function(e){var n=this._rgba.slice(),r=n.pop();return e&&n.push(~~(r*255)),"#"+t.map(n,function(e,t){return e=(e||0).toString(16),e.length===1?"0"+e:e}).join("")},toString:function(){return this._rgba[3]===0?"transparent":this.toRgbaString()}}),o.fn.parse.prototype=o.fn,u.hsla.to=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/255,n=e[1]/255,r=e[2]/255,i=e[3],s=Math.max(t,n,r),o=Math.min(t,n,r),u=s-o,a=s+o,f=a*.5,l,c;return o===s?l=0:t===s?l=60*(n-r)/u+360:n===s?l=60*(r-t)/u+120:l=60*(t-n)/u+240,f===0||f===1?c=f:f<=.5?c=u/a:c=u/(2-a),[Math.round(l)%360,c,f,i==null?1:i]},u.hsla.from=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/360,n=e[1],r=e[2],i=e[3],s=r<=.5?r*(1+n):r+n-r*n,o=2*r-s,u,a,f;return[Math.round(v(o,s,t+1/3)*255),Math.round(v(o,s,t)*255),Math.round(v(o,s,t-1/3)*255),i]},h(u,function(e,r){var s=r.props,u=r.cache,a=r.to,f=r.from;o.fn[e]=function(e){a&&!this[u]&&(this[u]=a(this._rgba));if(e===n)return this[u].slice();var r,i=t.type(e),l=i==="array"||i==="object"?e:arguments,c=this[u].slice();return h(s,function(e,t){var n=l[i==="object"?e:t.idx];n==null&&(n=c[t.idx]),c[t.idx]=p(n,t)}),f?(r=o(f(c)),r[u]=c,r):o(c)},h(s,function(n,r){if(o.fn[n])return;o.fn[n]=function(s){var o=t.type(s),u=n==="alpha"?this._hsla?"hsla":"rgba":e,a=this[u](),f=a[r.idx],l;return o==="undefined"?f:(o==="function"&&(s=s.call(this,f),o=t.type(s)),s==null&&r.empty?this:(o==="string"&&(l=i.exec(s),l&&(s=f+parseFloat(l[2])*(l[1]==="+"?1:-1))),a[r.idx]=s,this[u](a)))}})}),h(r,function(e,n){t.cssHooks[n]={set:function(e,r){var i,s,u="";if(t.type(r)!=="string"||(i=d(r))){r=o(i||r);if(!f.rgba&&r._rgba[3]!==1){s=n==="backgroundColor"?e.parentNode:e;while((u===""||u==="transparent")&&s&&s.style)try{u=t.css(s,"backgroundColor"),s=s.parentNode}catch(a){}r=r.blend(u&&u!=="transparent"?u:"_default")}r=r.toRgbaString()}try{e.style[n]=r}catch(r){}}},t.fx.step[n]=function(e){e.colorInit||(e.start=o(e.elem,n),e.end=o(e.end),e.colorInit=!0),t.cssHooks[n].set(e.elem,e.start.transition(e.end,e.pos))}}),t.cssHooks.borderColor={expand:function(e){var t={};return h(["Top","Right","Bottom","Left"],function(n,r){t["border"+r+"Color"]=e}),t}},c=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(){var t=this.ownerDocument.defaultView?this.ownerDocument.defaultView.getComputedStyle(this,null):this.currentStyle,n={},r,i,s;if(t&&t.length&&t[0]&&t[t[0]]){s=t.length;while(s--)r=t[s],typeof t[r]=="string"&&(n[e.camelCase(r)]=t[r])}else for(r in t)typeof t[r]=="string"&&(n[r]=t[r]);return n}function s(t,n){var i={},s,o;for(s in n)o=n[s],t[s]!==o&&!r[s]&&(e.fx.step[s]||!isNaN(parseFloat(o)))&&(i[s]=o);return i}var n=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,n){e.fx.step[n]=function(e){if(e.end!=="none"&&!e.setAttr||e.pos===1&&!e.setAttr)jQuery.style(e.elem,n,e.end),e.setAttr=!0}}),e.effects.animateClass=function(t,r,o,u){var a=e.speed(r,o,u);return this.queue(function(){var r=e(this),o=r.attr("class")||"",u,f=a.children?r.find("*").andSelf():r;f=f.map(function(){var t=e(this);return{el:t,start:i.call(this)}}),u=function(){e.each(n,function(e,n){t[n]&&r[n+"Class"](t[n])})},u(),f=f.map(function(){return this.end=i.call(this.el[0]),this.diff=s(this.start,this.end),this}),r.attr("class",o),f=f.map(function(){var t=this,n=e.Deferred(),r=jQuery.extend({},a,{queue:!1,complete:function(){n.resolve(t)}});return this.el.animate(this.diff,r),n.promise()}),e.when.apply(e,f.get()).done(function(){u(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),a.complete.call(r[0])})})},e.fn.extend({_addClass:e.fn.addClass,addClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{add:t},n,r,i):this._addClass(t)},_removeClass:e.fn.removeClass,removeClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{remove:t},n,r,i):this._removeClass(t)},_toggleClass:e.fn.toggleClass,toggleClass:function(n,r,i,s,o){return typeof r=="boolean"||r===t?i?e.effects.animateClass.call(this,r?{add:n}:{remove:n},i,s,o):this._toggleClass(n,r):e.effects.animateClass.call(this,{toggle:n},r,i,s)},switchClass:function(t,n,r,i,s){return e.effects.animateClass.call(this,{add:n,remove:t},r,i,s)}})}(),function(){function i(n,r,i,s){e.isPlainObject(n)&&(r=n,n=n.effect),n={effect:n},r===t&&(r={}),e.isFunction(r)&&(s=r,i=null,r={});if(typeof r=="number"||e.fx.speeds[r])s=i,i=r,r={};return e.isFunction(i)&&(s=i,i=null),r&&e.extend(n,r),i=i||r.duration,n.duration=e.fx.off?0:typeof i=="number"?i:i in e.fx.speeds?e.fx.speeds[i]:e.fx.speeds._default,n.complete=s||r.complete,n}function s(t){return!t||typeof t=="number"||e.fx.speeds[t]?!0:typeof t=="string"&&!e.effects.effect[t]?n&&e.effects[t]?!1:!0:!1}e.extend(e.effects,{version:"1.9.0",save:function(e,t){for(var n=0;n
            ").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),i={width:t.width(),height:t.height()},s=document.activeElement;try{s.id}catch(o){s=document.body}return t.wrap(r),(t[0]===s||e.contains(t[0],s))&&e(s).focus(),r=t.parent(),t.css("position")==="static"?(r.css({position:"relative"}),t.css({position:"relative"})):(e.extend(n,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,r){n[r]=t.css(r),isNaN(parseInt(n[r],10))&&(n[r]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(i),r.css(n).show()},removeWrapper:function(t){var n=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===n||e.contains(t[0],n))&&e(n).focus()),t},setTransition:function(t,n,r,i){return i=i||{},e.each(n,function(e,n){var s=t.cssUnit(n);s[0]>0&&(i[n]=s[0]*r+s[1])}),i}}),e.fn.extend({effect:function(t,r,s,o){function h(t){function s(){e.isFunction(r)&&r.call(n[0]),e.isFunction(t)&&t()}var n=e(this),r=u.complete,i=u.mode;(n.is(":hidden")?i==="hide":i==="show")?s():l.call(n[0],u,s)}var u=i.apply(this,arguments),a=u.mode,f=u.queue,l=e.effects.effect[u.effect],c=!l&&n&&e.effects[u.effect];return e.fx.off||!l&&!c?a?this[a](u.duration,u.complete):this.each(function(){u.complete&&u.complete.call(this)}):l?f===!1?this.each(h):this.queue(f||"fx",h):c.call(this,{options:u,duration:u.duration,callback:u.complete,mode:u.mode})},_show:e.fn.show,show:function(e){if(s(e))return this._show.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="show",this.effect.call(this,t)},_hide:e.fn.hide,hide:function(e){if(s(e))return this._hide.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="hide",this.effect.call(this,t)},__toggle:e.fn.toggle,toggle:function(t){if(s(t)||typeof t=="boolean"||e.isFunction(t))return this.__toggle.apply(this,arguments);var n=i.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)},cssUnit:function(t){var n=this.css(t),r=[];return e.each(["em","px","%","pt"],function(e,t){n.indexOf(t)>0&&(r=[parseFloat(n),t])}),r}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,n){t[n]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return e===0||e===1?e:-Math.pow(2,8*(e-1))*Math.sin(((e-1)*80-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){var t,n=4;while(e<((t=Math.pow(2,--n))-1)/11);return 1/Math.pow(4,3-n)-7.5625*Math.pow((t*3-2)/22-e,2)}}),e.each(t,function(t,n){e.easing["easeIn"+t]=n,e.easing["easeOut"+t]=function(e){return 1-n(1-e)},e.easing["easeInOut"+t]=function(e){return e<.5?n(e*2)/2:1-n(e*-2+2)/2}})}()}(jQuery);(function(e,t){var n=/up|down|vertical/,r=/up|left|vertical|horizontal/;e.effects.effect.blind=function(t,i){var s=e(this),o=["position","top","bottom","left","right","height","width"],u=e.effects.setMode(s,t.mode||"hide"),a=t.direction||"up",f=n.test(a),l=f?"height":"width",c=f?"top":"left",h=r.test(a),p={},d=u==="show",v,m,g;s.parent().is(".ui-effects-wrapper")?e.effects.save(s.parent(),o):e.effects.save(s,o),s.show(),v=e.effects.createWrapper(s).css({overflow:"hidden"}),m=v[l](),g=parseFloat(v.css(c))||0,p[l]=d?m:0,h||(s.css(f?"bottom":"right",0).css(f?"top":"left","auto").css({position:"absolute"}),p[c]=d?g:m+g),d&&(v.css(l,0),h||v.css(c,g+m)),v.animate(p,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){u==="hide"&&s.hide(),e.effects.restore(s,o),e.effects.removeWrapper(s),i()}})}})(jQuery);(function(e,t){e.effects.effect.bounce=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=s==="hide",u=s==="show",a=t.direction||"up",f=t.distance,l=t.times||5,c=l*2+(u||o?1:0),h=t.duration/c,p=t.easing,d=a==="up"||a==="down"?"top":"left",v=a==="up"||a==="left",m,g,y,b=r.queue(),w=b.length;(u||o)&&i.push("opacity"),e.effects.save(r,i),r.show(),e.effects.createWrapper(r),f||(f=r[d==="top"?"outerHeight":"outerWidth"]()/3),u&&(y={opacity:1},y[d]=0,r.css("opacity",0).css(d,v?-f*2:f*2).animate(y,h,p)),o&&(f/=Math.pow(2,l-1)),y={},y[d]=0;for(m=0;m1&&b.splice.apply(b,[1,0].concat(b.splice(w,c+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.clip=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"vertical",a=u==="vertical",f=a?"height":"width",l=a?"top":"left",c={},h,p,d;e.effects.save(r,i),r.show(),h=e.effects.createWrapper(r).css({overflow:"hidden"}),p=r[0].tagName==="IMG"?h:r,d=p[f](),o&&(p.css(f,0),p.css(l,d/2)),c[f]=o?d:0,c[l]=o?0:d/2,p.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o||r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.drop=function(t,n){var r=e(this),i=["position","top","bottom","left","right","opacity","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left"?"pos":"neg",l={opacity:o?1:0},c;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),c=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0)/2,o&&r.css("opacity",0).css(a,f==="pos"?-c:c),l[a]=(o?f==="pos"?"+=":"-=":f==="pos"?"-=":"+=")+c,r.animate(l,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.explode=function(t,n){function y(){c.push(this),c.length===r*i&&b()}function b(){s.css({visibility:"visible"}),e(c).remove(),u||s.hide(),n()}var r=t.pieces?Math.round(Math.sqrt(t.pieces)):3,i=r,s=e(this),o=e.effects.setMode(s,t.mode||"hide"),u=o==="show",a=s.show().css("visibility","hidden").offset(),f=Math.ceil(s.outerWidth()/i),l=Math.ceil(s.outerHeight()/r),c=[],h,p,d,v,m,g;for(h=0;h
            ").css({position:"absolute",visibility:"visible",left:-p*f,top:-h*l}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:f,height:l,left:d+(u?m*f:0),top:v+(u?g*l:0),opacity:u?0:1}).animate({left:d+(u?0:m*f),top:v+(u?0:g*l),opacity:u?1:0},t.duration||500,t.easing,y)}}})(jQuery);(function(e,t){e.effects.effect.fade=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"toggle");r.animate({opacity:i},{queue:!1,duration:t.duration,easing:t.easing,complete:n})}})(jQuery);(function(e,t){e.effects.effect.fold=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=s==="hide",a=t.size||15,f=/([0-9]+)%/.exec(a),l=!!t.horizFirst,c=o!==l,h=c?["width","height"]:["height","width"],p=t.duration/2,d,v,m={},g={};e.effects.save(r,i),r.show(),d=e.effects.createWrapper(r).css({overflow:"hidden"}),v=c?[d.width(),d.height()]:[d.height(),d.width()],f&&(a=parseInt(f[1],10)/100*v[u?0:1]),o&&d.css(l?{height:0,width:a}:{height:a,width:0}),m[h[0]]=o?v[0]:a,g[h[1]]=o?v[1]:0,d.animate(m,p,t.easing).animate(g,p,t.easing,function(){u&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()})}})(jQuery);(function(e,t){e.effects.effect.highlight=function(t,n){var r=e(this),i=["backgroundImage","backgroundColor","opacity"],s=e.effects.setMode(r,t.mode||"show"),o={backgroundColor:r.css("backgroundColor")};s==="hide"&&(o.opacity=0),e.effects.save(r,i),r.show().css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(o,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),n()}})}})(jQuery);(function(e,t){e.effects.effect.pulsate=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"show"),s=i==="show",o=i==="hide",u=s||i==="hide",a=(t.times||5)*2+(u?1:0),f=t.duration/a,l=0,c=r.queue(),h=c.length,p;if(s||!r.is(":visible"))r.css("opacity",0).show(),l=1;for(p=1;p1&&c.splice.apply(c,[1,0].concat(c.splice(h,a+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.puff=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"hide"),s=i==="hide",o=parseInt(t.percent,10)||150,u=o/100,a={height:r.height(),width:r.width()};e.extend(t,{effect:"scale",queue:!1,fade:!0,mode:i,complete:n,percent:s?o:100,from:s?a:{height:a.height*u,width:a.width*u}}),r.effect(t)},e.effects.effect.scale=function(t,n){var r=e(this),i=e.extend(!0,{},t),s=e.effects.setMode(r,t.mode||"effect"),o=parseInt(t.percent,10)||(parseInt(t.percent,10)===0?0:s==="hide"?0:100),u=t.direction||"both",a=t.origin,f={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()},l={y:u!=="horizontal"?o/100:1,x:u!=="vertical"?o/100:1};i.effect="size",i.queue=!1,i.complete=n,s!=="effect"&&(i.origin=a||["middle","center"],i.restore=!0),i.from=t.from||(s==="show"?{height:0,width:0}:f),i.to={height:f.height*l.y,width:f.width*l.x,outerHeight:f.outerHeight*l.y,outerWidth:f.outerWidth*l.x},i.fade&&(s==="show"&&(i.from.opacity=0,i.to.opacity=1),s==="hide"&&(i.from.opacity=1,i.to.opacity=0)),r.effect(i)},e.effects.effect.size=function(t,n){var r=e(this),i=["position","top","bottom","left","right","width","height","overflow","opacity"],s=["position","top","bottom","left","right","overflow","opacity"],o=["width","height","overflow"],u=["fontSize"],a=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],f=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],l=e.effects.setMode(r,t.mode||"effect"),c=t.restore||l!=="effect",h=t.scale||"both",p=t.origin||["middle","center"],d,v,m,g=r.css("position");l==="show"&&r.show(),d={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()},r.from=t.from||d,r.to=t.to||d,m={from:{y:r.from.height/d.height,x:r.from.width/d.width},to:{y:r.to.height/d.height,x:r.to.width/d.width}};if(h==="box"||h==="both")m.from.y!==m.to.y&&(i=i.concat(a),r.from=e.effects.setTransition(r,a,m.from.y,r.from),r.to=e.effects.setTransition(r,a,m.to.y,r.to)),m.from.x!==m.to.x&&(i=i.concat(f),r.from=e.effects.setTransition(r,f,m.from.x,r.from),r.to=e.effects.setTransition(r,f,m.to.x,r.to));(h==="content"||h==="both")&&m.from.y!==m.to.y&&(i=i.concat(u),r.from=e.effects.setTransition(r,u,m.from.y,r.from),r.to=e.effects.setTransition(r,u,m.to.y,r.to)),e.effects.save(r,c?i:s),r.show(),e.effects.createWrapper(r),r.css("overflow","hidden").css(r.from),p&&(v=e.effects.getBaseline(p,d),r.from.top=(d.outerHeight-r.outerHeight())*v.y,r.from.left=(d.outerWidth-r.outerWidth())*v.x,r.to.top=(d.outerHeight-r.to.outerHeight)*v.y,r.to.left=(d.outerWidth-r.to.outerWidth)*v.x),r.css(r.from);if(h==="content"||h==="both")a=a.concat(["marginTop","marginBottom"]).concat(u),f=f.concat(["marginLeft","marginRight"]),o=i.concat(a).concat(f),r.find("*[width]").each(function(){var n=e(this),r={height:n.height(),width:n.width()};c&&e.effects.save(n,o),n.from={height:r.height*m.from.y,width:r.width*m.from.x},n.to={height:r.height*m.to.y,width:r.width*m.to.x},m.from.y!==m.to.y&&(n.from=e.effects.setTransition(n,a,m.from.y,n.from),n.to=e.effects.setTransition(n,a,m.to.y,n.to)),m.from.x!==m.to.x&&(n.from=e.effects.setTransition(n,f,m.from.x,n.from),n.to=e.effects.setTransition(n,f,m.to.x,n.to)),n.css(n.from),n.animate(n.to,t.duration,t.easing,function(){c&&e.effects.restore(n,o)})});r.animate(r.to,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){r.to.opacity===0&&r.css("opacity",r.from.opacity),l==="hide"&&r.hide(),e.effects.restore(r,c?i:s),c||(g==="static"?r.css({position:"relative",top:r.to.top,left:r.to.left}):e.each(["top","left"],function(e,t){r.css(t,function(t,n){var i=parseInt(n,10),s=e?r.to.left:r.to.top;return n==="auto"?s+"px":i+s+"px"})})),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.shake=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=t.direction||"left",u=t.distance||20,a=t.times||3,f=a*2+1,l=Math.round(t.duration/f),c=o==="up"||o==="down"?"top":"left",h=o==="up"||o==="left",p={},d={},v={},m,g=r.queue(),y=g.length;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),p[c]=(h?"-=":"+=")+u,d[c]=(h?"+=":"-=")+u*2,v[c]=(h?"-=":"+=")+u*2,r.animate(p,l,t.easing);for(m=1;m1&&g.splice.apply(g,[1,0].concat(g.splice(y,f+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.slide=function(t,n){var r=e(this),i=["position","top","bottom","left","right","width","height"],s=e.effects.setMode(r,t.mode||"show"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left",l,c={};e.effects.save(r,i),r.show(),l=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0),e.effects.createWrapper(r).css({overflow:"hidden"}),o&&r.css(a,f?isNaN(l)?"-"+l:-l:l),c[a]=(o?f?"+=":"-=":f?"-=":"+=")+l,r.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.transfer=function(t,n){var r=e(this),i=e(t.to),s=i.css("position")==="fixed",o=e("body"),u=s?o.scrollTop():0,a=s?o.scrollLeft():0,f=i.offset(),l={top:f.top-u,left:f.left-a,height:i.innerHeight(),width:i.innerWidth()},c=r.offset(),h=e('
            ').appendTo(document.body).addClass(t.className).css({top:c.top-u,left:c.left-a,height:r.innerHeight(),width:r.innerWidth(),position:s?"fixed":"absolute"}).animate(l,t.duration,t.easing,function(){h.remove(),n()})}})(jQuery);(function(e,t){var n=!1;e.widget("ui.menu",{version:"1.9.0",defaultElement:"
              ",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,e.proxy(function(e){this.options.disabled&&e.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(e){e.preventDefault()},"click .ui-state-disabled > a":function(e){e.preventDefault()},"click .ui-menu-item:has(a)":function(t){var r=e(t.target).closest(".ui-menu-item");!n&&r.not(".ui-state-disabled").length&&(n=!0,this.select(t),r.has(".ui-menu").length?this.expand(t):this.element.is(":focus")||(this.element.trigger("focus",[!0]),this.active&&this.active.parents(".ui-menu").length===1&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){var n=e(t.currentTarget);n.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(t,n)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var n=this.active||this.element.children(".ui-menu-item").eq(0);t||this.focus(e,n)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){e(t.target).closest(".ui-menu").length||this.collapseAll(t),n=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").andSelf().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){function a(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var n,r,i,s,o,u=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:u=!1,r=this.previousFilter||"",i=String.fromCharCode(t.keyCode),s=!1,clearTimeout(this.filterTimer),i===r?s=!0:i=r+i,o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())}),n=s&&n.index(this.active.next())!==-1?this.active.nextAll(".ui-menu-item"):n,n.length||(i=String.fromCharCode(t.keyCode),o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())})),n.length?(this.focus(t,n),n.length>1?(this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}u&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(e):this.select(e))},refresh:function(){var t,n=this.options.icons.submenu,r=this.element.find(this.options.menus+":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"});t=r.add(this.element),t.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),t.children(":not(.ui-menu-item)").each(function(){var t=e(this);/[^\-—–\s]/.test(t.text())||t.addClass("ui-widget-content ui-menu-divider")}),t.children(".ui-state-disabled").attr("aria-disabled","true"),r.each(function(){var t=e(this),r=t.prev("a"),i=e("").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);r.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",r.attr("id"))}),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},focus:function(e,t){var n,r;this.blur(e,e&&e.type==="focus"),this._scrollIntoView(t),this.active=t.first(),r=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",r.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),e&&e.type==="keydown"?this._close():this.timer=this._delay(function(){this._close()},this.delay),n=t.children(".ui-menu"),n.length&&/^mouse/.test(e.type)&&this._startOpening(n),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var n,r,i,s,o,u;this._hasScroll()&&(n=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,r=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,i=t.offset().top-this.activeMenu.offset().top-n-r,s=this.activeMenu.scrollTop(),o=this.activeMenu.height(),u=t.height(),i<0?this.activeMenu.scrollTop(s+i):i+u>o&&this.activeMenu.scrollTop(s+i-o+u))},blur:function(e,t){t||clearTimeout(this.timer);if(!this.active)return;this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active})},_startOpening:function(e){clearTimeout(this.timer);if(e.attr("aria-hidden")!=="true")return;this.timer=this._delay(function(){this._close(),this._open(e)},this.delay)},_open:function(t){var n=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(n)},collapseAll:function(t,n){clearTimeout(this.timer),this.timer=this._delay(function(){var r=n?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));r.length||(r=this.element),this._close(r),this.blur(t),this.activeMenu=r},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,n){var r;this.active&&(e==="first"||e==="last"?r=this.active[e==="first"?"prevAll":"nextAll"](".ui-menu-item").eq(-1):r=this.active[e+"All"](".ui-menu-item").eq(0));if(!r||!r.length||!this.active)r=this.activeMenu.children(".ui-menu-item")[t]();this.focus(n,r)},nextPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isLastItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r-i<0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())},previousPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isFirstItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r+i>0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item").first())},_hasScroll:function(){return this.element.outerHeight()
            ").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(e){return e===t?this._value():(this._setOption("value",e),this)},_setOption:function(e,t){e==="value"&&(this.options.value=t,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),this._super(e,t)},_value:function(){var e=this.options.value;return typeof e!="number"&&(e=0),Math.min(this.options.max,Math.max(this.min,e))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var e=this.value(),t=this._percentage();this.oldValue!==e&&(this.oldValue=e,this._trigger("change")),this.valueDiv.toggle(e>this.min).toggleClass("ui-corner-right",e===this.options.max).width(t.toFixed(0)+"%"),this.element.attr("aria-valuenow",e)}})})(jQuery);(function(e,t){e.widget("ui.resizable",e.ui.mouse,{version:"1.9.0",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1e3},_create:function(){var t=this,n=this.options;this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!n.aspectRatio,aspectRatio:n.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:n.helper||n.ghost||n.animate?n.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e('
            ').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data("resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=n.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne,nw");var r=this.handles.split(",");this.handles={};for(var i=0;i
            ');u.css({zIndex:n.zIndex}),"se"==s&&u.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(u)}}this._renderAxis=function(t){t=t||this.element;for(var n in this.handles){this.handles[n].constructor==String&&(this.handles[n]=e(this.handles[n],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var r=e(this.handles[n],this.element),i=0;i=/sw|ne|nw|se|n|s/.test(n)?r.outerHeight():r.outerWidth();var s=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");t.css(s,i),this._proportionallyResize()}if(!e(this.handles[n]).length)continue}},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){if(!t.resizing){if(this.className)var e=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);t.axis=e&&e[1]?e[1]:"se"}}),n.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){if(n.disabled)return;e(this).removeClass("ui-resizable-autohide"),t._handles.show()}).mouseleave(function(){if(n.disabled)return;t.resizing||(e(this).addClass("ui-resizable-autohide"),t._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){t(this.element);var n=this.element;n.after(this.originalElement.css({position:n.css("position"),width:n.outerWidth(),height:n.outerHeight(),top:n.css("top"),left:n.css("left")})).remove()}return this.originalElement.css("resize",this.originalResizeStyle),t(this.originalElement),this},_mouseCapture:function(t){var n=!1;for(var r in this.handles)e(this.handles[r])[0]==t.target&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(t){var r=this.options,i=this.element.position(),s=this.element;this.resizing=!0,this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()},(s.is(".ui-draggable")||/absolute/.test(s.css("position")))&&s.css({position:"absolute",top:i.top,left:i.left}),this._renderProxy();var o=n(this.helper.css("left")),u=n(this.helper.css("top"));r.containment&&(o+=e(r.containment).scrollLeft()||0,u+=e(r.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:o,top:u},this.size=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalSize=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalPosition={left:o,top:u},this.sizeDiff={width:s.outerWidth()-s.width(),height:s.outerHeight()-s.height()},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio=typeof r.aspectRatio=="number"?r.aspectRatio:this.originalSize.width/this.originalSize.height||1;var a=e(".ui-resizable-"+this.axis).css("cursor");return e("body").css("cursor",a=="auto"?this.axis+"-resize":a),s.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(e){var t=this.helper,n=this.options,r={},i=this,s=this.originalMousePosition,o=this.axis,u=e.pageX-s.left||0,a=e.pageY-s.top||0,f=this._change[o];if(!f)return!1;var l=f.apply(this,[e,u,a]);this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey)l=this._updateRatio(l,e);return l=this._respectSize(l,e),this._propagate("resize",e),t.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigger("resize",e,this.ui()),!1},_mouseStop:function(t){this.resizing=!1;var n=this.options,r=this;if(this._helper){var i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),o=s&&e.ui.hasScroll(i[0],"left")?0:r.sizeDiff.height,u=s?0:r.sizeDiff.width,a={width:r.helper.width()-u,height:r.helper.height()-o},f=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,l=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;n.animate||this.element.css(e.extend(a,{top:l,left:f})),r.helper.height(r.size.height),r.helper.width(r.size.width),this._helper&&!n.animate&&this._proportionallyResize()}return e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t=this.options,n,i,s,o,u;u={minWidth:r(t.minWidth)?t.minWidth:0,maxWidth:r(t.maxWidth)?t.maxWidth:Infinity,minHeight:r(t.minHeight)?t.minHeight:0,maxHeight:r(t.maxHeight)?t.maxHeight:Infinity};if(this._aspectRatio||e)n=u.minHeight*this.aspectRatio,s=u.minWidth/this.aspectRatio,i=u.maxHeight*this.aspectRatio,o=u.maxWidth/this.aspectRatio,n>u.minWidth&&(u.minWidth=n),s>u.minHeight&&(u.minHeight=s),ie.width,l=r(e.height)&&i.minHeight&&i.minHeight>e.height;f&&(e.width=i.minWidth),l&&(e.height=i.minHeight),u&&(e.width=i.maxWidth),a&&(e.height=i.maxHeight);var c=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,p=/sw|nw|w/.test(o),d=/nw|ne|n/.test(o);f&&p&&(e.left=c-i.minWidth),u&&p&&(e.left=c-i.maxWidth),l&&d&&(e.top=h-i.minHeight),a&&d&&(e.top=h-i.maxHeight);var v=!e.width&&!e.height;return v&&!e.left&&e.top?e.top=null:v&&!e.top&&e.left&&(e.left=null),e},_proportionallyResize:function(){var t=this.options;if(!this._proportionallyResizeElements.length)return;var n=this.helper||this.element;for(var r=0;r
            ');var r=e.browser.msie&&e.browser.version<7,i=r?1:0,s=r?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+s,height:this.element.outerHeight()+s,position:"absolute",left:this.elementOffset.left-i+"px",top:this.elementOffset.top-i+"px",zIndex:++n.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(e,t,n){return{width:this.originalSize.width+t}},w:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{top:s.top+n,height:i.height-n}},s:function(e,t,n){return{height:this.originalSize.height+n}},se:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},sw:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,n,r]))},ne:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},nw:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,n,r]))}},_propagate:function(t,n){e.ui.plugin.call(this,t,[n,this.ui()]),t!="resize"&&this._trigger(t,n,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","alsoResize",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=function(t){e(t).each(function(){var t=e(this);t.data("resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};typeof i.alsoResize=="object"&&!i.alsoResize.parentNode?i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)}):s(i.alsoResize)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.originalSize,o=r.originalPosition,u={height:r.size.height-s.height||0,width:r.size.width-s.width||0,top:r.position.top-o.top||0,left:r.position.left-o.left||0},a=function(t,r){e(t).each(function(){var t=e(this),i=e(this).data("resizable-alsoresize"),s={},o=r&&r.length?r:t.parents(n.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var n=(i[t]||0)+(u[t]||0);n&&n>=0&&(s[t]=n||null)}),t.css(s)})};typeof i.alsoResize=="object"&&!i.alsoResize.nodeType?e.each(i.alsoResize,function(e,t){a(e,t)}):a(i.alsoResize)},stop:function(t,n){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","animate",{stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r._proportionallyResizeElements,o=s.length&&/textarea/i.test(s[0].nodeName),u=o&&e.ui.hasScroll(s[0],"left")?0:r.sizeDiff.height,a=o?0:r.sizeDiff.width,f={width:r.size.width-a,height:r.size.height-u},l=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,c=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;r.element.animate(e.extend(f,c&&l?{top:c,left:l}:{}),{duration:i.animateDuration,easing:i.animateEasing,step:function(){var n={width:parseInt(r.element.css("width"),10),height:parseInt(r.element.css("height"),10),top:parseInt(r.element.css("top"),10),left:parseInt(r.element.css("left"),10)};s&&s.length&&e(s[0]).css({width:n.width,height:n.height}),r._updateCache(n),r._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(t,r){var i=e(this).data("resizable"),s=i.options,o=i.element,u=s.containment,a=u instanceof e?u.get(0):/parent/.test(u)?o.parent().get(0):u;if(!a)return;i.containerElement=e(a);if(/document/.test(u)||u==document)i.containerOffset={left:0,top:0},i.containerPosition={left:0,top:0},i.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight};else{var f=e(a),l=[];e(["Top","Right","Left","Bottom"]).each(function(e,t){l[e]=n(f.css("padding"+t))}),i.containerOffset=f.offset(),i.containerPosition=f.position(),i.containerSize={height:f.innerHeight()-l[3],width:f.innerWidth()-l[1]};var c=i.containerOffset,h=i.containerSize.height,p=i.containerSize.width,d=e.ui.hasScroll(a,"left")?a.scrollWidth:p,v=e.ui.hasScroll(a)?a.scrollHeight:h;i.parentData={element:a,left:c.left,top:c.top,width:d,height:v}}},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.containerSize,o=r.containerOffset,u=r.size,a=r.position,f=r._aspectRatio||t.shiftKey,l={top:0,left:0},c=r.containerElement;c[0]!=document&&/static/.test(c.css("position"))&&(l=o),a.left<(r._helper?o.left:0)&&(r.size.width=r.size.width+(r._helper?r.position.left-o.left:r.position.left-l.left),f&&(r.size.height=r.size.width/r.aspectRatio),r.position.left=i.helper?o.left:0),a.top<(r._helper?o.top:0)&&(r.size.height=r.size.height+(r._helper?r.position.top-o.top:r.position.top),f&&(r.size.width=r.size.height*r.aspectRatio),r.position.top=r._helper?o.top:0),r.offset.left=r.parentData.left+r.position.left,r.offset.top=r.parentData.top+r.position.top;var h=Math.abs((r._helper?r.offset.left-l.left:r.offset.left-l.left)+r.sizeDiff.width),p=Math.abs((r._helper?r.offset.top-l.top:r.offset.top-o.top)+r.sizeDiff.height),d=r.containerElement.get(0)==r.element.parent().get(0),v=/relative|absolute/.test(r.containerElement.css("position"));d&&v&&(h-=r.parentData.left),h+r.size.width>=r.parentData.width&&(r.size.width=r.parentData.width-h,f&&(r.size.height=r.size.width/r.aspectRatio)),p+r.size.height>=r.parentData.height&&(r.size.height=r.parentData.height-p,f&&(r.size.width=r.size.height*r.aspectRatio))},stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.position,o=r.containerOffset,u=r.containerPosition,a=r.containerElement,f=e(r.helper),l=f.offset(),c=f.outerWidth()-r.sizeDiff.width,h=f.outerHeight()-r.sizeDiff.height;r._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h}),r._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h})}}),e.ui.plugin.add("resizable","ghost",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size;r.ghost=r.originalElement.clone(),r.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:""),r.ghost.appendTo(r.helper)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.ghost.css({position:"relative",height:r.size.height,width:r.size.width})},stop:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.helper&&r.helper.get(0).removeChild(r.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size,o=r.originalSize,u=r.originalPosition,a=r.axis,f=i._aspectRatio||t.shiftKey;i.grid=typeof i.grid=="number"?[i.grid,i.grid]:i.grid;var l=Math.round((s.width-o.width)/(i.grid[0]||1))*(i.grid[0]||1),c=Math.round((s.height-o.height)/(i.grid[1]||1))*(i.grid[1]||1);/^(se|s|e)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c):/^(ne)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c):/^(sw)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.left=u.left-l):(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c,r.position.left=u.left-l)}});var n=function(e){return parseInt(e,10)||0},r=function(e){return!isNaN(parseInt(e,10))}})(jQuery);(function(e,t){e.widget("ui.selectable",e.ui.mouse,{version:"1.9.0",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch"},_create:function(){var t=this;this.element.addClass("ui-selectable"),this.dragged=!1;var n;this.refresh=function(){n=e(t.options.filter,t.element[0]),n.addClass("ui-selectee"),n.each(function(){var t=e(this),n=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:n.left,top:n.top,right:n.left+t.outerWidth(),bottom:n.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=n.addClass("ui-selectee"),this._mouseInit(),this.helper=e("
            ")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var n=this;this.opos=[t.pageX,t.pageY];if(this.options.disabled)return;var r=this.options;this.selectees=e(r.filter,this.element[0]),this._trigger("start",t),e(r.appendTo).append(this.helper),this.helper.css({left:t.clientX,top:t.clientY,width:0,height:0}),r.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var r=e.data(this,"selectable-item");r.startselected=!0,!t.metaKey&&!t.ctrlKey&&(r.$element.removeClass("ui-selected"),r.selected=!1,r.$element.addClass("ui-unselecting"),r.unselecting=!0,n._trigger("unselecting",t,{unselecting:r.element}))}),e(t.target).parents().andSelf().each(function(){var r=e.data(this,"selectable-item");if(r){var i=!t.metaKey&&!t.ctrlKey||!r.$element.hasClass("ui-selected");return r.$element.removeClass(i?"ui-unselecting":"ui-selected").addClass(i?"ui-selecting":"ui-unselecting"),r.unselecting=!i,r.selecting=i,r.selected=i,i?n._trigger("selecting",t,{selecting:r.element}):n._trigger("unselecting",t,{unselecting:r.element}),!1}})},_mouseDrag:function(t){var n=this;this.dragged=!0;if(this.options.disabled)return;var r=this.options,i=this.opos[0],s=this.opos[1],o=t.pageX,u=t.pageY;if(i>o){var a=o;o=i,i=a}if(s>u){var a=u;u=s,s=a}return this.helper.css({left:i,top:s,width:o-i,height:u-s}),this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!a||a.element==n.element[0])return;var f=!1;r.tolerance=="touch"?f=!(a.left>o||a.rightu||a.bottomi&&a.rights&&a.bottom").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(r.range==="min"||r.range==="max"?" ui-slider-range-"+r.range:"")));for(t=i.length;tn&&(i=n,s=e(this),o=t)}),c.range===!0&&this.values(1)===c.min&&(o+=1,s=e(this.handles[o])),u=this._start(t,o),u===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,s.addClass("ui-state-active").focus(),a=s.offset(),f=!e(t.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=f?{left:0,top:0}:{left:t.pageX-a.left-s.width()/2,top:t.pageY-a.top-s.height()/2-(parseInt(s.css("borderTopWidth"),10)||0)-(parseInt(s.css("borderBottomWidth"),10)||0)+(parseInt(s.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(t,o,r),this._animateOff=!0,!0))},_mouseStart:function(e){return!0},_mouseDrag:function(e){var t={x:e.pageX,y:e.pageY},n=this._normValueFromMouse(t);return this._slide(e,this._handleIndex,n),!1},_mouseStop:function(e){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(e,this._handleIndex),this._change(e,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(e){var t,n,r,i,s;return this.orientation==="horizontal"?(t=this.elementSize.width,n=e.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(t=this.elementSize.height,n=e.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),r=n/t,r>1&&(r=1),r<0&&(r=0),this.orientation==="vertical"&&(r=1-r),i=this._valueMax()-this._valueMin(),s=this._valueMin()+r*i,this._trimAlignValue(s)},_start:function(e,t){var n={handle:this.handles[t],value:this.value()};return this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("start",e,n)},_slide:function(e,t,n){var r,i,s;this.options.values&&this.options.values.length?(r=this.values(t?0:1),this.options.values.length===2&&this.options.range===!0&&(t===0&&n>r||t===1&&n1){this.options.values[t]=this._trimAlignValue(n),this._refreshValue(),this._change(null,t);return}if(!arguments.length)return this._values();if(!e.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(t):this.value();r=this.options.values,i=arguments[0];for(s=0;s=this._valueMax())return this._valueMax();var t=this.options.step>0?this.options.step:1,n=(e-this._valueMin())%t,r=e-n;return Math.abs(n)*2>=t&&(r+=n>0?t:-t),parseFloat(r.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var t,n,r,i,s,o=this.options.range,u=this.options,a=this,f=this._animateOff?!1:u.animate,l={};this.options.values&&this.options.values.length?this.handles.each(function(r,i){n=(a.values(r)-a._valueMin())/(a._valueMax()-a._valueMin())*100,l[a.orientation==="horizontal"?"left":"bottom"]=n+"%",e(this).stop(1,1)[f?"animate":"css"](l,u.animate),a.options.range===!0&&(a.orientation==="horizontal"?(r===0&&a.range.stop(1,1)[f?"animate":"css"]({left:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({width:n-t+"%"},{queue:!1,duration:u.animate})):(r===0&&a.range.stop(1,1)[f?"animate":"css"]({bottom:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({height:n-t+"%"},{queue:!1,duration:u.animate}))),t=n}):(r=this.value(),i=this._valueMin(),s=this._valueMax(),n=s!==i?(r-i)/(s-i)*100:0,l[this.orientation==="horizontal"?"left":"bottom"]=n+"%",this.handle.stop(1,1)[f?"animate":"css"](l,u.animate),o==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[f?"animate":"css"]({width:n+"%"},u.animate),o==="max"&&this.orientation==="horizontal"&&this.range[f?"animate":"css"]({width:100-n+"%"},{queue:!1,duration:u.animate}),o==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[f?"animate":"css"]({height:n+"%"},u.animate),o==="max"&&this.orientation==="vertical"&&this.range[f?"animate":"css"]({height:100-n+"%"},{queue:!1,duration:u.animate}))}})})(jQuery);(function(e,t){e.widget("ui.sortable",e.ui.mouse,{version:"1.9.0",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?e.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_setOption:function(t,n){t==="disabled"?(this.options[t]=n,this.widget().toggleClass("ui-sortable-disabled",!!n)):e.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(t,n){var r=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(t);var i=null,s=e(t.target).parents().each(function(){if(e.data(this,r.widgetName+"-item")==r)return i=e(this),!1});e.data(t.target,r.widgetName+"-item")==r&&(i=e(t.target));if(!i)return!1;if(this.options.handle&&!n){var o=!1;e(this.options.handle,i).find("*").andSelf().each(function(){this==t.target&&(o=!0)});if(!o)return!1}return this.currentItem=i,this._removeCurrentsFromItems(),!0},_mouseStart:function(t,n,r){var i=this.options;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),i.containment&&this._setContainment(),i.cursor&&(e("body").css("cursor")&&(this._storedCursor=e("body").css("cursor")),e("body").css("cursor",i.cursor)),i.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",i.opacity)),i.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",i.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!r)for(var s=this.containers.length-1;s>=0;s--)this.containers[s]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var n=this.options,r=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY=0;i--){var s=this.items[i],o=s.item[0],u=this._intersectsWithPointer(s);if(!u)continue;if(s.instance!==this.currentContainer)continue;if(o!=this.currentItem[0]&&this.placeholder[u==1?"next":"prev"]()[0]!=o&&!e.contains(this.placeholder[0],o)&&(this.options.type=="semi-dynamic"?!e.contains(this.element[0],o):!0)){this.direction=u==1?"down":"up";if(this.options.tolerance!="pointer"&&!this._intersectsWithSides(s))break;this._rearrange(t,s),this._trigger("change",t,this._uiHash());break}}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,n){if(!t)return;e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t);if(this.options.revert){var r=this,i=this.placeholder.offset();this.reverting=!0,e(this.helper).animate({left:i.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:i.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){r._clear(t)})}else this._clear(t,n);return!1},cancel:function(){if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},e(n).each(function(){var n=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[-=_](.+)/);n&&r.push((t.key||n[1]+"[]")+"="+(t.key&&t.expression?n[1]:n[2]))}),!r.length&&t.key&&r.push(t.key+"="),r.join("&")},toArray:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},n.each(function(){r.push(e(t.item||this).attr(t.attribute||"id")||"")}),r},_intersectsWith:function(e){var t=this.positionAbs.left,n=t+this.helperProportions.width,r=this.positionAbs.top,i=r+this.helperProportions.height,s=e.left,o=s+e.width,u=e.top,a=u+e.height,f=this.offset.click.top,l=this.offset.click.left,c=r+f>u&&r+fs&&t+le[this.floating?"width":"height"]?c:s0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return e!=0&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor==String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){var n=[],r=[],i=this._connectWith();if(i&&t)for(var s=i.length-1;s>=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&r.push([e.isFunction(a.options.items)?a.options.items.call(a.element):e(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a])}}r.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var s=r.length-1;s>=0;s--)r[s][0].each(function(){n.push(this)});return e(n)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");for(var t=0;t=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&(r.push([e.isFunction(a.options.items)?a.options.items.call(a.element[0],t,{item:this.currentItem}):e(a.options.items,a.element),a]),this.containers.push(a))}}for(var s=r.length-1;s>=0;s--){var f=r[s][1],l=r[s][0];for(var u=0,c=l.length;u=0;n--){var r=this.items[n];if(r.instance!=this.currentContainer&&this.currentContainer&&r.item[0]!=this.currentItem[0])continue;var i=this.options.toleranceElement?e(this.options.toleranceElement,r.item):r.item;t||(r.width=i.outerWidth(),r.height=i.outerHeight());var s=i.offset();r.left=s.left,r.top=s.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var n=this.containers.length-1;n>=0;n--){var s=this.containers[n].element.offset();this.containers[n].containerCache.left=s.left,this.containers[n].containerCache.top=s.top,this.containers[n].containerCache.width=this.containers[n].element.outerWidth(),this.containers[n].containerCache.height=this.containers[n].element.outerHeight()}return this},_createPlaceholder:function(t){t=t||this;var n=t.options;if(!n.placeholder||n.placeholder.constructor==String){var r=n.placeholder;n.placeholder={element:function(){var n=e(document.createElement(t.currentItem[0].nodeName)).addClass(r||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return r||(n.style.visibility="hidden"),n},update:function(e,i){if(r&&!n.forcePlaceholderSize)return;i.height()||i.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),i.width()||i.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10))}}}t.placeholder=e(n.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),n.placeholder.update(t,t.placeholder)},_contactContainers:function(t){var n=null,r=null;for(var i=this.containers.length-1;i>=0;i--){if(e.contains(this.currentItem[0],this.containers[i].element[0]))continue;if(this._intersectsWith(this.containers[i].containerCache)){if(n&&e.contains(this.containers[i].element[0],n.element[0]))continue;n=this.containers[i],r=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",t,this._uiHash(this)),this.containers[i].containerCache.over=0)}if(!n)return;if(this.containers.length===1)this.containers[r]._trigger("over",t,this._uiHash(this)),this.containers[r].containerCache.over=1;else if(this.currentContainer!=this.containers[r]){var s=1e4,o=null,u=this.positionAbs[this.containers[r].floating?"left":"top"];for(var a=this.items.length-1;a>=0;a--){if(!e.contains(this.containers[r].element[0],this.items[a].item[0]))continue;var f=this.containers[r].floating?this.items[a].item.offset().left:this.items[a].item.offset().top;Math.abs(f-u)0?"down":"up")}if(!o&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[r],o?this._rearrange(t,o,null,!0):this._rearrange(t,null,this.containers[r].element,!0),this._trigger("change",t,this._uiHash()),this.containers[r]._trigger("change",t,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[r]._trigger("over",t,this._uiHash(this)),this.containers[r].containerCache.over=1}},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t,this.currentItem])):n.helper=="clone"?this.currentItem.clone():this.currentItem;return r.parents("body").length||e(n.appendTo!="parent"?n.appendTo:this.currentItem[0].parentNode)[0].appendChild(r[0]),r[0]==this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(r[0].style.width==""||n.forceHelperSize)&&r.width(this.currentItem.width()),(r[0].style.height==""||n.forceHelperSize)&&r.height(this.currentItem.height()),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&e.browser.msie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t=this.options;t.containment=="parent"&&(t.containment=this.helper[0].parentNode);if(t.containment=="document"||t.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,e(t.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(e(t.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(t.containment)){var n=e(t.containment)[0],r=e(t.containment).offset(),i=e(n).css("overflow")!="hidden";this.containment=[r.left+(parseInt(e(n).css("borderLeftWidth"),10)||0)+(parseInt(e(n).css("paddingLeft"),10)||0)-this.margins.left,r.top+(parseInt(e(n).css("borderTopWidth"),10)||0)+(parseInt(e(n).css("paddingTop"),10)||0)-this.margins.top,r.left+(i?Math.max(n.scrollWidth,n.offsetWidth):n.offsetWidth)-(parseInt(e(n).css("borderLeftWidth"),10)||0)-(parseInt(e(n).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,r.top+(i?Math.max(n.scrollHeight,n.offsetHeight):n.offsetHeight)-(parseInt(e(n).css("borderTopWidth"),10)||0)-(parseInt(e(n).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(t,n){n||(n=this.position);var r=t=="absolute"?1:-1,i=this.options,s=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(s[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():o?0:s.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():o?0:s.scrollLeft())*r}},_generatePosition:function(t){var n=this.options,r=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,i=/(html|body)/i.test(r[0].tagName);this.cssPosition=="relative"&&(this.scrollParent[0]==document||this.scrollParent[0]==this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset());var s=t.pageX,o=t.pageY;if(this.originalPosition){this.containment&&(t.pageX-this.offset.click.leftthis.containment[2]&&(s=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top));if(n.grid){var u=this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1];o=this.containment?u-this.offset.click.topthis.containment[3]?u-this.offset.click.topthis.containment[2]?a-this.offset.click.left=0;i--)n||r.push(function(e){return function(t){e._trigger("deactivate",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over&&(r.push(function(e){return function(t){e._trigger("out",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over=0);this._storedCursor&&e("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!n){this._trigger("beforeStop",t,this._uiHash());for(var i=0;i",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var t={},n=this.element;return e.each(["min","max","step"],function(e,r){var i=n.attr(r);i!==undefined&&i.length&&(t[r]=i)}),t},_events:{keydown:function(e){this._start(e)&&this._keydown(e)&&e.preventDefault()},keyup:"_stop",focus:function(){this.uiSpinner.addClass("ui-state-active"),this.previous=this.element.val()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}this._refresh(),this.uiSpinner.removeClass("ui-state-active"),this.previous!==this.element.val()&&this._trigger("change",e)},mousewheel:function(e,t){if(!t)return;if(!this.spinning&&!this._start(e))return!1;this._spin((t>0?1:-1)*this.options.step,e),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(e)},100),e.preventDefault()},"mousedown .ui-spinner-button":function(t){function r(){var e=this.element[0]===this.document[0].activeElement;e||(this.element.focus(),this.previous=n,this._delay(function(){this.previous=n}))}var n;n=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),t.preventDefault(),r.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,r.call(this)});if(this._start(t)===!1)return;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(t){if(!e(t.currentTarget).hasClass("ui-state-active"))return;if(this._start(t)===!1)return!1;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var e=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this._hoverable(e),this.element.attr("role","spinbutton"),this.buttons=e.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(e.height()*.5)&&e.height()>0&&e.height(e.height()),this.options.disabled&&this.disable()},_keydown:function(t){var n=this.options,r=e.ui.keyCode;switch(t.keyCode){case r.UP:return this._repeat(null,1,t),!0;case r.DOWN:return this._repeat(null,-1,t),!0;case r.PAGE_UP:return this._repeat(null,n.page,t),!0;case r.PAGE_DOWN:return this._repeat(null,-n.page,t),!0}return!1},_uiSpinnerHtml:function(){return""},_buttonHtml:function(){return""+""+""+""+""},_start:function(e){return!this.spinning&&this._trigger("start",e)===!1?!1:(this.counter||(this.counter=1),this.spinning=!0,!0)},_repeat:function(e,t,n){e=e||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,t,n)},e),this._spin(t*this.options.step,n)},_spin:function(e,t){var n=this.value()||0;this.counter||(this.counter=1),n=this._adjustValue(n+e*this._increment(this.counter));if(!this.spinning||this._trigger("spin",t,{value:n})!==!1)this._value(n),this.counter++},_increment:function(t){var n=this.options.incremental;return n?e.isFunction(n)?n(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var e=this._precisionOf(this.options.step);return this.options.min!==null&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=e.toString(),n=t.indexOf(".");return n===-1?0:t.length-n-1},_adjustValue:function(e){var t,n,r=this.options;return t=r.min!==null?r.min:0,n=e-t,n=Math.round(n/r.step)*r.step,e=t+n,e=parseFloat(e.toFixed(this._precision())),r.max!==null&&e>r.max?r.max:r.min!==null&&e1&&e.href.replace(r,"")===location.href.replace(r,"")}var n=0,r=/#.*$/;e.widget("ui.tabs",{version:"1.9.0",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var t,n=this,r=this.options,i=r.active;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",r.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs();if(i===null){location.hash&&this.anchors.each(function(e,t){if(t.hash===location.hash)return i=e,!1}),i===null&&(i=this.tabs.filter(".ui-tabs-active").index());if(i===null||i===-1)i=this.tabs.length?0:!1}i!==!1&&(i=this.tabs.index(this.tabs.eq(i)),i===-1&&(i=r.collapsible?!1:0)),r.active=i,!r.collapsible&&r.active===!1&&this.anchors.length&&(r.active=0),e.isArray(r.disabled)&&(r.disabled=e.unique(r.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return n.tabs.index(e)}))).sort()),this.options.active!==!1&&this.anchors.length?this.active=this._findActive(this.options.active):this.active=e(),this._refresh(),this.active.length&&this.load(r.active)},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var n=e(this.document[0].activeElement).closest("li"),r=this.tabs.index(n),i=!0;if(this._handlePageNav(t))return;switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:r++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:i=!1,r--;break;case e.ui.keyCode.END:r=this.anchors.length-1;break;case e.ui.keyCode.HOME:r=0;break;case e.ui.keyCode.SPACE:t.preventDefault(),clearTimeout(this.activating),this._activate(r);return;case e.ui.keyCode.ENTER:t.preventDefault(),clearTimeout(this.activating),this._activate(r===this.options.active?!1:r);return;default:return}t.preventDefault(),clearTimeout(this.activating),r=this._focusNextTab(r,i),t.ctrlKey||(n.attr("aria-selected","false"),this.tabs.eq(r).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",r)},this.delay))},_panelKeydown:function(t){if(this._handlePageNav(t))return;t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP)return this._activate(this._focusNextTab(this.options.active-1,!1)),!0;if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN)return this._activate(this._focusNextTab(this.options.active+1,!0)),!0},_findNextTab:function(t,n){function i(){return t>r&&(t=0),t<0&&(t=r),t}var r=this.tabs.length-1;while(e.inArray(i(),this.options.disabled)!==-1)t=n?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){if(e==="active"){this._activate(t);return}if(e==="disabled"){this._setupDisabled(t);return}this._super(e,t),e==="collapsible"&&(this.element.toggleClass("ui-tabs-collapsible",t),!t&&this.options.active===!1&&this._activate(0)),e==="event"&&this._setupEvents(t),e==="heightStyle"&&this._setupHeightStyle(t)},_tabId:function(e){return e.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t,n=this.options,r=this.tablist.children(":has(a[href])");n.disabled=e.map(r.filter(".ui-state-disabled"),function(e){return r.index(e)}),this._processTabs(),n.active===!1||!this.anchors.length?(n.active=!1,this.active=e()):this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===n.disabled.length?(n.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,n.active-1),!1)):n.active=this.tabs.index(this.active),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(n,r){var i,o,u,a=e(r).uniqueId().attr("id"),f=e(r).closest("li"),l=f.attr("aria-controls");s(r)?(i=r.hash,o=t.element.find(t._sanitizeSelector(i))):(u=t._tabId(f),i="#"+u,o=t.element.find(i),o.length||(o=t._createPanel(u),o.insertAfter(t.panels[n-1]||t.tablist)),o.attr("aria-live","polite")),o.length&&(t.panels=t.panels.add(o)),l&&f.data("ui-tabs-aria-controls",l),f.attr({"aria-controls":i.substring(1),"aria-labelledby":a}),o.attr("aria-labelledby",a)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("
            ").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var n=0,r;r=this.tabs[n];n++)t===!0||e.inArray(n,t)!==-1?e(r).addClass("ui-state-disabled").attr("aria-disabled","true"):e(r).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var n={click:function(e){e.preventDefault()}};t&&e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,n),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var n,r,i=this.element.parent();t==="fill"?(e.support.minHeight||(r=i.css("overflow"),i.css("overflow","hidden")),n=i.height(),this.element.siblings(":visible").each(function(){var t=e(this),r=t.css("position");if(r==="absolute"||r==="fixed")return;n-=t.outerHeight(!0)}),r&&i.css("overflow",r),this.element.children().not(this.panels).each(function(){n-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,n-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):t==="auto"&&(n=0,this.panels.each(function(){n=Math.max(n,e(this).height("").height())}).height(n))},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i.closest("li"),o=s[0]===r[0],u=o&&n.collapsible,a=u?e():this._getPanelForTab(s),f=r.length?this._getPanelForTab(r):e(),l={oldTab:r,oldPanel:f,newTab:u?e():s,newPanel:a};t.preventDefault();if(s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||o&&!n.collapsible||this._trigger("beforeActivate",t,l)===!1)return;n.active=u?!1:this.tabs.index(s),this.active=o?e():s,this.xhr&&this.xhr.abort(),!f.length&&!a.length&&e.error("jQuery UI Tabs: Mismatching fragment identifier."),a.length&&this.load(this.tabs.index(s),t),this._toggle(t,l)},_toggle:function(t,n){function o(){r.running=!1,r._trigger("activate",t,n)}function u(){n.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),i.length&&r.options.show?r._show(i,r.options.show,o):(i.show(),o())}var r=this,i=n.newPanel,s=n.oldPanel;this.running=!0,s.length&&this.options.hide?this._hide(s,this.options.hide,function(){n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),s.hide(),u()),s.attr({"aria-expanded":"false","aria-hidden":"true"}),n.oldTab.attr("aria-selected","false"),i.length&&s.length?n.oldTab.attr("tabIndex",-1):i.length&&this.tabs.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),i.attr({"aria-expanded":"true","aria-hidden":"false"}),n.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(t){var n,r=this._findActive(t);if(r[0]===this.active[0])return;r.length||(r=this.active),n=r.find(".ui-tabs-anchor")[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return typeof e=="string"&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeData("href.tabs").removeData("load.tabs").removeUniqueId(),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),n=t.data("ui-tabs-aria-controls");n?t.attr("aria-controls",n):t.removeAttr("aria-controls")}),this.options.heightStyle!=="content"&&this.panels.css("height","")},enable:function(n){var r=this.options.disabled;if(r===!1)return;n===t?r=!1:(n=this._getIndex(n),e.isArray(r)?r=e.map(r,function(e){return e!==n?e:null}):r=e.map(this.tabs,function(e,t){return t!==n?t:null})),this._setupDisabled(r)},disable:function(n){var r=this.options.disabled;if(r===!0)return;if(n===t)r=!0;else{n=this._getIndex(n);if(e.inArray(n,r)!==-1)return;e.isArray(r)?r=e.merge([n],r).sort():r=[n]}this._setupDisabled(r)},load:function(t,n){t=this._getIndex(t);var r=this,i=this.tabs.eq(t),o=i.find(".ui-tabs-anchor"),u=this._getPanelForTab(i),a={tab:i,panel:u};if(s(o[0]))return;this.xhr=e.ajax(this._ajaxSettings(o,n,a)),this.xhr&&this.xhr.statusText!=="canceled"&&(i.addClass("ui-tabs-loading"),u.attr("aria-busy","true"),this.xhr.success(function(e){setTimeout(function(){u.html(e),r._trigger("load",n,a)},1)}).complete(function(e,t){setTimeout(function(){t==="abort"&&r.panels.stop(!1,!0),i.removeClass("ui-tabs-loading"),u.removeAttr("aria-busy"),e===r.xhr&&delete r.xhr},1)}))},_ajaxSettings:function(t,n,r){var i=this;return{url:t.attr("href"),beforeSend:function(t,s){return i._trigger("beforeLoad",n,e.extend({jqXHR:t,ajaxSettings:s},r))}}},_getPanelForTab:function(t){var n=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+n))}}),e.uiBackCompat!==!1&&(e.ui.tabs.prototype._ui=function(e,t){return{tab:e,panel:t,index:this.anchors.index(e)}},e.widget("ui.tabs",e.ui.tabs,{url:function(e,t){this.anchors.eq(e).attr("href",t)}}),e.widget("ui.tabs",e.ui.tabs,{options:{ajaxOptions:null,cache:!1},_create:function(){this._super();var t=this;this._on({tabsbeforeload:function(n,r){if(e.data(r.tab[0],"cache.tabs")){n.preventDefault();return}r.jqXHR.success(function(){t.options.cache&&e.data(r.tab[0],"cache.tabs",!0)})}})},_ajaxSettings:function(t,n,r){var i=this.options.ajaxOptions;return e.extend({},i,{error:function(e,t,n){try{i.error(e,t,r.tab.closest("li").index(),r.tab[0])}catch(n){}}},this._superApply(arguments))},_setOption:function(e,t){e==="cache"&&t===!1&&this.anchors.removeData("cache.tabs"),this._super(e,t)},_destroy:function(){this.anchors.removeData("cache.tabs"),this._super()},url:function(e,t){this.anchors.eq(e).removeData("cache.tabs"),this._superApply(arguments)}}),e.widget("ui.tabs",e.ui.tabs,{abort:function(){this.xhr&&this.xhr.abort()}}),e.widget("ui.tabs",e.ui.tabs,{options:{spinner:"Loading…"},_create:function(){this._super(),this._on({tabsbeforeload:function(e,t){if(e.target!==this.element[0]||!this.options.spinner)return;var n=t.tab.find("span"),r=n.html();n.html(this.options.spinner),t.jqXHR.complete(function(){n.html(r)})}})}}),e.widget("ui.tabs",e.ui.tabs,{options:{enable:null,disable:null},enable:function(t){var n=this.options,r;if(t&&n.disabled===!0||e.isArray(n.disabled)&&e.inArray(t,n.disabled)!==-1)r=!0;this._superApply(arguments),r&&this._trigger("enable",null,this._ui(this.anchors[t],this.panels[t]))},disable:function(t){var n=this.options,r;if(t&&n.disabled===!1||e.isArray(n.disabled)&&e.inArray(t,n.disabled)===-1)r=!0;this._superApply(arguments),r&&this._trigger("disable",null,this._ui(this.anchors[t],this.panels[t]))}}),e.widget("ui.tabs",e.ui.tabs,{options:{add:null,remove:null,tabTemplate:"
          7. #{label}
          8. "},add:function(n,r,i){i===t&&(i=this.anchors.length);var s,o,u=this.options,a=e(u.tabTemplate.replace(/#\{href\}/g,n).replace(/#\{label\}/g,r)),f=n.indexOf("#")?this._tabId(a):n.replace("#","");return a.addClass("ui-state-default ui-corner-top").data("ui-tabs-destroy",!0),a.attr("aria-controls",f),s=i>=this.tabs.length,o=this.element.find("#"+f),o.length||(o=this._createPanel(f),s?i>0?o.insertAfter(this.panels.eq(-1)):o.appendTo(this.element):o.insertBefore(this.panels[i])),o.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").hide(),s?a.appendTo(this.tablist):a.insertBefore(this.tabs[i]),u.disabled=e.map(u.disabled,function(e){return e>=i?++e:e}),this.refresh(),this.tabs.length===1&&u.active===!1&&this.option("active",0),this._trigger("add",null,this._ui(this.anchors[i],this.panels[i])),this},remove:function(t){t=this._getIndex(t);var n=this.options,r=this.tabs.eq(t).remove(),i=this._getPanelForTab(r).remove();return r.hasClass("ui-tabs-active")&&this.anchors.length>2&&this._activate(t+(t+1=t?--e:e}),this.refresh(),this._trigger("remove",null,this._ui(r.find("a")[0],i[0])),this}}),e.widget("ui.tabs",e.ui.tabs,{length:function(){return this.anchors.length}}),e.widget("ui.tabs",e.ui.tabs,{options:{idPrefix:"ui-tabs-"},_tabId:function(t){var n=t.is("li")?t.find("a[href]"):t;return n=n[0],e(n).closest("li").attr("aria-controls")||n.title&&n.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF\-]/g,"")||this.options.idPrefix+i()}}),e.widget("ui.tabs",e.ui.tabs,{options:{panelTemplate:"
            "},_createPanel:function(t){return e(this.options.panelTemplate).attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)}}),e.widget("ui.tabs",e.ui.tabs,{_create:function(){var e=this.options;e.active===null&&e.selected!==t&&(e.active=e.selected===-1?!1:e.selected),this._super(),e.selected=e.active,e.selected===!1&&(e.selected=-1)},_setOption:function(e,t){if(e!=="selected")return this._super(e,t);var n=this.options;this._super("active",t===-1?!1:t),n.selected=n.active,n.selected===!1&&(n.selected=-1)},_eventHandler:function(e){this._superApply(arguments),this.options.selected=this.options.active,this.options.selected===!1&&(this.options.selected=-1)}}),e.widget("ui.tabs",e.ui.tabs,{options:{show:null,select:null},_create:function(){this._super(),this.options.active!==!1&&this._trigger("show",null,this._ui(this.active.find(".ui-tabs-anchor")[0],this._getPanelForTab(this.active)[0]))},_trigger:function(e,t,n){var r=this._superApply(arguments);return r?(e==="beforeActivate"&&n.newTab.length?r=this._super("select",t,{tab:n.newTab.find(".ui-tabs-anchor")[0],panel:n.newPanel[0],index:n.newTab.closest("li").index()}):e==="activate"&&n.newTab.length&&(r=this._super("show",t,{tab:n.newTab.find(".ui-tabs-anchor")[0],panel:n.newPanel[0],index:n.newTab.closest("li").index()})),r):!1}}),e.widget("ui.tabs",e.ui.tabs,{select:function(e){e=this._getIndex(e);if(e===-1){if(!this.options.collapsible||this.options.selected===-1)return;e=this.options.selected}this.anchors.eq(e).trigger(this.options.event+this.eventNamespace)}}),function(){var t=0;e.widget("ui.tabs",e.ui.tabs,{options:{cookie:null},_create:function(){var e=this.options,t;e.active==null&&e.cookie&&(t=parseInt(this._cookie(),10),t===-1&&(t=!1),e.active=t),this._super()},_cookie:function(n){var r=[this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+ ++t)];return arguments.length&&(r.push(n===!1?-1:n),r.push(this.options.cookie)),e.cookie.apply(null,r)},_refresh:function(){this._super(),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_eventHandler:function(e){this._superApply(arguments),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_destroy:function(){this._super(),this.options.cookie&&this._cookie(null,this.options.cookie)}})}(),e.widget("ui.tabs",e.ui.tabs,{_trigger:function(t,n,r){var i=e.extend({},r);return t==="load"&&(i.panel=i.panel[0],i.tab=i.tab.find(".ui-tabs-anchor")[0]),this._super(t,n,i)}}),e.widget("ui.tabs",e.ui.tabs,{options:{fx:null},_getFx:function(){var t,n,r=this.options.fx;return r&&(e.isArray(r)?(t=r[0],n=r[1]):t=n=r),r?{show:n,hide:t}:null},_toggle:function(e,t){function o(){n.running=!1,n._trigger("activate",e,t)}function u(){t.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),r.length&&s.show?r.animate(s.show,s.show.duration,function(){o()}):(r.show(),o())}var n=this,r=t.newPanel,i=t.oldPanel,s=this._getFx();if(!s)return this._super(e,t);n.running=!0,i.length&&s.hide?i.animate(s.hide,s.hide.duration,function(){t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),i.hide(),u())}}))})(jQuery);(function(e){function n(t,n){var r=(t.attr("aria-describedby")||"").split(/\s+/);r.push(n),t.data("ui-tooltip-id",n).attr("aria-describedby",e.trim(r.join(" ")))}function r(t){var n=t.data("ui-tooltip-id"),r=(t.attr("aria-describedby")||"").split(/\s+/),i=e.inArray(n,r);i!==-1&&r.splice(i,1),t.removeData("ui-tooltip-id"),r=e.trim(r.join(" ")),r?t.attr("aria-describedby",r):t.removeAttr("aria-describedby")}var t=0;e.widget("ui.tooltip",{version:"1.9.0",options:{content:function(){return e(this).attr("title")},hide:!0,items:"[title]",position:{my:"left+15 center",at:"right center",collision:"flipfit flipfit"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={}},_setOption:function(t,n){var r=this;if(t==="disabled"){this[n?"_disable":"_enable"](),this.options[t]=n;return}this._super(t,n),t==="content"&&e.each(this.tooltips,function(e,t){r._updateContent(t)})},_disable:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0)}),this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.is("[title]")&&t.data("ui-tooltip-title",t.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))})},open:function(t){var n=e(t?t.target:this.element).closest(this.options.items);if(!n.length)return;if(this.options.track&&n.data("ui-tooltip-id")){this._find(n).position(e.extend({of:n},this.options.position)),this._off(this.document,"mousemove");return}n.attr("title")&&n.data("ui-tooltip-title",n.attr("title")),n.data("tooltip-open",!0),this._updateContent(n,t)},_updateContent:function(e,t){var n,r=this.options.content,i=this;if(typeof r=="string")return this._open(t,e,r);n=r.call(e[0],function(n){if(!e.data("tooltip-open"))return;i._delay(function(){this._open(t,e,n)})}),n&&this._open(t,e,n)},_open:function(t,r,i){function u(e){o.of=e,s.position(o)}var s,o;if(!i)return;s=this._find(r);if(s.length){s.find(".ui-tooltip-content").html(i);return}r.is("[title]")&&(t&&t.type==="mouseover"?r.attr("title",""):r.removeAttr("title")),s=this._tooltip(r),n(r,s.attr("id")),s.find(".ui-tooltip-content").html(i),this.options.track&&t&&/^mouse/.test(t.originalEvent.type)?(o=e.extend({},this.options.position),this._on(this.document,{mousemove:u}),u(t)):s.position(e.extend({of:r},this.options.position)),s.hide(),this._show(s,this.options.show),this._trigger("open",t,{tooltip:s}),this._on(r,{mouseleave:"close",focusout:"close",keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var n=e.Event(t);n.currentTarget=r[0],this.close(n,!0)}}})},close:function(t,n){var i=this,s=e(t?t.currentTarget:this.element),o=this._find(s);if(this.closing)return;if(!n&&t&&t.type!=="focusout"&&this.document[0].activeElement===s[0])return;s.data("ui-tooltip-title")&&s.attr("title",s.data("ui-tooltip-title")),r(s),o.stop(!0),this._hide(o,this.options.hide,function(){e(this).remove(),delete i.tooltips[this.id]}),s.removeData("tooltip-open"),this._off(s,"mouseleave focusout keyup"),this._off(this.document,"mousemove"),this.closing=!0,this._trigger("close",t,{tooltip:o}),this.closing=!1},_tooltip:function(n){var r="ui-tooltip-"+t++,i=e("
            ").attr({id:r,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return e("
            ").addClass("ui-tooltip-content").appendTo(i),i.appendTo(this.document[0].body),e.fn.bgiframe&&i.bgiframe(),this.tooltips[r]=n,i},_find:function(t){var n=t.data("ui-tooltip-id");return n?e("#"+n):e()},_destroy:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0),e("#"+n).remove(),r.data("ui-tooltip-title")&&(r.attr("title",r.data("ui-tooltip-title")),r.removeData("ui-tooltip-title"))})}})})(jQuery); \ No newline at end of file diff --git a/nebula-exchange/target/site/scaladocs/lib/jquery.js b/nebula-exchange/target/site/scaladocs/lib/jquery.js new file mode 100644 index 0000000..bc3fbc8 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/lib/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.2 jquery.com | jquery.org/license */ +(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
            a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
            t
            ",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
            ",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
            ",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

            ",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
            ","
            "],thead:[1,"","
            "],tr:[2,"","
            "],td:[3,"","
            "],col:[2,"","
            "],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
            ","
            "]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
            ").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); \ No newline at end of file diff --git a/nebula-exchange/target/site/scaladocs/lib/jquery.layout.js b/nebula-exchange/target/site/scaladocs/lib/jquery.layout.js new file mode 100644 index 0000000..d5e008d --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/lib/jquery.layout.js @@ -0,0 +1,5486 @@ +/** + * @preserve jquery.layout 1.3.0 - Release Candidate 30.62 + * $Date: 2012-08-04 08:00:00 (Thu, 23 Aug 2012) $ + * $Rev: 303006 $ + * + * Copyright (c) 2012 + * Fabrizio Balliano (http://www.fabrizioballiano.net) + * Kevin Dalman (http://allpro.net) + * + * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html) + * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses. + * + * Changelog: http://layout.jquery-dev.net/changelog.cfm#1.3.0.rc30.62 + * NOTE: This is a short-term release to patch a couple of bugs. + * These bugs are listed as officially fixed in RC30.7, which will be released shortly. + * + * Docs: http://layout.jquery-dev.net/documentation.html + * Tips: http://layout.jquery-dev.net/tips.html + * Help: http://groups.google.com/group/jquery-ui-layout + */ + +/* JavaDoc Info: http://code.google.com/closure/compiler/docs/js-for-compiler.html + * {!Object} non-nullable type (never NULL) + * {?string} nullable type (sometimes NULL) - default for {Object} + * {number=} optional parameter + * {*} ALL types + */ + +// NOTE: For best readability, view with a fixed-width font and tabs equal to 4-chars + +;(function ($) { + +// alias Math methods - used a lot! +var min = Math.min +, max = Math.max +, round = Math.floor + +, isStr = function (v) { return $.type(v) === "string"; } + +, runPluginCallbacks = function (Instance, a_fn) { + if ($.isArray(a_fn)) + for (var i=0, c=a_fn.length; i
            ').appendTo("body"); + var d = { width: $c.width() - $c[0].clientWidth, height: $c.height() - $c[0].clientHeight }; + $c.remove(); + window.scrollbarWidth = d.width; + window.scrollbarHeight = d.height; + return dim.match(/^(width|height)$/) ? d[dim] : d; + } + + + /** + * Returns hash container 'display' and 'visibility' + * + * @see $.swap() - swaps CSS, runs callback, resets CSS + */ +, showInvisibly: function ($E, force) { + if ($E && $E.length && (force || $E.css('display') === "none")) { // only if not *already hidden* + var s = $E[0].style + // save ONLY the 'style' props because that is what we must restore + , CSS = { display: s.display || '', visibility: s.visibility || '' }; + // show element 'invisibly' so can be measured + $E.css({ display: "block", visibility: "hidden" }); + return CSS; + } + return {}; + } + + /** + * Returns data for setting size of an element (container or a pane). + * + * @see _create(), onWindowResize() for container, plus others for pane + * @return JSON Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc + */ +, getElementDimensions: function ($E) { + var + d = {} // dimensions hash + , x = d.css = {} // CSS hash + , i = {} // TEMP insets + , b, p // TEMP border, padding + , N = $.layout.cssNum + , off = $E.offset() + ; + d.offsetLeft = off.left; + d.offsetTop = off.top; + + $.each("Left,Right,Top,Bottom".split(","), function (idx, e) { // e = edge + b = x["border" + e] = $.layout.borderWidth($E, e); + p = x["padding"+ e] = $.layout.cssNum($E, "padding"+e); + i[e] = b + p; // total offset of content from outer side + d["inset"+ e] = p; // eg: insetLeft = paddingLeft + }); + + d.offsetWidth = $E.innerWidth(); // offsetWidth is used in calc when doing manual resize + d.offsetHeight = $E.innerHeight(); // ditto + d.outerWidth = $E.outerWidth(); + d.outerHeight = $E.outerHeight(); + d.innerWidth = max(0, d.outerWidth - i.Left - i.Right); + d.innerHeight = max(0, d.outerHeight - i.Top - i.Bottom); + + x.width = $E.width(); + x.height = $E.height(); + x.top = N($E,"top",true); + x.bottom = N($E,"bottom",true); + x.left = N($E,"left",true); + x.right = N($E,"right",true); + + //d.visible = $E.is(":visible");// && x.width > 0 && x.height > 0; + + return d; + } + +, getElementCSS: function ($E, list) { + var + CSS = {} + , style = $E[0].style + , props = list.split(",") + , sides = "Top,Bottom,Left,Right".split(",") + , attrs = "Color,Style,Width".split(",") + , p, s, a, i, j, k + ; + for (i=0; i < props.length; i++) { + p = props[i]; + if (p.match(/(border|padding|margin)$/)) + for (j=0; j < 4; j++) { + s = sides[j]; + if (p === "border") + for (k=0; k < 3; k++) { + a = attrs[k]; + CSS[p+s+a] = style[p+s+a]; + } + else + CSS[p+s] = style[p+s]; + } + else + CSS[p] = style[p]; + }; + return CSS + } + + /** + * Return the innerWidth for the current browser/doctype + * + * @see initPanes(), sizeMidPanes(), initHandles(), sizeHandles() + * @param {Array.} $E Must pass a jQuery object - first element is processed + * @param {number=} outerWidth (optional) Can pass a width, allowing calculations BEFORE element is resized + * @return {number} Returns the innerWidth of the elem by subtracting padding and borders + */ +, cssWidth: function ($E, outerWidth) { + // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed + if (outerWidth <= 0) return 0; + + if (!$.layout.browser.boxModel) return outerWidth; + + // strip border and padding from outerWidth to get CSS Width + var b = $.layout.borderWidth + , n = $.layout.cssNum + , W = outerWidth + - b($E, "Left") + - b($E, "Right") + - n($E, "paddingLeft") + - n($E, "paddingRight"); + + return max(0,W); + } + + /** + * Return the innerHeight for the current browser/doctype + * + * @see initPanes(), sizeMidPanes(), initHandles(), sizeHandles() + * @param {Array.} $E Must pass a jQuery object - first element is processed + * @param {number=} outerHeight (optional) Can pass a width, allowing calculations BEFORE element is resized + * @return {number} Returns the innerHeight of the elem by subtracting padding and borders + */ +, cssHeight: function ($E, outerHeight) { + // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed + if (outerHeight <= 0) return 0; + + if (!$.layout.browser.boxModel) return outerHeight; + + // strip border and padding from outerHeight to get CSS Height + var b = $.layout.borderWidth + , n = $.layout.cssNum + , H = outerHeight + - b($E, "Top") + - b($E, "Bottom") + - n($E, "paddingTop") + - n($E, "paddingBottom"); + + return max(0,H); + } + + /** + * Returns the 'current CSS numeric value' for a CSS property - 0 if property does not exist + * + * @see Called by many methods + * @param {Array.} $E Must pass a jQuery object - first element is processed + * @param {string} prop The name of the CSS property, eg: top, width, etc. + * @param {boolean=} [allowAuto=false] true = return 'auto' if that is value; false = return 0 + * @return {(string|number)} Usually used to get an integer value for position (top, left) or size (height, width) + */ +, cssNum: function ($E, prop, allowAuto) { + if (!$E.jquery) $E = $($E); + var CSS = $.layout.showInvisibly($E) + , p = $.css($E[0], prop, true) + , v = allowAuto && p=="auto" ? p : (parseInt(p, 10) || 0); + $E.css( CSS ); // RESET + return v; + } + +, borderWidth: function (el, side) { + if (el.jquery) el = el[0]; + var b = "border"+ side.substr(0,1).toUpperCase() + side.substr(1); // left => Left + return $.css(el, b+"Style", true) === "none" ? 0 : (parseInt($.css(el, b+"Width", true), 10) || 0); + } + + /** + * Mouse-tracking utility - FUTURE REFERENCE + * + * init: if (!window.mouse) { + * window.mouse = { x: 0, y: 0 }; + * $(document).mousemove( $.layout.trackMouse ); + * } + * + * @param {Object} evt + * +, trackMouse: function (evt) { + window.mouse = { x: evt.clientX, y: evt.clientY }; + } + */ + + /** + * SUBROUTINE for preventPrematureSlideClose option + * + * @param {Object} evt + * @param {Object=} el + */ +, isMouseOverElem: function (evt, el) { + var + $E = $(el || this) + , d = $E.offset() + , T = d.top + , L = d.left + , R = L + $E.outerWidth() + , B = T + $E.outerHeight() + , x = evt.pageX // evt.clientX ? + , y = evt.pageY // evt.clientY ? + ; + // if X & Y are < 0, probably means is over an open SELECT + return ($.layout.browser.msie && x < 0 && y < 0) || ((x >= L && x <= R) && (y >= T && y <= B)); + } + + /** + * Message/Logging Utility + * + * @example $.layout.msg("My message"); // log text + * @example $.layout.msg("My message", true); // alert text + * @example $.layout.msg({ foo: "bar" }, "Title"); // log hash-data, with custom title + * @example $.layout.msg({ foo: "bar" }, true, "Title", { sort: false }); -OR- + * @example $.layout.msg({ foo: "bar" }, "Title", { sort: false, display: true }); // alert hash-data + * + * @param {(Object|string)} info String message OR Hash/Array + * @param {(Boolean|string|Object)=} [popup=false] True means alert-box - can be skipped + * @param {(Object|string)=} [debugTitle=""] Title for Hash data - can be skipped + * @param {Object=} [debugOpts] Extra options for debug output + */ +, msg: function (info, popup, debugTitle, debugOpts) { + if ($.isPlainObject(info) && window.debugData) { + if (typeof popup === "string") { + debugOpts = debugTitle; + debugTitle = popup; + } + else if (typeof debugTitle === "object") { + debugOpts = debugTitle; + debugTitle = null; + } + var t = debugTitle || "log( )" + , o = $.extend({ sort: false, returnHTML: false, display: false }, debugOpts); + if (popup === true || o.display) + debugData( info, t, o ); + else if (window.console) + console.log(debugData( info, t, o )); + } + else if (popup) + alert(info); + else if (window.console) + console.log(info); + else { + var id = "#layoutLogger" + , $l = $(id); + if (!$l.length) + $l = createLog(); + $l.children("ul").append('
          9. '+ info.replace(/\/g,">") +'
          10. '); + } + + function createLog () { + var pos = $.support.fixedPosition ? 'fixed' : 'absolute' + , $e = $('
            ' + + '
            ' + + 'XLayout console.log
            ' + + '
              ' + + '
              ' + ).appendTo("body"); + $e.css('left', $(window).width() - $e.outerWidth() - 5) + if ($.ui.draggable) $e.draggable({ handle: ':first-child' }); + return $e; + }; + } + +}; + +// DEFAULT OPTIONS +$.layout.defaults = { +/* + * LAYOUT & LAYOUT-CONTAINER OPTIONS + * - none of these options are applicable to individual panes + */ + name: "" // Not required, but useful for buttons and used for the state-cookie +, containerSelector: "" // ONLY used when specifying a childOptions - to find container-element that is NOT directly-nested +, containerClass: "ui-layout-container" // layout-container element +, scrollToBookmarkOnLoad: true // after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark) +, resizeWithWindow: true // bind thisLayout.resizeAll() to the window.resize event +, resizeWithWindowDelay: 200 // delay calling resizeAll because makes window resizing very jerky +, resizeWithWindowMaxDelay: 0 // 0 = none - force resize every XX ms while window is being resized +, onresizeall_start: null // CALLBACK when resizeAll() STARTS - NOT pane-specific +, onresizeall_end: null // CALLBACK when resizeAll() ENDS - NOT pane-specific +, onload_start: null // CALLBACK when Layout inits - after options initialized, but before elements +, onload_end: null // CALLBACK when Layout inits - after EVERYTHING has been initialized +, onunload_start: null // CALLBACK when Layout is destroyed OR onWindowUnload +, onunload_end: null // CALLBACK when Layout is destroyed OR onWindowUnload +, initPanes: true // false = DO NOT initialize the panes onLoad - will init later +, showErrorMessages: true // enables fatal error messages to warn developers of common errors +, showDebugMessages: false // display console-and-alert debug msgs - IF this Layout version _has_ debugging code! +// Changing this zIndex value will cause other zIndex values to automatically change +, zIndex: null // the PANE zIndex - resizers and masks will be +1 +// DO NOT CHANGE the zIndex values below unless you clearly understand their relationships +, zIndexes: { // set _default_ z-index values here... + pane_normal: 0 // normal z-index for panes + , content_mask: 1 // applied to overlays used to mask content INSIDE panes during resizing + , resizer_normal: 2 // normal z-index for resizer-bars + , pane_sliding: 100 // applied to *BOTH* the pane and its resizer when a pane is 'slid open' + , pane_animate: 1000 // applied to the pane when being animated - not applied to the resizer + , resizer_drag: 10000 // applied to the CLONED resizer-bar when being 'dragged' + } +, errors: { + pane: "pane" // description of "layout pane element" - used only in error messages + , selector: "selector" // description of "jQuery-selector" - used only in error messages + , addButtonError: "Error Adding Button \n\nInvalid " + , containerMissing: "UI Layout Initialization Error\n\nThe specified layout-container does not exist." + , centerPaneMissing: "UI Layout Initialization Error\n\nThe center-pane element does not exist.\n\nThe center-pane is a required element." + , noContainerHeight: "UI Layout Initialization Warning\n\nThe layout-container \"CONTAINER\" has no height.\n\nTherefore the layout is 0-height and hence 'invisible'!" + , callbackError: "UI Layout Callback Error\n\nThe EVENT callback is not a valid function." + } +/* + * PANE DEFAULT SETTINGS + * - settings under the 'panes' key become the default settings for *all panes* + * - ALL pane-options can also be set specifically for each panes, which will override these 'default values' + */ +, panes: { // default options for 'all panes' - will be overridden by 'per-pane settings' + applyDemoStyles: false // NOTE: renamed from applyDefaultStyles for clarity + , closable: true // pane can open & close + , resizable: true // when open, pane can be resized + , slidable: true // when closed, pane can 'slide open' over other panes - closes on mouse-out + , initClosed: false // true = init pane as 'closed' + , initHidden: false // true = init pane as 'hidden' - no resizer-bar/spacing + // SELECTORS + //, paneSelector: "" // MUST be pane-specific - jQuery selector for pane + , contentSelector: ".ui-layout-content" // INNER div/element to auto-size so only it scrolls, not the entire pane! + , contentIgnoreSelector: ".ui-layout-ignore" // element(s) to 'ignore' when measuring 'content' + , findNestedContent: false // true = $P.find(contentSelector), false = $P.children(contentSelector) + // GENERIC ROOT-CLASSES - for auto-generated classNames + , paneClass: "ui-layout-pane" // Layout Pane + , resizerClass: "ui-layout-resizer" // Resizer Bar + , togglerClass: "ui-layout-toggler" // Toggler Button + , buttonClass: "ui-layout-button" // CUSTOM Buttons - eg: '[ui-layout-button]-toggle/-open/-close/-pin' + // ELEMENT SIZE & SPACING + //, size: 100 // MUST be pane-specific -initial size of pane + , minSize: 0 // when manually resizing a pane + , maxSize: 0 // ditto, 0 = no limit + , spacing_open: 6 // space between pane and adjacent panes - when pane is 'open' + , spacing_closed: 6 // ditto - when pane is 'closed' + , togglerLength_open: 50 // Length = WIDTH of toggler button on north/south sides - HEIGHT on east/west sides + , togglerLength_closed: 50 // 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden' + , togglerAlign_open: "center" // top/left, bottom/right, center, OR... + , togglerAlign_closed: "center" // 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right + , togglerContent_open: "" // text or HTML to put INSIDE the toggler + , togglerContent_closed: "" // ditto + // RESIZING OPTIONS + , resizerDblClickToggle: true // + , autoResize: true // IF size is 'auto' or a percentage, then recalc 'pixel size' whenever the layout resizes + , autoReopen: true // IF a pane was auto-closed due to noRoom, reopen it when there is room? False = leave it closed + , resizerDragOpacity: 1 // option for ui.draggable + //, resizerCursor: "" // MUST be pane-specific - cursor when over resizer-bar + , maskContents: false // true = add DIV-mask over-or-inside this pane so can 'drag' over IFRAMES + , maskObjects: false // true = add IFRAME-mask over-or-inside this pane to cover objects/applets - content-mask will overlay this mask + , maskZindex: null // will override zIndexes.content_mask if specified - not applicable to iframe-panes + , resizingGrid: false // grid size that the resizers will snap-to during resizing, eg: [20,20] + , livePaneResizing: false // true = LIVE Resizing as resizer is dragged + , liveContentResizing: false // true = re-measure header/footer heights as resizer is dragged + , liveResizingTolerance: 1 // how many px change before pane resizes, to control performance + // SLIDING OPTIONS + , sliderCursor: "pointer" // cursor when resizer-bar will trigger 'sliding' + , slideTrigger_open: "click" // click, dblclick, mouseenter + , slideTrigger_close: "mouseleave"// click, mouseleave + , slideDelay_open: 300 // applies only for mouseenter event - 0 = instant open + , slideDelay_close: 300 // applies only for mouseleave event (300ms is the minimum!) + , hideTogglerOnSlide: false // when pane is slid-open, should the toggler show? + , preventQuickSlideClose: $.layout.browser.webkit // Chrome triggers slideClosed as it is opening + , preventPrematureSlideClose: false // handle incorrect mouseleave trigger, like when over a SELECT-list in IE + // PANE-SPECIFIC TIPS & MESSAGES + , tips: { + Open: "Open" // eg: "Open Pane" + , Close: "Close" + , Resize: "Resize" + , Slide: "Slide Open" + , Pin: "Pin" + , Unpin: "Un-Pin" + , noRoomToOpen: "Not enough room to show this panel." // alert if user tries to open a pane that cannot + , minSizeWarning: "Panel has reached its minimum size" // displays in browser statusbar + , maxSizeWarning: "Panel has reached its maximum size" // ditto + } + // HOT-KEYS & MISC + , showOverflowOnHover: false // will bind allowOverflow() utility to pane.onMouseOver + , enableCursorHotkey: true // enabled 'cursor' hotkeys + //, customHotkey: "" // MUST be pane-specific - EITHER a charCode OR a character + , customHotkeyModifier: "SHIFT" // either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT' + // PANE ANIMATION + // NOTE: fxSss_open, fxSss_close & fxSss_size options (eg: fxName_open) are auto-generated if not passed + , fxName: "slide" // ('none' or blank), slide, drop, scale -- only relevant to 'open' & 'close', NOT 'size' + , fxSpeed: null // slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration + , fxSettings: {} // can be passed, eg: { easing: "easeOutBounce", duration: 1500 } + , fxOpacityFix: true // tries to fix opacity in IE to restore anti-aliasing after animation + , animatePaneSizing: false // true = animate resizing after dragging resizer-bar OR sizePane() is called + /* NOTE: Action-specific FX options are auto-generated from the options above if not specifically set: + fxName_open: "slide" // 'Open' pane animation + fnName_close: "slide" // 'Close' pane animation + fxName_size: "slide" // 'Size' pane animation - when animatePaneSizing = true + fxSpeed_open: null + fxSpeed_close: null + fxSpeed_size: null + fxSettings_open: {} + fxSettings_close: {} + fxSettings_size: {} + */ + // CHILD/NESTED LAYOUTS + , childOptions: null // Layout-options for nested/child layout - even {} is valid as options + , initChildLayout: true // true = child layout will be created as soon as _this_ layout completes initialization + , destroyChildLayout: true // true = destroy child-layout if this pane is destroyed + , resizeChildLayout: true // true = trigger child-layout.resizeAll() when this pane is resized + // EVENT TRIGGERING + , triggerEventsOnLoad: false // true = trigger onopen OR onclose callbacks when layout initializes + , triggerEventsDuringLiveResize: true // true = trigger onresize callback REPEATEDLY if livePaneResizing==true + // PANE CALLBACKS + , onshow_start: null // CALLBACK when pane STARTS to Show - BEFORE onopen/onhide_start + , onshow_end: null // CALLBACK when pane ENDS being Shown - AFTER onopen/onhide_end + , onhide_start: null // CALLBACK when pane STARTS to Close - BEFORE onclose_start + , onhide_end: null // CALLBACK when pane ENDS being Closed - AFTER onclose_end + , onopen_start: null // CALLBACK when pane STARTS to Open + , onopen_end: null // CALLBACK when pane ENDS being Opened + , onclose_start: null // CALLBACK when pane STARTS to Close + , onclose_end: null // CALLBACK when pane ENDS being Closed + , onresize_start: null // CALLBACK when pane STARTS being Resized ***FOR ANY REASON*** + , onresize_end: null // CALLBACK when pane ENDS being Resized ***FOR ANY REASON*** + , onsizecontent_start: null // CALLBACK when sizing of content-element STARTS + , onsizecontent_end: null // CALLBACK when sizing of content-element ENDS + , onswap_start: null // CALLBACK when pane STARTS to Swap + , onswap_end: null // CALLBACK when pane ENDS being Swapped + , ondrag_start: null // CALLBACK when pane STARTS being ***MANUALLY*** Resized + , ondrag_end: null // CALLBACK when pane ENDS being ***MANUALLY*** Resized + } +/* + * PANE-SPECIFIC SETTINGS + * - options listed below MUST be specified per-pane - they CANNOT be set under 'panes' + * - all options under the 'panes' key can also be set specifically for any pane + * - most options under the 'panes' key apply only to 'border-panes' - NOT the center-pane + */ +, north: { + paneSelector: ".ui-layout-north" + , size: "auto" // eg: "auto", "30%", .30, 200 + , resizerCursor: "n-resize" // custom = url(myCursor.cur) + , customHotkey: "" // EITHER a charCode (43) OR a character ("o") + } +, south: { + paneSelector: ".ui-layout-south" + , size: "auto" + , resizerCursor: "s-resize" + , customHotkey: "" + } +, east: { + paneSelector: ".ui-layout-east" + , size: 200 + , resizerCursor: "e-resize" + , customHotkey: "" + } +, west: { + paneSelector: ".ui-layout-west" + , size: 200 + , resizerCursor: "w-resize" + , customHotkey: "" + } +, center: { + paneSelector: ".ui-layout-center" + , minWidth: 0 + , minHeight: 0 + } +}; + +$.layout.optionsMap = { + // layout/global options - NOT pane-options + layout: ("stateManagement,effects,zIndexes,errors," + + "name,zIndex,scrollToBookmarkOnLoad,showErrorMessages," + + "resizeWithWindow,resizeWithWindowDelay,resizeWithWindowMaxDelay," + + "onresizeall,onresizeall_start,onresizeall_end,onload,onunload").split(",") +// borderPanes: [ ALL options that are NOT specified as 'layout' ] + // default.panes options that apply to the center-pane (most options apply _only_ to border-panes) +, center: ("paneClass,contentSelector,contentIgnoreSelector,findNestedContent,applyDemoStyles,triggerEventsOnLoad," + + "showOverflowOnHover,maskContents,maskObjects,liveContentResizing," + + "childOptions,initChildLayout,resizeChildLayout,destroyChildLayout," + + "onresize,onresize_start,onresize_end,onsizecontent,onsizecontent_start,onsizecontent_end").split(",") + // options that MUST be specifically set 'per-pane' - CANNOT set in the panes (defaults) key +, noDefault: ("paneSelector,resizerCursor,customHotkey").split(",") +}; + +/** + * Processes options passed in converts flat-format data into subkey (JSON) format + * In flat-format, subkeys are _currently_ separated with 2 underscores, like north__optName + * Plugins may also call this method so they can transform their own data + * + * @param {!Object} hash Data/options passed by user - may be a single level or nested levels + * @return {Object} Returns hash of minWidth & minHeight + */ +$.layout.transformData = function (hash) { + var json = { panes: {}, center: {} } // init return object + , data, branch, optKey, keys, key, val, i, c; + + if (typeof hash !== "object") return json; // no options passed + + // convert all 'flat-keys' to 'sub-key' format + for (optKey in hash) { + branch = json; + data = $.layout.optionsMap.layout; + val = hash[ optKey ]; + keys = optKey.split("__"); // eg: west__size or north__fxSettings__duration + c = keys.length - 1; + // convert underscore-delimited to subkeys + for (i=0; i <= c; i++) { + key = keys[i]; + if (i === c) + branch[key] = val; + else if (!branch[key]) + branch[key] = {}; // create the subkey + // recurse to sub-key for next loop - if not done + branch = branch[key]; + } + } + + return json; +}; + +// INTERNAL CONFIG DATA - DO NOT CHANGE THIS! +$.layout.backwardCompatibility = { + // data used by renameOldOptions() + map: { + // OLD Option Name: NEW Option Name + applyDefaultStyles: "applyDemoStyles" + , resizeNestedLayout: "resizeChildLayout" + , resizeWhileDragging: "livePaneResizing" + , resizeContentWhileDragging: "liveContentResizing" + , triggerEventsWhileDragging: "triggerEventsDuringLiveResize" + , maskIframesOnResize: "maskContents" + , useStateCookie: "stateManagement.enabled" + , "cookie.autoLoad": "stateManagement.autoLoad" + , "cookie.autoSave": "stateManagement.autoSave" + , "cookie.keys": "stateManagement.stateKeys" + , "cookie.name": "stateManagement.cookie.name" + , "cookie.domain": "stateManagement.cookie.domain" + , "cookie.path": "stateManagement.cookie.path" + , "cookie.expires": "stateManagement.cookie.expires" + , "cookie.secure": "stateManagement.cookie.secure" + // OLD Language options + , noRoomToOpenTip: "tips.noRoomToOpen" + , togglerTip_open: "tips.Close" // open = Close + , togglerTip_closed: "tips.Open" // closed = Open + , resizerTip: "tips.Resize" + , sliderTip: "tips.Slide" + } + +/** +* @param {Object} opts +*/ +, renameOptions: function (opts) { + var map = $.layout.backwardCompatibility.map + , oldData, newData, value + ; + for (var itemPath in map) { + oldData = getBranch( itemPath ); + value = oldData.branch[ oldData.key ]; + if (value !== undefined) { + newData = getBranch( map[itemPath], true ); + newData.branch[ newData.key ] = value; + delete oldData.branch[ oldData.key ]; + } + } + + /** + * @param {string} path + * @param {boolean=} [create=false] Create path if does not exist + */ + function getBranch (path, create) { + var a = path.split(".") // split keys into array + , c = a.length - 1 + , D = { branch: opts, key: a[c] } // init branch at top & set key (last item) + , i = 0, k, undef; + for (; i 0) { + if (autoHide && $E.data('autoHidden') && $E.innerHeight() > 0) { + $E.show().data('autoHidden', false); + if (!browser.mozilla) // FireFox refreshes iframes - IE does not + // make hidden, then visible to 'refresh' display after animation + $E.css(_c.hidden).css(_c.visible); + } + } + else if (autoHide && !$E.data('autoHidden')) + $E.hide().data('autoHidden', true); + } + + /** + * @param {(string|!Object)} el + * @param {number=} outerHeight + * @param {boolean=} [autoHide=false] + */ +, setOuterHeight = function (el, outerHeight, autoHide) { + var $E = el, h; + if (isStr(el)) $E = $Ps[el]; // west + else if (!el.jquery) $E = $(el); + h = cssH($E, outerHeight); + $E.css({ height: h, visibility: "visible" }); // may have been 'hidden' by sizeContent + if (h > 0 && $E.innerWidth() > 0) { + if (autoHide && $E.data('autoHidden')) { + $E.show().data('autoHidden', false); + if (!browser.mozilla) // FireFox refreshes iframes - IE does not + $E.css(_c.hidden).css(_c.visible); + } + } + else if (autoHide && !$E.data('autoHidden')) + $E.hide().data('autoHidden', true); + } + + /** + * @param {(string|!Object)} el + * @param {number=} outerSize + * @param {boolean=} [autoHide=false] + */ +, setOuterSize = function (el, outerSize, autoHide) { + if (_c[pane].dir=="horz") // pane = north or south + setOuterHeight(el, outerSize, autoHide); + else // pane = east or west + setOuterWidth(el, outerSize, autoHide); + } + + + /** + * Converts any 'size' params to a pixel/integer size, if not already + * If 'auto' or a decimal/percentage is passed as 'size', a pixel-size is calculated + * + /** + * @param {string} pane + * @param {(string|number)=} size + * @param {string=} [dir] + * @return {number} + */ +, _parseSize = function (pane, size, dir) { + if (!dir) dir = _c[pane].dir; + + if (isStr(size) && size.match(/%/)) + size = (size === '100%') ? -1 : parseInt(size, 10) / 100; // convert % to decimal + + if (size === 0) + return 0; + else if (size >= 1) + return parseInt(size, 10); + + var o = options, avail = 0; + if (dir=="horz") // north or south or center.minHeight + avail = sC.innerHeight - ($Ps.north ? o.north.spacing_open : 0) - ($Ps.south ? o.south.spacing_open : 0); + else if (dir=="vert") // east or west or center.minWidth + avail = sC.innerWidth - ($Ps.west ? o.west.spacing_open : 0) - ($Ps.east ? o.east.spacing_open : 0); + + if (size === -1) // -1 == 100% + return avail; + else if (size > 0) // percentage, eg: .25 + return round(avail * size); + else if (pane=="center") + return 0; + else { // size < 0 || size=='auto' || size==Missing || size==Invalid + // auto-size the pane + var dim = (dir === "horz" ? "height" : "width") + , $P = $Ps[pane] + , $C = dim === 'height' ? $Cs[pane] : false + , vis = $.layout.showInvisibly($P) // show pane invisibly if hidden + , szP = $P.css(dim) // SAVE current pane size + , szC = $C ? $C.css(dim) : 0 // SAVE current content size + ; + $P.css(dim, "auto"); + if ($C) $C.css(dim, "auto"); + size = (dim === "height") ? $P.outerHeight() : $P.outerWidth(); // MEASURE + $P.css(dim, szP).css(vis); // RESET size & visibility + if ($C) $C.css(dim, szC); + return size; + } + } + + /** + * Calculates current 'size' (outer-width or outer-height) of a border-pane - optionally with 'pane-spacing' added + * + * @param {(string|!Object)} pane + * @param {boolean=} [inclSpace=false] + * @return {number} Returns EITHER Width for east/west panes OR Height for north/south panes + */ +, getPaneSize = function (pane, inclSpace) { + var + $P = $Ps[pane] + , o = options[pane] + , s = state[pane] + , oSp = (inclSpace ? o.spacing_open : 0) + , cSp = (inclSpace ? o.spacing_closed : 0) + ; + if (!$P || s.isHidden) + return 0; + else if (s.isClosed || (s.isSliding && inclSpace)) + return cSp; + else if (_c[pane].dir === "horz") + return $P.outerHeight() + oSp; + else // dir === "vert" + return $P.outerWidth() + oSp; + } + + /** + * Calculate min/max pane dimensions and limits for resizing + * + * @param {string} pane + * @param {boolean=} [slide=false] + */ +, setSizeLimits = function (pane, slide) { + if (!isInitialized()) return; + var + o = options[pane] + , s = state[pane] + , c = _c[pane] + , dir = c.dir + , side = c.side.toLowerCase() + , type = c.sizeType.toLowerCase() + , isSliding = (slide != undefined ? slide : s.isSliding) // only open() passes 'slide' param + , $P = $Ps[pane] + , paneSpacing = o.spacing_open + // measure the pane on the *opposite side* from this pane + , altPane = _c.oppositeEdge[pane] + , altS = state[altPane] + , $altP = $Ps[altPane] + , altPaneSize = (!$altP || altS.isVisible===false || altS.isSliding ? 0 : (dir=="horz" ? $altP.outerHeight() : $altP.outerWidth())) + , altPaneSpacing = ((!$altP || altS.isHidden ? 0 : options[altPane][ altS.isClosed !== false ? "spacing_closed" : "spacing_open" ]) || 0) + // limitSize prevents this pane from 'overlapping' opposite pane + , containerSize = (dir=="horz" ? sC.innerHeight : sC.innerWidth) + , minCenterDims = cssMinDims("center") + , minCenterSize = dir=="horz" ? max(options.center.minHeight, minCenterDims.minHeight) : max(options.center.minWidth, minCenterDims.minWidth) + // if pane is 'sliding', then ignore center and alt-pane sizes - because 'overlays' them + , limitSize = (containerSize - paneSpacing - (isSliding ? 0 : (_parseSize("center", minCenterSize, dir) + altPaneSize + altPaneSpacing))) + , minSize = s.minSize = max( _parseSize(pane, o.minSize), cssMinDims(pane).minSize ) + , maxSize = s.maxSize = min( (o.maxSize ? _parseSize(pane, o.maxSize) : 100000), limitSize ) + , r = s.resizerPosition = {} // used to set resizing limits + , top = sC.insetTop + , left = sC.insetLeft + , W = sC.innerWidth + , H = sC.innerHeight + , rW = o.spacing_open // subtract resizer-width to get top/left position for south/east + ; + switch (pane) { + case "north": r.min = top + minSize; + r.max = top + maxSize; + break; + case "west": r.min = left + minSize; + r.max = left + maxSize; + break; + case "south": r.min = top + H - maxSize - rW; + r.max = top + H - minSize - rW; + break; + case "east": r.min = left + W - maxSize - rW; + r.max = left + W - minSize - rW; + break; + }; + } + + /** + * Returns data for setting the size/position of center pane. Also used to set Height for east/west panes + * + * @return JSON Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height + */ +, calcNewCenterPaneDims = function () { + var d = { + top: getPaneSize("north", true) // true = include 'spacing' value for pane + , bottom: getPaneSize("south", true) + , left: getPaneSize("west", true) + , right: getPaneSize("east", true) + , width: 0 + , height: 0 + }; + + // NOTE: sC = state.container + // calc center-pane outer dimensions + d.width = sC.innerWidth - d.left - d.right; // outerWidth + d.height = sC.innerHeight - d.bottom - d.top; // outerHeight + // add the 'container border/padding' to get final positions relative to the container + d.top += sC.insetTop; + d.bottom += sC.insetBottom; + d.left += sC.insetLeft; + d.right += sC.insetRight; + + return d; + } + + + /** + * @param {!Object} el + * @param {boolean=} [allStates=false] + */ +, getHoverClasses = function (el, allStates) { + var + $El = $(el) + , type = $El.data("layoutRole") + , pane = $El.data("layoutEdge") + , o = options[pane] + , root = o[type +"Class"] + , _pane = "-"+ pane // eg: "-west" + , _open = "-open" + , _closed = "-closed" + , _slide = "-sliding" + , _hover = "-hover " // NOTE the trailing space + , _state = $El.hasClass(root+_closed) ? _closed : _open + , _alt = _state === _closed ? _open : _closed + , classes = (root+_hover) + (root+_pane+_hover) + (root+_state+_hover) + (root+_pane+_state+_hover) + ; + if (allStates) // when 'removing' classes, also remove alternate-state classes + classes += (root+_alt+_hover) + (root+_pane+_alt+_hover); + + if (type=="resizer" && $El.hasClass(root+_slide)) + classes += (root+_slide+_hover) + (root+_pane+_slide+_hover); + + return $.trim(classes); + } +, addHover = function (evt, el) { + var $E = $(el || this); + if (evt && $E.data("layoutRole") === "toggler") + evt.stopPropagation(); // prevent triggering 'slide' on Resizer-bar + $E.addClass( getHoverClasses($E) ); + } +, removeHover = function (evt, el) { + var $E = $(el || this); + $E.removeClass( getHoverClasses($E, true) ); + } + +, onResizerEnter = function (evt) { // ALSO called by toggler.mouseenter + if ($.fn.disableSelection) + $("body").disableSelection(); + } +, onResizerLeave = function (evt, el) { + var + e = el || this // el is only passed when called by the timer + , pane = $(e).data("layoutEdge") + , name = pane +"ResizerLeave" + ; + timer.clear(pane+"_openSlider"); // cancel slideOpen timer, if set + timer.clear(name); // cancel enableSelection timer - may re/set below + // this method calls itself on a timer because it needs to allow + // enough time for dragging to kick-in and set the isResizing flag + // dragging has a 100ms delay set, so this delay must be >100 + if (!el) // 1st call - mouseleave event + timer.set(name, function(){ onResizerLeave(evt, e); }, 200); + // if user is resizing, then dragStop will enableSelection(), so can skip it here + else if (!state[pane].isResizing && $.fn.enableSelection) // 2nd call - by timer + $("body").enableSelection(); + } + +/* + * ########################### + * INITIALIZATION METHODS + * ########################### + */ + + /** + * Initialize the layout - called automatically whenever an instance of layout is created + * + * @see none - triggered onInit + * @return mixed true = fully initialized | false = panes not initialized (yet) | 'cancel' = abort + */ +, _create = function () { + // initialize config/options + initOptions(); + var o = options; + + // TEMP state so isInitialized returns true during init process + state.creatingLayout = true; + + // init plugins for this layout, if there are any (eg: stateManagement) + runPluginCallbacks( Instance, $.layout.onCreate ); + + // options & state have been initialized, so now run beforeLoad callback + // onload will CANCEL layout creation if it returns false + if (false === _runCallbacks("onload_start")) + return 'cancel'; + + // initialize the container element + _initContainer(); + + // bind hotkey function - keyDown - if required + initHotkeys(); + + // bind window.onunload + $(window).bind("unload."+ sID, unload); + + // init plugins for this layout, if there are any (eg: customButtons) + runPluginCallbacks( Instance, $.layout.onLoad ); + + // if layout elements are hidden, then layout WILL NOT complete initialization! + // initLayoutElements will set initialized=true and run the onload callback IF successful + if (o.initPanes) _initLayoutElements(); + + delete state.creatingLayout; + + return state.initialized; + } + + /** + * Initialize the layout IF not already + * + * @see All methods in Instance run this test + * @return boolean true = layoutElements have been initialized | false = panes are not initialized (yet) + */ +, isInitialized = function () { + if (state.initialized || state.creatingLayout) return true; // already initialized + else return _initLayoutElements(); // try to init panes NOW + } + + /** + * Initialize the layout - called automatically whenever an instance of layout is created + * + * @see _create() & isInitialized + * @return An object pointer to the instance created + */ +, _initLayoutElements = function (retry) { + // initialize config/options + var o = options; + + // CANNOT init panes inside a hidden container! + if (!$N.is(":visible")) { + // handle Chrome bug where popup window 'has no height' + // if layout is BODY element, try again in 50ms + // SEE: http://layout.jquery-dev.net/samples/test_popup_window.html + if ( !retry && browser.webkit && $N[0].tagName === "BODY" ) + setTimeout(function(){ _initLayoutElements(true); }, 50); + return false; + } + + // a center pane is required, so make sure it exists + if (!getPane("center").length) { + return _log( o.errors.centerPaneMissing ); + } + + // TEMP state so isInitialized returns true during init process + state.creatingLayout = true; + + // update Container dims + $.extend(sC, elDims( $N )); + + // initialize all layout elements + initPanes(); // size & position panes - calls initHandles() - which calls initResizable() + + if (o.scrollToBookmarkOnLoad) { + var l = self.location; + if (l.hash) l.replace( l.hash ); // scrollTo Bookmark + } + + // check to see if this layout 'nested' inside a pane + if (Instance.hasParentLayout) + o.resizeWithWindow = false; + // bind resizeAll() for 'this layout instance' to window.resize event + else if (o.resizeWithWindow) + $(window).bind("resize."+ sID, windowResize); + + delete state.creatingLayout; + state.initialized = true; + + // init plugins for this layout, if there are any + runPluginCallbacks( Instance, $.layout.onReady ); + + // now run the onload callback, if exists + _runCallbacks("onload_end"); + + return true; // elements initialized successfully + } + + /** + * Initialize nested layouts - called when _initLayoutElements completes + * + * NOT CURRENTLY USED + * + * @see _initLayoutElements + * @return An object pointer to the instance created + */ +, _initChildLayouts = function () { + $.each(_c.allPanes, function (idx, pane) { + if (options[pane].initChildLayout) + createChildLayout( pane ); + }); + } + + /** + * Initialize nested layouts for a specific pane - can optionally pass layout-options + * + * @see _initChildLayouts + * @param {string|Object} evt_or_pane The pane being opened, ie: north, south, east, or west + * @param {Object=} [opts] Layout-options - if passed, will OVERRRIDE options[pane].childOptions + * @return An object pointer to the layout instance created - or null + */ +, createChildLayout = function (evt_or_pane, opts) { + var pane = evtPane.call(this, evt_or_pane) + , $P = $Ps[pane] + , C = children + ; + if ($P) { + var $C = $Cs[pane] + , o = opts || options[pane].childOptions + , d = "layout" + // determine which element is supposed to be the 'child container' + // if pane has a 'containerSelector' OR a 'content-div', use those instead of the pane + , $Cont = o.containerSelector ? $P.find( o.containerSelector ) : ($C || $P) + , containerFound = $Cont.length + // see if a child-layout ALREADY exists on this element + , child = containerFound ? (C[pane] = $Cont.data(d) || null) : null + ; + // if no layout exists, but childOptions are set, try to create the layout now + if (!child && containerFound && o) + child = C[pane] = $Cont.eq(0).layout(o) || null; + if (child) + child.hasParentLayout = true; // set parent-flag in child + } + Instance[pane].child = C[pane]; // ALWAYS set pane-object pointer, even if null + } + +, windowResize = function () { + var delay = Number(options.resizeWithWindowDelay); + if (delay < 10) delay = 100; // MUST have a delay! + // resizing uses a delay-loop because the resize event fires repeatly - except in FF, but delay anyway + timer.clear("winResize"); // if already running + timer.set("winResize", function(){ + timer.clear("winResize"); + timer.clear("winResizeRepeater"); + var dims = elDims( $N ); + // only trigger resizeAll() if container has changed size + if (dims.innerWidth !== sC.innerWidth || dims.innerHeight !== sC.innerHeight) + resizeAll(); + }, delay); + // ALSO set fixed-delay timer, if not already running + if (!timer.data["winResizeRepeater"]) setWindowResizeRepeater(); + } + +, setWindowResizeRepeater = function () { + var delay = Number(options.resizeWithWindowMaxDelay); + if (delay > 0) + timer.set("winResizeRepeater", function(){ setWindowResizeRepeater(); resizeAll(); }, delay); + } + +, unload = function () { + var o = options; + + _runCallbacks("onunload_start"); + + // trigger plugin callabacks for this layout (eg: stateManagement) + runPluginCallbacks( Instance, $.layout.onUnload ); + + _runCallbacks("onunload_end"); + } + + /** + * Validate and initialize container CSS and events + * + * @see _create() + */ +, _initContainer = function () { + var + N = $N[0] + , tag = sC.tagName = N.tagName + , id = sC.id = N.id + , cls = sC.className = N.className + , o = options + , name = o.name + , fullPage= (tag === "BODY") + , props = "overflow,position,margin,padding,border" + , css = "layoutCSS" + , CSS = {} + , hid = "hidden" // used A LOT! + // see if this container is a 'pane' inside an outer-layout + , parent = $N.data("parentLayout") // parent-layout Instance + , pane = $N.data("layoutEdge") // pane-name in parent-layout + , isChild = parent && pane + ; + // sC -> state.container + sC.selector = $N.selector.split(".slice")[0]; + sC.ref = (o.name ? o.name +' layout / ' : '') + tag + (id ? "#"+id : cls ? '.['+cls+']' : ''); // used in messages + + $N .data({ + layout: Instance + , layoutContainer: sID // FLAG to indicate this is a layout-container - contains unique internal ID + }) + .addClass(o.containerClass) + ; + var layoutMethods = { + destroy: '' + , initPanes: '' + , resizeAll: 'resizeAll' + , resize: 'resizeAll' + }; + // loop hash and bind all methods - include layoutID namespacing + for (name in layoutMethods) { + $N.bind("layout"+ name.toLowerCase() +"."+ sID, Instance[ layoutMethods[name] || name ]); + } + + // if this container is another layout's 'pane', then set child/parent pointers + if (isChild) { + // update parent flag + Instance.hasParentLayout = true; + // set pointers to THIS child-layout (Instance) in parent-layout + // NOTE: parent.PANE.child is an ALIAS to parent.children.PANE + parent[pane].child = parent.children[pane] = $N.data("layout"); + } + + // SAVE original container CSS for use in destroy() + if (!$N.data(css)) { + // handle props like overflow different for BODY & HTML - has 'system default' values + if (fullPage) { + CSS = $.extend( elCSS($N, props), { + height: $N.css("height") + , overflow: $N.css("overflow") + , overflowX: $N.css("overflowX") + , overflowY: $N.css("overflowY") + }); + // ALSO SAVE CSS + var $H = $("html"); + $H.data(css, { + height: "auto" // FF would return a fixed px-size! + , overflow: $H.css("overflow") + , overflowX: $H.css("overflowX") + , overflowY: $H.css("overflowY") + }); + } + else // handle props normally for non-body elements + CSS = elCSS($N, props+",top,bottom,left,right,width,height,overflow,overflowX,overflowY"); + + $N.data(css, CSS); + } + + try { // format html/body if this is a full page layout + if (fullPage) { + $("html").css({ + height: "100%" + , overflow: hid + , overflowX: hid + , overflowY: hid + }); + $("body").css({ + position: "relative" + , height: "100%" + , overflow: hid + , overflowX: hid + , overflowY: hid + , margin: 0 + , padding: 0 // TODO: test whether body-padding could be handled? + , border: "none" // a body-border creates problems because it cannot be measured! + }); + + // set current layout-container dimensions + $.extend(sC, elDims( $N )); + } + else { // set required CSS for overflow and position + // ENSURE container will not 'scroll' + CSS = { overflow: hid, overflowX: hid, overflowY: hid } + var + p = $N.css("position") + , h = $N.css("height") + ; + // if this is a NESTED layout, then container/outer-pane ALREADY has position and height + if (!isChild) { + if (!p || !p.match(/fixed|absolute|relative/)) + CSS.position = "relative"; // container MUST have a 'position' + /* + if (!h || h=="auto") + CSS.height = "100%"; // container MUST have a 'height' + */ + } + $N.css( CSS ); + + // set current layout-container dimensions + if ( $N.is(":visible") ) { + $.extend(sC, elDims( $N )); + if (sC.innerHeight < 1) + _log( o.errors.noContainerHeight.replace(/CONTAINER/, sC.ref) ); + } + } + } catch (ex) {} + } + + /** + * Bind layout hotkeys - if options enabled + * + * @see _create() and addPane() + * @param {string=} [panes=""] The edge(s) to process + */ +, initHotkeys = function (panes) { + panes = panes ? panes.split(",") : _c.borderPanes; + // bind keyDown to capture hotkeys, if option enabled for ANY pane + $.each(panes, function (i, pane) { + var o = options[pane]; + if (o.enableCursorHotkey || o.customHotkey) { + $(document).bind("keydown."+ sID, keyDown); // only need to bind this ONCE + return false; // BREAK - binding was done + } + }); + } + + /** + * Build final OPTIONS data + * + * @see _create() + */ +, initOptions = function () { + var data, d, pane, key, val, i, c, o; + + // reprocess user's layout-options to have correct options sub-key structure + opts = $.layout.transformData( opts ); // panes = default subkey + + // auto-rename old options for backward compatibility + opts = $.layout.backwardCompatibility.renameAllOptions( opts ); + + // if user-options has 'panes' key (pane-defaults), clean it... + if (!$.isEmptyObject(opts.panes)) { + // REMOVE any pane-defaults that MUST be set per-pane + data = $.layout.optionsMap.noDefault; + for (i=0, c=data.length; i 0) { + z.pane_normal = zo; + z.content_mask = max(zo+1, z.content_mask); // MIN = +1 + z.resizer_normal = max(zo+2, z.resizer_normal); // MIN = +2 + } + + // DELETE 'panes' key now that we are done - values were copied to EACH pane + delete options.panes; + + + function createFxOptions ( pane ) { + var o = options[pane] + , d = options.panes; + // ensure fxSettings key to avoid errors + if (!o.fxSettings) o.fxSettings = {}; + if (!d.fxSettings) d.fxSettings = {}; + + $.each(["_open","_close","_size"], function (i,n) { + var + sName = "fxName"+ n + , sSpeed = "fxSpeed"+ n + , sSettings = "fxSettings"+ n + // recalculate fxName according to specificity rules + , fxName = o[sName] = + o[sName] // options.west.fxName_open + || d[sName] // options.panes.fxName_open + || o.fxName // options.west.fxName + || d.fxName // options.panes.fxName + || "none" // MEANS $.layout.defaults.panes.fxName == "" || false || null || 0 + ; + // validate fxName to ensure is valid effect - MUST have effect-config data in options.effects + if (fxName === "none" || !$.effects || !$.effects[fxName] || !options.effects[fxName]) + fxName = o[sName] = "none"; // effect not loaded OR unrecognized fxName + + // set vars for effects subkeys to simplify logic + var fx = options.effects[fxName] || {} // effects.slide + , fx_all = fx.all || null // effects.slide.all + , fx_pane = fx[pane] || null // effects.slide.west + ; + // create fxSpeed[_open|_close|_size] + o[sSpeed] = + o[sSpeed] // options.west.fxSpeed_open + || d[sSpeed] // options.west.fxSpeed_open + || o.fxSpeed // options.west.fxSpeed + || d.fxSpeed // options.panes.fxSpeed + || null // DEFAULT - let fxSetting.duration control speed + ; + // create fxSettings[_open|_close|_size] + o[sSettings] = $.extend( + true + , {} + , fx_all // effects.slide.all + , fx_pane // effects.slide.west + , d.fxSettings // options.panes.fxSettings + , o.fxSettings // options.west.fxSettings + , d[sSettings] // options.panes.fxSettings_open + , o[sSettings] // options.west.fxSettings_open + ); + }); + + // DONE creating action-specific-settings for this pane, + // so DELETE generic options - are no longer meaningful + delete o.fxName; + delete o.fxSpeed; + delete o.fxSettings; + } + } + + /** + * Initialize module objects, styling, size and position for all panes + * + * @see _initElements() + * @param {string} pane The pane to process + */ +, getPane = function (pane) { + var sel = options[pane].paneSelector + if (sel.substr(0,1)==="#") // ID selector + // NOTE: elements selected 'by ID' DO NOT have to be 'children' + return $N.find(sel).eq(0); + else { // class or other selector + var $P = $N.children(sel).eq(0); + // look for the pane nested inside a 'form' element + return $P.length ? $P : $N.children("form:first").children(sel).eq(0); + } + } + +, initPanes = function (evt) { + // stopPropagation if called by trigger("layoutinitpanes") - use evtPane utility + evtPane(evt); + + // NOTE: do north & south FIRST so we can measure their height - do center LAST + $.each(_c.allPanes, function (idx, pane) { + addPane( pane, true ); + }); + + // init the pane-handles NOW in case we have to hide or close the pane below + initHandles(); + + // now that all panes have been initialized and initially-sized, + // make sure there is really enough space available for each pane + $.each(_c.borderPanes, function (i, pane) { + if ($Ps[pane] && state[pane].isVisible) { // pane is OPEN + setSizeLimits(pane); + makePaneFit(pane); // pane may be Closed, Hidden or Resized by makePaneFit() + } + }); + // size center-pane AGAIN in case we 'closed' a border-pane in loop above + sizeMidPanes("center"); + + // Chrome/Webkit sometimes fires callbacks BEFORE it completes resizing! + // Before RC30.3, there was a 10ms delay here, but that caused layout + // to load asynchrously, which is BAD, so try skipping delay for now + + // process pane contents and callbacks, and init/resize child-layout if exists + $.each(_c.allPanes, function (i, pane) { + var o = options[pane]; + if ($Ps[pane]) { + if (state[pane].isVisible) { // pane is OPEN + sizeContent(pane); + // trigger pane.onResize if triggerEventsOnLoad = true + if (o.triggerEventsOnLoad) + _runCallbacks("onresize_end", pane); + else // automatic if onresize called, otherwise call it specifically + // resize child - IF inner-layout already exists (created before this layout) + resizeChildLayout(pane); + } + // init childLayout - even if pane is not visible + if (o.initChildLayout && o.childOptions) + createChildLayout(pane); + } + }); + } + + /** + * Add a pane to the layout - subroutine of initPanes() + * + * @see initPanes() + * @param {string} pane The pane to process + * @param {boolean=} [force=false] Size content after init + */ +, addPane = function (pane, force) { + if (!force && !isInitialized()) return; + var + o = options[pane] + , s = state[pane] + , c = _c[pane] + , fx = s.fx + , dir = c.dir + , spacing = o.spacing_open || 0 + , isCenter = (pane === "center") + , CSS = {} + , $P = $Ps[pane] + , size, minSize, maxSize + ; + // if pane-pointer already exists, remove the old one first + if ($P) + removePane( pane, false, true, false ); + else + $Cs[pane] = false; // init + + $P = $Ps[pane] = getPane(pane); + if (!$P.length) { + $Ps[pane] = false; // logic + return; + } + + // SAVE original Pane CSS + if (!$P.data("layoutCSS")) { + var props = "position,top,left,bottom,right,width,height,overflow,zIndex,display,backgroundColor,padding,margin,border"; + $P.data("layoutCSS", elCSS($P, props)); + } + + // create alias for pane data in Instance - initHandles will add more + Instance[pane] = { name: pane, pane: $Ps[pane], content: $Cs[pane], options: options[pane], state: state[pane], child: children[pane] }; + + // add classes, attributes & events + $P .data({ + parentLayout: Instance // pointer to Layout Instance + , layoutPane: Instance[pane] // NEW pointer to pane-alias-object + , layoutEdge: pane + , layoutRole: "pane" + }) + .css(c.cssReq).css("zIndex", options.zIndexes.pane_normal) + .css(o.applyDemoStyles ? c.cssDemo : {}) // demo styles + .addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector' + .bind("mouseenter."+ sID, addHover ) + .bind("mouseleave."+ sID, removeHover ) + ; + var paneMethods = { + hide: '' + , show: '' + , toggle: '' + , close: '' + , open: '' + , slideOpen: '' + , slideClose: '' + , slideToggle: '' + , size: 'sizePane' + , sizePane: 'sizePane' + , sizeContent: '' + , sizeHandles: '' + , enableClosable: '' + , disableClosable: '' + , enableSlideable: '' + , disableSlideable: '' + , enableResizable: '' + , disableResizable: '' + , swapPanes: 'swapPanes' + , swap: 'swapPanes' + , move: 'swapPanes' + , removePane: 'removePane' + , remove: 'removePane' + , createChildLayout: '' + , resizeChildLayout: '' + , resizeAll: 'resizeAll' + , resizeLayout: 'resizeAll' + } + , name; + // loop hash and bind all methods - include layoutID namespacing + for (name in paneMethods) { + $P.bind("layoutpane"+ name.toLowerCase() +"."+ sID, Instance[ paneMethods[name] || name ]); + } + + // see if this pane has a 'scrolling-content element' + initContent(pane, false); // false = do NOT sizeContent() - called later + + if (!isCenter) { + // call _parseSize AFTER applying pane classes & styles - but before making visible (if hidden) + // if o.size is auto or not valid, then MEASURE the pane and use that as its 'size' + size = s.size = _parseSize(pane, o.size); + minSize = _parseSize(pane,o.minSize) || 1; + maxSize = _parseSize(pane,o.maxSize) || 100000; + if (size > 0) size = max(min(size, maxSize), minSize); + + // state for border-panes + s.isClosed = false; // true = pane is closed + s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes + s.isResizing= false; // true = pane is in process of being resized + s.isHidden = false; // true = pane is hidden - no spacing, resizer or toggler is visible! + + // array for 'pin buttons' whose classNames are auto-updated on pane-open/-close + if (!s.pins) s.pins = []; + } + // states common to ALL panes + s.tagName = $P[0].tagName; + s.edge = pane; // useful if pane is (or about to be) 'swapped' - easy find out where it is (or is going) + s.noRoom = false; // true = pane 'automatically' hidden due to insufficient room - will unhide automatically + s.isVisible = true; // false = pane is invisible - closed OR hidden - simplify logic + + // set css-position to account for container borders & padding + switch (pane) { + case "north": CSS.top = sC.insetTop; + CSS.left = sC.insetLeft; + CSS.right = sC.insetRight; + break; + case "south": CSS.bottom = sC.insetBottom; + CSS.left = sC.insetLeft; + CSS.right = sC.insetRight; + break; + case "west": CSS.left = sC.insetLeft; // top, bottom & height set by sizeMidPanes() + break; + case "east": CSS.right = sC.insetRight; // ditto + break; + case "center": // top, left, width & height set by sizeMidPanes() + } + + if (dir === "horz") // north or south pane + CSS.height = cssH($P, size); + else if (dir === "vert") // east or west pane + CSS.width = cssW($P, size); + //else if (isCenter) {} + + $P.css(CSS); // apply size -- top, bottom & height will be set by sizeMidPanes + if (dir != "horz") sizeMidPanes(pane, true); // true = skipCallback + + // close or hide the pane if specified in settings + if (o.initClosed && o.closable && !o.initHidden) + close(pane, true, true); // true, true = force, noAnimation + else if (o.initHidden || o.initClosed) + hide(pane); // will be completely invisible - no resizer or spacing + else if (!s.noRoom) + // make the pane visible - in case was initially hidden + $P.css("display","block"); + // ELSE setAsOpen() - called later by initHandles() + + // RESET visibility now - pane will appear IF display:block + $P.css("visibility","visible"); + + // check option for auto-handling of pop-ups & drop-downs + if (o.showOverflowOnHover) + $P.hover( allowOverflow, resetOverflow ); + + // if manually adding a pane AFTER layout initialization, then... + if (state.initialized) { + initHandles( pane ); + initHotkeys( pane ); + resizeAll(); // will sizeContent if pane is visible + if (s.isVisible) { // pane is OPEN + if (o.triggerEventsOnLoad) + _runCallbacks("onresize_end", pane); + else // automatic if onresize called, otherwise call it specifically + // resize child - IF inner-layout already exists (created before this layout) + resizeChildLayout(pane); // a previously existing childLayout + } + if (o.initChildLayout && o.childOptions) + createChildLayout(pane); + } + } + + /** + * Initialize module objects, styling, size and position for all resize bars and toggler buttons + * + * @see _create() + * @param {string=} [panes=""] The edge(s) to process + */ +, initHandles = function (panes) { + panes = panes ? panes.split(",") : _c.borderPanes; + + // create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV + $.each(panes, function (i, pane) { + var $P = $Ps[pane]; + $Rs[pane] = false; // INIT + $Ts[pane] = false; + if (!$P) return; // pane does not exist - skip + + var + o = options[pane] + , s = state[pane] + , c = _c[pane] + , paneId = o.paneSelector.substr(0,1) === "#" ? o.paneSelector.substr(1) : "" + , rClass = o.resizerClass + , tClass = o.togglerClass + , side = c.side.toLowerCase() + , spacing = (s.isVisible ? o.spacing_open : o.spacing_closed) + , _pane = "-"+ pane // used for classNames + , _state = (s.isVisible ? "-open" : "-closed") // used for classNames + , I = Instance[pane] + // INIT RESIZER BAR + , $R = I.resizer = $Rs[pane] = $("
              ") + // INIT TOGGLER BUTTON + , $T = I.toggler = (o.closable ? $Ts[pane] = $("
              ") : false) + ; + + //if (s.isVisible && o.resizable) ... handled by initResizable + if (!s.isVisible && o.slidable) + $R.attr("title", o.tips.Slide).css("cursor", o.sliderCursor); + + $R // if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer" + .attr("id", paneId ? paneId +"-resizer" : "" ) + .data({ + parentLayout: Instance + , layoutPane: Instance[pane] // NEW pointer to pane-alias-object + , layoutEdge: pane + , layoutRole: "resizer" + }) + .css(_c.resizers.cssReq).css("zIndex", options.zIndexes.resizer_normal) + .css(o.applyDemoStyles ? _c.resizers.cssDemo : {}) // add demo styles + .addClass(rClass +" "+ rClass+_pane) + .hover(addHover, removeHover) // ALWAYS add hover-classes, even if resizing is not enabled - handle with CSS instead + .hover(onResizerEnter, onResizerLeave) // ALWAYS NEED resizer.mouseleave to balance toggler.mouseenter + .appendTo($N) // append DIV to container + ; + + if ($T) { + $T // if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "#paneLeft-toggler" + .attr("id", paneId ? paneId +"-toggler" : "" ) + .data({ + parentLayout: Instance + , layoutPane: Instance[pane] // NEW pointer to pane-alias-object + , layoutEdge: pane + , layoutRole: "toggler" + }) + .css(_c.togglers.cssReq) // add base/required styles + .css(o.applyDemoStyles ? _c.togglers.cssDemo : {}) // add demo styles + .addClass(tClass +" "+ tClass+_pane) + .hover(addHover, removeHover) // ALWAYS add hover-classes, even if toggling is not enabled - handle with CSS instead + .bind("mouseenter", onResizerEnter) // NEED toggler.mouseenter because mouseenter MAY NOT fire on resizer + .appendTo($R) // append SPAN to resizer DIV + ; + // ADD INNER-SPANS TO TOGGLER + if (o.togglerContent_open) // ui-layout-open + $(""+ o.togglerContent_open +"") + .data({ + layoutEdge: pane + , layoutRole: "togglerContent" + }) + .data("layoutRole", "togglerContent") + .data("layoutEdge", pane) + .addClass("content content-open") + .css("display","none") + .appendTo( $T ) + //.hover( addHover, removeHover ) // use ui-layout-toggler-west-hover .content-open instead! + ; + if (o.togglerContent_closed) // ui-layout-closed + $(""+ o.togglerContent_closed +"") + .data({ + layoutEdge: pane + , layoutRole: "togglerContent" + }) + .addClass("content content-closed") + .css("display","none") + .appendTo( $T ) + //.hover( addHover, removeHover ) // use ui-layout-toggler-west-hover .content-closed instead! + ; + // ADD TOGGLER.click/.hover + enableClosable(pane); + } + + // add Draggable events + initResizable(pane); + + // ADD CLASSNAMES & SLIDE-BINDINGS - eg: class="resizer resizer-west resizer-open" + if (s.isVisible) + setAsOpen(pane); // onOpen will be called, but NOT onResize + else { + setAsClosed(pane); // onClose will be called + bindStartSlidingEvent(pane, true); // will enable events IF option is set + } + + }); + + // SET ALL HANDLE DIMENSIONS + sizeHandles(); + } + + + /** + * Initialize scrolling ui-layout-content div - if exists + * + * @see initPane() - or externally after an Ajax injection + * @param {string} [pane] The pane to process + * @param {boolean=} [resize=true] Size content after init + */ +, initContent = function (pane, resize) { + if (!isInitialized()) return; + var + o = options[pane] + , sel = o.contentSelector + , I = Instance[pane] + , $P = $Ps[pane] + , $C + ; + if (sel) $C = I.content = $Cs[pane] = (o.findNestedContent) + ? $P.find(sel).eq(0) // match 1-element only + : $P.children(sel).eq(0) + ; + if ($C && $C.length) { + $C.data("layoutRole", "content"); + // SAVE original Pane CSS + if (!$C.data("layoutCSS")) + $C.data("layoutCSS", elCSS($C, "height")); + $C.css( _c.content.cssReq ); + if (o.applyDemoStyles) { + $C.css( _c.content.cssDemo ); // add padding & overflow: auto to content-div + $P.css( _c.content.cssDemoPane ); // REMOVE padding/scrolling from pane + } + state[pane].content = {}; // init content state + if (resize !== false) sizeContent(pane); + // sizeContent() is called AFTER init of all elements + } + else + I.content = $Cs[pane] = false; + } + + + /** + * Add resize-bars to all panes that specify it in options + * -dependancy: $.fn.resizable - will skip if not found + * + * @see _create() + * @param {string=} [panes=""] The edge(s) to process + */ +, initResizable = function (panes) { + var draggingAvailable = $.layout.plugins.draggable + , side // set in start() + ; + panes = panes ? panes.split(",") : _c.borderPanes; + + $.each(panes, function (idx, pane) { + var o = options[pane]; + if (!draggingAvailable || !$Ps[pane] || !o.resizable) { + o.resizable = false; + return true; // skip to next + } + + var s = state[pane] + , z = options.zIndexes + , c = _c[pane] + , side = c.dir=="horz" ? "top" : "left" + , opEdge = _c.oppositeEdge[pane] + , masks = pane +",center,"+ opEdge + (c.dir=="horz" ? ",west,east" : "") + , $P = $Ps[pane] + , $R = $Rs[pane] + , base = o.resizerClass + , lastPos = 0 // used when live-resizing + , r, live // set in start because may change + // 'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process + , resizerClass = base+"-drag" // resizer-drag + , resizerPaneClass = base+"-"+pane+"-drag" // resizer-north-drag + // 'helper' class is applied to the CLONED resizer-bar while it is being dragged + , helperClass = base+"-dragging" // resizer-dragging + , helperPaneClass = base+"-"+pane+"-dragging" // resizer-north-dragging + , helperLimitClass = base+"-dragging-limit" // resizer-drag + , helperPaneLimitClass = base+"-"+pane+"-dragging-limit" // resizer-north-drag + , helperClassesSet = false // logic var + ; + + if (!s.isClosed) + $R.attr("title", o.tips.Resize) + .css("cursor", o.resizerCursor); // n-resize, s-resize, etc + + $R.draggable({ + containment: $N[0] // limit resizing to layout container + , axis: (c.dir=="horz" ? "y" : "x") // limit resizing to horz or vert axis + , delay: 0 + , distance: 1 + , grid: o.resizingGrid + // basic format for helper - style it using class: .ui-draggable-dragging + , helper: "clone" + , opacity: o.resizerDragOpacity + , addClasses: false // avoid ui-state-disabled class when disabled + //, iframeFix: o.draggableIframeFix // TODO: consider using when bug is fixed + , zIndex: z.resizer_drag + + , start: function (e, ui) { + // REFRESH options & state pointers in case we used swapPanes + o = options[pane]; + s = state[pane]; + // re-read options + live = o.livePaneResizing; + + // ondrag_start callback - will CANCEL hide if returns false + // TODO: dragging CANNOT be cancelled like this, so see if there is a way? + if (false === _runCallbacks("ondrag_start", pane)) return false; + + s.isResizing = true; // prevent pane from closing while resizing + timer.clear(pane+"_closeSlider"); // just in case already triggered + + // SET RESIZER LIMITS - used in drag() + setSizeLimits(pane); // update pane/resizer state + r = s.resizerPosition; + lastPos = ui.position[ side ] + + $R.addClass( resizerClass +" "+ resizerPaneClass ); // add drag classes + helperClassesSet = false; // reset logic var - see drag() + + // DISABLE TEXT SELECTION (probably already done by resizer.mouseOver) + $('body').disableSelection(); + + // MASK PANES CONTAINING IFRAMES, APPLETS OR OTHER TROUBLESOME ELEMENTS + showMasks( masks ); + } + + , drag: function (e, ui) { + if (!helperClassesSet) { // can only add classes after clone has been added to the DOM + //$(".ui-draggable-dragging") + ui.helper + .addClass( helperClass +" "+ helperPaneClass ) // add helper classes + .css({ right: "auto", bottom: "auto" }) // fix dir="rtl" issue + .children().css("visibility","hidden") // hide toggler inside dragged resizer-bar + ; + helperClassesSet = true; + // draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane! + if (s.isSliding) $Ps[pane].css("zIndex", z.pane_sliding); + } + // CONTAIN RESIZER-BAR TO RESIZING LIMITS + var limit = 0; + if (ui.position[side] < r.min) { + ui.position[side] = r.min; + limit = -1; + } + else if (ui.position[side] > r.max) { + ui.position[side] = r.max; + limit = 1; + } + // ADD/REMOVE dragging-limit CLASS + if (limit) { + ui.helper.addClass( helperLimitClass +" "+ helperPaneLimitClass ); // at dragging-limit + window.defaultStatus = (limit>0 && pane.match(/(north|west)/)) || (limit<0 && pane.match(/(south|east)/)) ? o.tips.maxSizeWarning : o.tips.minSizeWarning; + } + else { + ui.helper.removeClass( helperLimitClass +" "+ helperPaneLimitClass ); // not at dragging-limit + window.defaultStatus = ""; + } + // DYNAMICALLY RESIZE PANES IF OPTION ENABLED + // won't trigger unless resizer has actually moved! + if (live && Math.abs(ui.position[side] - lastPos) >= o.liveResizingTolerance) { + lastPos = ui.position[side]; + resizePanes(e, ui, pane) + } + } + + , stop: function (e, ui) { + $('body').enableSelection(); // RE-ENABLE TEXT SELECTION + window.defaultStatus = ""; // clear 'resizing limit' message from statusbar + $R.removeClass( resizerClass +" "+ resizerPaneClass ); // remove drag classes from Resizer + s.isResizing = false; + resizePanes(e, ui, pane, true, masks); // true = resizingDone + } + + }); + }); + + /** + * resizePanes + * + * Sub-routine called from stop() - and drag() if livePaneResizing + * + * @param {!Object} evt + * @param {!Object} ui + * @param {string} pane + * @param {boolean=} [resizingDone=false] + */ + var resizePanes = function (evt, ui, pane, resizingDone, masks) { + var dragPos = ui.position + , c = _c[pane] + , o = options[pane] + , s = state[pane] + , resizerPos + ; + switch (pane) { + case "north": resizerPos = dragPos.top; break; + case "west": resizerPos = dragPos.left; break; + case "south": resizerPos = sC.offsetHeight - dragPos.top - o.spacing_open; break; + case "east": resizerPos = sC.offsetWidth - dragPos.left - o.spacing_open; break; + }; + // remove container margin from resizer position to get the pane size + var newSize = resizerPos - sC["inset"+ c.side]; + + // Disable OR Resize Mask(s) created in drag.start + if (!resizingDone) { + // ensure we meet liveResizingTolerance criteria + if (Math.abs(newSize - s.size) < o.liveResizingTolerance) + return; // SKIP resize this time + // resize the pane + manualSizePane(pane, newSize, false, true); // true = noAnimation + sizeMasks(); // resize all visible masks + } + else { // resizingDone + // ondrag_end callback + if (false !== _runCallbacks("ondrag_end", pane)) + manualSizePane(pane, newSize, false, true); // true = noAnimation + hideMasks(); // hide all masks, which include panes with 'content/iframe-masks' + if (s.isSliding && masks) // RE-SHOW only 'object-masks' so objects won't show through sliding pane + showMasks( masks, true ); // true = onlyForObjects + } + }; + } + + /** + * sizeMask + * + * Needed to overlay a DIV over an IFRAME-pane because mask CANNOT be *inside* the pane + * Called when mask created, and during livePaneResizing + */ +, sizeMask = function () { + var $M = $(this) + , pane = $M.data("layoutMask") // eg: "west" + , s = state[pane] + ; + // only masks over an IFRAME-pane need manual resizing + if (s.tagName == "IFRAME" && s.isVisible) // no need to mask closed/hidden panes + $M.css({ + top: s.offsetTop + , left: s.offsetLeft + , width: s.outerWidth + , height: s.outerHeight + }); + /* ALT Method... + var $P = $Ps[pane]; + $M.css( $P.position() ).css({ width: $P[0].offsetWidth, height: $P[0].offsetHeight }); + */ + } +, sizeMasks = function () { + $Ms.each( sizeMask ); // resize all 'visible' masks + } + +, showMasks = function (panes, onlyForObjects) { + var a = panes ? panes.split(",") : $.layout.config.allPanes + , z = options.zIndexes + , o, s; + $.each(a, function(i,p){ + s = state[p]; + o = options[p]; + if (s.isVisible && ( (!onlyForObjects && o.maskContents) || o.maskObjects )) { + getMasks(p).each(function(){ + sizeMask.call(this); + this.style.zIndex = s.isSliding ? z.pane_sliding+1 : z.pane_normal+1 + this.style.display = "block"; + }); + } + }); + } + +, hideMasks = function () { + // ensure no pane is resizing - could be a timing issue + var skip; + $.each( $.layout.config.borderPanes, function(i,p){ + if (state[p].isResizing) { + skip = true; + return false; // BREAK + } + }); + if (!skip) + $Ms.hide(); // hide ALL masks + } + +, getMasks = function (pane) { + var $Masks = $([]) + , $M, i = 0, c = $Ms.length + ; + for (; i CSS + if (sC.tagName === "BODY" && ($N = $("html")).data(css)) // RESET CSS + $N.css( $N.data(css) ).removeData(css); + + // trigger plugins for this layout, if there are any + runPluginCallbacks( Instance, $.layout.onDestroy ); + + // trigger state-management and onunload callback + unload(); + + // clear the Instance of everything except for container & options (so could recreate) + // RE-CREATE: myLayout = myLayout.container.layout( myLayout.options ); + for (n in Instance) + if (!n.match(/^(container|options)$/)) delete Instance[ n ]; + // add a 'destroyed' flag to make it easy to check + Instance.destroyed = true; + + // if this is a child layout, CLEAR the child-pointer in the parent + /* for now the pointer REMAINS, but with only container, options and destroyed keys + if (parentPane) { + var layout = parentPane.pane.data("parentLayout"); + parentPane.child = layout.children[ parentPane.name ] = null; + } + */ + + return Instance; // for coding convenience + } + + /** + * Remove a pane from the layout - subroutine of destroy() + * + * @see destroy() + * @param {string|Object} evt_or_pane The pane to process + * @param {boolean=} [remove=false] Remove the DOM element? + * @param {boolean=} [skipResize=false] Skip calling resizeAll()? + * @param {boolean=} [destroyChild=true] Destroy Child-layouts? If not passed, obeys options setting + */ +, removePane = function (evt_or_pane, remove, skipResize, destroyChild) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $P = $Ps[pane] + , $C = $Cs[pane] + , $R = $Rs[pane] + , $T = $Ts[pane] + ; + // NOTE: elements can still exist even after remove() + // so check for missing data(), which is cleared by removed() + if ($P && $.isEmptyObject( $P.data() )) $P = false; + if ($C && $.isEmptyObject( $C.data() )) $C = false; + if ($R && $.isEmptyObject( $R.data() )) $R = false; + if ($T && $.isEmptyObject( $T.data() )) $T = false; + + if ($P) $P.stop(true, true); + + // check for a child layout + var o = options[pane] + , s = state[pane] + , d = "layout" + , css = "layoutCSS" + , child = children[pane] || ($P ? $P.data(d) : 0) || ($C ? $C.data(d) : 0) || null + , destroy = destroyChild !== undefined ? destroyChild : o.destroyChildLayout + ; + + // FIRST destroy the child-layout(s) + if (destroy && child && !child.destroyed) { + child.destroy(true); // tell child-layout to destroy ALL its child-layouts too + if (child.destroyed) // destroy was successful + child = null; // clear pointer for logic below + } + + if ($P && remove && !child) + $P.remove(); + else if ($P && $P[0]) { + // create list of ALL pane-classes that need to be removed + var root = o.paneClass // default="ui-layout-pane" + , pRoot = root +"-"+ pane // eg: "ui-layout-pane-west" + , _open = "-open" + , _sliding= "-sliding" + , _closed = "-closed" + , classes = [ root, root+_open, root+_closed, root+_sliding, // generic classes + pRoot, pRoot+_open, pRoot+_closed, pRoot+_sliding ] // pane-specific classes + ; + $.merge(classes, getHoverClasses($P, true)); // ADD hover-classes + // remove all Layout classes from pane-element + $P .removeClass( classes.join(" ") ) // remove ALL pane-classes + .removeData("parentLayout") + .removeData("layoutPane") + .removeData("layoutRole") + .removeData("layoutEdge") + .removeData("autoHidden") // in case set + .unbind("."+ sID) // remove ALL Layout events + // TODO: remove these extra unbind commands when jQuery is fixed + //.unbind("mouseenter"+ sID) + //.unbind("mouseleave"+ sID) + ; + // do NOT reset CSS if this pane/content is STILL the container of a nested layout! + // the nested layout will reset its 'container' CSS when/if it is destroyed + if ($C && $C.data(d)) { + // a content-div may not have a specific width, so give it one to contain the Layout + $C.width( $C.width() ); + child.resizeAll(); // now resize the Layout + } + else if ($C) + $C.css( $C.data(css) ).removeData(css).removeData("layoutRole"); + // remove pane AFTER content in case there was a nested layout + if (!$P.data(d)) + $P.css( $P.data(css) ).removeData(css); + } + + // REMOVE pane resizer and toggler elements + if ($T) $T.remove(); + if ($R) $R.remove(); + + // CLEAR all pointers and state data + Instance[pane] = $Ps[pane] = $Cs[pane] = $Rs[pane] = $Ts[pane] = children[pane] = false; + s = { removed: true }; + + if (!skipResize) + resizeAll(); + } + + +/* + * ########################### + * ACTION METHODS + * ########################### + */ + +, _hidePane = function (pane) { + var $P = $Ps[pane] + , o = options[pane] + , s = $P[0].style + ; + if (o.useOffscreenClose) { + if (!$P.data(_c.offscreenReset)) + $P.data(_c.offscreenReset, { left: s.left, right: s.right }); + $P.css( _c.offscreenCSS ); + } + else + $P.hide().removeData(_c.offscreenReset); + } + +, _showPane = function (pane) { + var $P = $Ps[pane] + , o = options[pane] + , off = _c.offscreenCSS + , old = $P.data(_c.offscreenReset) + , s = $P[0].style + ; + $P .show() // ALWAYS show, just in case + .removeData(_c.offscreenReset); + if (o.useOffscreenClose && old) { + if (s.left == off.left) + s.left = old.left; + if (s.right == off.right) + s.right = old.right; + } + } + + + /** + * Completely 'hides' a pane, including its spacing - as if it does not exist + * The pane is not actually 'removed' from the source, so can use 'show' to un-hide it + * + * @param {string|Object} evt_or_pane The pane being hidden, ie: north, south, east, or west + * @param {boolean=} [noAnimation=false] + */ +, hide = function (evt_or_pane, noAnimation) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , o = options[pane] + , s = state[pane] + , $P = $Ps[pane] + , $R = $Rs[pane] + ; + if (!$P || s.isHidden) return; // pane does not exist OR is already hidden + + // onhide_start callback - will CANCEL hide if returns false + if (state.initialized && false === _runCallbacks("onhide_start", pane)) return; + + s.isSliding = false; // just in case + + // now hide the elements + if ($R) $R.hide(); // hide resizer-bar + if (!state.initialized || s.isClosed) { + s.isClosed = true; // to trigger open-animation on show() + s.isHidden = true; + s.isVisible = false; + if (!state.initialized) + _hidePane(pane); // no animation when loading page + sizeMidPanes(_c[pane].dir === "horz" ? "" : "center"); + if (state.initialized || o.triggerEventsOnLoad) + _runCallbacks("onhide_end", pane); + } + else { + s.isHiding = true; // used by onclose + close(pane, false, noAnimation); // adjust all panes to fit + } + } + + /** + * Show a hidden pane - show as 'closed' by default unless openPane = true + * + * @param {string|Object} evt_or_pane The pane being opened, ie: north, south, east, or west + * @param {boolean=} [openPane=false] + * @param {boolean=} [noAnimation=false] + * @param {boolean=} [noAlert=false] + */ +, show = function (evt_or_pane, openPane, noAnimation, noAlert) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , o = options[pane] + , s = state[pane] + , $P = $Ps[pane] + , $R = $Rs[pane] + ; + if (!$P || !s.isHidden) return; // pane does not exist OR is not hidden + + // onshow_start callback - will CANCEL show if returns false + if (false === _runCallbacks("onshow_start", pane)) return; + + s.isSliding = false; // just in case + s.isShowing = true; // used by onopen/onclose + //s.isHidden = false; - will be set by open/close - if not cancelled + + // now show the elements + //if ($R) $R.show(); - will be shown by open/close + if (openPane === false) + close(pane, true); // true = force + else + open(pane, false, noAnimation, noAlert); // adjust all panes to fit + } + + + /** + * Toggles a pane open/closed by calling either open or close + * + * @param {string|Object} evt_or_pane The pane being toggled, ie: north, south, east, or west + * @param {boolean=} [slide=false] + */ +, toggle = function (evt_or_pane, slide) { + if (!isInitialized()) return; + var evt = evtObj(evt_or_pane) + , pane = evtPane.call(this, evt_or_pane) + , s = state[pane] + ; + if (evt) // called from to $R.dblclick OR triggerPaneEvent + evt.stopImmediatePropagation(); + if (s.isHidden) + show(pane); // will call 'open' after unhiding it + else if (s.isClosed) + open(pane, !!slide); + else + close(pane); + } + + + /** + * Utility method used during init or other auto-processes + * + * @param {string} pane The pane being closed + * @param {boolean=} [setHandles=false] + */ +, _closePane = function (pane, setHandles) { + var + $P = $Ps[pane] + , s = state[pane] + ; + _hidePane(pane); + s.isClosed = true; + s.isVisible = false; + // UNUSED: if (setHandles) setAsClosed(pane, true); // true = force + } + + /** + * Close the specified pane (animation optional), and resize all other panes as needed + * + * @param {string|Object} evt_or_pane The pane being closed, ie: north, south, east, or west + * @param {boolean=} [force=false] + * @param {boolean=} [noAnimation=false] + * @param {boolean=} [skipCallback=false] + */ +, close = function (evt_or_pane, force, noAnimation, skipCallback) { + var pane = evtPane.call(this, evt_or_pane); + // if pane has been initialized, but NOT the complete layout, close pane instantly + if (!state.initialized && $Ps[pane]) { + _closePane(pane); // INIT pane as closed + return; + } + if (!isInitialized()) return; + + var + $P = $Ps[pane] + , $R = $Rs[pane] + , $T = $Ts[pane] + , o = options[pane] + , s = state[pane] + , c = _c[pane] + , doFX, isShowing, isHiding, wasSliding; + + // QUEUE in case another action/animation is in progress + $N.queue(function( queueNext ){ + + if ( !$P + || (!o.closable && !s.isShowing && !s.isHiding) // invalid request // (!o.resizable && !o.closable) ??? + || (!force && s.isClosed && !s.isShowing) // already closed + ) return queueNext(); + + // onclose_start callback - will CANCEL hide if returns false + // SKIP if just 'showing' a hidden pane as 'closed' + var abort = !s.isShowing && false === _runCallbacks("onclose_start", pane); + + // transfer logic vars to temp vars + isShowing = s.isShowing; + isHiding = s.isHiding; + wasSliding = s.isSliding; + // now clear the logic vars (REQUIRED before aborting) + delete s.isShowing; + delete s.isHiding; + + if (abort) return queueNext(); + + doFX = !noAnimation && !s.isClosed && (o.fxName_close != "none"); + s.isMoving = true; + s.isClosed = true; + s.isVisible = false; + // update isHidden BEFORE sizing panes + if (isHiding) s.isHidden = true; + else if (isShowing) s.isHidden = false; + + if (s.isSliding) // pane is being closed, so UNBIND trigger events + bindStopSlidingEvents(pane, false); // will set isSliding=false + else // resize panes adjacent to this one + sizeMidPanes(_c[pane].dir === "horz" ? "" : "center", false); // false = NOT skipCallback + + // if this pane has a resizer bar, move it NOW - before animation + setAsClosed(pane); + + // CLOSE THE PANE + if (doFX) { // animate the close + // mask panes with objects + var masks = "center"+ (c.dir=="horz" ? ",west,east" : ""); + showMasks( masks, true ); // true = ONLY mask panes with maskObjects=true + lockPaneForFX(pane, true); // need to set left/top so animation will work + $P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () { + lockPaneForFX(pane, false); // undo + if (s.isClosed) close_2(); + queueNext(); + }); + } + else { // hide the pane without animation + _hidePane(pane); + close_2(); + queueNext(); + }; + }); + + // SUBROUTINE + function close_2 () { + s.isMoving = false; + bindStartSlidingEvent(pane, true); // will enable if o.slidable = true + + // if opposite-pane was autoClosed, see if it can be autoOpened now + var altPane = _c.oppositeEdge[pane]; + if (state[ altPane ].noRoom) { + setSizeLimits( altPane ); + makePaneFit( altPane ); + } + + // hide any masks shown while closing + hideMasks(); + + if (!skipCallback && (state.initialized || o.triggerEventsOnLoad)) { + // onclose callback - UNLESS just 'showing' a hidden pane as 'closed' + if (!isShowing) _runCallbacks("onclose_end", pane); + // onhide OR onshow callback + if (isShowing) _runCallbacks("onshow_end", pane); + if (isHiding) _runCallbacks("onhide_end", pane); + } + } + } + + /** + * @param {string} pane The pane just closed, ie: north, south, east, or west + */ +, setAsClosed = function (pane) { + var + $P = $Ps[pane] + , $R = $Rs[pane] + , $T = $Ts[pane] + , o = options[pane] + , s = state[pane] + , side = _c[pane].side.toLowerCase() + , inset = "inset"+ _c[pane].side + , rClass = o.resizerClass + , tClass = o.togglerClass + , _pane = "-"+ pane // used for classNames + , _open = "-open" + , _sliding= "-sliding" + , _closed = "-closed" + ; + $R + .css(side, sC[inset]) // move the resizer + .removeClass( rClass+_open +" "+ rClass+_pane+_open ) + .removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding ) + .addClass( rClass+_closed +" "+ rClass+_pane+_closed ) + .unbind("dblclick."+ sID) + ; + // DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvent? + if (o.resizable && $.layout.plugins.draggable) + $R + .draggable("disable") + .removeClass("ui-state-disabled") // do NOT apply disabled styling - not suitable here + .css("cursor", "default") + .attr("title","") + ; + + // if pane has a toggler button, adjust that too + if ($T) { + $T + .removeClass( tClass+_open +" "+ tClass+_pane+_open ) + .addClass( tClass+_closed +" "+ tClass+_pane+_closed ) + .attr("title", o.tips.Open) // may be blank + ; + // toggler-content - if exists + $T.children(".content-open").hide(); + $T.children(".content-closed").css("display","block"); + } + + // sync any 'pin buttons' + syncPinBtns(pane, false); + + if (state.initialized) { + // resize 'length' and position togglers for adjacent panes + sizeHandles(); + } + } + + /** + * Open the specified pane (animation optional), and resize all other panes as needed + * + * @param {string|Object} evt_or_pane The pane being opened, ie: north, south, east, or west + * @param {boolean=} [slide=false] + * @param {boolean=} [noAnimation=false] + * @param {boolean=} [noAlert=false] + */ +, open = function (evt_or_pane, slide, noAnimation, noAlert) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $P = $Ps[pane] + , $R = $Rs[pane] + , $T = $Ts[pane] + , o = options[pane] + , s = state[pane] + , c = _c[pane] + , doFX, isShowing + ; + // QUEUE in case another action/animation is in progress + $N.queue(function( queueNext ){ + + if ( !$P + || (!o.resizable && !o.closable && !s.isShowing) // invalid request + || (s.isVisible && !s.isSliding) // already open + ) return queueNext(); + + // pane can ALSO be unhidden by just calling show(), so handle this scenario + if (s.isHidden && !s.isShowing) { + queueNext(); // call before show() because it needs the queue free + show(pane, true); + return; + } + + if (o.autoResize && s.size != o.size) // resize pane to original size set in options + sizePane(pane, o.size, true, true, true); // true=skipCallback/forceResize/noAnimation + else + // make sure there is enough space available to open the pane + setSizeLimits(pane, slide); + + // onopen_start callback - will CANCEL open if returns false + var cbReturn = _runCallbacks("onopen_start", pane); + + if (cbReturn === "abort") + return queueNext(); + + // update pane-state again in case options were changed in onopen_start + if (cbReturn !== "NC") // NC = "No Callback" + setSizeLimits(pane, slide); + + if (s.minSize > s.maxSize) { // INSUFFICIENT ROOM FOR PANE TO OPEN! + syncPinBtns(pane, false); // make sure pin-buttons are reset + if (!noAlert && o.tips.noRoomToOpen) + alert(o.tips.noRoomToOpen); + return queueNext(); // ABORT + } + + if (slide) // START Sliding - will set isSliding=true + bindStopSlidingEvents(pane, true); // BIND trigger events to close sliding-pane + else if (s.isSliding) // PIN PANE (stop sliding) - open pane 'normally' instead + bindStopSlidingEvents(pane, false); // UNBIND trigger events - will set isSliding=false + else if (o.slidable) + bindStartSlidingEvent(pane, false); // UNBIND trigger events + + s.noRoom = false; // will be reset by makePaneFit if 'noRoom' + makePaneFit(pane); + + // transfer logic var to temp var + isShowing = s.isShowing; + // now clear the logic var + delete s.isShowing; + + doFX = !noAnimation && s.isClosed && (o.fxName_open != "none"); + s.isMoving = true; + s.isVisible = true; + s.isClosed = false; + // update isHidden BEFORE sizing panes - WHY??? Old? + if (isShowing) s.isHidden = false; + + if (doFX) { // ANIMATE + // mask panes with objects + var masks = "center"+ (c.dir=="horz" ? ",west,east" : ""); + if (s.isSliding) masks += ","+ _c.oppositeEdge[pane]; + showMasks( masks, true ); // true = ONLY mask panes with maskObjects=true + lockPaneForFX(pane, true); // need to set left/top so animation will work + $P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() { + lockPaneForFX(pane, false); // undo + if (s.isVisible) open_2(); // continue + queueNext(); + }); + } + else { // no animation + _showPane(pane);// just show pane and... + open_2(); // continue + queueNext(); + }; + }); + + // SUBROUTINE + function open_2 () { + s.isMoving = false; + + // cure iframe display issues + _fixIframe(pane); + + // NOTE: if isSliding, then other panes are NOT 'resized' + if (!s.isSliding) { // resize all panes adjacent to this one + hideMasks(); // remove any masks shown while opening + sizeMidPanes(_c[pane].dir=="vert" ? "center" : "", false); // false = NOT skipCallback + } + + // set classes, position handles and execute callbacks... + setAsOpen(pane); + }; + + } + + /** + * @param {string} pane The pane just opened, ie: north, south, east, or west + * @param {boolean=} [skipCallback=false] + */ +, setAsOpen = function (pane, skipCallback) { + var + $P = $Ps[pane] + , $R = $Rs[pane] + , $T = $Ts[pane] + , o = options[pane] + , s = state[pane] + , side = _c[pane].side.toLowerCase() + , inset = "inset"+ _c[pane].side + , rClass = o.resizerClass + , tClass = o.togglerClass + , _pane = "-"+ pane // used for classNames + , _open = "-open" + , _closed = "-closed" + , _sliding= "-sliding" + ; + $R + .css(side, sC[inset] + getPaneSize(pane)) // move the resizer + .removeClass( rClass+_closed +" "+ rClass+_pane+_closed ) + .addClass( rClass+_open +" "+ rClass+_pane+_open ) + ; + if (s.isSliding) + $R.addClass( rClass+_sliding +" "+ rClass+_pane+_sliding ) + else // in case 'was sliding' + $R.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding ) + + if (o.resizerDblClickToggle) + $R.bind("dblclick", toggle ); + removeHover( 0, $R ); // remove hover classes + if (o.resizable && $.layout.plugins.draggable) + $R .draggable("enable") + .css("cursor", o.resizerCursor) + .attr("title", o.tips.Resize); + else if (!s.isSliding) + $R.css("cursor", "default"); // n-resize, s-resize, etc + + // if pane also has a toggler button, adjust that too + if ($T) { + $T .removeClass( tClass+_closed +" "+ tClass+_pane+_closed ) + .addClass( tClass+_open +" "+ tClass+_pane+_open ) + .attr("title", o.tips.Close); // may be blank + removeHover( 0, $T ); // remove hover classes + // toggler-content - if exists + $T.children(".content-closed").hide(); + $T.children(".content-open").css("display","block"); + } + + // sync any 'pin buttons' + syncPinBtns(pane, !s.isSliding); + + // update pane-state dimensions - BEFORE resizing content + $.extend(s, elDims($P)); + + if (state.initialized) { + // resize resizer & toggler sizes for all panes + sizeHandles(); + // resize content every time pane opens - to be sure + sizeContent(pane, true); // true = remeasure headers/footers, even if 'pane.isMoving' + } + + if (!skipCallback && (state.initialized || o.triggerEventsOnLoad) && $P.is(":visible")) { + // onopen callback + _runCallbacks("onopen_end", pane); + // onshow callback - TODO: should this be here? + if (s.isShowing) _runCallbacks("onshow_end", pane); + + // ALSO call onresize because layout-size *may* have changed while pane was closed + if (state.initialized) + _runCallbacks("onresize_end", pane); + } + + // TODO: Somehow sizePane("north") is being called after this point??? + } + + + /** + * slideOpen / slideClose / slideToggle + * + * Pass-though methods for sliding + */ +, slideOpen = function (evt_or_pane) { + if (!isInitialized()) return; + var evt = evtObj(evt_or_pane) + , pane = evtPane.call(this, evt_or_pane) + , s = state[pane] + , delay = options[pane].slideDelay_open + ; + // prevent event from triggering on NEW resizer binding created below + if (evt) evt.stopImmediatePropagation(); + + if (s.isClosed && evt && evt.type === "mouseenter" && delay > 0) + // trigger = mouseenter - use a delay + timer.set(pane+"_openSlider", open_NOW, delay); + else + open_NOW(); // will unbind events if is already open + + /** + * SUBROUTINE for timed open + */ + function open_NOW () { + if (!s.isClosed) // skip if no longer closed! + bindStopSlidingEvents(pane, true); // BIND trigger events to close sliding-pane + else if (!s.isMoving) + open(pane, true); // true = slide - open() will handle binding + }; + } + +, slideClose = function (evt_or_pane) { + if (!isInitialized()) return; + var evt = evtObj(evt_or_pane) + , pane = evtPane.call(this, evt_or_pane) + , o = options[pane] + , s = state[pane] + , delay = s.isMoving ? 1000 : 300 // MINIMUM delay - option may override + ; + if (s.isClosed || s.isResizing) + return; // skip if already closed OR in process of resizing + else if (o.slideTrigger_close === "click") + close_NOW(); // close immediately onClick + else if (o.preventQuickSlideClose && s.isMoving) + return; // handle Chrome quick-close on slide-open + else if (o.preventPrematureSlideClose && evt && $.layout.isMouseOverElem(evt, $Ps[pane])) + return; // handle incorrect mouseleave trigger, like when over a SELECT-list in IE + else if (evt) // trigger = mouseleave - use a delay + // 1 sec delay if 'opening', else .3 sec + timer.set(pane+"_closeSlider", close_NOW, max(o.slideDelay_close, delay)); + else // called programically + close_NOW(); + + /** + * SUBROUTINE for timed close + */ + function close_NOW () { + if (s.isClosed) // skip 'close' if already closed! + bindStopSlidingEvents(pane, false); // UNBIND trigger events - TODO: is this needed here? + else if (!s.isMoving) + close(pane); // close will handle unbinding + }; + } + + /** + * @param {string|Object} evt_or_pane The pane being opened, ie: north, south, east, or west + */ +, slideToggle = function (evt_or_pane) { + var pane = evtPane.call(this, evt_or_pane); + toggle(pane, true); + } + + + /** + * Must set left/top on East/South panes so animation will work properly + * + * @param {string} pane The pane to lock, 'east' or 'south' - any other is ignored! + * @param {boolean} doLock true = set left/top, false = remove + */ +, lockPaneForFX = function (pane, doLock) { + var $P = $Ps[pane] + , s = state[pane] + , o = options[pane] + , z = options.zIndexes + ; + if (doLock) { + $P.css({ zIndex: z.pane_animate }); // overlay all elements during animation + if (pane=="south") + $P.css({ top: sC.insetTop + sC.innerHeight - $P.outerHeight() }); + else if (pane=="east") + $P.css({ left: sC.insetLeft + sC.innerWidth - $P.outerWidth() }); + } + else { // animation DONE - RESET CSS + // TODO: see if this can be deleted. It causes a quick-close when sliding in Chrome + $P.css({ zIndex: (s.isSliding ? z.pane_sliding : z.pane_normal) }); + if (pane=="south") + $P.css({ top: "auto" }); + // if pane is positioned 'off-screen', then DO NOT screw with it! + else if (pane=="east" && !$P.css("left").match(/\-99999/)) + $P.css({ left: "auto" }); + // fix anti-aliasing in IE - only needed for animations that change opacity + if (browser.msie && o.fxOpacityFix && o.fxName_open != "slide" && $P.css("filter") && $P.css("opacity") == 1) + $P[0].style.removeAttribute('filter'); + } + } + + + /** + * Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger + * + * @see open(), close() + * @param {string} pane The pane to enable/disable, 'north', 'south', etc. + * @param {boolean} enable Enable or Disable sliding? + */ +, bindStartSlidingEvent = function (pane, enable) { + var o = options[pane] + , $P = $Ps[pane] + , $R = $Rs[pane] + , evtName = o.slideTrigger_open.toLowerCase() + ; + if (!$R || (enable && !o.slidable)) return; + + // make sure we have a valid event + if (evtName.match(/mouseover/)) + evtName = o.slideTrigger_open = "mouseenter"; + else if (!evtName.match(/(click|dblclick|mouseenter)/)) + evtName = o.slideTrigger_open = "click"; + + $R + // add or remove event + [enable ? "bind" : "unbind"](evtName +'.'+ sID, slideOpen) + // set the appropriate cursor & title/tip + .css("cursor", enable ? o.sliderCursor : "default") + .attr("title", enable ? o.tips.Slide : "") + ; + } + + /** + * Add or remove 'mouseleave' events to 'slide close' when pane is 'sliding' open or closed + * Also increases zIndex when pane is sliding open + * See bindStartSlidingEvent for code to control 'slide open' + * + * @see slideOpen(), slideClose() + * @param {string} pane The pane to process, 'north', 'south', etc. + * @param {boolean} enable Enable or Disable events? + */ +, bindStopSlidingEvents = function (pane, enable) { + var o = options[pane] + , s = state[pane] + , c = _c[pane] + , z = options.zIndexes + , evtName = o.slideTrigger_close.toLowerCase() + , action = (enable ? "bind" : "unbind") + , $P = $Ps[pane] + , $R = $Rs[pane] + ; + s.isSliding = enable; // logic + timer.clear(pane+"_closeSlider"); // just in case + + // remove 'slideOpen' event from resizer + // ALSO will raise the zIndex of the pane & resizer + if (enable) bindStartSlidingEvent(pane, false); + + // RE/SET zIndex - increases when pane is sliding-open, resets to normal when not + $P.css("zIndex", enable ? z.pane_sliding : z.pane_normal); + $R.css("zIndex", enable ? z.pane_sliding+2 : z.resizer_normal); // NOTE: mask = pane_sliding+1 + + // make sure we have a valid event + if (!evtName.match(/(click|mouseleave)/)) + evtName = o.slideTrigger_close = "mouseleave"; // also catches 'mouseout' + + // add/remove slide triggers + $R[action](evtName, slideClose); // base event on resize + // need extra events for mouseleave + if (evtName === "mouseleave") { + // also close on pane.mouseleave + $P[action]("mouseleave."+ sID, slideClose); + // cancel timer when mouse moves between 'pane' and 'resizer' + $R[action]("mouseenter."+ sID, cancelMouseOut); + $P[action]("mouseenter."+ sID, cancelMouseOut); + } + + if (!enable) + timer.clear(pane+"_closeSlider"); + else if (evtName === "click" && !o.resizable) { + // IF pane is not resizable (which already has a cursor and tip) + // then set the a cursor & title/tip on resizer when sliding + $R.css("cursor", enable ? o.sliderCursor : "default"); + $R.attr("title", enable ? o.tips.Close : ""); // use Toggler-tip, eg: "Close Pane" + } + + // SUBROUTINE for mouseleave timer clearing + function cancelMouseOut (evt) { + timer.clear(pane+"_closeSlider"); + evt.stopPropagation(); + } + } + + + /** + * Hides/closes a pane if there is insufficient room - reverses this when there is room again + * MUST have already called setSizeLimits() before calling this method + * + * @param {string} pane The pane being resized + * @param {boolean=} [isOpening=false] Called from onOpen? + * @param {boolean=} [skipCallback=false] Should the onresize callback be run? + * @param {boolean=} [force=false] + */ +, makePaneFit = function (pane, isOpening, skipCallback, force) { + var + o = options[pane] + , s = state[pane] + , c = _c[pane] + , $P = $Ps[pane] + , $R = $Rs[pane] + , isSidePane = c.dir==="vert" + , hasRoom = false + ; + // special handling for center & east/west panes + if (pane === "center" || (isSidePane && s.noVerticalRoom)) { + // see if there is enough room to display the pane + // ERROR: hasRoom = s.minHeight <= s.maxHeight && (isSidePane || s.minWidth <= s.maxWidth); + hasRoom = (s.maxHeight >= 0); + if (hasRoom && s.noRoom) { // previously hidden due to noRoom, so show now + _showPane(pane); + if ($R) $R.show(); + s.isVisible = true; + s.noRoom = false; + if (isSidePane) s.noVerticalRoom = false; + _fixIframe(pane); + } + else if (!hasRoom && !s.noRoom) { // not currently hidden, so hide now + _hidePane(pane); + if ($R) $R.hide(); + s.isVisible = false; + s.noRoom = true; + } + } + + // see if there is enough room to fit the border-pane + if (pane === "center") { + // ignore center in this block + } + else if (s.minSize <= s.maxSize) { // pane CAN fit + hasRoom = true; + if (s.size > s.maxSize) // pane is too big - shrink it + sizePane(pane, s.maxSize, skipCallback, force, true); // true = noAnimation + else if (s.size < s.minSize) // pane is too small - enlarge it + sizePane(pane, s.minSize, skipCallback, force, true); + // need s.isVisible because new pseudoClose method keeps pane visible, but off-screen + else if ($R && s.isVisible && $P.is(":visible")) { + // make sure resizer-bar is positioned correctly + // handles situation where nested layout was 'hidden' when initialized + var side = c.side.toLowerCase() + , pos = s.size + sC["inset"+ c.side] + ; + if ($.layout.cssNum($R, side) != pos) $R.css( side, pos ); + } + + // if was previously hidden due to noRoom, then RESET because NOW there is room + if (s.noRoom) { + // s.noRoom state will be set by open or show + if (s.wasOpen && o.closable) { + if (o.autoReopen) + open(pane, false, true, true); // true = noAnimation, true = noAlert + else // leave the pane closed, so just update state + s.noRoom = false; + } + else + show(pane, s.wasOpen, true, true); // true = noAnimation, true = noAlert + } + } + else { // !hasRoom - pane CANNOT fit + if (!s.noRoom) { // pane not set as noRoom yet, so hide or close it now... + s.noRoom = true; // update state + s.wasOpen = !s.isClosed && !s.isSliding; + if (s.isClosed){} // SKIP + else if (o.closable) // 'close' if possible + close(pane, true, true); // true = force, true = noAnimation + else // 'hide' pane if cannot just be closed + hide(pane, true); // true = noAnimation + } + } + } + + + /** + * sizePane / manualSizePane + * sizePane is called only by internal methods whenever a pane needs to be resized + * manualSizePane is an exposed flow-through method allowing extra code when pane is 'manually resized' + * + * @param {string|Object} evt_or_pane The pane being resized + * @param {number} size The *desired* new size for this pane - will be validated + * @param {boolean=} [skipCallback=false] Should the onresize callback be run? + * @param {boolean=} [noAnimation=false] + */ +, manualSizePane = function (evt_or_pane, size, skipCallback, noAnimation) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , o = options[pane] + , s = state[pane] + // if resizing callbacks have been delayed and resizing is now DONE, force resizing to complete... + , forceResize = o.livePaneResizing && !s.isResizing + ; + // ANY call to manualSizePane disables autoResize - ie, percentage sizing + o.autoResize = false; + // flow-through... + sizePane(pane, size, skipCallback, forceResize, noAnimation); // will animate resize if option enabled + } + + /** + * @param {string|Object} evt_or_pane The pane being resized + * @param {number} size The *desired* new size for this pane - will be validated + * @param {boolean=} [skipCallback=false] Should the onresize callback be run? + * @param {boolean=} [force=false] Force resizing even if does not seem necessary + * @param {boolean=} [noAnimation=false] + */ +, sizePane = function (evt_or_pane, size, skipCallback, force, noAnimation) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) // probably NEVER called from event? + , o = options[pane] + , s = state[pane] + , $P = $Ps[pane] + , $R = $Rs[pane] + , side = _c[pane].side.toLowerCase() + , dimName = _c[pane].sizeType.toLowerCase() + , inset = "inset"+ _c[pane].side + , skipResizeWhileDragging = s.isResizing && !o.triggerEventsDuringLiveResize + , doFX = noAnimation !== true && o.animatePaneSizing + , oldSize, newSize + ; + // QUEUE in case another action/animation is in progress + $N.queue(function( queueNext ){ + // calculate 'current' min/max sizes + setSizeLimits(pane); // update pane-state + oldSize = s.size; + size = _parseSize(pane, size); // handle percentages & auto + size = max(size, _parseSize(pane, o.minSize)); + size = min(size, s.maxSize); + if (size < s.minSize) { // not enough room for pane! + queueNext(); // call before makePaneFit() because it needs the queue free + makePaneFit(pane, false, skipCallback); // will hide or close pane + return; + } + + // IF newSize is same as oldSize, then nothing to do - abort + if (!force && size === oldSize) + return queueNext(); + + // onresize_start callback CANNOT cancel resizing because this would break the layout! + if (!skipCallback && state.initialized && s.isVisible) + _runCallbacks("onresize_start", pane); + + // resize the pane, and make sure its visible + newSize = cssSize(pane, size); + + if (doFX && $P.is(":visible")) { // ANIMATE + var fx = $.layout.effects.size[pane] || $.layout.effects.size.all + , easing = o.fxSettings_size.easing || fx.easing + , z = options.zIndexes + , props = {}; + props[ dimName ] = newSize +'px'; + s.isMoving = true; + // overlay all elements during animation + $P.css({ zIndex: z.pane_animate }) + .show().animate( props, o.fxSpeed_size, easing, function(){ + // reset zIndex after animation + $P.css({ zIndex: (s.isSliding ? z.pane_sliding : z.pane_normal) }); + s.isMoving = false; + sizePane_2(); // continue + queueNext(); + }); + } + else { // no animation + $P.css( dimName, newSize ); // resize pane + // if pane is visible, then + if ($P.is(":visible")) + sizePane_2(); // continue + else { + // pane is NOT VISIBLE, so just update state data... + // when pane is *next opened*, it will have the new size + s.size = size; // update state.size + $.extend(s, elDims($P)); // update state dimensions + } + queueNext(); + }; + + }); + + // SUBROUTINE + function sizePane_2 () { + /* Panes are sometimes not sized precisely in some browsers!? + * This code will resize the pane up to 3 times to nudge the pane to the correct size + */ + var actual = dimName==='width' ? $P.outerWidth() : $P.outerHeight() + , tries = [{ + pane: pane + , count: 1 + , target: size + , actual: actual + , correct: (size === actual) + , attempt: size + , cssSize: newSize + }] + , lastTry = tries[0] + , thisTry = {} + , msg = 'Inaccurate size after resizing the '+ pane +'-pane.' + ; + while ( !lastTry.correct ) { + thisTry = { pane: pane, count: lastTry.count+1, target: size }; + + if (lastTry.actual > size) + thisTry.attempt = max(0, lastTry.attempt - (lastTry.actual - size)); + else // lastTry.actual < size + thisTry.attempt = max(0, lastTry.attempt + (size - lastTry.actual)); + + thisTry.cssSize = cssSize(pane, thisTry.attempt); + $P.css( dimName, thisTry.cssSize ); + + thisTry.actual = dimName=='width' ? $P.outerWidth() : $P.outerHeight(); + thisTry.correct = (size === thisTry.actual); + + // log attempts and alert the user of this *non-fatal error* (if showDebugMessages) + if ( tries.length === 1) { + _log(msg, false, true); + _log(lastTry, false, true); + } + _log(thisTry, false, true); + // after 4 tries, is as close as its gonna get! + if (tries.length > 3) break; + + tries.push( thisTry ); + lastTry = tries[ tries.length - 1 ]; + } + // END TESTING CODE + + // update pane-state dimensions + s.size = size; + $.extend(s, elDims($P)); + + if (s.isVisible && $P.is(":visible")) { + // reposition the resizer-bar + if ($R) $R.css( side, size + sC[inset] ); + // resize the content-div + sizeContent(pane); + } + + if (!skipCallback && !skipResizeWhileDragging && state.initialized && s.isVisible) + _runCallbacks("onresize_end", pane); + + // resize all the adjacent panes, and adjust their toggler buttons + // when skipCallback passed, it means the controlling method will handle 'other panes' + if (!skipCallback) { + // also no callback if live-resize is in progress and NOT triggerEventsDuringLiveResize + if (!s.isSliding) sizeMidPanes(_c[pane].dir=="horz" ? "" : "center", skipResizeWhileDragging, force); + sizeHandles(); + } + + // if opposite-pane was autoClosed, see if it can be autoOpened now + var altPane = _c.oppositeEdge[pane]; + if (size < oldSize && state[ altPane ].noRoom) { + setSizeLimits( altPane ); + makePaneFit( altPane, false, skipCallback ); + } + + // DEBUG - ALERT user/developer so they know there was a sizing problem + if (tries.length > 1) + _log(msg +'\nSee the Error Console for details.', true, true); + } + } + + /** + * @see initPanes(), sizePane(), resizeAll(), open(), close(), hide() + * @param {Array.|string} panes The pane(s) being resized, comma-delmited string + * @param {boolean=} [skipCallback=false] Should the onresize callback be run? + * @param {boolean=} [force=false] + */ +, sizeMidPanes = function (panes, skipCallback, force) { + panes = (panes ? panes : "east,west,center").split(","); + + $.each(panes, function (i, pane) { + if (!$Ps[pane]) return; // NO PANE - skip + var + o = options[pane] + , s = state[pane] + , $P = $Ps[pane] + , $R = $Rs[pane] + , isCenter= (pane=="center") + , hasRoom = true + , CSS = {} + , newCenter = calcNewCenterPaneDims() + ; + // update pane-state dimensions + $.extend(s, elDims($P)); + + if (pane === "center") { + if (!force && s.isVisible && newCenter.width === s.outerWidth && newCenter.height === s.outerHeight) + return true; // SKIP - pane already the correct size + // set state for makePaneFit() logic + $.extend(s, cssMinDims(pane), { + maxWidth: newCenter.width + , maxHeight: newCenter.height + }); + CSS = newCenter; + // convert OUTER width/height to CSS width/height + CSS.width = cssW($P, CSS.width); + // NEW - allow pane to extend 'below' visible area rather than hide it + CSS.height = cssH($P, CSS.height); + hasRoom = CSS.width >= 0 && CSS.height >= 0; // height >= 0 = ALWAYS TRUE NOW + // during layout init, try to shrink east/west panes to make room for center + if (!state.initialized && o.minWidth > s.outerWidth) { + var + reqPx = o.minWidth - s.outerWidth + , minE = options.east.minSize || 0 + , minW = options.west.minSize || 0 + , sizeE = state.east.size + , sizeW = state.west.size + , newE = sizeE + , newW = sizeW + ; + if (reqPx > 0 && state.east.isVisible && sizeE > minE) { + newE = max( sizeE-minE, sizeE-reqPx ); + reqPx -= sizeE-newE; + } + if (reqPx > 0 && state.west.isVisible && sizeW > minW) { + newW = max( sizeW-minW, sizeW-reqPx ); + reqPx -= sizeW-newW; + } + // IF we found enough extra space, then resize the border panes as calculated + if (reqPx === 0) { + if (sizeE && sizeE != minE) + sizePane('east', newE, true, force, true); // true = skipCallback/noAnimation - initPanes will handle when done + if (sizeW && sizeW != minW) + sizePane('west', newW, true, force, true); + // now start over! + sizeMidPanes('center', skipCallback, force); + return; // abort this loop + } + } + } + else { // for east and west, set only the height, which is same as center height + // set state.min/maxWidth/Height for makePaneFit() logic + if (s.isVisible && !s.noVerticalRoom) + $.extend(s, elDims($P), cssMinDims(pane)) + if (!force && !s.noVerticalRoom && newCenter.height === s.outerHeight) + return true; // SKIP - pane already the correct size + // east/west have same top, bottom & height as center + CSS.top = newCenter.top; + CSS.bottom = newCenter.bottom; + // NEW - allow pane to extend 'below' visible area rather than hide it + CSS.height = cssH($P, newCenter.height); + s.maxHeight = CSS.height; + hasRoom = (s.maxHeight >= 0); // ALWAYS TRUE NOW + if (!hasRoom) s.noVerticalRoom = true; // makePaneFit() logic + } + + if (hasRoom) { + // resizeAll passes skipCallback because it triggers callbacks after ALL panes are resized + if (!skipCallback && state.initialized) + _runCallbacks("onresize_start", pane); + + $P.css(CSS); // apply the CSS to pane + if (pane !== "center") + sizeHandles(pane); // also update resizer length + if (s.noRoom && !s.isClosed && !s.isHidden) + makePaneFit(pane); // will re-open/show auto-closed/hidden pane + if (s.isVisible) { + $.extend(s, elDims($P)); // update pane dimensions + if (state.initialized) sizeContent(pane); // also resize the contents, if exists + } + } + else if (!s.noRoom && s.isVisible) // no room for pane + makePaneFit(pane); // will hide or close pane + + if (!s.isVisible) + return true; // DONE - next pane + + /* + * Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes + * Normally these panes have only 'left' & 'right' positions so pane auto-sizes + * ALSO required when pane is an IFRAME because will NOT default to 'full width' + * TODO: Can I use width:100% for a north/south iframe? + * TODO: Sounds like a job for $P.outerWidth( sC.innerWidth ) SETTER METHOD + */ + if (pane === "center") { // finished processing midPanes + var fix = browser.isIE6 || !browser.boxModel; + if ($Ps.north && (fix || state.north.tagName=="IFRAME")) + $Ps.north.css("width", cssW($Ps.north, sC.innerWidth)); + if ($Ps.south && (fix || state.south.tagName=="IFRAME")) + $Ps.south.css("width", cssW($Ps.south, sC.innerWidth)); + } + + // resizeAll passes skipCallback because it triggers callbacks after ALL panes are resized + if (!skipCallback && state.initialized) + _runCallbacks("onresize_end", pane); + }); + } + + + /** + * @see window.onresize(), callbacks or custom code + */ +, resizeAll = function (evt) { + // stopPropagation if called by trigger("layoutdestroy") - use evtPane utility + evtPane(evt); + + if (!state.initialized) { + _initLayoutElements(); + return; // no need to resize since we just initialized! + } + var oldW = sC.innerWidth + , oldH = sC.innerHeight + ; + // cannot size layout when 'container' is hidden or collapsed + if (!$N.is(":visible") ) return; + $.extend(state.container, elDims( $N )); // UPDATE container dimensions + if (!sC.outerHeight) return; + + // onresizeall_start will CANCEL resizing if returns false + // state.container has already been set, so user can access this info for calcuations + if (false === _runCallbacks("onresizeall_start")) return false; + + var // see if container is now 'smaller' than before + shrunkH = (sC.innerHeight < oldH) + , shrunkW = (sC.innerWidth < oldW) + , $P, o, s, dir + ; + // NOTE special order for sizing: S-N-E-W + $.each(["south","north","east","west"], function (i, pane) { + if (!$Ps[pane]) return; // no pane - SKIP + s = state[pane]; + o = options[pane]; + dir = _c[pane].dir; + + if (o.autoResize && s.size != o.size) // resize pane to original size set in options + sizePane(pane, o.size, true, true, true); // true=skipCallback/forceResize/noAnimation + else { + setSizeLimits(pane); + makePaneFit(pane, false, true, true); // true=skipCallback/forceResize + } + }); + + sizeMidPanes("", true, true); // true=skipCallback, true=forceResize + sizeHandles(); // reposition the toggler elements + + // trigger all individual pane callbacks AFTER layout has finished resizing + o = options; // reuse alias + $.each(_c.allPanes, function (i, pane) { + $P = $Ps[pane]; + if (!$P) return; // SKIP + if (state[pane].isVisible) // undefined for non-existent panes + _runCallbacks("onresize_end", pane); // callback - if exists + }); + + _runCallbacks("onresizeall_end"); + //_triggerLayoutEvent(pane, 'resizeall'); + } + + /** + * Whenever a pane resizes or opens that has a nested layout, trigger resizeAll + * + * @param {string|Object} evt_or_pane The pane just resized or opened + */ +, resizeChildLayout = function (evt_or_pane) { + var pane = evtPane.call(this, evt_or_pane); + if (!options[pane].resizeChildLayout) return; + var $P = $Ps[pane] + , $C = $Cs[pane] + , d = "layout" + , P = Instance[pane] + , L = children[pane] + ; + // user may have manually set EITHER instance pointer, so handle that + if (P.child && !L) { + // have to reverse the pointers! + var el = P.child.container; + L = children[pane] = (el ? el.data(d) : 0) || null; // set pointer _directly_ to layout instance + } + + // if a layout-pointer exists, see if child has been destroyed + if (L && L.destroyed) + L = children[pane] = null; // clear child pointers + // no child layout pointer is set - see if there is a child layout NOW + if (!L) L = children[pane] = $P.data(d) || ($C ? $C.data(d) : 0) || null; // set/update child pointers + + // ALWAYS refresh the pane.child alias + P.child = children[pane]; + + if (L) L.resizeAll(); + } + + + /** + * IF pane has a content-div, then resize all elements inside pane to fit pane-height + * + * @param {string|Object} evt_or_panes The pane(s) being resized + * @param {boolean=} [remeasure=false] Should the content (header/footer) be remeasured? + */ +, sizeContent = function (evt_or_panes, remeasure) { + if (!isInitialized()) return; + + var panes = evtPane.call(this, evt_or_panes); + panes = panes ? panes.split(",") : _c.allPanes; + + $.each(panes, function (idx, pane) { + var + $P = $Ps[pane] + , $C = $Cs[pane] + , o = options[pane] + , s = state[pane] + , m = s.content // m = measurements + ; + if (!$P || !$C || !$P.is(":visible")) return true; // NOT VISIBLE - skip + + // if content-element was REMOVED, update OR remove the pointer + if (!$C.length) { + initContent(pane, false); // false = do NOT sizeContent() - already there! + if (!$C) return; // no replacement element found - pointer have been removed + } + + // onsizecontent_start will CANCEL resizing if returns false + if (false === _runCallbacks("onsizecontent_start", pane)) return; + + // skip re-measuring offsets if live-resizing + if ((!s.isMoving && !s.isResizing) || o.liveContentResizing || remeasure || m.top == undefined) { + _measure(); + // if any footers are below pane-bottom, they may not measure correctly, + // so allow pane overflow and re-measure + if (m.hiddenFooters > 0 && $P.css("overflow") === "hidden") { + $P.css("overflow", "visible"); + _measure(); // remeasure while overflowing + $P.css("overflow", "hidden"); + } + } + // NOTE: spaceAbove/Below *includes* the pane paddingTop/Bottom, but not pane.borders + var newH = s.innerHeight - (m.spaceAbove - s.css.paddingTop) - (m.spaceBelow - s.css.paddingBottom); + + if (!$C.is(":visible") || m.height != newH) { + // size the Content element to fit new pane-size - will autoHide if not enough room + setOuterHeight($C, newH, true); // true=autoHide + m.height = newH; // save new height + }; + + if (state.initialized) + _runCallbacks("onsizecontent_end", pane); + + function _below ($E) { + return max(s.css.paddingBottom, (parseInt($E.css("marginBottom"), 10) || 0)); + }; + + function _measure () { + var + ignore = options[pane].contentIgnoreSelector + , $Fs = $C.nextAll().not(ignore || ':lt(0)') // not :lt(0) = ALL + , $Fs_vis = $Fs.filter(':visible') + , $F = $Fs_vis.filter(':last') + ; + m = { + top: $C[0].offsetTop + , height: $C.outerHeight() + , numFooters: $Fs.length + , hiddenFooters: $Fs.length - $Fs_vis.length + , spaceBelow: 0 // correct if no content footer ($E) + } + m.spaceAbove = m.top; // just for state - not used in calc + m.bottom = m.top + m.height; + if ($F.length) + //spaceBelow = (LastFooter.top + LastFooter.height) [footerBottom] - Content.bottom + max(LastFooter.marginBottom, pane.paddingBotom) + m.spaceBelow = ($F[0].offsetTop + $F.outerHeight()) - m.bottom + _below($F); + else // no footer - check marginBottom on Content element itself + m.spaceBelow = _below($C); + }; + }); + } + + + /** + * Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary + * + * @see initHandles(), open(), close(), resizeAll() + * @param {string|Object} evt_or_panes The pane(s) being resized + */ +, sizeHandles = function (evt_or_panes) { + var panes = evtPane.call(this, evt_or_panes) + panes = panes ? panes.split(",") : _c.borderPanes; + + $.each(panes, function (i, pane) { + var + o = options[pane] + , s = state[pane] + , $P = $Ps[pane] + , $R = $Rs[pane] + , $T = $Ts[pane] + , $TC + ; + if (!$P || !$R) return; + + var + dir = _c[pane].dir + , _state = (s.isClosed ? "_closed" : "_open") + , spacing = o["spacing"+ _state] + , togAlign = o["togglerAlign"+ _state] + , togLen = o["togglerLength"+ _state] + , paneLen + , left + , offset + , CSS = {} + ; + + if (spacing === 0) { + $R.hide(); + return; + } + else if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason + $R.show(); // in case was previously hidden + + // Resizer Bar is ALWAYS same width/height of pane it is attached to + if (dir === "horz") { // north/south + //paneLen = $P.outerWidth(); // s.outerWidth || + paneLen = sC.innerWidth; // handle offscreen-panes + s.resizerLength = paneLen; + left = $.layout.cssNum($P, "left") + $R.css({ + width: cssW($R, paneLen) // account for borders & padding + , height: cssH($R, spacing) // ditto + , left: left > -9999 ? left : sC.insetLeft // handle offscreen-panes + }); + } + else { // east/west + paneLen = $P.outerHeight(); // s.outerHeight || + s.resizerLength = paneLen; + $R.css({ + height: cssH($R, paneLen) // account for borders & padding + , width: cssW($R, spacing) // ditto + , top: sC.insetTop + getPaneSize("north", true) // TODO: what if no North pane? + //, top: $.layout.cssNum($Ps["center"], "top") + }); + } + + // remove hover classes + removeHover( o, $R ); + + if ($T) { + if (togLen === 0 || (s.isSliding && o.hideTogglerOnSlide)) { + $T.hide(); // always HIDE the toggler when 'sliding' + return; + } + else + $T.show(); // in case was previously hidden + + if (!(togLen > 0) || togLen === "100%" || togLen > paneLen) { + togLen = paneLen; + offset = 0; + } + else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed + if (isStr(togAlign)) { + switch (togAlign) { + case "top": + case "left": offset = 0; + break; + case "bottom": + case "right": offset = paneLen - togLen; + break; + case "middle": + case "center": + default: offset = round((paneLen - togLen) / 2); // 'default' catches typos + } + } + else { // togAlign = number + var x = parseInt(togAlign, 10); // + if (togAlign >= 0) offset = x; + else offset = paneLen - togLen + x; // NOTE: x is negative! + } + } + + if (dir === "horz") { // north/south + var width = cssW($T, togLen); + $T.css({ + width: width // account for borders & padding + , height: cssH($T, spacing) // ditto + , left: offset // TODO: VERIFY that toggler positions correctly for ALL values + , top: 0 + }); + // CENTER the toggler content SPAN + $T.children(".content").each(function(){ + $TC = $(this); + $TC.css("marginLeft", round((width-$TC.outerWidth())/2)); // could be negative + }); + } + else { // east/west + var height = cssH($T, togLen); + $T.css({ + height: height // account for borders & padding + , width: cssW($T, spacing) // ditto + , top: offset // POSITION the toggler + , left: 0 + }); + // CENTER the toggler content SPAN + $T.children(".content").each(function(){ + $TC = $(this); + $TC.css("marginTop", round((height-$TC.outerHeight())/2)); // could be negative + }); + } + + // remove ALL hover classes + removeHover( 0, $T ); + } + + // DONE measuring and sizing this resizer/toggler, so can be 'hidden' now + if (!state.initialized && (o.initHidden || s.noRoom)) { + $R.hide(); + if ($T) $T.hide(); + } + }); + } + + + /** + * @param {string|Object} evt_or_pane + */ +, enableClosable = function (evt_or_pane) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $T = $Ts[pane] + , o = options[pane] + ; + if (!$T) return; + o.closable = true; + $T .bind("click."+ sID, function(evt){ evt.stopPropagation(); toggle(pane); }) + .css("visibility", "visible") + .css("cursor", "pointer") + .attr("title", state[pane].isClosed ? o.tips.Open : o.tips.Close) // may be blank + .show(); + } + /** + * @param {string|Object} evt_or_pane + * @param {boolean=} [hide=false] + */ +, disableClosable = function (evt_or_pane, hide) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $T = $Ts[pane] + ; + if (!$T) return; + options[pane].closable = false; + // is closable is disable, then pane MUST be open! + if (state[pane].isClosed) open(pane, false, true); + $T .unbind("."+ sID) + .css("visibility", hide ? "hidden" : "visible") // instead of hide(), which creates logic issues + .css("cursor", "default") + .attr("title", ""); + } + + + /** + * @param {string|Object} evt_or_pane + */ +, enableSlidable = function (evt_or_pane) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $R = $Rs[pane] + ; + if (!$R || !$R.data('draggable')) return; + options[pane].slidable = true; + if (state[pane].isClosed) + bindStartSlidingEvent(pane, true); + } + /** + * @param {string|Object} evt_or_pane + */ +, disableSlidable = function (evt_or_pane) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $R = $Rs[pane] + ; + if (!$R) return; + options[pane].slidable = false; + if (state[pane].isSliding) + close(pane, false, true); + else { + bindStartSlidingEvent(pane, false); + $R .css("cursor", "default") + .attr("title", ""); + removeHover(null, $R[0]); // in case currently hovered + } + } + + + /** + * @param {string|Object} evt_or_pane + */ +, enableResizable = function (evt_or_pane) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $R = $Rs[pane] + , o = options[pane] + ; + if (!$R || !$R.data('draggable')) return; + o.resizable = true; + $R.draggable("enable"); + if (!state[pane].isClosed) + $R .css("cursor", o.resizerCursor) + .attr("title", o.tips.Resize); + } + /** + * @param {string|Object} evt_or_pane + */ +, disableResizable = function (evt_or_pane) { + if (!isInitialized()) return; + var pane = evtPane.call(this, evt_or_pane) + , $R = $Rs[pane] + ; + if (!$R || !$R.data('draggable')) return; + options[pane].resizable = false; + $R .draggable("disable") + .css("cursor", "default") + .attr("title", ""); + removeHover(null, $R[0]); // in case currently hovered + } + + + /** + * Move a pane from source-side (eg, west) to target-side (eg, east) + * If pane exists on target-side, move that to source-side, ie, 'swap' the panes + * + * @param {string|Object} evt_or_pane1 The pane/edge being swapped + * @param {string} pane2 ditto + */ +, swapPanes = function (evt_or_pane1, pane2) { + if (!isInitialized()) return; + var pane1 = evtPane.call(this, evt_or_pane1); + // change state.edge NOW so callbacks can know where pane is headed... + state[pane1].edge = pane2; + state[pane2].edge = pane1; + // run these even if NOT state.initialized + if (false === _runCallbacks("onswap_start", pane1) + || false === _runCallbacks("onswap_start", pane2) + ) { + state[pane1].edge = pane1; // reset + state[pane2].edge = pane2; + return; + } + + var + oPane1 = copy( pane1 ) + , oPane2 = copy( pane2 ) + , sizes = {} + ; + sizes[pane1] = oPane1 ? oPane1.state.size : 0; + sizes[pane2] = oPane2 ? oPane2.state.size : 0; + + // clear pointers & state + $Ps[pane1] = false; + $Ps[pane2] = false; + state[pane1] = {}; + state[pane2] = {}; + + // ALWAYS remove the resizer & toggler elements + if ($Ts[pane1]) $Ts[pane1].remove(); + if ($Ts[pane2]) $Ts[pane2].remove(); + if ($Rs[pane1]) $Rs[pane1].remove(); + if ($Rs[pane2]) $Rs[pane2].remove(); + $Rs[pane1] = $Rs[pane2] = $Ts[pane1] = $Ts[pane2] = false; + + // transfer element pointers and data to NEW Layout keys + move( oPane1, pane2 ); + move( oPane2, pane1 ); + + // cleanup objects + oPane1 = oPane2 = sizes = null; + + // make panes 'visible' again + if ($Ps[pane1]) $Ps[pane1].css(_c.visible); + if ($Ps[pane2]) $Ps[pane2].css(_c.visible); + + // fix any size discrepancies caused by swap + resizeAll(); + + // run these even if NOT state.initialized + _runCallbacks("onswap_end", pane1); + _runCallbacks("onswap_end", pane2); + + return; + + function copy (n) { // n = pane + var + $P = $Ps[n] + , $C = $Cs[n] + ; + return !$P ? false : { + pane: n + , P: $P ? $P[0] : false + , C: $C ? $C[0] : false + , state: $.extend(true, {}, state[n]) + , options: $.extend(true, {}, options[n]) + } + }; + + function move (oPane, pane) { + if (!oPane) return; + var + P = oPane.P + , C = oPane.C + , oldPane = oPane.pane + , c = _c[pane] + , side = c.side.toLowerCase() + , inset = "inset"+ c.side + // save pane-options that should be retained + , s = $.extend(true, {}, state[pane]) + , o = options[pane] + // RETAIN side-specific FX Settings - more below + , fx = { resizerCursor: o.resizerCursor } + , re, size, pos + ; + $.each("fxName,fxSpeed,fxSettings".split(","), function (i, k) { + fx[k +"_open"] = o[k +"_open"]; + fx[k +"_close"] = o[k +"_close"]; + fx[k +"_size"] = o[k +"_size"]; + }); + + // update object pointers and attributes + $Ps[pane] = $(P) + .data({ + layoutPane: Instance[pane] // NEW pointer to pane-alias-object + , layoutEdge: pane + }) + .css(_c.hidden) + .css(c.cssReq) + ; + $Cs[pane] = C ? $(C) : false; + + // set options and state + options[pane] = $.extend(true, {}, oPane.options, fx); + state[pane] = $.extend(true, {}, oPane.state); + + // change classNames on the pane, eg: ui-layout-pane-east ==> ui-layout-pane-west + re = new RegExp(o.paneClass +"-"+ oldPane, "g"); + P.className = P.className.replace(re, o.paneClass +"-"+ pane); + + // ALWAYS regenerate the resizer & toggler elements + initHandles(pane); // create the required resizer & toggler + + // if moving to different orientation, then keep 'target' pane size + if (c.dir != _c[oldPane].dir) { + size = sizes[pane] || 0; + setSizeLimits(pane); // update pane-state + size = max(size, state[pane].minSize); + // use manualSizePane to disable autoResize - not useful after panes are swapped + manualSizePane(pane, size, true, true); // true/true = skipCallback/noAnimation + } + else // move the resizer here + $Rs[pane].css(side, sC[inset] + (state[pane].isVisible ? getPaneSize(pane) : 0)); + + + // ADD CLASSNAMES & SLIDE-BINDINGS + if (oPane.state.isVisible && !s.isVisible) + setAsOpen(pane, true); // true = skipCallback + else { + setAsClosed(pane); + bindStartSlidingEvent(pane, true); // will enable events IF option is set + } + + // DESTROY the object + oPane = null; + }; + } + + + /** + * INTERNAL method to sync pin-buttons when pane is opened or closed + * Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes + * + * @see open(), setAsOpen(), setAsClosed() + * @param {string} pane These are the params returned to callbacks by layout() + * @param {boolean} doPin True means set the pin 'down', False means 'up' + */ +, syncPinBtns = function (pane, doPin) { + if ($.layout.plugins.buttons) + $.each(state[pane].pins, function (i, selector) { + $.layout.buttons.setPinState(Instance, $(selector), pane, doPin); + }); + } + +; // END var DECLARATIONS + + /** + * Capture keys when enableCursorHotkey - toggle pane if hotkey pressed + * + * @see document.keydown() + */ + function keyDown (evt) { + if (!evt) return true; + var code = evt.keyCode; + if (code < 33) return true; // ignore special keys: ENTER, TAB, etc + + var + PANE = { + 38: "north" // Up Cursor - $.ui.keyCode.UP + , 40: "south" // Down Cursor - $.ui.keyCode.DOWN + , 37: "west" // Left Cursor - $.ui.keyCode.LEFT + , 39: "east" // Right Cursor - $.ui.keyCode.RIGHT + } + , ALT = evt.altKey // no worky! + , SHIFT = evt.shiftKey + , CTRL = evt.ctrlKey + , CURSOR = (CTRL && code >= 37 && code <= 40) + , o, k, m, pane + ; + + if (CURSOR && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey + pane = PANE[code]; + else if (CTRL || SHIFT) // check to see if this matches a custom-hotkey + $.each(_c.borderPanes, function (i, p) { // loop each pane to check its hotkey + o = options[p]; + k = o.customHotkey; + m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT" + if ((SHIFT && m=="SHIFT") || (CTRL && m=="CTRL") || (CTRL && SHIFT)) { // Modifier matches + if (k && code === (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches + pane = p; + return false; // BREAK + } + } + }); + + // validate pane + if (!pane || !$Ps[pane] || !options[pane].closable || state[pane].isHidden) + return true; + + toggle(pane); + + evt.stopPropagation(); + evt.returnValue = false; // CANCEL key + return false; + }; + + +/* + * ###################################### + * UTILITY METHODS + * called externally or by initButtons + * ###################################### + */ + + /** + * Change/reset a pane overflow setting & zIndex to allow popups/drop-downs to work + * + * @param {Object=} [el] (optional) Can also be 'bound' to a click, mouseOver, or other event + */ + function allowOverflow (el) { + if (!isInitialized()) return; + if (this && this.tagName) el = this; // BOUND to element + var $P; + if (isStr(el)) + $P = $Ps[el]; + else if ($(el).data("layoutRole")) + $P = $(el); + else + $(el).parents().each(function(){ + if ($(this).data("layoutRole")) { + $P = $(this); + return false; // BREAK + } + }); + if (!$P || !$P.length) return; // INVALID + + var + pane = $P.data("layoutEdge") + , s = state[pane] + ; + + // if pane is already raised, then reset it before doing it again! + // this would happen if allowOverflow is attached to BOTH the pane and an element + if (s.cssSaved) + resetOverflow(pane); // reset previous CSS before continuing + + // if pane is raised by sliding or resizing, or its closed, then abort + if (s.isSliding || s.isResizing || s.isClosed) { + s.cssSaved = false; + return; + } + + var + newCSS = { zIndex: (options.zIndexes.resizer_normal + 1) } + , curCSS = {} + , of = $P.css("overflow") + , ofX = $P.css("overflowX") + , ofY = $P.css("overflowY") + ; + // determine which, if any, overflow settings need to be changed + if (of != "visible") { + curCSS.overflow = of; + newCSS.overflow = "visible"; + } + if (ofX && !ofX.match(/(visible|auto)/)) { + curCSS.overflowX = ofX; + newCSS.overflowX = "visible"; + } + if (ofY && !ofY.match(/(visible|auto)/)) { + curCSS.overflowY = ofX; + newCSS.overflowY = "visible"; + } + + // save the current overflow settings - even if blank! + s.cssSaved = curCSS; + + // apply new CSS to raise zIndex and, if necessary, make overflow 'visible' + $P.css( newCSS ); + + // make sure the zIndex of all other panes is normal + $.each(_c.allPanes, function(i, p) { + if (p != pane) resetOverflow(p); + }); + + }; + /** + * @param {Object=} [el] (optional) Can also be 'bound' to a click, mouseOver, or other event + */ + function resetOverflow (el) { + if (!isInitialized()) return; + if (this && this.tagName) el = this; // BOUND to element + var $P; + if (isStr(el)) + $P = $Ps[el]; + else if ($(el).data("layoutRole")) + $P = $(el); + else + $(el).parents().each(function(){ + if ($(this).data("layoutRole")) { + $P = $(this); + return false; // BREAK + } + }); + if (!$P || !$P.length) return; // INVALID + + var + pane = $P.data("layoutEdge") + , s = state[pane] + , CSS = s.cssSaved || {} + ; + // reset the zIndex + if (!s.isSliding && !s.isResizing) + $P.css("zIndex", options.zIndexes.pane_normal); + + // reset Overflow - if necessary + $P.css( CSS ); + + // clear var + s.cssSaved = false; + }; + +/* + * ##################### + * CREATE/RETURN LAYOUT + * ##################### + */ + + // validate that container exists + var $N = $(this).eq(0); // FIRST matching Container element + if (!$N.length) { + return _log( options.errors.containerMissing ); + }; + + // Users retrieve Instance of a layout with: $N.layout() OR $N.data("layout") + // return the Instance-pointer if layout has already been initialized + if ($N.data("layoutContainer") && $N.data("layout")) + return $N.data("layout"); // cached pointer + + // init global vars + var + $Ps = {} // Panes x5 - set in initPanes() + , $Cs = {} // Content x5 - set in initPanes() + , $Rs = {} // Resizers x4 - set in initHandles() + , $Ts = {} // Togglers x4 - set in initHandles() + , $Ms = $([]) // Masks - up to 2 masks per pane (IFRAME + DIV) + // aliases for code brevity + , sC = state.container // alias for easy access to 'container dimensions' + , sID = state.id // alias for unique layout ID/namespace - eg: "layout435" + ; + + // create Instance object to expose data & option Properties, and primary action Methods + var Instance = { + // layout data + options: options // property - options hash + , state: state // property - dimensions hash + // object pointers + , container: $N // property - object pointers for layout container + , panes: $Ps // property - object pointers for ALL Panes: panes.north, panes.center + , contents: $Cs // property - object pointers for ALL Content: contents.north, contents.center + , resizers: $Rs // property - object pointers for ALL Resizers, eg: resizers.north + , togglers: $Ts // property - object pointers for ALL Togglers, eg: togglers.north + // border-pane open/close + , hide: hide // method - ditto + , show: show // method - ditto + , toggle: toggle // method - pass a 'pane' ("north", "west", etc) + , open: open // method - ditto + , close: close // method - ditto + , slideOpen: slideOpen // method - ditto + , slideClose: slideClose // method - ditto + , slideToggle: slideToggle // method - ditto + // pane actions + , setSizeLimits: setSizeLimits // method - pass a 'pane' - update state min/max data + , _sizePane: sizePane // method -intended for user by plugins only! + , sizePane: manualSizePane // method - pass a 'pane' AND an 'outer-size' in pixels or percent, or 'auto' + , sizeContent: sizeContent // method - pass a 'pane' + , swapPanes: swapPanes // method - pass TWO 'panes' - will swap them + , showMasks: showMasks // method - pass a 'pane' OR list of panes - default = all panes with mask option set + , hideMasks: hideMasks // method - ditto' + // pane element methods + , initContent: initContent // method - ditto + , addPane: addPane // method - pass a 'pane' + , removePane: removePane // method - pass a 'pane' to remove from layout, add 'true' to delete the pane-elem + , createChildLayout: createChildLayout// method - pass a 'pane' and (optional) layout-options (OVERRIDES options[pane].childOptions + // special pane option setting + , enableClosable: enableClosable // method - pass a 'pane' + , disableClosable: disableClosable // method - ditto + , enableSlidable: enableSlidable // method - ditto + , disableSlidable: disableSlidable // method - ditto + , enableResizable: enableResizable // method - ditto + , disableResizable: disableResizable// method - ditto + // utility methods for panes + , allowOverflow: allowOverflow // utility - pass calling element (this) + , resetOverflow: resetOverflow // utility - ditto + // layout control + , destroy: destroy // method - no parameters + , initPanes: isInitialized // method - no parameters + , resizeAll: resizeAll // method - no parameters + // callback triggering + , runCallbacks: _runCallbacks // method - pass evtName & pane (if a pane-event), eg: trigger("onopen", "west") + // alias collections of options, state and children - created in addPane and extended elsewhere + , hasParentLayout: false // set by initContainer() + , children: children // pointers to child-layouts, eg: Instance.children["west"] + , north: false // alias group: { name: pane, pane: $Ps[pane], options: options[pane], state: state[pane], child: children[pane] } + , south: false // ditto + , west: false // ditto + , east: false // ditto + , center: false // ditto + }; + + // create the border layout NOW + if (_create() === 'cancel') // onload_start callback returned false to CANCEL layout creation + return null; + else // true OR false -- if layout-elements did NOT init (hidden or do not exist), can auto-init later + return Instance; // return the Instance object + +} + + +/* OLD versions of jQuery only set $.support.boxModel after page is loaded + * so if this is IE, use support.boxModel to test for quirks-mode (ONLY IE changes boxModel). + */ +$(function(){ + var b = $.layout.browser; + if (b.msie) b.boxModel = $.support.boxModel; +}); + + +/** + * jquery.layout.state 1.0 + * $Date: 2011-07-16 08:00:00 (Sat, 16 July 2011) $ + * + * Copyright (c) 2010 + * Kevin Dalman (http://allpro.net) + * + * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html) + * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses. + * + * @dependancies: UI Layout 1.3.0.rc30.1 or higher + * @dependancies: $.ui.cookie (above) + * + * @support: http://groups.google.com/group/jquery-ui-layout + */ +/* + * State-management options stored in options.stateManagement, which includes a .cookie hash + * Default options saves ALL KEYS for ALL PANES, ie: pane.size, pane.isClosed, pane.isHidden + * + * // STATE/COOKIE OPTIONS + * @example $(el).layout({ + stateManagement: { + enabled: true + , stateKeys: "east.size,west.size,east.isClosed,west.isClosed" + , cookie: { name: "appLayout", path: "/" } + } + }) + * @example $(el).layout({ stateManagement__enabled: true }) // enable auto-state-management using cookies + * @example $(el).layout({ stateManagement__cookie: { name: "appLayout", path: "/" } }) + * @example $(el).layout({ stateManagement__cookie__name: "appLayout", stateManagement__cookie__path: "/" }) + * + * // STATE/COOKIE METHODS + * @example myLayout.saveCookie( "west.isClosed,north.size,south.isHidden", {expires: 7} ); + * @example myLayout.loadCookie(); + * @example myLayout.deleteCookie(); + * @example var JSON = myLayout.readState(); // CURRENT Layout State + * @example var JSON = myLayout.readCookie(); // SAVED Layout State (from cookie) + * @example var JSON = myLayout.state.stateData; // LAST LOADED Layout State (cookie saved in layout.state hash) + * + * CUSTOM STATE-MANAGEMENT (eg, saved in a database) + * @example var JSON = myLayout.readState( "west.isClosed,north.size,south.isHidden" ); + * @example myLayout.loadState( JSON ); + */ + +/** + * UI COOKIE UTILITY + * + * A $.cookie OR $.ui.cookie namespace *should be standard*, but until then... + * This creates $.ui.cookie so Layout does not need the cookie.jquery.js plugin + * NOTE: This utility is REQUIRED by the layout.state plugin + * + * Cookie methods in Layout are created as part of State Management + */ +if (!$.ui) $.ui = {}; +$.ui.cookie = { + + // cookieEnabled is not in DOM specs, but DOES works in all browsers,including IE6 + acceptsCookies: !!navigator.cookieEnabled + +, read: function (name) { + var + c = document.cookie + , cs = c ? c.split(';') : [] + , pair // loop var + ; + for (var i=0, n=cs.length; i < n; i++) { + pair = $.trim(cs[i]).split('='); // name=value pair + if (pair[0] == name) // found the layout cookie + return decodeURIComponent(pair[1]); + + } + return null; + } + +, write: function (name, val, cookieOpts) { + var + params = '' + , date = '' + , clear = false + , o = cookieOpts || {} + , x = o.expires + ; + if (x && x.toUTCString) + date = x; + else if (x === null || typeof x === 'number') { + date = new Date(); + if (x > 0) + date.setDate(date.getDate() + x); + else { + date.setFullYear(1970); + clear = true; + } + } + if (date) params += ';expires='+ date.toUTCString(); + if (o.path) params += ';path='+ o.path; + if (o.domain) params += ';domain='+ o.domain; + if (o.secure) params += ';secure'; + document.cookie = name +'='+ (clear ? "" : encodeURIComponent( val )) + params; // write or clear cookie + } + +, clear: function (name) { + $.ui.cookie.write(name, '', {expires: -1}); + } + +}; +// if cookie.jquery.js is not loaded, create an alias to replicate it +// this may be useful to other plugins or code dependent on that plugin +if (!$.cookie) $.cookie = function (k, v, o) { + var C = $.ui.cookie; + if (v === null) + C.clear(k); + else if (v === undefined) + return C.read(k); + else + C.write(k, v, o); +}; + + +// tell Layout that the state plugin is available +$.layout.plugins.stateManagement = true; + +// Add State-Management options to layout.defaults +$.layout.config.optionRootKeys.push("stateManagement"); +$.layout.defaults.stateManagement = { + enabled: false // true = enable state-management, even if not using cookies +, autoSave: true // Save a state-cookie when page exits? +, autoLoad: true // Load the state-cookie when Layout inits? + // List state-data to save - must be pane-specific +, stateKeys: "north.size,south.size,east.size,west.size,"+ + "north.isClosed,south.isClosed,east.isClosed,west.isClosed,"+ + "north.isHidden,south.isHidden,east.isHidden,west.isHidden" +, cookie: { + name: "" // If not specified, will use Layout.name, else just "Layout" + , domain: "" // blank = current domain + , path: "" // blank = current page, '/' = entire website + , expires: "" // 'days' to keep cookie - leave blank for 'session cookie' + , secure: false + } +}; +// Set stateManagement as a layout-option, NOT a pane-option +$.layout.optionsMap.layout.push("stateManagement"); + +/* + * State Management methods + */ +$.layout.state = { + + /** + * Get the current layout state and save it to a cookie + * + * myLayout.saveCookie( keys, cookieOpts ) + * + * @param {Object} inst + * @param {(string|Array)=} keys + * @param {Object=} cookieOpts + */ + saveCookie: function (inst, keys, cookieOpts) { + var o = inst.options + , oS = o.stateManagement + , oC = $.extend(true, {}, oS.cookie, cookieOpts || null) + , data = inst.state.stateData = inst.readState( keys || oS.stateKeys ) // read current panes-state + ; + $.ui.cookie.write( oC.name || o.name || "Layout", $.layout.state.encodeJSON(data), oC ); + return $.extend(true, {}, data); // return COPY of state.stateData data + } + + /** + * Remove the state cookie + * + * @param {Object} inst + */ +, deleteCookie: function (inst) { + var o = inst.options; + $.ui.cookie.clear( o.stateManagement.cookie.name || o.name || "Layout" ); + } + + /** + * Read & return data from the cookie - as JSON + * + * @param {Object} inst + */ +, readCookie: function (inst) { + var o = inst.options; + var c = $.ui.cookie.read( o.stateManagement.cookie.name || o.name || "Layout" ); + // convert cookie string back to a hash and return it + return c ? $.layout.state.decodeJSON(c) : {}; + } + + /** + * Get data from the cookie and USE IT to loadState + * + * @param {Object} inst + */ +, loadCookie: function (inst) { + var c = $.layout.state.readCookie(inst); // READ the cookie + if (c) { + inst.state.stateData = $.extend(true, {}, c); // SET state.stateData + inst.loadState(c); // LOAD the retrieved state + } + return c; + } + + /** + * Update layout options from the cookie, if one exists + * + * @param {Object} inst + * @param {Object=} stateData + * @param {boolean=} animate + */ +, loadState: function (inst, stateData, animate) { + stateData = $.layout.transformData( stateData ); // panes = default subkey + if ($.isEmptyObject( stateData )) return; + $.extend(true, inst.options, stateData); // update layout options + // if layout has already been initialized, then UPDATE layout state + if (inst.state.initialized) { + var pane, vis, o, s, h, c + , noAnimate = (animate===false) + ; + $.each($.layout.config.borderPanes, function (idx, pane) { + state = inst.state[pane]; + o = stateData[ pane ]; + if (typeof o != 'object') return; // no key, continue + s = o.size; + c = o.initClosed; + h = o.initHidden; + vis = state.isVisible; + // resize BEFORE opening + if (!vis) + inst.sizePane(pane, s, false, false); + if (h === true) inst.hide(pane, noAnimate); + else if (c === false) inst.open (pane, false, noAnimate); + else if (c === true) inst.close(pane, false, noAnimate); + else if (h === false) inst.show (pane, false, noAnimate); + // resize AFTER any other actions + if (vis) + inst.sizePane(pane, s, false, noAnimate); // animate resize if option passed + }); + }; + } + + /** + * Get the *current layout state* and return it as a hash + * + * @param {Object=} inst + * @param {(string|Array)=} keys + */ +, readState: function (inst, keys) { + var + data = {} + , alt = { isClosed: 'initClosed', isHidden: 'initHidden' } + , state = inst.state + , panes = $.layout.config.allPanes + , pair, pane, key, val + ; + if (!keys) keys = inst.options.stateManagement.stateKeys; // if called by user + if ($.isArray(keys)) keys = keys.join(","); + // convert keys to an array and change delimiters from '__' to '.' + keys = keys.replace(/__/g, ".").split(','); + // loop keys and create a data hash + for (var i=0, n=keys.length; i < n; i++) { + pair = keys[i].split("."); + pane = pair[0]; + key = pair[1]; + if ($.inArray(pane, panes) < 0) continue; // bad pane! + val = state[ pane ][ key ]; + if (val == undefined) continue; + if (key=="isClosed" && state[pane]["isSliding"]) + val = true; // if sliding, then *really* isClosed + ( data[pane] || (data[pane]={}) )[ alt[key] ? alt[key] : key ] = val; + } + return data; + } + + /** + * Stringify a JSON hash so can save in a cookie or db-field + */ +, encodeJSON: function (JSON) { + return parse(JSON); + function parse (h) { + var D=[], i=0, k, v, t; // k = key, v = value + for (k in h) { + v = h[k]; + t = typeof v; + if (t == 'string') // STRING - add quotes + v = '"'+ v +'"'; + else if (t == 'object') // SUB-KEY - recurse into it + v = parse(v); + D[i++] = '"'+ k +'":'+ v; + } + return '{'+ D.join(',') +'}'; + }; + } + + /** + * Convert stringified JSON back to a hash object + * @see $.parseJSON(), adding in jQuery 1.4.1 + */ +, decodeJSON: function (str) { + try { return $.parseJSON ? $.parseJSON(str) : window["eval"]("("+ str +")") || {}; } + catch (e) { return {}; } + } + + +, _create: function (inst) { + var _ = $.layout.state; + // ADD State-Management plugin methods to inst + $.extend( inst, { + // readCookie - update options from cookie - returns hash of cookie data + readCookie: function () { return _.readCookie(inst); } + // deleteCookie + , deleteCookie: function () { _.deleteCookie(inst); } + // saveCookie - optionally pass keys-list and cookie-options (hash) + , saveCookie: function (keys, cookieOpts) { return _.saveCookie(inst, keys, cookieOpts); } + // loadCookie - readCookie and use to loadState() - returns hash of cookie data + , loadCookie: function () { return _.loadCookie(inst); } + // loadState - pass a hash of state to use to update options + , loadState: function (stateData, animate) { _.loadState(inst, stateData, animate); } + // readState - returns hash of current layout-state + , readState: function (keys) { return _.readState(inst, keys); } + // add JSON utility methods too... + , encodeJSON: _.encodeJSON + , decodeJSON: _.decodeJSON + }); + + // init state.stateData key, even if plugin is initially disabled + inst.state.stateData = {}; + + // read and load cookie-data per options + var oS = inst.options.stateManagement; + if (oS.enabled) { + if (oS.autoLoad) // update the options from the cookie + inst.loadCookie(); + else // don't modify options - just store cookie data in state.stateData + inst.state.stateData = inst.readCookie(); + } + } + +, _unload: function (inst) { + var oS = inst.options.stateManagement; + if (oS.enabled) { + if (oS.autoSave) // save a state-cookie automatically + inst.saveCookie(); + else // don't save a cookie, but do store state-data in state.stateData key + inst.state.stateData = inst.readState(); + } + } + +}; + +// add state initialization method to Layout's onCreate array of functions +$.layout.onCreate.push( $.layout.state._create ); +$.layout.onUnload.push( $.layout.state._unload ); + + + + +/** + * jquery.layout.buttons 1.0 + * $Date: 2011-07-16 08:00:00 (Sat, 16 July 2011) $ + * + * Copyright (c) 2010 + * Kevin Dalman (http://allpro.net) + * + * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html) + * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses. + * + * @dependancies: UI Layout 1.3.0.rc30.1 or higher + * + * @support: http://groups.google.com/group/jquery-ui-layout + * + * Docs: [ to come ] + * Tips: [ to come ] + */ + +// tell Layout that the state plugin is available +$.layout.plugins.buttons = true; + +// Add buttons options to layout.defaults +$.layout.defaults.autoBindCustomButtons = false; +// Specify autoBindCustomButtons as a layout-option, NOT a pane-option +$.layout.optionsMap.layout.push("autoBindCustomButtons"); + +/* + * Button methods + */ +$.layout.buttons = { + + /** + * Searches for .ui-layout-button-xxx elements and auto-binds them as layout-buttons + * + * @see _create() + * + * @param {Object} inst Layout Instance object + */ + init: function (inst) { + var pre = "ui-layout-button-" + , layout = inst.options.name || "" + , name; + $.each("toggle,open,close,pin,toggle-slide,open-slide".split(","), function (i, action) { + $.each($.layout.config.borderPanes, function (ii, pane) { + $("."+pre+action+"-"+pane).each(function(){ + // if button was previously 'bound', data.layoutName was set, but is blank if layout has no 'name' + name = $(this).data("layoutName") || $(this).attr("layoutName"); + if (name == undefined || name === layout) + inst.bindButton(this, action, pane); + }); + }); + }); + } + + /** + * Helper function to validate params received by addButton utilities + * + * Two classes are added to the element, based on the buttonClass... + * The type of button is appended to create the 2nd className: + * - ui-layout-button-pin // action btnClass + * - ui-layout-button-pin-west // action btnClass + pane + * - ui-layout-button-toggle + * - ui-layout-button-open + * - ui-layout-button-close + * + * @param {Object} inst Layout Instance object + * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" + * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. + * + * @return {Array.} If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise returns null + */ +, get: function (inst, selector, pane, action) { + var $E = $(selector) + , o = inst.options + , err = o.errors.addButtonError + ; + if (!$E.length) { // element not found + $.layout.msg(err +" "+ o.errors.selector +": "+ selector, true); + } + else if ($.inArray(pane, $.layout.config.borderPanes) < 0) { // invalid 'pane' sepecified + $.layout.msg(err +" "+ o.errors.pane +": "+ pane, true); + $E = $(""); // NO BUTTON + } + else { // VALID + var btn = o[pane].buttonClass +"-"+ action; + $E .addClass( btn +" "+ btn +"-"+ pane ) + .data("layoutName", o.name); // add layout identifier - even if blank! + } + return $E; + } + + + /** + * NEW syntax for binding layout-buttons - will eventually replace addToggle, addOpen, etc. + * + * @param {Object} inst Layout Instance object + * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" + * @param {string} action + * @param {string} pane + */ +, bind: function (inst, selector, action, pane) { + var _ = $.layout.buttons; + switch (action.toLowerCase()) { + case "toggle": _.addToggle (inst, selector, pane); break; + case "open": _.addOpen (inst, selector, pane); break; + case "close": _.addClose (inst, selector, pane); break; + case "pin": _.addPin (inst, selector, pane); break; + case "toggle-slide": _.addToggle (inst, selector, pane, true); break; + case "open-slide": _.addOpen (inst, selector, pane, true); break; + } + return inst; + } + + /** + * Add a custom Toggler button for a pane + * + * @param {Object} inst Layout Instance object + * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" + * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. + * @param {boolean=} slide true = slide-open, false = pin-open + */ +, addToggle: function (inst, selector, pane, slide) { + $.layout.buttons.get(inst, selector, pane, "toggle") + .click(function(evt){ + inst.toggle(pane, !!slide); + evt.stopPropagation(); + }); + return inst; + } + + /** + * Add a custom Open button for a pane + * + * @param {Object} inst Layout Instance object + * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" + * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. + * @param {boolean=} slide true = slide-open, false = pin-open + */ +, addOpen: function (inst, selector, pane, slide) { + $.layout.buttons.get(inst, selector, pane, "open") + .attr("title", inst.options[pane].tips.Open) + .click(function (evt) { + inst.open(pane, !!slide); + evt.stopPropagation(); + }); + return inst; + } + + /** + * Add a custom Close button for a pane + * + * @param {Object} inst Layout Instance object + * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" + * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. + */ +, addClose: function (inst, selector, pane) { + $.layout.buttons.get(inst, selector, pane, "close") + .attr("title", inst.options[pane].tips.Close) + .click(function (evt) { + inst.close(pane); + evt.stopPropagation(); + }); + return inst; + } + + /** + * Add a custom Pin button for a pane + * + * Four classes are added to the element, based on the paneClass for the associated pane... + * Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin: + * - ui-layout-pane-pin + * - ui-layout-pane-west-pin + * - ui-layout-pane-pin-up + * - ui-layout-pane-west-pin-up + * + * @param {Object} inst Layout Instance object + * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" + * @param {string} pane Name of the pane the pin is for: 'north', 'south', etc. + */ +, addPin: function (inst, selector, pane) { + var _ = $.layout.buttons + , $E = _.get(inst, selector, pane, "pin"); + if ($E.length) { + var s = inst.state[pane]; + $E.click(function (evt) { + _.setPinState(inst, $(this), pane, (s.isSliding || s.isClosed)); + if (s.isSliding || s.isClosed) inst.open( pane ); // change from sliding to open + else inst.close( pane ); // slide-closed + evt.stopPropagation(); + }); + // add up/down pin attributes and classes + _.setPinState(inst, $E, pane, (!s.isClosed && !s.isSliding)); + // add this pin to the pane data so we can 'sync it' automatically + // PANE.pins key is an array so we can store multiple pins for each pane + s.pins.push( selector ); // just save the selector string + } + return inst; + } + + /** + * Change the class of the pin button to make it look 'up' or 'down' + * + * @see addPin(), syncPins() + * + * @param {Object} inst Layout Instance object + * @param {Array.} $Pin The pin-span element in a jQuery wrapper + * @param {string} pane These are the params returned to callbacks by layout() + * @param {boolean} doPin true = set the pin 'down', false = set it 'up' + */ +, setPinState: function (inst, $Pin, pane, doPin) { + var updown = $Pin.attr("pin"); + if (updown && doPin === (updown=="down")) return; // already in correct state + var + o = inst.options[pane] + , pin = o.buttonClass +"-pin" + , side = pin +"-"+ pane + , UP = pin +"-up "+ side +"-up" + , DN = pin +"-down "+side +"-down" + ; + $Pin + .attr("pin", doPin ? "down" : "up") // logic + .attr("title", doPin ? o.tips.Unpin : o.tips.Pin) + .removeClass( doPin ? UP : DN ) + .addClass( doPin ? DN : UP ) + ; + } + + /** + * INTERNAL function to sync 'pin buttons' when pane is opened or closed + * Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes + * + * @see open(), close() + * + * @param {Object} inst Layout Instance object + * @param {string} pane These are the params returned to callbacks by layout() + * @param {boolean} doPin True means set the pin 'down', False means 'up' + */ +, syncPinBtns: function (inst, pane, doPin) { + // REAL METHOD IS _INSIDE_ LAYOUT - THIS IS HERE JUST FOR REFERENCE + $.each(inst.state[pane].pins, function (i, selector) { + $.layout.buttons.setPinState(inst, $(selector), pane, doPin); + }); + } + + +, _load: function (inst) { + var _ = $.layout.buttons; + // ADD Button methods to Layout Instance + // Note: sel = jQuery Selector string + $.extend( inst, { + bindButton: function (sel, action, pane) { return _.bind(inst, sel, action, pane); } + // DEPRECATED METHODS + , addToggleBtn: function (sel, pane, slide) { return _.addToggle(inst, sel, pane, slide); } + , addOpenBtn: function (sel, pane, slide) { return _.addOpen(inst, sel, pane, slide); } + , addCloseBtn: function (sel, pane) { return _.addClose(inst, sel, pane); } + , addPinBtn: function (sel, pane) { return _.addPin(inst, sel, pane); } + }); + + // init state array to hold pin-buttons + for (var i=0; i<4; i++) { + var pane = $.layout.config.borderPanes[i]; + inst.state[pane].pins = []; + } + + // auto-init buttons onLoad if option is enabled + if ( inst.options.autoBindCustomButtons ) + _.init(inst); + } + +, _unload: function (inst) { + // TODO: unbind all buttons??? + } + +}; + +// add initialization method to Layout's onLoad array of functions +$.layout.onLoad.push( $.layout.buttons._load ); +//$.layout.onUnload.push( $.layout.buttons._unload ); + + + +/** + * jquery.layout.browserZoom 1.0 + * $Date: 2011-12-29 08:00:00 (Thu, 29 Dec 2011) $ + * + * Copyright (c) 2012 + * Kevin Dalman (http://allpro.net) + * + * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html) + * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses. + * + * @dependancies: UI Layout 1.3.0.rc30.1 or higher + * + * @support: http://groups.google.com/group/jquery-ui-layout + * + * @todo: Extend logic to handle other problematic zooming in browsers + * @todo: Add hotkey/mousewheel bindings to _instantly_ respond to these zoom event + */ + +// tell Layout that the plugin is available +$.layout.plugins.browserZoom = true; + +$.layout.defaults.browserZoomCheckInterval = 1000; +$.layout.optionsMap.layout.push("browserZoomCheckInterval"); + +/* + * browserZoom methods + */ +$.layout.browserZoom = { + + _init: function (inst) { + // abort if browser does not need this check + if ($.layout.browserZoom.ratio() !== false) + $.layout.browserZoom._setTimer(inst); + } + +, _setTimer: function (inst) { + // abort if layout destroyed or browser does not need this check + if (inst.destroyed) return; + var o = inst.options + , s = inst.state + // don't need check if inst has parentLayout, but check occassionally in case parent destroyed! + // MINIMUM 100ms interval, for performance + , ms = inst.hasParentLayout ? 5000 : Math.max( o.browserZoomCheckInterval, 100 ) + ; + // set the timer + setTimeout(function(){ + if (inst.destroyed || !o.resizeWithWindow) return; + var d = $.layout.browserZoom.ratio(); + if (d !== s.browserZoom) { + s.browserZoom = d; + inst.resizeAll(); + } + // set a NEW timeout + $.layout.browserZoom._setTimer(inst); + } + , ms ); + } + +, ratio: function () { + var w = window + , s = screen + , d = document + , dE = d.documentElement || d.body + , b = $.layout.browser + , v = b.version + , r, sW, cW + ; + // we can ignore all browsers that fire window.resize event onZoom + if ((b.msie && v > 8) + || !b.msie + ) return false; // don't need to track zoom + + if (s.deviceXDPI) + return calc(s.deviceXDPI, s.systemXDPI); + // everything below is just for future reference! + if (b.webkit && (r = d.body.getBoundingClientRect)) + return calc((r.left - r.right), d.body.offsetWidth); + if (b.webkit && (sW = w.outerWidth)) + return calc(sW, w.innerWidth); + if ((sW = s.width) && (cW = dE.clientWidth)) + return calc(sW, cW); + return false; // no match, so cannot - or don't need to - track zoom + + function calc (x,y) { return (parseInt(x,10) / parseInt(y,10) * 100).toFixed(); } + } + +}; +// add initialization method to Layout's onLoad array of functions +$.layout.onReady.push( $.layout.browserZoom._init ); + + + +})( jQuery ); diff --git a/nebula-exchange/target/site/scaladocs/lib/modernizr.custom.js b/nebula-exchange/target/site/scaladocs/lib/modernizr.custom.js new file mode 100644 index 0000000..4688d63 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/lib/modernizr.custom.js @@ -0,0 +1,4 @@ +/* Modernizr 2.5.3 (Custom Build) | MIT & BSD + * Build: http://www.modernizr.com/download/#-inlinesvg + */ +;window.Modernizr=function(a,b,c){function u(a){i.cssText=a}function v(a,b){return u(prefixes.join(a+";")+(b||""))}function w(a,b){return typeof a===b}function x(a,b){return!!~(""+a).indexOf(b)}function y(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:w(f,"function")?f.bind(d||b):f}return!1}var d="2.5.3",e={},f=b.documentElement,g="modernizr",h=b.createElement(g),i=h.style,j,k={}.toString,l={svg:"http://www.w3.org/2000/svg"},m={},n={},o={},p=[],q=p.slice,r,s={}.hasOwnProperty,t;!w(s,"undefined")&&!w(s.call,"undefined")?t=function(a,b){return s.call(a,b)}:t=function(a,b){return b in a&&w(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=q.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(q.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(q.call(arguments)))};return e}),m.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==l.svg};for(var z in m)t(m,z)&&(r=z.toLowerCase(),e[r]=m[z](),p.push((e[r]?"":"no-")+r));return u(""),h=j=null,e._version=d,e}(this,this.document); \ No newline at end of file diff --git a/nebula-exchange/target/site/scaladocs/lib/navigation-li-a.png b/nebula-exchange/target/site/scaladocs/lib/navigation-li-a.png new file mode 100644 index 0000000000000000000000000000000000000000..9b32288e045cd94e6aaa0e35f1382a32b66b64da GIT binary patch literal 1198 zcmV;f1X25mP)0Ed!4I%dZ`*&Mwa}$^y=pHO+G~4PFP7cgqNtZ$C@d7b6ueY6EfuxhrRxTb z)T~ya&4-y}ob2<=X3~k7NxbNd&;u{Yob#Obyyrdd`As60N+sbYO%iU{{(GSei@|cR zGuS!IGHA!t)YSc>qoYVJmkV`tbOa?y%A-GH<cUdUK5PPe5tZ@r@f1t2MrgzaZ_?1v&`X^EOYTd)E}{V5 zBrKVnoSggx-ATO$jP%fpVLd%Pujc0F5{5_@ayADsL3F#_>Dk%Yz5f3G7Z^K)6)Qpn zoJ9)q;cz%LF)?w9y#0>;RLvb1c-_vPEfnk7>VDetXch|w0?yBgaf#`E?QVv5aiCz&KRmDhNAfN^78T-K0o8c>nA1wPy%=( z5O)C7Bna^FIwN@nhG5-_N*fR(<+ zq>qj3TywAajG8nc@EFK`im!TA3)hW85RIX9A?8oY4r+x)7>pTN`NDE(b3=>*Kswq` zNUzwar=gJ9Ku*PmLY@vbr8N{X*`Qgbp%6vFqur}3(J40bgKfgu z08jxxn!Z|ES}Ii0%)Df8Z?DkT*Y{|3b@d57S1nymg#dUKQ9<9L>pLLu-{j-%q}L*f zRsa{DVTI4v*4BQbh?6UYJ3Ku6bNMgH6WG(0l@54P5=M^ M07*qoM6N<$g5>W?*#H0l literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/navigation-li.png b/nebula-exchange/target/site/scaladocs/lib/navigation-li.png new file mode 100644 index 0000000000000000000000000000000000000000..fd0ad06e819742b15f3a982a9b2e50bbaa886a1e GIT binary patch literal 2441 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 TK(qrA00000NkvXXu0mjfp!~2x literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/object_diagram.png b/nebula-exchange/target/site/scaladocs/lib/object_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..6e9f2f743f67c15e04846f14819a913713b216e4 GIT binary patch literal 3903 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 N002ovPDHLkV1kt{Q<4Ax literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/object_to_class_big.png b/nebula-exchange/target/site/scaladocs/lib/object_to_class_big.png new file mode 100644 index 0000000000000000000000000000000000000000..7502942eb68134f5569c5c00e84533f452093c43 GIT binary patch literal 9158 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 Qv;Y7A07*qoM6N<$f);0?GXMYp literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/object_to_trait_big.png b/nebula-exchange/target/site/scaladocs/lib/object_to_trait_big.png new file mode 100644 index 0000000000000000000000000000000000000000..c777bfce8dd0a169f484641a3f439720fd23c427 GIT binary patch literal 9200 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 Qv;Y7A07*qoM6N<$f);0?GXMYp literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/ownderbg2.gif b/nebula-exchange/target/site/scaladocs/lib/ownderbg2.gif new file mode 100644 index 0000000000000000000000000000000000000000..848dd5963a133dc18b9f055928150dc5e762dde0 GIT binary patch literal 1145 zcmZ?wbhEHbWMq(F*v!D-Kff?yQ@u%!Pt?vPr`9;D%FyV&t)7!JLsnHrA8cd50E+*) zBYXoCToOwXfwYZ%ML}Y6c4~=2Qfhi;o~_dR-TRdkGE;1o!cBb*d<&dYGcrA@ic*8C z{6dnevXd=SlxV%Qmue&kg&dz0$52&wylyQ zNJ0T*r*nQ$s)DJWfo`&anSp|tp`M|!iMhGCj)IYap@F`Ek-njkuA#Y=v5}R5fdUjL z0c|TvNwW%aaf8|g1^l#~=$>Fbx5m+O@q>*W`v>l<2HT7t|lGSUUA&@HaaD@m-- z%_~-hnc$LIoLrPyP?DLSrvNfBF)6>a#8wIDQivCF3*g4)73+b$qnDhYt6z~=pl_&W z0P+${p|3A~rMbCq)x{-2sR;LCHMlsWvLIDID784hv?w_hs9YIjRe_arQEFmIeo;t% zehw@Y12XbU@{2R_3lyA#O%;3-lQZ)`e6V_7Un|eN;*!L?t5X6BYAPL3ueX-RQWVL^UgZccVqW=48iYD#iaVnTdeY)o`iWJGvaXh?8SV1U1$uaCEv zr-!?ntBbRfql3Mjt&O#nrG>efsfn=>FiYv_>S$|eYN)HJswgWdD#**p%1BE|N{EYz ziUvE+||Kg4FF`M Bj3xj8 literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/ownerbg.gif b/nebula-exchange/target/site/scaladocs/lib/ownerbg.gif new file mode 100644 index 0000000000000000000000000000000000000000..34a04249ee9edc75662a2539fe7daa04424cbe8d GIT binary patch literal 1118 zcmZ?wbhEHbWMq(FSj50^;>3wdmoDwuvuDGG4L5JzWPkz1|J)J20SYdOC5b@V#=fE; zF*!T6L?J0PJu}Z%>HY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C$yM3OmMKd1b_zBX zRu#Dgxv3?I3Kh9IdBs*0wn~X9`AMl(KsHENUr7P1q$Jx`$q^)>0J76LzbI9~RL?*+ z*}%*|!OT$4(AdP>++0V&$iUD*-@r)U&`8(N+{)O<%D_MY3Y37h6{VzE1-ZCE?E>;_ zl`=|73as??%gf94%8m8%i_-NCEiElUW*8ai0#)c1SLT%@R_NvxE5l51Ni9w;$}A|! z%+FH*nV6WAUs__T1av9H3%LbwWAlpjz~0eI&d=4aNG#Ad)H48i38v837r)ZnT)67u zlAu(Cd$Af^98y`3svneEoL^d$oC;K~46>@g%DE^tu_V7JBtJg~7K#BG`6cQEUIa|mjQ{`r z{qy_R&mZ5vef{$J)5j0*-@SeF`qj%9&!0Vg^7zri2lwyYy>t84%^TORUA=Po(!~qs z&z(JU`qar2$B!L7a`@1}1N-;w-Lrew&K=vgZQZhY)5ZeMTG_V zdAT{+S(zE>X{jm6Nr?&Zaj`McQIQehVWAmo_rKzE=rmCW>q^KY-Co3Z@B`F~;CMqH&FX#K^#)_>%=(Oz40}P&vZD%P=Ep@ zplwAdX;wilZcw{`JX@uVl9B=|ef{$Ca=mh6z5JqdeM3u2OOP2xM!G;1y2X`wC5aWf zdBw^w6I@b@lZ!G7N;32F6hI~>Cgqow*eU^C3h_d20o>TUVm+{T^pf*)^(zt!^bPe4 zKwg3=^!3HBG&dKny0|1L72#g21{a4^7NqJ2r55Lx7A2%-qt%$eX-RQWVL^UgZccVqW=48iYD#iaVnTdeY)o`iWJGva zXh?8SV1U1$uaCEvr-!?ntBbRfql3Mjt&KG>(#*|FO^l6zSxQe=M_Wr%LtRZ(MOjHv zL0(Q)Mp{ZzLR?H#L|8~rfS-?-hntI&gPo0)g_((wfkE*n3%I<{0g<5cg@J|3;H2kk MO(h-&o-PJ!02;c9Qvd(} literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/package.png b/nebula-exchange/target/site/scaladocs/lib/package.png new file mode 100644 index 0000000000000000000000000000000000000000..6ea17ac320ec13c02680c5549cf496d007ea6acf GIT binary patch literal 3335 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 Y0AfCQM(Z-J8vp 0) { + var fn = scheduler.queues[idx].shift(); + } + return fn; + } + this.add = function(labelName, fn, self, args) { + var doWork = function() { + scheduler.timeout = setTimeout(function() { + var work = scheduler.nextWork(); + if (work != undefined) { + if (work.args == undefined) { work.args = new Array(0); } + work.fn.apply(work.self, work.args); + doWork(); + } + else { + scheduler.timeout = undefined; + } + }, resolution); + } + var idx = 0; + while (idx < scheduler.labels.length && scheduler.labels[idx].name != labelName) { idx = idx + 1; } + if (idx < scheduler.queues.length && scheduler.labels[idx].name == labelName) { + scheduler.queues[idx].push(new scheduler.work(fn, self, args)); + if (scheduler.timeout == undefined) doWork(); + } + else throw("queue for add is non existant"); + } + this.clear = function(labelName) { + var idx = 0; + while (idx < scheduler.labels.length && scheduler.labels[idx].name != labelName) { idx = idx + 1; } + if (idx < scheduler.queues.length && scheduler.labels[idx].name == labelName) { + scheduler.queues[idx] = new Array(); + } + } +}; diff --git a/nebula-exchange/target/site/scaladocs/lib/selected-implicits.png b/nebula-exchange/target/site/scaladocs/lib/selected-implicits.png new file mode 100644 index 0000000000000000000000000000000000000000..bc29efb3e60134039e702d5449e685a3bc103f06 GIT binary patch literal 1150 zcmV-^1cCdBP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyb% z5H~J^JxS;Q00aI>L_t(|+U?vuZxlxy$MNqx?(E$@E}a zfjgk2pr?ZZI(iC9{1RM5N`az8f(nF?5D#);fpbJL7e%q}e0%#alfpQ%40!>*o6k0< z)o$~be)`Ys+>8hzu;10IR{^+p@16iY2d04rkO6`yI{X6A1$Kbce*=Su~m%6x<};NBO|^=w zk&&8I8D)eJLdB9s!^&AlTBkBiQk->uv$J_(rL!`)+`6oQUo`M-?(?sntUozBH8I6_ zIxd}cS_u`9v4GL=Q$k^s5ms8Mgc48JpPpKtTHbQf?P%cW>elMKv(Ak-$BSmt)JB*% z&xl4SAz&~lr34aLhuW=ft3By}IX+c#V!libhr?D})eoI+@M^s{y;vSm62A^F$)OitB>WC^wMc2_eXZ#=?IA zNtVo#TvKb>y}k`n5t#j!>IqWhwOAZQtfS?qODbc_%JAp{Bv5|M;+$+>D$O;$h+90zjvct@cD=76Um1hr9bhBs%or0LWw(j4&M0NBo?c3qpt*ILGd`+j8&ukM^WrzkZ!NckX<_?$*Qo z%j$87JsKwA!0%(gp9dfM)S(Ug1JPplRFf1Ki#3gg$o7X})F#m3e@->|7sOS0SbEhV Q8UO$Q07*qoM6N<$f{R8S_y7O^ literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/selected-right-implicits.png b/nebula-exchange/target/site/scaladocs/lib/selected-right-implicits.png new file mode 100644 index 0000000000000000000000000000000000000000..8313f4975b4e7191d18183adcd8de77659622874 GIT binary patch literal 646 zcmV;10(t$3P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyb% z5H~yS;H?7y00IU{L_t(2&vlbOOIu+S#((eM`{pLzge0aSMr^2qDdNx~brL!h$3j7H z=vW-w3a;+`2(EsF7W@=C3J!%zHAAgkY^&GY>pfj!nreDpp6v(E!+Xx7MC2K81$+m7 zY;JA}!0zrYqoX!HZG4C;@vnu)3ujyHtzOXK7&rxF6g124mS1OCmYnuZ+xuVlXOgMJ zc6`SIH$XZB*WRzaisM*(@Q6t1;PXM}h@;wSWAz%)z$JjLPE>VcqCu%&tubaS2&iC#PW!0_66=%;<0xw^{i3hE^%|)B*O~&n z_No#p0t9Or59T^YDWxZ)$rSL`sPP#KDG(7o7tf`4A3h$uEr?7cOKwR6k+oR=z_!RK zib5?;EM6I9H1O7H{;seXyi77R9j3Fc?F#S)IJZhEKbk8qa%RJ9KCtw_HwGuc_mMD0-%8I-SJwdoORkUZ|94)X^T?I0M7??$cDj1@Kjbd8waHTjq5uE@07*qoM6N<$g8d5^?*IS* literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/selected-right.png b/nebula-exchange/target/site/scaladocs/lib/selected-right.png new file mode 100644 index 0000000000000000000000000000000000000000..04eda2f3071a81ada129b906e60709eb5b1c4e29 GIT binary patch literal 1380 zcmeAS@N?(olHy`uVBq!ia0vp^AhtLM8;~@ry7vP}NtU=qlmzFem6RtIr7}3C)9WTXpJp<7&;SCUwvn^&w1Gr=XbIJqdZpd>RtPXT0NVp4u- ziLDaQr4TRV7Ql_oD~1LWFu?RH5)1SV^$b8>f+_U%#ji9s7p}UvBq$Z(UaSTehg24% z>IbD3=a&{G10ya?8Dv#~m2**QVo82cNPd0}EEEGW@=NlIGx7@*oP$jjd=ry1^FVyC zdS72F&%EN2#JuEGPZwJypb2`JnJHGz78Y(MCeDVYmgbIzhOP!qZqAm@u103&mL^V) zCPpSOy)OC5rManjB{01y2)#x)^@5T@ZUN9{m(-%nveXo}qWoM1u$Qeeak|CH4X1ff zy(zfeVt`YxKF~4xpom3^XqXT%^?;c0WDDfL6MkwQFtrx}ll6<;A<7I4j5j=8978H@ z)dcU&QVNvVTm1ao`79at5FR1swyg%5$;tYPy#hCG-BSM`+EU9h|6u!#OUJxif~2?K zxN4GUe$wFaojJf9z)p z5$Ey};}0o`4QH}B9yFW z>98SDtSD?}jGxoZxo6X!U$AKQw|sQq!}8b$jjl6i(~7%3uRQeB{zzBi?B~JhyI$eR9CQS uH6MIndtb!u6IcAC@Ew*lAuIQC8Zg|Lxqpi1i6>#8a?jJ%&t;ucLK6TZv;Euv literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/selected.png b/nebula-exchange/target/site/scaladocs/lib/selected.png new file mode 100644 index 0000000000000000000000000000000000000000..c89765239e074f40ac120c7429b5d65a47dc218d GIT binary patch literal 1864 zcmaJ?c~BEq91ceTBSb(%MUFLype4yBBtTLE0s#pnDTc!!APL!pL`ZhCSs~!4NQ)J% zjYlz75elf(`(i|jO7Osgf;y;Fj)H?0s2weyqg2|B3iglEo!Ncw_vZV)-}ip+_hw7u z#fu%tZe$XP z91$o&BVnZ~rVxV@3dMnm*8Y~u#K+tpr8eFcYX>{J>3IbTC zz*H!%LNtI`QJ#sc#Q9Xh>H96H(Fs|N?n9Y~f-&@Rl)L{K0yfdh!-3YEqj zzr%|}JfTL1%QXsEDBx2G1-eQF@z`8Wa5TsX=5T|!OlA}q5go~mjA8`_aoG{!Y!-W* zD?k)0)vyL1=RzO3+)26SR#2lvW&w<;@?a<$L)5^#E%Q{9dkLIW?*kW_+)L1;Tn1r= zVLsS@9rXAT(LLtrMB5U%^S)m|2QQ!4P`HdBBOI%t8E8By$ z)tP&nmBpWMprzkM_|>^sro&sKcBBkCJasJiG9=P9#hP5QNL2+TkyCcgr_WpFbHr7_ z87m!#YYJH5*b!RP{<^=_J_~2|c=d7fAA8(7t(HqhM@QR7hK6D;&9z@F^LTl&+LYOL zUU{>=KQOIits!(3RqM9J$$Df>Q`4Hfywlrm3@To|dNr2U=+QrVeb>z4pMI4}rAnXe z*Su0wQ(?oEXC7Y0{o&u+%(Fh0o}PZBvZ5lZ@LWaJ!Gk4?)RX?H)qdpTZS_XZsax{y z_MKk#HqH@?F3d85ExWtByE8h5+2NQ~XRSrmZE49;u~@u3JtM<+b!er-?p^yG>?l!7 z)@R5TNdqW$9-&m@9!cz z)|KJ#YjcI$M2lT>D1eiHE7md=9Cb6o??`g%oXydj8XFrc(Rq-nRo~Dc92oPqc4`7jYVX4t*9L^0KwY`(Dn^c;fmUh^Z+y;JQ``m+ENO>F}JvzOG zpA_eOow0f6Rfv^j2{j}iqIq*6)BTacb1Yxm)_q06>xylb&!4}+!4jGxigiTeRX*Cn z<30Wx9WD2E4BzxN*jb#kdlW+%OtH1PfPLmI3$H$qQEoeA@M_zz(dMBx)_57yUHsNs zdvF1nVkziYxo1DV=eKeTc|*$c+^@3gOx8(~UC-Pht#*mPtJ;FH$u9Fm&%)M|KTg|f z5*U9$Nu>g6#DPS~Y)4n$4Wb>UOWwc=wp*D7L1rwgy--9rSyofByyv~cY4K+bR|b+B z((YQ6@^?+kI+3=oS=N8}mgQ8nYNyMpfy*0n{`@+ksvim5?MYSE)$MuW)=GnC(9&ES zE)MxRPw9$#K{-F$s=Aq5o>LYZb)fSRyT%9IcD!es`-6BtsJf2jWPf{YuBrE$LxQ!? zVn<`|QHj6njN1xoI7>WT>~c56r$ss7B6`$yLi+Pwn&+jdS}L$Vm@DT=KyDXF%TVr`iW&f2@9*rcCpU*G%kN@v);?Q2jJaQE~K zoxVPGny*U6lIkvBzs-GdKdhGVrt|YT^Vdn8*CU*fW}Ci*yY2_L3v1RibMA*BoY$Y4 ZNDtm_>Mc9CX5mbjz-9e{{de~$lm|} literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/selected2-right.png b/nebula-exchange/target/site/scaladocs/lib/selected2-right.png new file mode 100644 index 0000000000000000000000000000000000000000..bf984ef0bac9acacf732a22f6dbb9f648a6dc26a GIT binary patch literal 1434 zcmeAS@N?(olHy`uVBq!ia0vp^JU}eY!3HGlQ`YSVQj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS=07?_nZLn2Bde0{8v^Ko2Tt~skz|cV7z)0WFNY~KZ%Gk)tz(4^Clz_GsrKDK}xwt{?0`hE?GD=Dctn~HE z%ggo3jrH=2()A53EiFN27#ZmTRp=I1=9MH?=;jqG!%T2VElw`VEGWs$&r<-In3$Ab zT4JjNbScCOxdm`z^NOLt1Pn0!io^naLp=kKmtYEgeeo;J&4sHjE(uCSxEHIz#UYgi zsro^w#rdU0$-sz9QwCX8VC7ttnpl!w6q28x0}I7~jQo=P;*9(P1?ON>1>eNv%sdbu ztlrnx$}_LHBrz{J)zigR321^|W@d_&iKVH9n}Ml`sinE4p`ojRlbf@pv#XJrxuuDd zqlu9TOs`9Ra%paAUI|QZ3PP_bPQ9R{kXrz>*(J3ovn(~mttdZN0qkX~Oe}7(Ft;>z zbaFKYnrDICEfBpaSlj~D3-Skcz4}1M=z}5_DWYLQz|;d`!jmnK15fy=dBD_O1WeXN zFSNEXFfj3Xx;TbZ-0BJTJuQ?dve&rp{{2Ne1Xv0M^`dqN6o#(7v-^@5ry`4P^EBOC zzl3jzHSWk1W|3sw);Ue+g;U^>O>?#=UP&uCcCNM}UQqY`_d|&fD$mXQ{c(==)z@ET z6-8WsJ}cX8&(eI*ZD~+t^J3nFi-8`!Zq6JfvCFS!sWLo#9-#4MO^n|D15*n%rrdh_ z?c64vTY1}4B-qwo&yLa&V>QjXcQ{Ddg|Gg%9v?OhmP@U{K>-_Wb*=L_APe@*L{q(Jr$a~Dp z0uLUnIsEVgw zb^Gh3!#nG_`dl;Ss7o9b$omss5Haua%O~3xUd$-@yryCEjht$dO0588|FJa{;N_gy{FZdcQZ9v{BdisYp- zHJ`kr@ZNF#_2kvBmj=Bo*P0sDSkC@KndR}v2pt}MKL2LzQ)!#4?B=IGa(;02XkB+e z+UA+9e^cKCtnU1>r)$si?G5_sWsaKjKm0w#%lN*ryrD|bs&hXR4};S~mM6aHstZA- NrKhW(%Q~loCIFxO8+`x( literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/selected2.png b/nebula-exchange/target/site/scaladocs/lib/selected2.png new file mode 100644 index 0000000000000000000000000000000000000000..a790bb1169b6b54de1d51f7778ee552979f52183 GIT binary patch literal 1965 zcmeAS@N?(olHy`uVBq!ia0vp^CxBR-gAGXf88D;(DajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_cg49rTIArU1JzCKpT`MG+DAT@dwxdlMo3=B5*6$OdO*{LN8 zNvY|XdA3ULckfqH$V{%1*XSQL?vFu&J;D8jzb> zlBiITo0C^;Rbi_HHrEQs1_|pcDS(xfWZNo192Makpx~Tel&WB=XP}#GU}m6TW~gUq zY+`P1uA^XNU}&IkV5Dzoq-$tyWo%?+V4wg6Nh+i#(Mch>H3D2mX;thjEr=FDs+o0^GXscbn}XpVJ5hw7AF^F7L;V>=P7_pOiaoz zEwNPsx)kDt+yc06!V;*iRM zRQ;gT;{4L0WMIUlDTAykuyQU+O)SYT3dzsUfrVl~Mt(_taYlZDf^)E`f^TASW*&$S zR`2U;<(XGpl9-pA>gi&u1T;Y}Gc(1?!rao>(aF`&)Y9C-(9qSu$<5i)+11F*+|tC! z(Zt9Erq?AuximL5uLPzy1)LqEuE@a9jJa{g3^D*&Fs~}@sPg}hA3HW}*bs2zZP}lLlevA=_U-n$=5&5bna|Ro zr2Kq;ZlP0ibWR_hJ9lpWiz!uc8tF`mg%K|cGE-8Xi0*W2U!-y9WyzzY#H~@SH*>@$ zseF`8+a!0Y?a0N869Ym+-@Jd{U1771b?3>~^XAPvzD32YutZHj$X%{hPhM8G*7Ie^ z?(45b`P!X@+s~$5zT+&;Zp|_IEnicE2OmGbsk)-GK&Ok7i<02OvfcN~%FFGSFVz;w zJpHni>#DT=iM(5&U57r%J7!PHj4vV0>!_hwa)V3FU5<)V5Wtj)rUr z_x@OMhrMuthvj{s_~K>J23#ctD--tXEDh3}dGw%xx?U5Hm;SAjt|^^YCOO8>;4W(W z`B>!wi)4Fbk%f#_R5Z`wIShpf%kMrdS{am?`BMMP;)KgC^MezCb}+X!3X04>KYc=0 zR#uX=we_tFVODdWSs#%Qo55lt(Cc>b)!)p`H+`n$c~0B4YuEdQ0Un!0#W<5w8WS1> zjU#(|d+lGSYu^gc9Ub-|XBRjj>V(vLdtFNI}x@X#@rKBc({rdHG zadB}{adEJA$PLdKG5RM0gA$&|svdjvXi-LPZg17zxGkmW8{DepS^O^EzhB?FuRbCo zqQKAJ|8#0<>Y`n{qHYIXSzdKBa7IiaPpnJ@zlsD;l83n~+r%|1R@_*u>MJ6h&ct{_ z=H=_x!7m;MuX2_MXn9M_J+Cm-hTNpH>=mNsC<9kP)$a(UEUF`RJRVHGw%nH4A_E h2-=FCwErWPz_6w1NS~Nz6ep+x^>p=fS?83{1OQq_0~!DT literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/signaturebg.gif b/nebula-exchange/target/site/scaladocs/lib/signaturebg.gif new file mode 100644 index 0000000000000000000000000000000000000000..b6ac4415e4a3a3ce7e38401a476beea7b1938585 GIT binary patch literal 1214 zcmZ?wbhEHbWMoihIKsei_wL=3Cr`e6|Ni^;?>BB-U$kh^&6_u0zkc=h?b|o6U*ElR z_x}C+_wL<0ckbN#ckgfCzWw^m>zlW3y?yug<;zz$Zrr$Y=gynAZ*JYXb^ZGFckkZ4 zdiCo6|Njg~K=D6!gl~X?OJYePkhZa}C`e4sPAySLN=?tqvsHS(d%u!GW{Ry+xT&v! zZ-H}aMy5wqQEG6NUr2IQcCuxPlD(aRO@&oOZb5EpNuokUZcbjYRfVlmVoH8esuhq8 z64qBz04piUwpDTjNhpBqbj~kIRWQ{v&`mZlGf*%y)H5_TF*i5YQ7|$vG|)FN(l<2H zH8i&}HnK7>P=Ep@plwAdX;wilZcw{`JX@uVl9B=|ef{$Ca=mh6z5JqdeM3u2OOP2x zM!G;1y2X`wC5aWfdBw^w6I@b@lZ!G7N;32F6hI~>Cgqow*eU^C3h_d20o>TUVm+{T z^pf*)^(zt!^bPe4Kwg3=^!3HBG&dKny0|1L72#g21{a4^7NqJ2r55Lx7A2!(A3h{#L&>yz{$%-qt%$9UanL3(T0L?SR?iPsN6x?nx z!08r!pkwqw5sMVjFd<;-0Wsmp7RZ4o{M0;PYA*sNYsUZo{{H#>>*tT}-@bnN{ORL| z_wRsN?$yf|&!0Vg^7zri2lwyYy>t84%^TORUA=Po(!~qs&z(JU`qar2$B!L7a`@1} z1N-;w-Lrew&K=vgZQZhY)5ZeMTG_VdAT{+S(zE>X{jm6Nr?&Z zaj`McQIQehVWAmo_ zrKzE=rmCW>q^KY-Co3Z@B`F~;CMqH&FX#K^#)_>%=(Qs{t4 sPRwL~E)H9a%WR_Xoj{Yna%DYi=CroINg16w1-Ypui3%0DIeEoa6}C!=DfvmMRzNmLSYJs2tfVB{R>=`0p#ZYe zIlm}X!Bo#cH`&0({$jZP#0Sc6WwiTtM zSp~VcLG1$aY?U%fN(!v>^~=l4^~#O)@{7{-4J|D#L1q{k=>k>g7FXt#Bv$C=6)VF` za7isrF3Kz@$;{7F0GXJWlwVq6s|0i@#0$9vaAWg|^}ycIOU}>LuShJ=H`Fr#c?qV_ z*B8Ii++4Wo;*y|LgnO|XTpUtakg6Y)TAW{6l$;7wt_-rOz{ATTy({MavwGFa70Z_`U9x!5!Ugl^&7CuQ*322xr%jzQdD6rQ{e8VX-Cdm>?QN|s z%}tFB^>wv1)m4=h1nAc$w`R`@o}*+(NU2R;bEa6!9jrm z{(inb-d>&_?ryFw&Q6XF_I9>5)>f7l=4PfQ#zw#_rKhW-t);1EF>tv&&SKd&Be*V&c@2Z%*4pRp!kyoTyW@sNKkpiz$&$%l_m71iJOQf Yv$AL3W|;;C$CD p { + margin-top: 5px; +} + +#types ol li:last-child { + margin-bottom: 5px; +} + +/* +#definition { + padding: 6px 0 6px 6px; + min-height: 59px; + color: white; +} +*/ + +#definition { + display: block-inline; + padding: 5px 0px; + height: 61px; +} + +#definition > img { + float: left; + padding-right: 6px; + padding-left: 5px; +} + +#definition > a > img { + float: left; + padding-right: 6px; + padding-left: 5px; +} + +#definition p + h1 { + margin-top: 3px; +} + +#definition > h1 { +/* padding: 12px 0 12px 6px;*/ + color: white; + text-shadow: 3px black; + text-shadow: black 0px 2px 0px; + font-size: 24pt; + display: inline-block; + overflow: hidden; + margin-top: 10px; +} + +#definition h1 > a { + color: #ffffff; + font-size: 24pt; + text-shadow: black 0px 2px 0px; +/* text-shadow: black 0px 0px 0px;*/ +text-decoration: none; +} + +#definition #owner { + color: #ffffff; + margin-top: 4px; + font-size: 10pt; + overflow: hidden; +} + +#definition #owner > a { + color: #ffffff; +} + +#definition #owner > a:hover { + text-decoration: none; +} + +#signature { + background-image:url('signaturebg2.gif'); + background-color: #d7d7d7; + min-height: 18px; + background-repeat:repeat-x; + font-size: 11.5pt; +/* margin-bottom: 10px;*/ + padding: 8px; +} + +#signature > span.modifier_kind { + display: inline; + float: left; + text-align: left; + width: auto; + position: static; + text-shadow: 2px white; + text-shadow: white 0px 1px 0px; +} + +#signature > span.symbol { + text-align: left; + display: inline; + padding-left: 0.7em; + text-shadow: 2px white; + text-shadow: white 0px 1px 0px; +} + +/* Linear super types and known subclasses */ +.hiddenContent { + display: none; +} + +.toggleContainer .toggle { + cursor: pointer; + padding-left: 15px; + background: url("arrow-right.png") no-repeat 0 3px transparent; +} + +.toggleContainer .toggle.open { + background: url("arrow-down.png") no-repeat 0 3px transparent; +} + +.toggleContainer .hiddenContent { + margin-top: 5px; +} + +.value #definition { + background-color: #2C475C; /* blue */ + background-image:url('defbg-blue.gif'); + background-repeat:repeat-x; +} + +.type #definition { + background-color: #316555; /* green */ + background-image:url('defbg-green.gif'); + background-repeat:repeat-x; +} + +#template { + margin-bottom: 50px; +} + +h3 { + color: white; + padding: 5px 10px; + font-size: 12pt; + font-weight: bold; + text-shadow: black 1px 1px 0px; +} + +dl.attributes > dt { + display: block; + float: left; + font-style: italic; +} + +dl.attributes > dt.implicit { + font-weight: bold; + color: darkgreen; +} + +dl.attributes > dd { + display: block; + padding-left: 10em; + margin-bottom: 5px; + min-height: 15px; +} + +#template .values > h3 { + background: #2C475C url("valuemembersbg.gif") repeat-x bottom left; /* grayish blue */ + height: 18px; +} + +#values ol li:last-child { + margin-bottom: 5px; +} + +#template .types > h3 { + background: #316555 url("typebg.gif") repeat-x bottom left; /* green */ + height: 18px; +} + +#constructors > h3 { + background: #4f504f url("constructorsbg.gif") repeat-x bottom left; /* gray */ + height: 18px; +} + +#inheritedMembers > div.parent > h3 { + background: #dadada url("constructorsbg.gif") repeat-x bottom left; /* gray */ + height: 17px; + font-style: italic; + font-size: 12pt; +} + +#inheritedMembers > div.parent > h3 * { + color: white; +} + +#inheritedMembers > div.conversion > h3 { + background: #dadada url("conversionbg.gif") repeat-x bottom left; /* gray */ + height: 17px; + font-style: italic; + font-size: 12pt; +} + +#inheritedMembers > div.conversion > h3 * { + color: white; +} + +#groupedMembers > div.group > h3 { + background: #dadada url("typebg.gif") repeat-x bottom left; /* green */ + height: 17px; + font-size: 12pt; +} + +#groupedMembers > div.group > h3 * { + color: white; +} + + +/* Member cells */ + +div.members > ol { + background-color: white; + list-style: none +} + +div.members > ol > li { + display: block; + border-bottom: 1px solid gray; + padding: 5px 0 6px; + margin: 0 10px; + position: relative; +} + +div.members > ol > li:last-child { + border: 0; + padding: 5px 0 5px; +} + +/* Member signatures */ + +#tooltip { + background: #EFD5B5; + border: 1px solid gray; + color: black; + display: none; + padding: 5px; + position: absolute; +} + +.signature { + font-family: monospace; + font-size: 10pt; + line-height: 18px; + clear: both; + display: block; + text-shadow: 2px white; + text-shadow: white 0px 1px 0px; +} + +.signature .modifier_kind { + position: absolute; + text-align: right; + width: 14em; +} + +.signature > a > .symbol > .name { + text-decoration: underline; +} + +.signature > a:hover > .symbol > .name { + text-decoration: none; +} + +.signature > a { + text-decoration: none; +} + +.signature > .symbol { + display: block; + padding-left: 14.7em; +} + +.signature .name { + display: inline-block; + font-weight: bold; +} + +.signature .symbol > .implicit { + display: inline-block; + font-weight: bold; + text-decoration: underline; + color: darkgreen; +} + +.signature .symbol .shadowed { + color: darkseagreen; +} + +.signature .symbol .params > .implicit { + font-style: italic; +} + +.signature .symbol .deprecated { + text-decoration: line-through; +} + +.signature .symbol .params .default { + font-style: italic; +} + +#template .signature.closed { + background: url("arrow-right.png") no-repeat 0 5px transparent; + cursor: pointer; +} + +#template .signature.opened { + background: url("arrow-down.png") no-repeat 0 5px transparent; + cursor: pointer; +} + +#template .values .signature .name { + color: darkblue; +} + +#template .types .signature .name { + color: darkgreen; +} + +.full-signature-usecase h4 span { + font-size: 10pt; +} + +.full-signature-usecase > #signature { + padding-top: 0px; +} + +#template .full-signature-usecase > .signature.closed { + background: none; +} + +#template .full-signature-usecase > .signature.opened { + background: none; +} + +.full-signature-block { + padding: 5px 0 0; + border-top: 1px solid #EBEBEB; + margin-top: 5px; + margin-bottom: 5px; +} + +#definition .morelinks { + text-align: right; + position: absolute; + top: 40px; + right: 10px; + width: 450px; +} + +#definition .morelinks a { + color: #EBEBEB; +} + +#template .members li .permalink { + position: absolute; + top: 5px; + right: 5px; +} + +#definition .permalink { + position: absolute; + top: 10px; + right: 15px; +} + +#definition .permalink a { + color: #EBEBEB; +} + +#template .members li .permalink, +#definition .permalink a { + display: none; +} + +#template .members li:hover .permalink, +#definition:hover .permalink a { + display: block; +} + +#template .members li .permalink a, +#definition .permalink a { + text-decoration: none; + font-weight: bold; +} + +/* Comments text formating */ + +.cmt {} + +.cmt p { + margin: 0.7em 0; +} + +.cmt p:first-child { + margin-top: 0; +} + +.cmt p:last-child { + margin-bottom: 0; +} + +.cmt h3, +.cmt h4, +.cmt h5, +.cmt h6 { + margin-bottom: 0.7em; + margin-top: 1.4em; + display: block; + text-align: left; + font-weight: bold; +} + +.cmt h3 { + font-size: 14pt; +} + +.cmt h4 { + font-size: 13pt; +} + +.cmt h5 { + font-size: 12pt; +} + +.cmt h6 { + font-size: 11pt; +} + +.cmt pre { + padding: 5px; + border: 1px solid #ddd; + background-color: #eee; + margin: 5px 0; + display: block; + font-family: monospace; +} + +.cmt pre span.ano { + color: blue; +} + +.cmt pre span.cmt { + color: green; +} + +.cmt pre span.kw { + font-weight: bold; +} + +.cmt pre span.lit { + color: #c71585; +} + +.cmt pre span.num { + color: #1e90ff; /* dodgerblue */ +} + +.cmt pre span.std { + color: #008080; /* teal */ +} + +.cmt ul { + display: block; + list-style: circle; + padding-left: 20px; +} + +.cmt ol { + display: block; + padding-left:20px; +} + +.cmt ol.decimal { + list-style: decimal; +} + +.cmt ol.lowerAlpha { + list-style: lower-alpha; +} + +.cmt ol.upperAlpha { + list-style: upper-alpha; +} + +.cmt ol.lowerRoman { + list-style: lower-roman; +} + +.cmt ol.upperRoman { + list-style: upper-roman; +} + +.cmt li { + display: list-item; +} + +.cmt code { + font-family: monospace; +} + +.cmt a { + font-style: bold; +} + +.cmt em, .cmt i { + font-style: italic; +} + +.cmt strong, .cmt b { + font-weight: bold; +} + +/* Comments structured layout */ + +.group > div.comment { + padding-top: 5px; + padding-bottom: 5px; + padding-right: 5px; + padding-left: 5px; + border: 1px solid #ddd; + background-color: #eeeee; + margin-top:5px; + margin-bottom:5px; + margin-right:5px; + margin-left:5px; + display: block; +} + +p.comment { + display: block; + margin-left: 14.7em; + margin-top: 5px; +} + +.shortcomment { + display: block; + margin: 5px 10px; +} + +div.fullcommenttop { + padding: 10px 10px; + background-image:url('fullcommenttopbg.gif'); + background-repeat:repeat-x; +} + +div.fullcomment { + margin: 5px 10px; +} + +#template div.fullcommenttop, +#template div.fullcomment { + display:none; + margin: 5px 0 0 14.7em; +} + +#template .shortcomment { + margin: 5px 0 0 14.7em; + padding: 0; +} + +div.fullcomment .block { + padding: 5px 0 0; + border-top: 1px solid #EBEBEB; + margin-top: 5px; + overflow: hidden; +} + +div.fullcommenttop .block { + padding: 5px 0 0; + border-top: 1px solid #EBEBEB; + margin-top: 5px; + margin-bottom: 5px +} + +div.fullcomment div.block ol li p, +div.fullcomment div.block ol li { + display:inline +} + +div.fullcomment .block > h5 { + font-style: italic; + font-weight: normal; + display: inline-block; +} + +div.fullcomment .comment { + margin: 5px 0 10px; +} + +div.fullcommenttop .comment:last-child, +div.fullcomment .comment:last-child { + margin-bottom: 0; +} + +div.fullcommenttop dl.paramcmts { + margin-bottom: 0.8em; + padding-bottom: 0.8em; +} + +div.fullcommenttop dl.paramcmts > dt, +div.fullcomment dl.paramcmts > dt { + display: block; + float: left; + font-weight: bold; + min-width: 70px; +} + +div.fullcommenttop dl.paramcmts > dd, +div.fullcomment dl.paramcmts > dd { + display: block; + padding-left: 10px; + margin-bottom: 5px; + margin-left: 70px; + min-height: 15px; +} + +/* Members filter tool */ + +#textfilter { + position: relative; + display: block; + height: 20px; + margin-bottom: 5px; +} + +#textfilter > .pre { + display: block; + position: absolute; + top: 0; + left: 0; + height: 23px; + width: 21px; + background: url("filter_box_left.png"); +} + +#textfilter > .input { + display: block; + position: absolute; + top: 0; + right: 20px; + left: 20px; +} + +#textfilter > .input > input { + height: 20px; + padding: 1px; + font-weight: bold; + color: #000000; + background: #ffffff url("filterboxbarbg.png") repeat-x top left; + width: 100%; +} + +#textfilter > .post { + display: block; + position: absolute; + top: 0; + right: 0; + height: 23px; + width: 21px; + background: url("filter_box_right.png"); +} + +#mbrsel { + padding: 5px 10px; + background-color: #ededee; /* light gray */ + background-image:url('filterboxbg.gif'); + background-repeat:repeat-x; + font-size: 9.5pt; + display: block; + margin-top: 1em; +/* margin-bottom: 1em; */ +} + +#mbrsel > div { + margin-bottom: 5px; +} + +#mbrsel > div:last-child { + margin-bottom: 0; +} + +#mbrsel > div > span.filtertype { + padding: 4px; + margin-right: 5px; + float: left; + display: inline-block; + color: #000000; + font-weight: bold; + text-shadow: white 0px 1px 0px; + width: 4.5em; +} + +#mbrsel > div > ol { + display: inline-block; +} + +#mbrsel > div > a { + position:relative; + top: -8px; + font-size: 11px; + text-shadow: #ffffff 0 1px 0; +} + +#mbrsel > div > ol#linearization { + display: table; + margin-left: 70px; +} + +#mbrsel > div > ol#linearization > li.in { + text-decoration: none; + float: left; + padding-right: 10px; + margin-right: 5px; + background: url(selected-right.png) no-repeat; + background-position: right 0px; +} + +#mbrsel > div > ol#linearization > li.in > span{ + color: #404040; + float: left; + padding: 1px 0 1px 10px; + background: url(selected.png) no-repeat; + background-position: 0px 0px; + text-shadow: #ffffff 0 1px 0; +} + +#mbrsel > div > ol#implicits { + display: table; + margin-left: 70px; +} + +#mbrsel > div > ol#implicits > li.in { + text-decoration: none; + float: left; + padding-right: 10px; + margin-right: 5px; + background: url(selected-right-implicits.png) no-repeat; + background-position: right 0px; +} + +#mbrsel > div > ol#implicits > li.in > span{ + color: #404040; + float: left; + padding: 1px 0 1px 10px; + background: url(selected-implicits.png) no-repeat; + background-position: 0px 0px; + text-shadow: #ffffff 0 1px 0; +} + +#mbrsel > div > ol > li { +/* padding: 3px 10px;*/ + line-height: 16pt; + display: inline-block; + cursor: pointer; +} + +#mbrsel > div > ol > li.in { + text-decoration: none; + float: left; + padding-right: 10px; + margin-right: 5px; + background: url(selected-right.png) no-repeat; + background-position: right 0px; +} + +#mbrsel > div > ol > li.in > span{ + color: #404040; + float: left; + padding: 1px 0 1px 10px; + background: url(selected.png) no-repeat; + background-position: 0px 0px; + text-shadow: #ffffff 0 1px 0; +} + +#mbrsel > div > ol > li.out { + text-decoration: none; + float: left; + padding-right: 10px; + margin-right: 5px; +} + +#mbrsel > div > ol > li.out > span{ + color: #747474; +/* background-color: #999; */ + float: left; + padding: 1px 0 1px 10px; +/* background: url(unselected.png) no-repeat;*/ + background-position: 0px -1px; + text-shadow: #ffffff 0 1px 0; +} +/* +#mbrsel .hideall { + color: #4C4C4C; + line-height: 16px; + font-weight: bold; +} + +#mbrsel .hideall span { + color: #4C4C4C; + font-weight: bold; +} + +#mbrsel .showall { + color: #4C4C4C; + line-height: 16px; + font-weight: bold; +} + +#mbrsel .showall span { + color: #4C4C4C; + font-weight: bold; +}*/ + +.badge { + display: inline-block; + padding: 2px 4px; + font-size: 11.844px; + font-weight: bold; + line-height: 14px; + color: #ffffff; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + white-space: nowrap; + vertical-align: baseline; + background-color: #999999; + padding-right: 9px; + padding-left: 9px; + -webkit-border-radius: 9px; + -moz-border-radius: 9px; + border-radius: 9px; +} + +.badge-red { + background-color: #b94a48; +} diff --git a/nebula-exchange/target/site/scaladocs/lib/template.js b/nebula-exchange/target/site/scaladocs/lib/template.js new file mode 100644 index 0000000..798a2d4 --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/lib/template.js @@ -0,0 +1,500 @@ +// © 2009–2010 EPFL/LAMP +// code by Gilles Dubochet with contributions by Pedro Furlanetto and Marcin Kubala + +$(document).ready(function(){ + + var controls = { + visibility: { + publicOnly: $("#visbl").find("> ol > li.public"), + all: $("#visbl").find("> ol > li.all") + } + }; + + // Escapes special characters and returns a valid jQuery selector + function escapeJquery(str){ + return str.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=<>\|])/g, '\\$1'); + } + + function toggleVisibilityFilter(ctrlToEnable, ctrToDisable) { + if (ctrlToEnable.hasClass("out")) { + ctrlToEnable.removeClass("out").addClass("in"); + ctrToDisable.removeClass("in").addClass("out"); + filter(); + } + } + + controls.visibility.publicOnly.click(function () { + toggleVisibilityFilter(controls.visibility.publicOnly, controls.visibility.all); + }); + + controls.visibility.all.click(function () { + toggleVisibilityFilter(controls.visibility.all, controls.visibility.publicOnly); + }); + + function exposeMember(jqElem) { + var jqElemParent = jqElem.parent(), + parentName = jqElemParent.attr("name"), + linearizationName = /^([^#]*)(#.*)?$/gi.exec(parentName)[1]; + + // switch visibility filter if necessary + if (jqElemParent.attr("visbl") == "prt") { + toggleVisibilityFilter(controls.visibility.all, controls.visibility.publicOnly); + } + + // toggle appropriate linearization buttons + if (linearizationName) { + $("#linearization li.out[name='" + linearizationName + "']").removeClass("out").addClass("in"); + } + + filter(); + window.scrollTo(0, 0); + jqElemParent.effect("highlight", {color: "#FFCC85"}, 3000); + $('html,body').animate({scrollTop: jqElemParent.offset().top}, 1000); + } + + var isHiddenClass = function (name) { + return name == 'scala.Any' || + name == 'scala.AnyRef'; + }; + + var isHidden = function (elem) { + return $(elem).attr("data-hidden") == 'true'; + }; + + $("#linearization li:gt(0)").filter(function(){ + return isHiddenClass($(this).attr("name")); + }).removeClass("in").addClass("out"); + + $("#implicits li").filter(function(){ + return isHidden(this); + }).removeClass("in").addClass("out"); + + // Pre-filter members + filter(); + + // Member filter box + var input = $("#textfilter input"); + input.bind("keyup", function(event) { + + switch ( event.keyCode ) { + + case 27: // escape key + input.val(""); + filter(true); + break; + + case 38: // up + input.val(""); + filter(false); + window.scrollTo(0, $("body").offset().top); + input.focus(); + break; + + case 33: //page up + input.val(""); + filter(false); + break; + + case 34: //page down + input.val(""); + filter(false); + break; + + default: + window.scrollTo(0, $("#mbrsel").offset().top); + filter(true); + break; + + } + }); + input.focus(function(event) { + input.select(); + }); + $("#textfilter > .post").click(function() { + $("#textfilter input").attr("value", ""); + filter(); + }); + $(document).keydown(function(event) { + + if (event.keyCode == 9) { // tab + $("#index-input", window.parent.document).focus(); + input.attr("value", ""); + return false; + } + }); + + $("#linearization li").click(function(){ + if ($(this).hasClass("in")) { + $(this).removeClass("in"); + $(this).addClass("out"); + } + else if ($(this).hasClass("out")) { + $(this).removeClass("out"); + $(this).addClass("in"); + } + filter(); + }); + + $("#implicits li").click(function(){ + if ($(this).hasClass("in")) { + $(this).removeClass("in"); + $(this).addClass("out"); + } + else if ($(this).hasClass("out")) { + $(this).removeClass("out"); + $(this).addClass("in"); + } + filter(); + }); + + $("#mbrsel > div[id=ancestors] > ol > li.hideall").click(function() { + $("#linearization li.in").removeClass("in").addClass("out"); + $("#linearization li:first").removeClass("out").addClass("in"); + $("#implicits li.in").removeClass("in").addClass("out"); + + if ($(this).hasClass("out") && $("#mbrsel > div[id=ancestors] > ol > li.showall").hasClass("in")) { + $(this).removeClass("out").addClass("in"); + $("#mbrsel > div[id=ancestors] > ol > li.showall").removeClass("in").addClass("out"); + } + + filter(); + }) + $("#mbrsel > div[id=ancestors] > ol > li.showall").click(function() { + var filteredLinearization = + $("#linearization li.out").filter(function() { + return ! isHiddenClass($(this).attr("name")); + }); + filteredLinearization.removeClass("out").addClass("in"); + + var filteredImplicits = + $("#implicits li.out").filter(function() { + return ! isHidden(this); + }); + filteredImplicits.removeClass("out").addClass("in"); + + if ($(this).hasClass("out") && $("#mbrsel > div[id=ancestors] > ol > li.hideall").hasClass("in")) { + $(this).removeClass("out").addClass("in"); + $("#mbrsel > div[id=ancestors] > ol > li.hideall").removeClass("in").addClass("out"); + } + + filter(); + }); + $("#order > ol > li.alpha").click(function() { + if ($(this).hasClass("out")) { + orderAlpha(); + } + }) + $("#order > ol > li.inherit").click(function() { + if ($(this).hasClass("out")) { + orderInherit(); + } + }); + $("#order > ol > li.group").click(function() { + if ($(this).hasClass("out")) { + orderGroup(); + } + }); + $("#groupedMembers").hide(); + + initInherit(); + + // Create tooltips + $(".extype").add(".defval").tooltip({ + tip: "#tooltip", + position: "top center", + predelay: 500, + onBeforeShow: function(ev) { + $(this.getTip()).text(this.getTrigger().attr("name")); + } + }); + + /* Add toggle arrows */ + //var docAllSigs = $("#template li").has(".fullcomment").find(".signature"); + // trying to speed things up a little bit + var docAllSigs = $("#template li[fullComment=yes] .signature"); + + function commentToggleFct(signature){ + var parent = signature.parent(); + var shortComment = $(".shortcomment", parent); + var fullComment = $(".fullcomment", parent); + var vis = $(":visible", fullComment); + signature.toggleClass("closed").toggleClass("opened"); + if (vis.length > 0) { + shortComment.slideDown(100); + fullComment.slideUp(100); + } + else { + shortComment.slideUp(100); + fullComment.slideDown(100); + } + }; + docAllSigs.addClass("closed"); + docAllSigs.click(function() { + commentToggleFct($(this)); + }); + + /* Linear super types and known subclasses */ + function toggleShowContentFct(e){ + e.toggleClass("open"); + var content = $(".hiddenContent", e.parent().get(0)); + if (content.is(':visible')) { + content.slideUp(100); + } + else { + content.slideDown(100); + } + }; + + $(".toggle:not(.diagram-link)").click(function() { + toggleShowContentFct($(this)); + }); + + // Set parent window title + windowTitle(); + + if ($("#order > ol > li.group").length == 1) { orderGroup(); }; + + function findElementByHash(locationHash) { + var temp = locationHash.replace('#', ''); + var memberSelector = '#' + escapeJquery(temp); + return $(memberSelector); + } + + // highlight and jump to selected member + if (window.location.hash) { + var jqElem = findElementByHash(window.location.hash); + if (jqElem.length > 0) { + exposeMember(jqElem); + } + } +}); + +function orderAlpha() { + $("#order > ol > li.alpha").removeClass("out").addClass("in"); + $("#order > ol > li.inherit").removeClass("in").addClass("out"); + $("#order > ol > li.group").removeClass("in").addClass("out"); + $("#template > div.parent").hide(); + $("#template > div.conversion").hide(); + $("#mbrsel > div[id=ancestors]").show(); + filter(); +}; + +function orderInherit() { + $("#order > ol > li.inherit").removeClass("out").addClass("in"); + $("#order > ol > li.alpha").removeClass("in").addClass("out"); + $("#order > ol > li.group").removeClass("in").addClass("out"); + $("#template > div.parent").show(); + $("#template > div.conversion").show(); + $("#mbrsel > div[id=ancestors]").hide(); + filter(); +}; + +function orderGroup() { + $("#order > ol > li.group").removeClass("out").addClass("in"); + $("#order > ol > li.alpha").removeClass("in").addClass("out"); + $("#order > ol > li.inherit").removeClass("in").addClass("out"); + $("#template > div.parent").hide(); + $("#template > div.conversion").hide(); + $("#mbrsel > div[id=ancestors]").show(); + filter(); +}; + +/** Prepares the DOM for inheritance-based display. To do so it will: + * - hide all statically-generated parents headings; + * - copy all members from the value and type members lists (flat members) to corresponding lists nested below the + * parent headings (inheritance-grouped members); + * - initialises a control variable used by the filter method to control whether filtering happens on flat members + * or on inheritance-grouped members. */ +function initInherit() { + // inheritParents is a map from fully-qualified names to the DOM node of parent headings. + var inheritParents = new Object(); + var groupParents = new Object(); + $("#inheritedMembers > div.parent").each(function(){ + inheritParents[$(this).attr("name")] = $(this); + }); + $("#inheritedMembers > div.conversion").each(function(){ + inheritParents[$(this).attr("name")] = $(this); + }); + $("#groupedMembers > div.group").each(function(){ + groupParents[$(this).attr("name")] = $(this); + }); + + $("#types > ol > li").each(function(){ + var mbr = $(this); + this.mbrText = mbr.find("> .fullcomment .cmt").text(); + var qualName = mbr.attr("name"); + var owner = qualName.slice(0, qualName.indexOf("#")); + var name = qualName.slice(qualName.indexOf("#") + 1); + var inheritParent = inheritParents[owner]; + if (inheritParent != undefined) { + var types = $("> .types > ol", inheritParent); + if (types.length == 0) { + inheritParent.append("

              Type Members

                "); + types = $("> .types > ol", inheritParent); + } + var clone = mbr.clone(); + clone[0].mbrText = this.mbrText; + types.append(clone); + } + var group = mbr.attr("group") + var groupParent = groupParents[group]; + if (groupParent != undefined) { + var types = $("> .types > ol", groupParent); + if (types.length == 0) { + groupParent.append("
                  "); + types = $("> .types > ol", groupParent); + } + var clone = mbr.clone(); + clone[0].mbrText = this.mbrText; + types.append(clone); + } + }); + + $("#values > ol > li").each(function(){ + var mbr = $(this); + this.mbrText = mbr.find("> .fullcomment .cmt").text(); + var qualName = mbr.attr("name"); + var owner = qualName.slice(0, qualName.indexOf("#")); + var name = qualName.slice(qualName.indexOf("#") + 1); + var inheritParent = inheritParents[owner]; + if (inheritParent != undefined) { + var values = $("> .values > ol", inheritParent); + if (values.length == 0) { + inheritParent.append("

                  Value Members

                    "); + values = $("> .values > ol", inheritParent); + } + var clone = mbr.clone(); + clone[0].mbrText = this.mbrText; + values.append(clone); + } + var group = mbr.attr("group") + var groupParent = groupParents[group]; + if (groupParent != undefined) { + var values = $("> .values > ol", groupParent); + if (values.length == 0) { + groupParent.append("
                      "); + values = $("> .values > ol", groupParent); + } + var clone = mbr.clone(); + clone[0].mbrText = this.mbrText; + values.append(clone); + } + }); + $("#inheritedMembers > div.parent").each(function() { + if ($("> div.members", this).length == 0) { $(this).remove(); }; + }); + $("#inheritedMembers > div.conversion").each(function() { + if ($("> div.members", this).length == 0) { $(this).remove(); }; + }); + $("#groupedMembers > div.group").each(function() { + if ($("> div.members", this).length == 0) { $(this).remove(); }; + }); +}; + +/* filter used to take boolean scrollToMember */ +function filter() { + var query = $.trim($("#textfilter input").val()).toLowerCase(); + query = query.replace(/[-[\]{}()*+?.,\\^$|#]/g, "\\$&").replace(/\s+/g, "|"); + var queryRegExp = new RegExp(query, "i"); + var privateMembersHidden = $("#visbl > ol > li.public").hasClass("in"); + var orderingAlphabetic = $("#order > ol > li.alpha").hasClass("in"); + var orderingInheritance = $("#order > ol > li.inherit").hasClass("in"); + var orderingGroups = $("#order > ol > li.group").hasClass("in"); + var hiddenSuperclassElementsLinearization = orderingInheritance ? $("#linearization > li:gt(0)") : $("#linearization > li.out"); + var hiddenSuperclassesLinearization = hiddenSuperclassElementsLinearization.map(function() { + return $(this).attr("name"); + }).get(); + var hiddenSuperclassElementsImplicits = orderingInheritance ? $("#implicits > li") : $("#implicits > li.out"); + var hiddenSuperclassesImplicits = hiddenSuperclassElementsImplicits.map(function() { + return $(this).attr("name"); + }).get(); + + var hideInheritedMembers; + + if (orderingAlphabetic) { + $("#allMembers").show(); + $("#inheritedMembers").hide(); + $("#groupedMembers").hide(); + hideInheritedMembers = true; + $("#allMembers > .members").each(filterFunc); + } else if (orderingGroups) { + $("#groupedMembers").show(); + $("#inheritedMembers").hide(); + $("#allMembers").hide(); + hideInheritedMembers = true; + $("#groupedMembers > .group > .members").each(filterFunc); + $("#groupedMembers > div.group").each(function() { + $(this).show(); + if ($("> div.members", this).not(":hidden").length == 0) { + $(this).hide(); + } else { + $(this).show(); + } + }); + } else if (orderingInheritance) { + $("#inheritedMembers").show(); + $("#groupedMembers").hide(); + $("#allMembers").hide(); + hideInheritedMembers = false; + $("#inheritedMembers > .parent > .members").each(filterFunc); + $("#inheritedMembers > .conversion > .members").each(filterFunc); + } + + + function filterFunc() { + var membersVisible = false; + var members = $(this); + members.find("> ol > li").each(function() { + var mbr = $(this); + if (privateMembersHidden && mbr.attr("visbl") == "prt") { + mbr.hide(); + return; + } + var name = mbr.attr("name"); + // Owner filtering must not happen in "inherited from" member lists + if (hideInheritedMembers) { + var ownerIndex = name.indexOf("#"); + if (ownerIndex < 0) { + ownerIndex = name.lastIndexOf("."); + } + var owner = name.slice(0, ownerIndex); + for (var i = 0; i < hiddenSuperclassesLinearization.length; i++) { + if (hiddenSuperclassesLinearization[i] == owner) { + mbr.hide(); + return; + } + }; + for (var i = 0; i < hiddenSuperclassesImplicits.length; i++) { + if (hiddenSuperclassesImplicits[i] == owner) { + mbr.hide(); + return; + } + }; + } + if (query && !(queryRegExp.test(name) || queryRegExp.test(this.mbrText))) { + mbr.hide(); + return; + } + mbr.show(); + membersVisible = true; + }); + + if (membersVisible) + members.show(); + else + members.hide(); + }; + + return false; +}; + +function windowTitle() +{ + try { + parent.document.title=document.title; + } + catch(e) { + // Chrome doesn't allow settings the parent's title when + // used on the local file system. + } +}; diff --git a/nebula-exchange/target/site/scaladocs/lib/tools.tooltip.js b/nebula-exchange/target/site/scaladocs/lib/tools.tooltip.js new file mode 100644 index 0000000..0af34ec --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/lib/tools.tooltip.js @@ -0,0 +1,14 @@ +/* + * tools.tooltip 1.1.3 - Tooltips done right. + * + * Copyright (c) 2009 Tero Piirainen + * http://flowplayer.org/tools/tooltip.html + * + * Dual licensed under MIT and GPL 2+ licenses + * http://www.opensource.org/licenses + * + * Launch : November 2008 + * Date: ${date} + * Revision: ${revision} + */ +(function(c){var d=[];c.tools=c.tools||{};c.tools.tooltip={version:"1.1.3",conf:{effect:"toggle",fadeOutSpeed:"fast",tip:null,predelay:0,delay:30,opacity:1,lazy:undefined,position:["top","center"],offset:[0,0],cancelDefault:true,relative:false,oneInstance:true,events:{def:"mouseover,mouseout",input:"focus,blur",widget:"focus mouseover,blur mouseout",tooltip:"mouseover,mouseout"},api:false},addEffect:function(e,g,f){b[e]=[g,f]}};var b={toggle:[function(e){var f=this.getConf(),g=this.getTip(),h=f.opacity;if(h<1){g.css({opacity:h})}g.show();e.call()},function(e){this.getTip().hide();e.call()}],fade:[function(e){this.getTip().fadeIn(this.getConf().fadeInSpeed,e)},function(e){this.getTip().fadeOut(this.getConf().fadeOutSpeed,e)}]};function a(f,g){var p=this,k=c(this);f.data("tooltip",p);var l=f.next();if(g.tip){l=c(g.tip);if(l.length>1){l=f.nextAll(g.tip).eq(0);if(!l.length){l=f.parent().nextAll(g.tip).eq(0)}}}function o(u){var t=g.relative?f.position().top:f.offset().top,s=g.relative?f.position().left:f.offset().left,v=g.position[0];t-=l.outerHeight()-g.offset[0];s+=f.outerWidth()+g.offset[1];var q=l.outerHeight()+f.outerHeight();if(v=="center"){t+=q/2}if(v=="bottom"){t+=q}v=g.position[1];var r=l.outerWidth()+f.outerWidth();if(v=="center"){s-=r/2}if(v=="left"){s-=r}return{top:t,left:s}}var i=f.is(":input"),e=i&&f.is(":checkbox, :radio, select, :button"),h=f.attr("type"),n=g.events[h]||g.events[i?(e?"widget":"input"):"def"];n=n.split(/,\s*/);if(n.length!=2){throw"Tooltip: bad events configuration for "+h}f.bind(n[0],function(r){if(g.oneInstance){c.each(d,function(){this.hide()})}var q=l.data("trigger");if(q&&q[0]!=this){l.hide().stop(true,true)}r.target=this;p.show(r);n=g.events.tooltip.split(/,\s*/);l.bind(n[0],function(){p.show(r)});if(n[1]){l.bind(n[1],function(){p.hide(r)})}});f.bind(n[1],function(q){p.hide(q)});if(!c.browser.msie&&!i&&!g.predelay){f.mousemove(function(){if(!p.isShown()){f.triggerHandler("mouseover")}})}if(g.opacity<1){l.css("opacity",g.opacity)}var m=0,j=f.attr("title");if(j&&g.cancelDefault){f.removeAttr("title");f.data("title",j)}c.extend(p,{show:function(r){if(r){f=c(r.target)}clearTimeout(l.data("timer"));if(l.is(":animated")||l.is(":visible")){return p}function q(){l.data("trigger",f);var t=o(r);if(g.tip&&j){l.html(f.data("title"))}r=r||c.Event();r.type="onBeforeShow";k.trigger(r,[t]);if(r.isDefaultPrevented()){return p}t=o(r);l.css({position:"absolute",top:t.top,left:t.left});var s=b[g.effect];if(!s){throw'Nonexistent effect "'+g.effect+'"'}s[0].call(p,function(){r.type="onShow";k.trigger(r)})}if(g.predelay){clearTimeout(m);m=setTimeout(q,g.predelay)}else{q()}return p},hide:function(r){clearTimeout(l.data("timer"));clearTimeout(m);if(!l.is(":visible")){return}function q(){r=r||c.Event();r.type="onBeforeHide";k.trigger(r);if(r.isDefaultPrevented()){return}b[g.effect][1].call(p,function(){r.type="onHide";k.trigger(r)})}if(g.delay&&r){l.data("timer",setTimeout(q,g.delay))}else{q()}return p},isShown:function(){return l.is(":visible, :animated")},getConf:function(){return g},getTip:function(){return l},getTrigger:function(){return f},bind:function(q,r){k.bind(q,r);return p},onHide:function(q){return this.bind("onHide",q)},onBeforeShow:function(q){return this.bind("onBeforeShow",q)},onShow:function(q){return this.bind("onShow",q)},onBeforeHide:function(q){return this.bind("onBeforeHide",q)},unbind:function(q){k.unbind(q);return p}});c.each(g,function(q,r){if(c.isFunction(r)){p.bind(q,r)}})}c.prototype.tooltip=function(e){var f=this.eq(typeof e=="number"?e:0).data("tooltip");if(f){return f}var g=c.extend(true,{},c.tools.tooltip.conf);if(c.isFunction(e)){e={onBeforeShow:e}}else{if(typeof e=="string"){e={tip:e}}}e=c.extend(true,g,e);if(typeof e.position=="string"){e.position=e.position.split(/,?\s/)}if(e.lazy!==false&&(e.lazy===true||this.length>20)){this.one("mouseover",function(h){f=new a(c(this),e);f.show(h);d.push(f)})}else{this.each(function(){f=new a(c(this),e);d.push(f)})}return e.api?f:this}})(jQuery); \ No newline at end of file diff --git a/nebula-exchange/target/site/scaladocs/lib/trait.png b/nebula-exchange/target/site/scaladocs/lib/trait.png new file mode 100644 index 0000000000000000000000000000000000000000..fb961a2eda3f55c9d8272a4793549e23120aec6b GIT binary patch literal 3374 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 Ef&ySVw*UYD literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/trait_big.png b/nebula-exchange/target/site/scaladocs/lib/trait_big.png new file mode 100644 index 0000000000000000000000000000000000000000..625d9251cba32d350beb988fcd072672d5f3b375 GIT binary patch literal 7410 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 literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/trait_diagram.png b/nebula-exchange/target/site/scaladocs/lib/trait_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..88983254ce3a4295951e4d3af927d50b50a3146d GIT binary patch literal 3882 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 literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/type_diagram.png b/nebula-exchange/target/site/scaladocs/lib/type_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..d8152529fdc350853f4b1e7debb0a0c8d632ff7f GIT binary patch literal 1841 zcmaJ?c~BE)99T$Lr=we%F*v^CE}IxJ--BM^o`!9R>q2MpO@j3bQT^*1$SrURFCC z2>>oM1k&PKWSh-nWFHq$`FD5iZZP_mU) z32Z{*^D%gSz6vtrXBfhbw5YjYBq1UN%rLG433H~!CL+YN*SaEd?$~D0z}FBwLri;< zlvb$*B`5}i0w$YbV2857P!5yB;|qntIUtwKVYAp=7Kh8=2t_=uh|LDyJ~T2KW=s`n zr1H11$d#C8!f~sJ#mddiW#;mjD3-?JgolSaG`L&_iD20BEVzzfSZqPV3R2i+zz{2r zpcc@fsMDj_xR^#}`lbZ4bwt);d)p?mVJt#tWpS8nM@hp#rSkuwX7dQzhHKz=`TnP{ z4a&2^EDdZ!voQmCaH&C#P*#xygLOEHK`5Fz+(oqs#Zj9HwStoQ0#Kk;ub192qxO9xI4phs&jMDLuu=8ia*d7`^PQtaB8%V%dM-8hnc zWXxx0wa@!*AHI2bF!i_Rsq(Dc+_=BBRdhN%c)_>(jM>>q_pqkTg98IJUyQoI+fvHW+Ky=RaJHK_H8<_+r@L-=`&~A@8@htuCFyo7|Ye*XR%m1bgeEg zFQ4e-O%5~QhcSJ@+e3+4u5h&TQ7=ol(Sy|%)oB~3rR9qStw?S1qbph5q z&KC1Zo}!x;7&ze>Pnnolwm_0_hq|G?I5}umOoG6-og;M~aFwb0gA-m@CB*>;j`-^fFX zREb^}yI;P1`Atbl3E!lcmDl{`I!vRPV6Uv~sjI8I^y}`yW}g)QO8e{-t(G`lzw?&2 vpS!x@6ME$tZpA+Dnp^bdh^L`1X14%ymwB@Ei@#dw_=zcGDrrOPlA?bAm}bg0 literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/type_to_object_big.png b/nebula-exchange/target/site/scaladocs/lib/type_to_object_big.png new file mode 100644 index 0000000000000000000000000000000000000000..ef2615bacc702f153594af64f60e4443ab91ea99 GIT binary patch literal 4969 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 SK}x{k>c&71H4lFd25SHaTcP{_ literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/unselected.png b/nebula-exchange/target/site/scaladocs/lib/unselected.png new file mode 100644 index 0000000000000000000000000000000000000000..d5ac639405ffe0a45fd51de2904692c7e905c5ef GIT binary patch literal 1879 zcmaJ?Yg7|Q6b|^HqG$*RJ1=z=bYV{JM(?ty?5^2v#TP* zXV}>~*-|JJJE=r0C+8;ear$C7`R*|}n8|585uzZXu~b42X<$l_3QK_jDGJSlaJAasf;LDeyc*Eo3}9c9H=gDj{Q* zj|`OIA~+3^WNF~&tne6R)&eD8#Rv=l{0#z90EGz%Frevbt-v5;yw??wYs)r^0lbG0 z3xtdhK`CUBfC$sTfDaS&Qi8r9;LB#Ry}5pVe$xRC$Oc&;hsEZ2vHb+z903Rd9|wc< zrctE|2w4^iul*#@dilU#;T0#zg zj`u%>wK17E%#y=eOs7$jg-dm_xWWY@4Ga;OCI-XO2W~Mk4I?mZ8ioU+XdgfZDG{~B zevg;Q1X8t@fYeG@Di$(G1tx;11R@?Ul*<+Q`0)LL*z6E6I8?+Jg>ZcR_}t(iE{8k7 z6=O;r3ag0$uIe+_cTldS6;Pb?EQU46LRb~5!BF6R$^vBYSiA?-`^Z%d9t(F+E{hC? zWhv~x3O%qzc8_KGsclK)Q{%&GvfDLeTemlSSw(&=%~EktjN#goZ7tzWkmK?P5!pej zcgbngf{{xfoysL(v+nXQ%V%{s8|-goFJRRzm(JR?+Cz5Dqrf!(w;eBS^2Qbbyz`?P z!dmMqkhh4rBr`&DuXwy7?8M666TRIP!-Kxd6IZT;-`w47yRIJLS&eDFPkXt3%K^K0 zxvd>{PEz7$&yN26$`x-%mz9NYMy!!sV%a`j^Hs;A+6_meQ|#(84dYrLzs#D0a-9-> zXp5TI*lAt)^L4$LtW3r!u0(7U$M3WNxbFl#Y6)sfCuM_h0Dj+_NI#oU82h zEYn8MB55VEC76D(^U%6(537s|`qy0xuZxiTBPUkw7FpA|oa|q3x&rEbad)k3?r)?p z@(*3r=L{pJ@|ua7?#u&Zb4jDw}LwD`?cl&LflP?-Dcam`y7@w(rfe&hxxzG!8Rq zd3cU-TVqO9e@jct0m#uM%YI6=c)izt$FXzkCGNCDn?3f0)m2qh)oXI)+J))tQ`J%yf$?jzi#;wb6p+pl6@I6FDcU8S@0 z2yYs0)wkxB8$U4cUAkWXYVtGH@3;Xl6o>{ z`8r;g@W#_6H@AB)wLXucXl($Gw>h+!R+r@OGB4r}H<=k5E!h!hFNAsK@*auZUlX^W z*9BWOitVMP{KWY9K4SyCd2$@CpV8szA3vS`;7CnPa`sOhN%_yZfk4XNe)i15yy{pC4X~ch)SnB{P)qSs-VcSX*DP3r<@Yyzrk~MM=TqvuBRvF tur|z~H^sL5c+!MS88ch*;^?;{KuWlJ)Eh;9cd6x9Ck+V~n}X*q`v(^B>01B* literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/lib/valuemembersbg.gif b/nebula-exchange/target/site/scaladocs/lib/valuemembersbg.gif new file mode 100644 index 0000000000000000000000000000000000000000..2a949311d7869cb769ef7fd48a9c03a57937b60d GIT binary patch literal 1206 zcmZ?wbhEHbWMq(GIKsdnZ{h0@Uu7LxEUIN)Ic=RqSb?mWkG6ZfPfmw%K&HM|vRQDB zZ(f&YMvIb7kh)W(qIH0ZeVAK%lWR)7rb~>DTbx&Ro3x3ip?;Zqle1Gx6p~WYGxKbf-tXS8q>!0ns}yePYv5bpoSKp8QB{;0 zT;&&%T$P<{nWAKGr(jcIRgqhen_7~nP?4LHS8P>btCX0MpOk6^WP^nDl@!2AO0sR0 z96=HaAUmD&i&7O#^$c{A4a^J_%nbDmjZMtW&2GK4GRy>*)Z*l#%z~24{5%DaiHS-1r6smXK$k+ikXryZHm_I@>>a)2{9OHt!~%Uo zJp+)JUEg{v+u2}(t{7puX=A(aKG`a!A1`K3k4sX*n*AgcnUy@&(kzb(T9BiuKo0y!L2jYX(`}$gW<`tJD<|U_ky4WfKP0-8COtCUC zHgGd=G%zu>baFB@bTx2tbGCGLH8L}|G;wk?F*1Sab;(aI%}vcKf$2>_=rzTu7nBro z3xGDeq!wkCrKY$Q<>xAZy=;|<+bu>o&4cPq!R;1foO<VgsyL#pFrHdENpF4Zz^r@34jvqUEVojbN~+qz}*ri~lc zuUorj^{SOCmM>enWbvYf3+B(8J7@N+nKPzOn>uCkq=^&y`+9r2yE;4C+ge+in;IMH z>uPJNt12tX%Sua%iwXi?qaq{1!$L!Xg8~Em{d|4A zy*xeK-CSLqog5wP?QCtVtt>6f%}h;V~x zOjJZzNKk;EkC%s=i<5($jg^I&iIIUp@h1zoq|gD8pz?@;RXoAfpyR4Xuvm`MMwJ;w P0sc=M8VWO=IT)+~jV+!7 literal 0 HcmV?d00001 diff --git a/nebula-exchange/target/site/scaladocs/package.html b/nebula-exchange/target/site/scaladocs/package.html new file mode 100644 index 0000000..0cf59ee --- /dev/null +++ b/nebula-exchange/target/site/scaladocs/package.html @@ -0,0 +1,118 @@ + + + + root - nebula-exchange 2.0.0 API - _root_ + + + + + + + + + + + + + + + + + +

                      + + + package + + + root + +

                      + +
                      + + +
                      +
                      + + +
                      + Visibility +
                      1. Public
                      2. All
                      +
                      +
                      + +
                      +
                      + + + + + + +
                      +

                      Value Members

                      +
                      1. + + +

                        + + + package + + + com + +

                        + + Permalink + + + +
                      +
                      + + + + +
                      + +
                      + + +
                      + +
                      +
                      +

                      Ungrouped

                      + +
                      +
                      + +
                      + +
                      + + + + + + diff --git a/nebula-exchange/target/test-classes.timestamp b/nebula-exchange/target/test-classes.timestamp new file mode 100644 index 0000000..945c9b4 --- /dev/null +++ b/nebula-exchange/target/test-classes.timestamp @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/nebula-spark-connector/pom.xml b/nebula-spark-connector/pom.xml new file mode 100644 index 0000000..9dbd072 --- /dev/null +++ b/nebula-spark-connector/pom.xml @@ -0,0 +1,14 @@ + + + + nebula-spark + com.vesoft + 2.0.0 + + 4.0.0 + + nebula-spark-connector + + \ No newline at end of file diff --git a/nebula-spark-connector/target/maven-archiver/pom.properties b/nebula-spark-connector/target/maven-archiver/pom.properties new file mode 100644 index 0000000..d111b8b --- /dev/null +++ b/nebula-spark-connector/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Wed Dec 09 18:47:46 CST 2020 +version=2.0.0 +groupId=com.vesoft +artifactId=nebula-spark-connector diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..111b621 --- /dev/null +++ b/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + + com.vesoft + nebula-spark + pom + 2.0.0 + + + UTF-8 + + + + nebula-spark + Nebula Spark Tools + https://github.com/vesoft-inc/nebula-spark-utils + + scm:git:https://github.com/vesoft-inc/nebula + https://github.com/vesoft-inc/nebula + scm:git:https://github.com/vesoft-inc/nebula + + + + Apache License, Version 2.0 + https://www.apache.org/licenses/LICENSE-2.0.txt + repo + license + + + + + + nebula + Nebula Graph + nebula-spark-utils@vesoft-inc.com + vesoft + + architect + developer + + + + + + nebula-exchange + nebula-spark-connector + + + + + release + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + snapshots + https://oss.sonatype.org/content/repositories/snapshots/ + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + verify + + sign + + + + + + + From f52d3aba0f00c1aa9fa95c16b4fd625353cd3e66 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 9 Dec 2020 19:23:57 +0800 Subject: [PATCH 003/213] add ignore & add notes --- .gitignore | 20 +++++++++++++------ .../nebula/tools/importer/GraphProvider.scala | 2 +- .../nebula/tools/importer/reader/Reader.scala | 2 +- .../importer/writer/FileBaseWriter.scala | 2 +- .../importer/writer/ServerBaseWriter.scala | 2 -- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index b5562b0..3877c83 100644 --- a/.gitignore +++ b/.gitignore @@ -7,12 +7,6 @@ # BlueJ files *.ctxt -# iml -*.iml - -# .idea -.idea - # Mobile Tools for Java (J2ME) .mtj.tmp/ @@ -27,3 +21,17 @@ # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* + +# build target +target/ + +# IDE +.idea/ +.eclipse/ +*.iml + +spark-importer.ipr +spark-importer.iws + +# mac +.DS_Store diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/GraphProvider.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/GraphProvider.scala index ab48520..d99bb05 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/GraphProvider.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/GraphProvider.scala @@ -17,7 +17,7 @@ import scala.collection.JavaConverters._ import scala.collection.mutable.ListBuffer /** - * + * GraphProvider for Nebula Graph Service */ class GraphProvider(addresses: List[HostAndPort]) extends AutoCloseable with Serializable { private[this] lazy val LOG = Logger.getLogger(this.getClass) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/Reader.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/Reader.scala index 3fae084..d10f102 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/Reader.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/Reader.scala @@ -11,7 +11,7 @@ import com.vesoft.nebula.tools.importer.utils.HDFSUtils import org.apache.spark.sql.{DataFrame, SparkSession} /** - * The Reader is used for create a DataFrame from the source. Such as Hive or HDFS. + * The Reader is used to create a DataFrame from the source, such as Hive or HDFS. */ trait Reader extends Serializable { def session: SparkSession diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/FileBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/FileBaseWriter.scala index 28cbbe9..2fad1d2 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/FileBaseWriter.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/FileBaseWriter.scala @@ -15,7 +15,7 @@ import org.rocksdb.{ import org.slf4j.LoggerFactory /** - * + * NebulaSSTWriter * @param path */ class NebulaSSTWriter(path: String) extends Writer { diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.scala index a1e923f..6482dd1 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.scala @@ -45,7 +45,6 @@ abstract class ServerBaseWriter extends Writer { vertices.propertyNames, vertices.values .map { vertex => - // TODO Check if (vertices.policy.isEmpty) { INSERT_VALUE_TEMPLATE.format(vertex.vertexID, vertex.propertyValues) } else { @@ -70,7 +69,6 @@ abstract class ServerBaseWriter extends Writer { .map { edge => (for (element <- edge.source.split(",")) yield { - // TODO Check and Test val source = edges.sourcePolicy match { case Some(KeyPolicy.HASH) => ENDPOINT_TEMPLATE.format(KeyPolicy.HASH.toString, element) From 5e7a7734141c5a05ed60c44f73fb90d29c571980 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 10 Dec 2020 09:20:18 +0800 Subject: [PATCH 004/213] add .gitignore file --- nebula-exchange/.gitignore | 36 + nebula-exchange/target/classes.timestamp | 1 - .../target/classes/application.conf | 129 - .../target/classes/server_application.conf | 183 - .../target/classes/stream_application.conf | 143 - .../target/classes/test_application.conf | 109 - .../target/maven-archiver/pom.properties | 5 - .../compile/default-compile/inputFiles.lst | 0 .../default-testCompile/createdFiles.lst | 2 - .../default-testCompile/inputFiles.lst | 1 - .../target/site/scaladocs/com/package.html | 118 - .../scaladocs/com/vesoft/nebula/package.html | 118 - .../nebula/tools/importer/Argument.html | 544 -- .../tools/importer/CheckPointHandler$.html | 534 -- .../nebula/tools/importer/ErrorHandler$.html | 516 -- .../nebula/tools/importer/Exchange$.html | 500 -- .../nebula/tools/importer/GraphProvider.html | 644 -- .../nebula/tools/importer/MetaProvider.html | 628 -- .../importer/TooManyErrorsException.html | 684 -- .../nebula/tools/importer/VidType$.html | 786 --- .../tools/importer/config/Configs$.html | 540 -- .../nebula/tools/importer/config/Configs.html | 632 -- .../config/ConnectionConfigEntry.html | 511 -- .../importer/config/DataBaseConfigEntry.html | 562 -- .../importer/config/DataSinkConfigEntry.html | 506 -- .../config/DataSourceConfigEntry.html | 506 -- .../importer/config/EdgeConfigEntry.html | 750 --- .../importer/config/ErrorConfigEntry.html | 511 -- .../importer/config/ExecutionConfigEntry.html | 528 -- .../config/FileBaseSinkConfigEntry.html | 530 -- .../config/FileBaseSourceConfigEntry.html | 549 -- .../config/FileDataSourceConfigEntry.html | 524 -- .../config/HBaseSourceConfigEntry.html | 599 -- .../importer/config/HiveConfigEntry.html | 561 -- .../config/HiveSourceConfigEntry.html | 515 -- .../config/JanusGraphSourceConfigEntry.html | 531 -- .../config/KafkaSourceConfigEntry.html | 549 -- .../config/MySQLSourceConfigEntry.html | 617 -- .../config/NebulaSinkConfigEntry.html | 513 -- .../config/Neo4JSourceConfigEntry.html | 651 -- .../config/PulsarSourceConfigEntry.html | 566 -- .../importer/config/RateConfigEntry.html | 511 -- .../importer/config/SchemaConfigEntry.html | 625 -- .../config/ServerDataSourceConfigEntry.html | 524 -- .../tools/importer/config/SinkCategory$.html | 790 --- .../tools/importer/config/SinkCategory.html | 504 -- .../importer/config/SourceCategory$.html | 976 --- .../tools/importer/config/SourceCategory.html | 504 -- .../importer/config/SparkConfigEntry$.html | 505 -- .../importer/config/SparkConfigEntry.html | 496 -- .../StreamingDataSourceConfigEntry.html | 524 -- .../tools/importer/config/TagConfigEntry.html | 648 -- .../nebula/tools/importer/config/Type$.html | 786 --- .../importer/config/UserConfigEntry.html | 511 -- .../nebula/tools/importer/config/package.html | 700 --- .../nebula/tools/importer/package$$Edge.html | 578 -- .../nebula/tools/importer/package$$Edges.html | 561 -- .../tools/importer/package$$KeyPolicy$.html | 786 --- .../tools/importer/package$$Offset.html | 493 -- .../tools/importer/package$$Vertex.html | 527 -- .../tools/importer/package$$Vertices.html | 544 -- .../vesoft/nebula/tools/importer/package.html | 709 --- .../importer/processor/EdgeProcessor.html | 582 -- .../tools/importer/processor/Processor.html | 568 -- .../importer/processor/ReloadProcessor.html | 582 -- .../importer/processor/VerticesProcessor.html | 582 -- .../tools/importer/processor/package.html | 172 - .../tools/importer/reader/CSVReader.html | 580 -- .../importer/reader/CheckPointSupport.html | 506 -- .../tools/importer/reader/CustomReader.html | 581 -- .../tools/importer/reader/FileBaseReader.html | 583 -- .../tools/importer/reader/HBaseReader.html | 578 -- .../tools/importer/reader/HiveReader.html | 579 -- .../tools/importer/reader/JSONReader.html | 579 -- .../importer/reader/JanusGraphReader.html | 597 -- .../tools/importer/reader/KafkaReader.html | 561 -- .../tools/importer/reader/MySQLReader.html | 580 -- .../tools/importer/reader/NebulaReader.html | 578 -- .../tools/importer/reader/Neo4JReader.html | 598 -- .../tools/importer/reader/ORCReader.html | 579 -- .../tools/importer/reader/ParquetReader.html | 579 -- .../tools/importer/reader/PulsarReader.html | 561 -- .../nebula/tools/importer/reader/Reader.html | 544 -- .../importer/reader/ServerBaseReader.html | 583 -- .../importer/reader/StreamingBaseReader.html | 566 -- .../nebula/tools/importer/reader/package.html | 419 -- .../tools/importer/utils/HDFSUtils$.html | 584 -- .../tools/importer/utils/KafkaUtils$.html | 516 -- .../tools/importer/utils/NebulaUtils$.html | 550 -- .../nebula/tools/importer/utils/package.html | 152 - .../writer/NebulaGraphClientWriter.html | 646 -- .../importer/writer/NebulaSSTWriter.html | 610 -- .../writer/NebulaStorageClientWriter.html | 629 -- .../importer/writer/NebulaWriterCallback.html | 538 -- .../importer/writer/ServerBaseWriter.html | 616 -- .../nebula/tools/importer/writer/Writer.html | 526 -- .../nebula/tools/importer/writer/package.html | 203 - .../com/vesoft/nebula/tools/package.html | 118 - .../site/scaladocs/com/vesoft/package.html | 118 - .../target/site/scaladocs/index.html | 80 - .../target/site/scaladocs/index.js | 1 - .../target/site/scaladocs/index/index-a.html | 29 - .../target/site/scaladocs/index/index-b.html | 17 - .../target/site/scaladocs/index/index-c.html | 74 - .../target/site/scaladocs/index/index-d.html | 44 - .../target/site/scaladocs/index/index-e.html | 80 - .../target/site/scaladocs/index/index-f.html | 32 - .../target/site/scaladocs/index/index-g.html | 74 - .../target/site/scaladocs/index/index-h.html | 53 - .../target/site/scaladocs/index/index-i.html | 35 - .../target/site/scaladocs/index/index-j.html | 29 - .../target/site/scaladocs/index/index-k.html | 29 - .../target/site/scaladocs/index/index-l.html | 29 - .../target/site/scaladocs/index/index-m.html | 35 - .../target/site/scaladocs/index/index-n.html | 59 - .../target/site/scaladocs/index/index-o.html | 32 - .../target/site/scaladocs/index/index-p.html | 89 - .../target/site/scaladocs/index/index-r.html | 53 - .../target/site/scaladocs/index/index-s.html | 104 - .../target/site/scaladocs/index/index-t.html | 59 - .../target/site/scaladocs/index/index-u.html | 32 - .../target/site/scaladocs/index/index-v.html | 50 - .../target/site/scaladocs/index/index-w.html | 38 - .../target/site/scaladocs/lib/arrow-down.png | Bin 6232 -> 0 bytes .../target/site/scaladocs/lib/arrow-right.png | Bin 6220 -> 0 bytes .../target/site/scaladocs/lib/class.png | Bin 3357 -> 0 bytes .../target/site/scaladocs/lib/class_big.png | Bin 7516 -> 0 bytes .../site/scaladocs/lib/class_diagram.png | Bin 3910 -> 0 bytes .../scaladocs/lib/class_to_object_big.png | Bin 9006 -> 0 bytes .../site/scaladocs/lib/constructorsbg.gif | Bin 1206 -> 0 bytes .../site/scaladocs/lib/conversionbg.gif | Bin 167 -> 0 bytes .../target/site/scaladocs/lib/defbg-blue.gif | Bin 1544 -> 0 bytes .../target/site/scaladocs/lib/defbg-green.gif | Bin 1341 -> 0 bytes .../target/site/scaladocs/lib/diagrams.css | 143 - .../target/site/scaladocs/lib/diagrams.js | 324 - .../site/scaladocs/lib/filter_box_left.png | Bin 1692 -> 0 bytes .../site/scaladocs/lib/filter_box_left2.gif | Bin 1462 -> 0 bytes .../site/scaladocs/lib/filter_box_right.png | Bin 1803 -> 0 bytes .../target/site/scaladocs/lib/filterbg.gif | Bin 1324 -> 0 bytes .../site/scaladocs/lib/filterboxbarbg.gif | Bin 1104 -> 0 bytes .../site/scaladocs/lib/filterboxbarbg.png | Bin 965 -> 0 bytes .../target/site/scaladocs/lib/filterboxbg.gif | Bin 1366 -> 0 bytes .../site/scaladocs/lib/fullcommenttopbg.gif | Bin 1115 -> 0 bytes .../target/site/scaladocs/lib/index.css | 339 - .../target/site/scaladocs/lib/index.js | 577 -- .../target/site/scaladocs/lib/jquery-ui.js | 6 - .../target/site/scaladocs/lib/jquery.js | 2 - .../site/scaladocs/lib/jquery.layout.js | 5486 ----------------- .../site/scaladocs/lib/modernizr.custom.js | 4 - .../site/scaladocs/lib/navigation-li-a.png | Bin 1198 -> 0 bytes .../site/scaladocs/lib/navigation-li.png | Bin 2441 -> 0 bytes .../target/site/scaladocs/lib/object.png | Bin 3356 -> 0 bytes .../target/site/scaladocs/lib/object_big.png | Bin 7653 -> 0 bytes .../site/scaladocs/lib/object_diagram.png | Bin 3903 -> 0 bytes .../scaladocs/lib/object_to_class_big.png | Bin 9158 -> 0 bytes .../scaladocs/lib/object_to_trait_big.png | Bin 9200 -> 0 bytes .../site/scaladocs/lib/object_to_type_big.png | Bin 9158 -> 0 bytes .../target/site/scaladocs/lib/ownderbg2.gif | Bin 1145 -> 0 bytes .../target/site/scaladocs/lib/ownerbg.gif | Bin 1118 -> 0 bytes .../target/site/scaladocs/lib/ownerbg2.gif | Bin 1145 -> 0 bytes .../target/site/scaladocs/lib/package.png | Bin 3335 -> 0 bytes .../target/site/scaladocs/lib/package_big.png | Bin 7312 -> 0 bytes .../target/site/scaladocs/lib/packagesbg.gif | Bin 1201 -> 0 bytes .../target/site/scaladocs/lib/permalink.png | Bin 943 -> 0 bytes .../target/site/scaladocs/lib/ref-index.css | 30 - .../target/site/scaladocs/lib/remove.png | Bin 3186 -> 0 bytes .../target/site/scaladocs/lib/scheduler.js | 71 - .../site/scaladocs/lib/selected-implicits.png | Bin 1150 -> 0 bytes .../lib/selected-right-implicits.png | Bin 646 -> 0 bytes .../site/scaladocs/lib/selected-right.png | Bin 1380 -> 0 bytes .../target/site/scaladocs/lib/selected.png | Bin 1864 -> 0 bytes .../site/scaladocs/lib/selected2-right.png | Bin 1434 -> 0 bytes .../target/site/scaladocs/lib/selected2.png | Bin 1965 -> 0 bytes .../target/site/scaladocs/lib/signaturebg.gif | Bin 1214 -> 0 bytes .../site/scaladocs/lib/signaturebg2.gif | Bin 1209 -> 0 bytes .../target/site/scaladocs/lib/template.css | 893 --- .../target/site/scaladocs/lib/template.js | 500 -- .../site/scaladocs/lib/tools.tooltip.js | 14 - .../target/site/scaladocs/lib/trait.png | Bin 3374 -> 0 bytes .../target/site/scaladocs/lib/trait_big.png | Bin 7410 -> 0 bytes .../site/scaladocs/lib/trait_diagram.png | Bin 3882 -> 0 bytes .../scaladocs/lib/trait_to_object_big.png | Bin 8967 -> 0 bytes .../target/site/scaladocs/lib/type.png | Bin 1445 -> 0 bytes .../target/site/scaladocs/lib/type_big.png | Bin 4236 -> 0 bytes .../site/scaladocs/lib/type_diagram.png | Bin 1841 -> 0 bytes .../site/scaladocs/lib/type_to_object_big.png | Bin 4969 -> 0 bytes .../target/site/scaladocs/lib/typebg.gif | Bin 1206 -> 0 bytes .../target/site/scaladocs/lib/unselected.png | Bin 1879 -> 0 bytes .../site/scaladocs/lib/valuemembersbg.gif | Bin 1206 -> 0 bytes .../target/site/scaladocs/package.html | 118 - nebula-exchange/target/test-classes.timestamp | 1 - nebula-spark-connector/.gitignore | 36 + .../target/maven-archiver/pom.properties | 5 - 193 files changed, 72 insertions(+), 58891 deletions(-) create mode 100644 nebula-exchange/.gitignore delete mode 100644 nebula-exchange/target/classes.timestamp delete mode 100644 nebula-exchange/target/classes/application.conf delete mode 100644 nebula-exchange/target/classes/server_application.conf delete mode 100644 nebula-exchange/target/classes/stream_application.conf delete mode 100644 nebula-exchange/target/classes/test_application.conf delete mode 100644 nebula-exchange/target/maven-archiver/pom.properties delete mode 100644 nebula-exchange/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst delete mode 100644 nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst delete mode 100644 nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst delete mode 100644 nebula-exchange/target/site/scaladocs/com/package.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/package.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Argument.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/CheckPointHandler$.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/ErrorHandler$.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Exchange$.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/GraphProvider.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/MetaProvider.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/TooManyErrorsException.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/VidType$.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs$.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ConnectionConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataBaseConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSinkConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSourceConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/EdgeConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ErrorConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ExecutionConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSinkConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSourceConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileDataSourceConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HBaseSourceConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveSourceConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/JanusGraphSourceConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/KafkaSourceConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/MySQLSourceConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/NebulaSinkConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Neo4JSourceConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/PulsarSourceConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/RateConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SchemaConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ServerDataSourceConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory$.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory$.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry$.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/StreamingDataSourceConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/TagConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Type$.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/UserConfigEntry.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/package.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edge.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edges.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$KeyPolicy$.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Offset.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertex.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertices.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/Processor.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/ReloadProcessor.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/package.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CSVReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CheckPointSupport.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CustomReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/FileBaseReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HBaseReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HiveReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JSONReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JanusGraphReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/KafkaReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/MySQLReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/NebulaReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Neo4JReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ORCReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ParquetReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/PulsarReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Reader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ServerBaseReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/StreamingBaseReader.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/package.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/HDFSUtils$.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/KafkaUtils$.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/NebulaUtils$.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/package.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaGraphClientWriter.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaSSTWriter.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaStorageClientWriter.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaWriterCallback.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/Writer.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/package.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/package.html delete mode 100644 nebula-exchange/target/site/scaladocs/com/vesoft/package.html delete mode 100644 nebula-exchange/target/site/scaladocs/index.html delete mode 100644 nebula-exchange/target/site/scaladocs/index.js delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-a.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-b.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-c.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-d.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-e.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-f.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-g.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-h.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-i.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-j.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-k.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-l.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-m.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-n.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-o.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-p.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-r.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-s.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-t.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-u.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-v.html delete mode 100644 nebula-exchange/target/site/scaladocs/index/index-w.html delete mode 100644 nebula-exchange/target/site/scaladocs/lib/arrow-down.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/arrow-right.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/class.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/class_big.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/class_diagram.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/class_to_object_big.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/constructorsbg.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/conversionbg.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/defbg-blue.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/defbg-green.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/diagrams.css delete mode 100644 nebula-exchange/target/site/scaladocs/lib/diagrams.js delete mode 100644 nebula-exchange/target/site/scaladocs/lib/filter_box_left.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/filter_box_left2.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/filter_box_right.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/filterbg.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/filterboxbarbg.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/filterboxbarbg.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/filterboxbg.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/fullcommenttopbg.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/index.css delete mode 100644 nebula-exchange/target/site/scaladocs/lib/index.js delete mode 100644 nebula-exchange/target/site/scaladocs/lib/jquery-ui.js delete mode 100644 nebula-exchange/target/site/scaladocs/lib/jquery.js delete mode 100644 nebula-exchange/target/site/scaladocs/lib/jquery.layout.js delete mode 100644 nebula-exchange/target/site/scaladocs/lib/modernizr.custom.js delete mode 100644 nebula-exchange/target/site/scaladocs/lib/navigation-li-a.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/navigation-li.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/object.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/object_big.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/object_diagram.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/object_to_class_big.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/object_to_trait_big.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/object_to_type_big.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/ownderbg2.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/ownerbg.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/ownerbg2.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/package.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/package_big.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/packagesbg.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/permalink.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/ref-index.css delete mode 100644 nebula-exchange/target/site/scaladocs/lib/remove.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/scheduler.js delete mode 100644 nebula-exchange/target/site/scaladocs/lib/selected-implicits.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/selected-right-implicits.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/selected-right.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/selected.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/selected2-right.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/selected2.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/signaturebg.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/signaturebg2.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/template.css delete mode 100644 nebula-exchange/target/site/scaladocs/lib/template.js delete mode 100644 nebula-exchange/target/site/scaladocs/lib/tools.tooltip.js delete mode 100644 nebula-exchange/target/site/scaladocs/lib/trait.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/trait_big.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/trait_diagram.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/trait_to_object_big.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/type.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/type_big.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/type_diagram.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/type_to_object_big.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/typebg.gif delete mode 100644 nebula-exchange/target/site/scaladocs/lib/unselected.png delete mode 100644 nebula-exchange/target/site/scaladocs/lib/valuemembersbg.gif delete mode 100644 nebula-exchange/target/site/scaladocs/package.html delete mode 100644 nebula-exchange/target/test-classes.timestamp create mode 100644 nebula-spark-connector/.gitignore delete mode 100644 nebula-spark-connector/target/maven-archiver/pom.properties diff --git a/nebula-exchange/.gitignore b/nebula-exchange/.gitignore new file mode 100644 index 0000000..84e7a6b --- /dev/null +++ b/nebula-exchange/.gitignore @@ -0,0 +1,36 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# build target +target/ + +# IDE +.idea/ +.eclipse/ +*.iml + +spark-importer.ipr +spark-importer.iws + +.DS_Store diff --git a/nebula-exchange/target/classes.timestamp b/nebula-exchange/target/classes.timestamp deleted file mode 100644 index 945c9b4..0000000 --- a/nebula-exchange/target/classes.timestamp +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file diff --git a/nebula-exchange/target/classes/application.conf b/nebula-exchange/target/classes/application.conf deleted file mode 100644 index 61bfa28..0000000 --- a/nebula-exchange/target/classes/application.conf +++ /dev/null @@ -1,129 +0,0 @@ -{ - # Spark relation config - spark: { - app: { - name: Nebula Exchange 2.0 - } - - driver: { - cores: 1 - maxResultSize: 1G - } - - executor: { - memory:1G - } - - cores:{ - max: 16 - } - } - - # Nebula Graph relation config - nebula: { - address:{ - graph:["127.0.0.1:3699"] - meta:["127.0.0.1:45500"] - } - user: user - pswd: password - space: test - - connection { - timeout: 3000 - retry: 3 - } - - execution { - retry: 3 - } - - error: { - max: 32 - # failed import job will be recorded in output path - output: /tmp/errors - } - - rate: { - limit: 1024 - timeout: 1000 - } - } - - # Processing tags - tags: [ - - # Loading tag from HDFS and data type is parquet - { - name: tag-name-0 - type: { - source: parquet - sink: client - } - path: hdfs tag path 0 - fields: [parquet-field-0, parquet-field-1, parquet-field-2] - nebula.fields: [nebula-field-0 nebula-field-1 nebula-field-2] - vertex: hive-field-0 - batch: 256 - partition: 32 - } - - # Loading tag from HDFS and data type is csv - { - name: tag-name-2 - type: { - source: csv - sink: client - } - path: hdfs tag path 2 - fields: [csv-field-0, csv-field-1, csv-field-2] - nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - vertex: hive-field-0 - separator: "," - header: true - batch: 256 - partition: 32 - } - - # Loading tag from HDFS and data type is csv - { - name: tag-name-2 - type: { - source: csv - sink: client - } - path: hdfs tag path 2 - fields: [csv-field-0, csv-field-1, csv-field-2] - nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - vertex: hive-field-0 - separator: "," - header: true - batch: 256 - partition: 32 - } - ] - - # Processing edges - edges: [ - # Loading tag from HDFS and data type is json - { - name: edge-name-0 - type: { - source: json - sink: client - } - path: hdfs edge path 0 - fields: [json-field-0, json-field-1, json-field-2] - nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - source: { - field: hive-field-0 - } - target: { - field: hive-field-1 - } - ranking: hive-field-2 - batch: 256 - partition: 32 - } - ] -} diff --git a/nebula-exchange/target/classes/server_application.conf b/nebula-exchange/target/classes/server_application.conf deleted file mode 100644 index 8e6118b..0000000 --- a/nebula-exchange/target/classes/server_application.conf +++ /dev/null @@ -1,183 +0,0 @@ -{ - # Spark relation config - spark: { - driver: { - cores: 1 - maxResultSize: 1G - } - - cores { - max: 16 - } - } - - # if the hive is in the same cluster with spark, you can ignore this hive configure - hive: { - waredir: "hdfs://HOSTNAME:9000/apps/svr/hive-0.13.1-cdh5.3.2/warehouse/" - connectionURL: "jdbc:mysql://your_ip:3306/hive_spark?characterEncoding=UTF-8" - connectionDriverName: "com.mysql.jdbc.Driver" - connectionUserName: "user" - connectionPassword: "password" - } - - # Nebula Graph relation config - nebula: { - address:{ - graph:["127.0.0.1:3699"] - meta:["127.0.0.1:45500"] - } - user: user - pswd: password - space: test - - connection { - timeout: 3000 - retry: 3 - } - - execution { - retry: 3 - } - - error: { - max: 32 - # failed import job will be recorded in output path - output: /tmp/errors - } - - rate: { - limit: 1024 - timeout: 1000 - } - } - - # Processing tags - tags: [ - # Loading from Hive - { - name: tag-name-1 - type: { - source: hive - sink: client - } - exec: "select hive-field0, hive-field1, hive-field2 from database.table" - fields: [hive-field-0, hive-field-1, hive-field-2] - nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - vertex: { - field: hive-field-0 - # nebula 2.0 does not support int vid yet, so do not config policy. - # policy: "hash" - } - vertex: hive-field-0 - batch: 256 - partition: 32 - } - - # Loading tag from neo4j - { - name: tag-name-0 - type: { - source: neo4j - sink: client - } - server: "bolt://127.0.0.1:7687" - user: neo4j - password: neo4j - exec: "match (n:label) return n.neo4j-field-0 as neo4j-field-0, n.neo4j-field-1 as neo4j-field-1 order by (n.neo4j-field-0)" - fields: [neo4j-field-0, neo4j-field-1] - nebula.fields: [nebula-field-0, nebula-field-1] - vertex: { - field:neo4j-field-0 - # nebula 2.0 does not support int vid yet, so do not config policy. - # policy:uuid - } - partition: 10 - batch: 1000 - check_point_path: /tmp/test - } - - # Loading from HBase, if fields or vertex contains rowkey, please configure it as rowkey. - { - name: hbase-table-name - type: { - source: hbase - sink: client - } - host:127.0.0.1 - port:2181 - table:hbase-table - columnFamily:hbase-table-cloumnfamily - fields: [hbase-column-0, hbase-column-1] - nebula.fields: [nebula-field-0, nebula-field-1] - vertex: rowkey - partition: 10 - batch: 1000 - } - ] - - # Processing edges - edges: [ - # Loading from Hive - { - name: edge-name-1 - type: { - source: hive - sink: client - } - exec: "select hive-field0, hive-field1, hive-field2 from database.table" - fields: [ hive-field-0, hive-field-1, hive-field-2] - nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - source: hive-field-0 - target: hive-field-1 - batch: 256 - partition: 32 - } - - # Loading from neo4j - { - name: edge-name-0 - type: { - source: neo4j - sink: client - } - server: "bolt://127.0.0.1:7687" - user: neo4j - password: neo4j - exec: "match (a:vertex_label)-[r:edge_label]->(b:vertex_label) return a.neo4j-source-field, b.neo4j-target-field, r.neo4j-field-0 as neo4j-field-0, r.neo4j-field-1 as neo4j-field-1 order by id(r)" - fields: [neo4j-field-0, neo4j-field-1] - nebula.fields: [nebula-field-0, nebula-field-1] - source: { - field: a.neo4j-source-field - } - target: { - field: b.neo4j-target-field - } - partition: 10 - batch: 1000 - check_point_path: /tmp/test - } - - # Loading from hbase - { - name: hbase-table-name - type: { - source: hbase - sink: client - } - host:127.0.0.1 - port:2181 - table:hbase-table - columnFamily:hbase-table-cloumnfamily - fields: [hbase-column-0, hbase-column-1] - nebula.fields:[nebula-field-0, nebula-field-1] - source: { - field: hbase-column-k - } - target: { - field: hbase-column-h - } - partition: 10 - batch: 1000 - } - ] -} diff --git a/nebula-exchange/target/classes/stream_application.conf b/nebula-exchange/target/classes/stream_application.conf deleted file mode 100644 index ab0a201..0000000 --- a/nebula-exchange/target/classes/stream_application.conf +++ /dev/null @@ -1,143 +0,0 @@ -{ - # Spark relation config - spark: { - app: { - name: Spark Writer - } - - driver: { - cores: 1 - maxResultSize: 1G - } - - cores { - max: 16 - } - } - - # Nebula Graph relation config - nebula: { - address:{ - graph:["127.0.0.1:3699"] - meta:["127.0.0.1:45500"] - } - user: user - pswd: password - space: test - - connection { - timeout: 3000 - retry: 3 - } - - execution { - retry: 3 - } - - error: { - max: 32 - # failed import job will be recorded in output path - output: /tmp/errors - } - - rate: { - limit: 1024 - timeout: 1000 - } - } - - # Processing tags - tags: [ - - # Loading tag from pulsar - { - name: tag-name-0 - type: { - source: pulsar - sink: client - } - service: "pulsar://localhost:6650" - admin: "http://localhost:8081" - options: { - # choose one of "topic", "topics", "topicsPattern" - topics: "topic1,topic2" - } - fields: [pulsar-field-0, pulsar-field-1, pulsar-field-2] - nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - vertex: { - field:pulsar-field-0 - # nebula 2.0 does not support int vid yet, so do not config policy. - # policy:hash - } - partition: 10 - batch: 1000 - interval.seconds: 10 - } - - # Loading from KAFKA - { - name: tag-name-1 - type: { - source: kafka - sink: client - } - service: "kafka.service.address" - topic: "topic-name" - fields: [kafka-field-0, kafka-field-1, kafka-field-2] - nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - vertex: kafka-field-0 - partition: 10 - batch: 10 - interval.seconds: 10 - } - ] - - # Processing edges - edges: [ - - # Loading tag from pulsar - { - name: edge-name-0 - type: { - source: pulsar - sink: client - } - service: "pulsar://localhost:6650" - admin: "http://localhost:8081" - options: { - # choose one of "topic", "topics", "topicsPattern" - topic: "topic1" - } - fields: [pulsar-field-0, pulsar-field-1, pulsar-field-2] - nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - source: { - field: pulsar-field-0 - } - target: { - field: pulsar-field-1 - } - ranking: pulsar-field-2 - partition: 10 - batch: 10 - interval.seconds: 10 - } - - # Loading from KAFKA - { - name: edge-name-1 - type: { - source: kafka - sink: client - } - service: "kafka.service.address" - topic: "topic-name" - fields: [kafka-field-0, kafka-field-1, kafka-field-2] - nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - source: kafka-field-0 - target: kafka-field-1 - partition: 10 - batch: 1000 - interval.seconds: 10 - } - ] -} diff --git a/nebula-exchange/target/classes/test_application.conf b/nebula-exchange/target/classes/test_application.conf deleted file mode 100644 index 652de01..0000000 --- a/nebula-exchange/target/classes/test_application.conf +++ /dev/null @@ -1,109 +0,0 @@ -{ - # Spark relation config - spark: { - - - driver: { - cores: 1 - maxResultSize: 1G - } - - cores { - max: 16 - } - } - - # Nebula Graph relation config - nebula: { - address:{ - graph:["192.168.8.172:3799"] - meta:["192.168.8.172:45509"] - } - user: user - pswd: password - space: exchange - - connection { - timeout: 3000 - retry: 3 - } - - execution { - retry: 3 - } - - error: { - max: 32 - # failed import job will be recorded in output path - output: /tmp/errors - } - - rate: { - limit: 1024 - timeout: 1000 - } - } - - # Processing tags - tags: [ - - # Loading tag from HDFS and data type is csv - { - name: person - type: { - source: csv - sink: client - } - path: "hdfs://192.168.8.171:9000/ldbc/tags/person.csv" - fields: [firstName] - nebula.fields: [first_name] - vertex: firstName - separator: "|" - header: true - batch: 256 - partition: 32 - } - - # Loading tag from neo4j - { - name: person1 - type: { - source: neo4j - sink: client - } - server: "bolt://192.168.8.164:7687" - user: neo4j - password: nebula - exec: "match (n:team) return n.name as name" - fields: [name] - nebula.fields: [name] - vertex: { - field:name - # nebula 2.0 does not support int vid yet, so do not config policy. - # policy:uuid - } - partition: 10 - batch: 1000 - check_point_path: /tmp/test - } - ] - - edges:[ - { - name: knows1 - type: { - source: csv - sink: client - } - path: "hdfs://192.168.8.171:9000/ldbc/edges/person_knows_person.csv" - fields: [creationDate] - nebula.fields: [timep] - source: Person.id1 - target: Person.id2 - separator: "|" - header: true - batch: 256 - partition: 32 - } - ] -} diff --git a/nebula-exchange/target/maven-archiver/pom.properties b/nebula-exchange/target/maven-archiver/pom.properties deleted file mode 100644 index c0c4f12..0000000 --- a/nebula-exchange/target/maven-archiver/pom.properties +++ /dev/null @@ -1,5 +0,0 @@ -#Generated by Maven -#Wed Dec 09 18:46:41 CST 2020 -version=2.0.0 -groupId=com.vesoft -artifactId=nebula-exchange diff --git a/nebula-exchange/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/nebula-exchange/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst deleted file mode 100644 index e69de29..0000000 diff --git a/nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst deleted file mode 100644 index ea46e29..0000000 --- a/nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst +++ /dev/null @@ -1,2 +0,0 @@ -mock/MockQueryServer.class -mock/MockQueryServer$1.class diff --git a/nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst deleted file mode 100644 index 0734639..0000000 --- a/nebula-exchange/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst +++ /dev/null @@ -1 +0,0 @@ -/Users/nicole/workspace/nebula/nebula-spark-utils/nebula-exchange/src/test/scala/mock/MockQueryServer.java diff --git a/nebula-exchange/target/site/scaladocs/com/package.html b/nebula-exchange/target/site/scaladocs/com/package.html deleted file mode 100644 index 2ef3274..0000000 --- a/nebula-exchange/target/site/scaladocs/com/package.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - com - nebula-exchange 2.0.0 API - com - - - - - - - - - - - - - - - -
                      - Package - -

                      com

                      - - Permalink - - -
                      - -

                      - - - package - - - com - -

                      - -
                      - - -
                      -
                      - - -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - - package - - - vesoft - -

                        - - Permalink - - - -
                      -
                      - - - - -
                      - -
                      - - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/package.html deleted file mode 100644 index 52d0317..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/package.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - nebula - nebula-exchange 2.0.0 API - com.vesoft.nebula - - - - - - - - - - - - - - - -
                      - Package -

                      com.vesoft

                      -

                      nebula

                      - - Permalink - - -
                      - -

                      - - - package - - - nebula - -

                      - -
                      - - -
                      -
                      - - -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - - package - - - tools - -

                        - - Permalink - - - -
                      -
                      - - - - -
                      - -
                      - - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Argument.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Argument.html deleted file mode 100644 index 3cf4620..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Argument.html +++ /dev/null @@ -1,544 +0,0 @@ - - - - Argument - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.Argument - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer

                      -

                      Argument

                      Related Doc: - package importer -

                      - - Permalink - - -
                      - -

                      - - final - case class - - - Argument(config: File = new File("application.conf"), hive: Boolean = false, directly: Boolean = false, dry: Boolean = false, reload: String = "") extends Product with Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. Argument
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - Argument(config: File = new File("application.conf"), hive: Boolean = false, directly: Boolean = false, dry: Boolean = false, reload: String = "") - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - val - - - config: File - -

                        - - Permalink - - - -
                      7. - - -

                        - - - val - - - directly: Boolean - -

                        - - Permalink - - - -
                      8. - - -

                        - - - val - - - dry: Boolean - -

                        - - Permalink - - - -
                      9. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      10. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      11. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - - val - - - hive: Boolean - -

                        - - Permalink - - - -
                      13. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      14. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - - val - - - reload: String - -

                        - - Permalink - - - -
                      18. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/CheckPointHandler$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/CheckPointHandler$.html deleted file mode 100644 index ce1b1a5..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/CheckPointHandler$.html +++ /dev/null @@ -1,534 +0,0 @@ - - - - CheckPointHandler - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.CheckPointHandler - - - - - - - - - - - - - - - -
                      - Object -

                      com.vesoft.nebula.tools.importer

                      -

                      CheckPointHandler

                      Related Doc: - package importer -

                      - - Permalink - - -
                      - -

                      - - - object - - - CheckPointHandler - -

                      - -

                      CheckPointHandler handle the checkpoint files for Neo4j and Janusgraph -

                      - Linear Supertypes -
                      AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. CheckPointHandler
                      2. AnyRef
                      3. Any
                      4. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - checkSupportResume(value: config.SourceCategory.Value): Boolean - -

                        - - Permalink - - - -
                      6. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - fetchOffset(path: String): Long - -

                        - - Permalink - - - -
                      10. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      11. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - - def - - - getPathAndOffset(schemaConfig: SchemaConfigEntry, breakPointCount: Long): Option[(String, Long)] - -

                        - - Permalink - - - -
                      13. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      14. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      15. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      20. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/ErrorHandler$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/ErrorHandler$.html deleted file mode 100644 index 143aa13..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/ErrorHandler$.html +++ /dev/null @@ -1,516 +0,0 @@ - - - - ErrorHandler - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.ErrorHandler - - - - - - - - - - - - - - - -
                      - Object -

                      com.vesoft.nebula.tools.importer

                      -

                      ErrorHandler

                      Related Doc: - package importer -

                      - - Permalink - - -
                      - -

                      - - - object - - - ErrorHandler - -

                      - -
                      - Linear Supertypes -
                      AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. ErrorHandler
                      2. AnyRef
                      3. Any
                      4. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - existError(path: String): Boolean - -

                        - - Permalink - - - -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - save(buffer: ArrayBuffer[String], path: String): Unit - -

                        - - Permalink - - - -
                      17. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      19. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Exchange$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Exchange$.html deleted file mode 100644 index 98b6319..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/Exchange$.html +++ /dev/null @@ -1,500 +0,0 @@ - - - - Exchange - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.Exchange - - - - - - - - - - - - - - - -
                      - Object -

                      com.vesoft.nebula.tools.importer

                      -

                      Exchange

                      Related Doc: - package importer -

                      - - Permalink - - -
                      - -

                      - - - object - - - Exchange - -

                      - -

                      SparkClientGenerator is a simple spark job used to write data into Nebula Graph parallel. -

                      - Linear Supertypes -
                      AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. Exchange
                      2. AnyRef
                      3. Any
                      4. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - - def - - - main(args: Array[String]): Unit - -

                        - - Permalink - - - -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      18. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/GraphProvider.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/GraphProvider.html deleted file mode 100644 index 2fc9025..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/GraphProvider.html +++ /dev/null @@ -1,644 +0,0 @@ - - - - GraphProvider - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.GraphProvider - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer

                      -

                      GraphProvider

                      Related Doc: - package importer -

                      - - Permalink - - -
                      - -

                      - - - class - - - GraphProvider extends AutoCloseable with Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Serializable, AutoCloseable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. GraphProvider
                      2. Serializable
                      3. Serializable
                      4. AutoCloseable
                      5. AnyRef
                      6. Any
                      7. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - GraphProvider(addresses: scala.List[HostAndPort]) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - - val - - - address: ListBuffer[HostAddress] - -

                        - - Permalink - - - -
                      5. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      6. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      7. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        GraphProvider → AutoCloseable
                        -
                      8. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      9. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      11. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - - def - - - getGraphClient(userConfigEntry: UserConfigEntry): Session - -

                        - - Permalink - - - -
                      13. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      14. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      15. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - val - - - nebulaPoolConfig: NebulaPoolConfig - -

                        - - Permalink - - - -
                      17. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - - val - - - pool: NebulaPool - -

                        - - Permalink - - - -
                      20. - - -

                        - - - def - - - releaseGraphClient(session: Session): Unit - -

                        - - Permalink - - - -
                      21. - - -

                        - - - def - - - submit(session: Session, statement: String): ResultSet - -

                        - - Permalink - - - -
                      22. - - -

                        - - - def - - - switchSpace(session: Session, space: String): Boolean - -

                        - - Permalink - - - -
                      23. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      24. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      25. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      26. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      27. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AutoCloseable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/MetaProvider.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/MetaProvider.html deleted file mode 100644 index c07934a..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/MetaProvider.html +++ /dev/null @@ -1,628 +0,0 @@ - - - - MetaProvider - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.MetaProvider - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer

                      -

                      MetaProvider

                      Related Doc: - package importer -

                      - - Permalink - - -
                      - -

                      - - - class - - - MetaProvider extends AutoCloseable with Serializable - -

                      - -

                      MetaProvider provide nebula graph meta query operations. -

                      - Linear Supertypes -
                      Serializable, Serializable, AutoCloseable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. MetaProvider
                      2. Serializable
                      3. Serializable
                      4. AutoCloseable
                      5. AnyRef
                      6. Any
                      7. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - MetaProvider(addresses: scala.List[HostAndPort]) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - - val - - - address: ListBuffer[HostAddress] - -

                        - - Permalink - - - -
                      5. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      6. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      7. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        MetaProvider → AutoCloseable
                        -
                      8. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      9. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      11. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - - def - - - getEdgeSchema(space: String, edge: String): scala.Predef.Map[String, Integer] - -

                        - - Permalink - - - -
                      13. - - -

                        - - - def - - - getLabelType(space: String, label: String): config.Type.Value - -

                        - - Permalink - - - -
                      14. - - -

                        - - - def - - - getPartNumber(space: String): Unit - -

                        - - Permalink - - - -
                      15. - - -

                        - - - def - - - getTagSchema(space: String, tag: String): scala.Predef.Map[String, Integer] - -

                        - - Permalink - - - -
                      16. - - -

                        - - - def - - - getVidType(space: String): VidType.Value - -

                        - - Permalink - - - -
                      17. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      18. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      19. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      21. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      22. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      23. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      24. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      25. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      26. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AutoCloseable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/TooManyErrorsException.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/TooManyErrorsException.html deleted file mode 100644 index d9c1023..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/TooManyErrorsException.html +++ /dev/null @@ -1,684 +0,0 @@ - - - - TooManyErrorsException - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.TooManyErrorsException - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer

                      -

                      TooManyErrorsException

                      Related Doc: - package importer -

                      - - Permalink - - -
                      - -

                      - - final - case class - - - TooManyErrorsException(message: String) extends Exception with Product with Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Product, Equals, Exception, Throwable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. TooManyErrorsException
                      2. Serializable
                      3. Product
                      4. Equals
                      5. Exception
                      6. Throwable
                      7. Serializable
                      8. AnyRef
                      9. Any
                      10. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - TooManyErrorsException(message: String) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - addSuppressed(arg0: Throwable): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        Throwable
                        -
                      5. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      6. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - fillInStackTrace(): Throwable - -

                        - - Permalink - - -
                        Definition Classes
                        Throwable
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - - def - - - getCause(): Throwable - -

                        - - Permalink - - -
                        Definition Classes
                        Throwable
                        -
                      11. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - - def - - - getLocalizedMessage(): String - -

                        - - Permalink - - -
                        Definition Classes
                        Throwable
                        -
                      13. - - -

                        - - - def - - - getMessage(): String - -

                        - - Permalink - - -
                        Definition Classes
                        Throwable
                        -
                      14. - - -

                        - - - def - - - getStackTrace(): Array[StackTraceElement] - -

                        - - Permalink - - -
                        Definition Classes
                        Throwable
                        -
                      15. - - -

                        - - final - def - - - getSuppressed(): Array[Throwable] - -

                        - - Permalink - - -
                        Definition Classes
                        Throwable
                        -
                      16. - - -

                        - - - def - - - initCause(arg0: Throwable): Throwable - -

                        - - Permalink - - -
                        Definition Classes
                        Throwable
                        -
                      17. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      18. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      21. - - -

                        - - - def - - - printStackTrace(arg0: PrintWriter): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        Throwable
                        -
                      22. - - -

                        - - - def - - - printStackTrace(arg0: PrintStream): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        Throwable
                        -
                      23. - - -

                        - - - def - - - printStackTrace(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        Throwable
                        -
                      24. - - -

                        - - - def - - - setStackTrace(arg0: Array[StackTraceElement]): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        Throwable
                        -
                      25. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      26. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        Throwable → AnyRef → Any
                        -
                      27. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      28. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      29. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from Exception

                      -
                      -

                      Inherited from Throwable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/VidType$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/VidType$.html deleted file mode 100644 index c8fba7d..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/VidType$.html +++ /dev/null @@ -1,786 +0,0 @@ - - - - VidType - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.VidType - - - - - - - - - - - - - - - -
                      - Object -

                      com.vesoft.nebula.tools.importer

                      -

                      VidType

                      Related Doc: - package importer -

                      - - Permalink - - -
                      - -

                      - - - object - - - VidType extends Enumeration - -

                      - -
                      - Linear Supertypes -
                      Enumeration, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. VidType
                      2. Enumeration
                      3. Serializable
                      4. Serializable
                      5. AnyRef
                      6. Any
                      7. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - -
                      -

                      Type Members

                      -
                      1. - - -

                        - - - type - - - Type = Value - -

                        - - Permalink - - - -
                      2. - - -

                        - - - class - - - Val extends Value with Serializable - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        Annotations
                        - @SerialVersionUID() - -
                        -
                      3. - - -

                        - - abstract - class - - - Value extends Ordered[Value] with Serializable - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        Annotations
                        - @SerialVersionUID() - -
                        -
                      4. - - -

                        - - - class - - - ValueSet extends AbstractSet[Value] with SortedSet[Value] with SortedSetLike[Value, ValueSet] with Serializable - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      -
                      - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - - val - - - INT: Value - -

                        - - Permalink - - - -
                      5. - - -

                        - - - val - - - STRING: Value - -

                        - - Permalink - - - -
                      6. - - -

                        - - final - def - - - Value(i: Int, name: String): Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      7. - - -

                        - - final - def - - - Value(name: String): Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      8. - - -

                        - - final - def - - - Value(i: Int): Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      9. - - -

                        - - final - def - - - Value: Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      10. - - -

                        - - final - def - - - apply(x: Int): Value - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      11. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      13. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      15. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      16. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      17. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      18. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      19. - - -

                        - - final - def - - - maxId: Int - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      20. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      21. - - -

                        - - - var - - - nextId: Int - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      22. - - -

                        - - - var - - - nextName: Iterator[String] - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      23. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      24. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      25. - - -

                        - - - def - - - readResolve(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      26. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      27. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration → AnyRef → Any
                        -
                      28. - - -

                        - - - def - - - values: ValueSet - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      29. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      30. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      31. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      32. - - -

                        - - final - def - - - withName(s: String): Value - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Enumeration

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs$.html deleted file mode 100644 index 03d13b2..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs$.html +++ /dev/null @@ -1,540 +0,0 @@ - - - - Configs - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.Configs - - - - - - - - - - - - - - - - - -

                      - - - object - - - Configs extends Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. Configs
                      2. Serializable
                      3. Serializable
                      4. AnyRef
                      5. Any
                      6. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - getConfigOrNone(config: Config, path: String): Option[Config] - -

                        - - Permalink - - -

                        Get the config by the path.

                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - parse(configPath: File): Configs - -

                        - - Permalink - - -

                        -
                      17. - - -

                        - - - def - - - parser(args: Array[String], programName: String): Option[Argument] - -

                        - - Permalink - - -

                        Use to parse command line arguments.

                        Use to parse command line arguments. -

                        returns

                        Argument

                        -
                      18. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      20. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs.html deleted file mode 100644 index 6957086..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Configs.html +++ /dev/null @@ -1,632 +0,0 @@ - - - - Configs - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.Configs - - - - - - - - - - - - - - - - - -

                      - - - case class - - - Configs(databaseConfig: DataBaseConfigEntry, userConfig: UserConfigEntry, connectionConfig: ConnectionConfigEntry, executionConfig: ExecutionConfigEntry, errorConfig: ErrorConfigEntry, rateConfig: RateConfigEntry, sparkConfigEntry: SparkConfigEntry, tagsConfig: scala.List[TagConfigEntry], edgesConfig: scala.List[EdgeConfigEntry], hiveConfigEntry: Option[HiveConfigEntry] = None) extends Product with Serializable - -

                      - -

                      Configs -

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. Configs
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - Configs(databaseConfig: DataBaseConfigEntry, userConfig: UserConfigEntry, connectionConfig: ConnectionConfigEntry, executionConfig: ExecutionConfigEntry, errorConfig: ErrorConfigEntry, rateConfig: RateConfigEntry, sparkConfigEntry: SparkConfigEntry, tagsConfig: scala.List[TagConfigEntry], edgesConfig: scala.List[EdgeConfigEntry], hiveConfigEntry: Option[HiveConfigEntry] = None) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - val - - - connectionConfig: ConnectionConfigEntry - -

                        - - Permalink - - - -
                      7. - - -

                        - - - val - - - databaseConfig: DataBaseConfigEntry - -

                        - - Permalink - - - -
                      8. - - -

                        - - - val - - - edgesConfig: scala.List[EdgeConfigEntry] - -

                        - - Permalink - - - -
                      9. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      10. - - -

                        - - - val - - - errorConfig: ErrorConfigEntry - -

                        - - Permalink - - - -
                      11. - - -

                        - - - val - - - executionConfig: ExecutionConfigEntry - -

                        - - Permalink - - - -
                      12. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      13. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      14. - - -

                        - - - val - - - hiveConfigEntry: Option[HiveConfigEntry] - -

                        - - Permalink - - - -
                      15. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      16. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - - val - - - rateConfig: RateConfigEntry - -

                        - - Permalink - - - -
                      20. - - -

                        - - - val - - - sparkConfigEntry: SparkConfigEntry - -

                        - - Permalink - - - -
                      21. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      22. - - -

                        - - - val - - - tagsConfig: scala.List[TagConfigEntry] - -

                        - - Permalink - - - -
                      23. - - -

                        - - - val - - - userConfig: UserConfigEntry - -

                        - - Permalink - - - -
                      24. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      25. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      26. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ConnectionConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ConnectionConfigEntry.html deleted file mode 100644 index 8504231..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ConnectionConfigEntry.html +++ /dev/null @@ -1,511 +0,0 @@ - - - - ConnectionConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.ConnectionConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      ConnectionConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - ConnectionConfigEntry(timeout: Int, retry: Int) extends Product with Serializable - -

                      - -

                      ConnectionConfigEntry -

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. ConnectionConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - ConnectionConfigEntry(timeout: Int, retry: Int) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      8. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      10. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      11. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      12. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - - val - - - retry: Int - -

                        - - Permalink - - - -
                      14. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - - val - - - timeout: Int - -

                        - - Permalink - - - -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        ConnectionConfigEntry → AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataBaseConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataBaseConfigEntry.html deleted file mode 100644 index 18fc83e..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataBaseConfigEntry.html +++ /dev/null @@ -1,562 +0,0 @@ - - - - DataBaseConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.DataBaseConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      DataBaseConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - DataBaseConfigEntry(graphAddress: scala.List[String], space: String, metaAddresses: scala.List[String]) extends Product with Serializable - -

                      - -

                      DataBaseConfigEntry describe the nebula cluster's address and which space will be used. -

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. DataBaseConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - DataBaseConfigEntry(graphAddress: scala.List[String], space: String, metaAddresses: scala.List[String]) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      8. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - getGraphAddress: scala.List[HostAndPort] - -

                        - - Permalink - - - -
                      10. - - -

                        - - - def - - - getMetaAddress: scala.List[HostAndPort] - -

                        - - Permalink - - - -
                      11. - - -

                        - - - val - - - graphAddress: scala.List[String] - -

                        - - Permalink - - - -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - - val - - - metaAddresses: scala.List[String] - -

                        - - Permalink - - - -
                      14. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - - val - - - space: String - -

                        - - Permalink - - - -
                      18. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        DataBaseConfigEntry → AnyRef → Any
                        -
                      20. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSinkConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSinkConfigEntry.html deleted file mode 100644 index 0d8dadb..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSinkConfigEntry.html +++ /dev/null @@ -1,506 +0,0 @@ - - - - DataSinkConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.DataSinkConfigEntry - - - - - - - - - - - - - - - -
                      - Trait -

                      com.vesoft.nebula.tools.importer.config

                      -

                      DataSinkConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - sealed - trait - - - DataSinkConfigEntry extends AnyRef - -

                      - -

                      DataSinkConfigEntry -

                      - Linear Supertypes -
                      AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. DataSinkConfigEntry
                      2. AnyRef
                      3. Any
                      4. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - -
                      -

                      Abstract Value Members

                      -
                      1. - - -

                        - - abstract - def - - - category: SinkCategory.Value - -

                        - - Permalink - - - -
                      -
                      - -
                      -

                      Concrete Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSourceConfigEntry.html deleted file mode 100644 index d9c8f8c..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/DataSourceConfigEntry.html +++ /dev/null @@ -1,506 +0,0 @@ - - - - DataSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.DataSourceConfigEntry - - - - - - - - - - - - - - - -
                      - Trait -

                      com.vesoft.nebula.tools.importer.config

                      -

                      DataSourceConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - sealed - trait - - - DataSourceConfigEntry extends AnyRef - -

                      - - - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. DataSourceConfigEntry
                      2. AnyRef
                      3. Any
                      4. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - -
                      -

                      Abstract Value Members

                      -
                      1. - - -

                        - - abstract - def - - - category: SourceCategory.Value - -

                        - - Permalink - - - -
                      -
                      - -
                      -

                      Concrete Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/EdgeConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/EdgeConfigEntry.html deleted file mode 100644 index d26d69d..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/EdgeConfigEntry.html +++ /dev/null @@ -1,750 +0,0 @@ - - - - EdgeConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.EdgeConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      EdgeConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - EdgeConfigEntry(name: String, dataSourceConfigEntry: DataSourceConfigEntry, dataSinkConfigEntry: DataSinkConfigEntry, fields: scala.List[String], nebulaFields: scala.List[String], sourceField: String, sourcePolicy: Option[KeyPolicy.Value], rankingField: Option[String], targetField: String, targetPolicy: Option[KeyPolicy.Value], isGeo: Boolean, latitude: Option[String], longitude: Option[String], batch: Int, partition: Int, checkPointPath: Option[String]) extends SchemaConfigEntry with Product with Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, SchemaConfigEntry, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. EdgeConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. SchemaConfigEntry
                      7. AnyRef
                      8. Any
                      9. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - EdgeConfigEntry(name: String, dataSourceConfigEntry: DataSourceConfigEntry, dataSinkConfigEntry: DataSinkConfigEntry, fields: scala.List[String], nebulaFields: scala.List[String], sourceField: String, sourcePolicy: Option[KeyPolicy.Value], rankingField: Option[String], targetField: String, targetPolicy: Option[KeyPolicy.Value], isGeo: Boolean, latitude: Option[String], longitude: Option[String], batch: Int, partition: Int, checkPointPath: Option[String]) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - val - - - batch: Int - -

                        - - Permalink - - -

                        vertex or edge amount of one batch import

                        vertex or edge amount of one batch import

                        Definition Classes
                        EdgeConfigEntrySchemaConfigEntry
                        -
                      6. - - -

                        - - - val - - - checkPointPath: Option[String] - -

                        - - Permalink - - -

                        check point path

                        check point path

                        Definition Classes
                        EdgeConfigEntrySchemaConfigEntry
                        -
                      7. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      8. - - -

                        - - - val - - - dataSinkConfigEntry: DataSinkConfigEntry - -

                        - - Permalink - - -

                        seeDataSinkConfigEntry

                        -
                      9. - - -

                        - - - val - - - dataSourceConfigEntry: DataSourceConfigEntry - -

                        - - Permalink - - -

                        seeDataSourceConfigEntry

                        -
                      10. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      11. - - -

                        - - - val - - - fields: scala.List[String] - -

                        - - Permalink - - -

                        data source fields which are going to be import to nebula as properties

                        data source fields which are going to be import to nebula as properties

                        Definition Classes
                        EdgeConfigEntrySchemaConfigEntry
                        -
                      12. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      13. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      14. - - -

                        - - - val - - - isGeo: Boolean - -

                        - - Permalink - - - -
                      15. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      16. - - -

                        - - - val - - - latitude: Option[String] - -

                        - - Permalink - - - -
                      17. - - -

                        - - - val - - - longitude: Option[String] - -

                        - - Permalink - - - -
                      18. - - -

                        - - - val - - - name: String - -

                        - - Permalink - - -

                        nebula tag or edge name

                        nebula tag or edge name

                        Definition Classes
                        EdgeConfigEntrySchemaConfigEntry
                        -
                      19. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - val - - - nebulaFields: scala.List[String] - -

                        - - Permalink - - -

                        nebula properties which are going to fill value with data source value

                        nebula properties which are going to fill value with data source value

                        Definition Classes
                        EdgeConfigEntrySchemaConfigEntry
                        -
                      21. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      22. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      23. - - -

                        - - - val - - - partition: Int - -

                        - - Permalink - - -

                        spark partition

                        spark partition

                        Definition Classes
                        EdgeConfigEntrySchemaConfigEntry
                        -
                      24. - - -

                        - - - val - - - rankingField: Option[String] - -

                        - - Permalink - - - -
                      25. - - -

                        - - - val - - - sourceField: String - -

                        - - Permalink - - - -
                      26. - - -

                        - - - val - - - sourcePolicy: Option[KeyPolicy.Value] - -

                        - - Permalink - - - -
                      27. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      28. - - -

                        - - - val - - - targetField: String - -

                        - - Permalink - - - -
                      29. - - -

                        - - - val - - - targetPolicy: Option[KeyPolicy.Value] - -

                        - - Permalink - - - -
                      30. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        EdgeConfigEntry → AnyRef → Any
                        -
                      31. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      32. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      33. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from SchemaConfigEntry

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ErrorConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ErrorConfigEntry.html deleted file mode 100644 index bdc2203..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ErrorConfigEntry.html +++ /dev/null @@ -1,511 +0,0 @@ - - - - ErrorConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.ErrorConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      ErrorConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - ErrorConfigEntry(errorPath: String, errorMaxSize: Int) extends Product with Serializable - -

                      - -

                      ErrorConfigEntry -

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. ErrorConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - ErrorConfigEntry(errorPath: String, errorMaxSize: Int) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - val - - - errorMaxSize: Int - -

                        - - Permalink - - - -
                      8. - - -

                        - - - val - - - errorPath: String - -

                        - - Permalink - - - -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        ErrorConfigEntry → AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ExecutionConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ExecutionConfigEntry.html deleted file mode 100644 index 1595d37..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ExecutionConfigEntry.html +++ /dev/null @@ -1,528 +0,0 @@ - - - - ExecutionConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.ExecutionConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      ExecutionConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - ExecutionConfigEntry(timeout: Int, retry: Int, interval: Int) extends Product with Serializable - -

                      - -

                      ExecutionConfigEntry -

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. ExecutionConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - ExecutionConfigEntry(timeout: Int, retry: Int, interval: Int) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      8. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - val - - - interval: Int - -

                        - - Permalink - - - -
                      10. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      11. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      12. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - - val - - - retry: Int - -

                        - - Permalink - - - -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - val - - - timeout: Int - -

                        - - Permalink - - - -
                      17. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        ExecutionConfigEntry → AnyRef → Any
                        -
                      18. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSinkConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSinkConfigEntry.html deleted file mode 100644 index 549493f..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSinkConfigEntry.html +++ /dev/null @@ -1,530 +0,0 @@ - - - - FileBaseSinkConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.FileBaseSinkConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      FileBaseSinkConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - FileBaseSinkConfigEntry(category: SinkCategory.Value, localPath: String, remotePath: String) extends DataSinkConfigEntry with Product with Serializable - -

                      - -

                      FileBaseSinkConfigEntry -

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, DataSinkConfigEntry, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. FileBaseSinkConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. DataSinkConfigEntry
                      7. AnyRef
                      8. Any
                      9. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - FileBaseSinkConfigEntry(category: SinkCategory.Value, localPath: String, remotePath: String) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - val - - - category: SinkCategory.Value - -

                        - - Permalink - - - -
                      6. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      11. - - -

                        - - - val - - - localPath: String - -

                        - - Permalink - - - -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - - val - - - remotePath: String - -

                        - - Permalink - - - -
                      16. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        FileBaseSinkConfigEntry → AnyRef → Any
                        -
                      18. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from DataSinkConfigEntry

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSourceConfigEntry.html deleted file mode 100644 index 73fc8aa..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileBaseSourceConfigEntry.html +++ /dev/null @@ -1,549 +0,0 @@ - - - - FileBaseSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.FileBaseSourceConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      FileBaseSourceConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - FileBaseSourceConfigEntry(category: SourceCategory.Value, path: String, separator: Option[String] = None, header: Option[Boolean] = None) extends FileDataSourceConfigEntry with Product with Serializable - -

                      - -

                      FileBaseSourceConfigEntry -

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, FileDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. FileBaseSourceConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. FileDataSourceConfigEntry
                      7. DataSourceConfigEntry
                      8. AnyRef
                      9. Any
                      10. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - FileBaseSourceConfigEntry(category: SourceCategory.Value, path: String, separator: Option[String] = None, header: Option[Boolean] = None) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - val - - - category: SourceCategory.Value - -

                        - - Permalink - - - -
                      6. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - val - - - header: Option[Boolean] - -

                        - - Permalink - - - -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - - val - - - path: String - -

                        - - Permalink - - - -
                      16. - - -

                        - - - val - - - separator: Option[String] - -

                        - - Permalink - - - -
                      17. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        FileBaseSourceConfigEntry → AnyRef → Any
                        -
                      19. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from FileDataSourceConfigEntry

                      -
                      -

                      Inherited from DataSourceConfigEntry

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileDataSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileDataSourceConfigEntry.html deleted file mode 100644 index 59b062f..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/FileDataSourceConfigEntry.html +++ /dev/null @@ -1,524 +0,0 @@ - - - - FileDataSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.FileDataSourceConfigEntry - - - - - - - - - - - - - - - -
                      - Trait -

                      com.vesoft.nebula.tools.importer.config

                      -

                      FileDataSourceConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - sealed - trait - - - FileDataSourceConfigEntry extends DataSourceConfigEntry - -

                      - -
                      - Linear Supertypes - -
                      - Known Subclasses - -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. FileDataSourceConfigEntry
                      2. DataSourceConfigEntry
                      3. AnyRef
                      4. Any
                      5. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - -
                      -

                      Abstract Value Members

                      -
                      1. - - -

                        - - abstract - def - - - category: SourceCategory.Value - -

                        - - Permalink - - -
                        Definition Classes
                        DataSourceConfigEntry
                        -
                      2. - - -

                        - - abstract - def - - - path: String - -

                        - - Permalink - - - -
                      -
                      - -
                      -

                      Concrete Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from DataSourceConfigEntry

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HBaseSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HBaseSourceConfigEntry.html deleted file mode 100644 index ed0228c..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HBaseSourceConfigEntry.html +++ /dev/null @@ -1,599 +0,0 @@ - - - - HBaseSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.HBaseSourceConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      HBaseSourceConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - HBaseSourceConfigEntry(category: SourceCategory.Value, host: String, port: String, table: String, columnFamily: String, fields: scala.List[String]) extends ServerDataSourceConfigEntry with Product with Serializable - -

                      - -

                      HBaseSourceConfigEntry

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, ServerDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. HBaseSourceConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. ServerDataSourceConfigEntry
                      7. DataSourceConfigEntry
                      8. AnyRef
                      9. Any
                      10. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - HBaseSourceConfigEntry(category: SourceCategory.Value, host: String, port: String, table: String, columnFamily: String, fields: scala.List[String]) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - val - - - category: SourceCategory.Value - -

                        - - Permalink - - - -
                      6. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      7. - - -

                        - - - val - - - columnFamily: String - -

                        - - Permalink - - - -
                      8. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      9. - - -

                        - - - val - - - fields: scala.List[String] - -

                        - - Permalink - - - -
                      10. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      11. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - - val - - - host: String - -

                        - - Permalink - - - -
                      13. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      14. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - - val - - - port: String - -

                        - - Permalink - - - -
                      18. - - -

                        - - - val - - - sentence: String - -

                        - - Permalink - - - -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - val - - - table: String - -

                        - - Permalink - - - -
                      21. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        HBaseSourceConfigEntry → AnyRef → Any
                        -
                      22. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      24. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from ServerDataSourceConfigEntry

                      -
                      -

                      Inherited from DataSourceConfigEntry

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveConfigEntry.html deleted file mode 100644 index 772fce6..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveConfigEntry.html +++ /dev/null @@ -1,561 +0,0 @@ - - - - HiveConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.HiveConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      HiveConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - HiveConfigEntry(waredir: String, connectionURL: String, connectionDriverName: String, connectionUserName: String, connectionPassWord: String) extends Product with Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. HiveConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - HiveConfigEntry(waredir: String, connectionURL: String, connectionDriverName: String, connectionUserName: String, connectionPassWord: String) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - val - - - connectionDriverName: String - -

                        - - Permalink - - - -
                      7. - - -

                        - - - val - - - connectionPassWord: String - -

                        - - Permalink - - - -
                      8. - - -

                        - - - val - - - connectionURL: String - -

                        - - Permalink - - - -
                      9. - - -

                        - - - val - - - connectionUserName: String - -

                        - - Permalink - - - -
                      10. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      11. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      12. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      13. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      14. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        HiveConfigEntry → AnyRef → Any
                        -
                      19. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - - val - - - waredir: String - -

                        - - Permalink - - - -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveSourceConfigEntry.html deleted file mode 100644 index 111b4d6..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/HiveSourceConfigEntry.html +++ /dev/null @@ -1,515 +0,0 @@ - - - - HiveSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.HiveSourceConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      HiveSourceConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - HiveSourceConfigEntry(category: SourceCategory.Value, sentence: String) extends ServerDataSourceConfigEntry with Product with Serializable - -

                      - -

                      HiveSourceConfigEntry -

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, ServerDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. HiveSourceConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. ServerDataSourceConfigEntry
                      7. DataSourceConfigEntry
                      8. AnyRef
                      9. Any
                      10. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - HiveSourceConfigEntry(category: SourceCategory.Value, sentence: String) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - val - - - category: SourceCategory.Value - -

                        - - Permalink - - - -
                      6. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      11. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      12. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - - val - - - sentence: String - -

                        - - Permalink - - - -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        HiveSourceConfigEntry → AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from ServerDataSourceConfigEntry

                      -
                      -

                      Inherited from DataSourceConfigEntry

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/JanusGraphSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/JanusGraphSourceConfigEntry.html deleted file mode 100644 index 780bcec..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/JanusGraphSourceConfigEntry.html +++ /dev/null @@ -1,531 +0,0 @@ - - - - JanusGraphSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.JanusGraphSourceConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      JanusGraphSourceConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - JanusGraphSourceConfigEntry(category: SourceCategory.Value, sentence: String, isEdge: Boolean) extends ServerDataSourceConfigEntry with Product with Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, ServerDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. JanusGraphSourceConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. ServerDataSourceConfigEntry
                      7. DataSourceConfigEntry
                      8. AnyRef
                      9. Any
                      10. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - JanusGraphSourceConfigEntry(category: SourceCategory.Value, sentence: String, isEdge: Boolean) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - val - - - category: SourceCategory.Value - -

                        - - Permalink - - - -
                      6. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - val - - - isEdge: Boolean - -

                        - - Permalink - - - -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - - val - - - sentence: String - -

                        - - Permalink - - - -
                      16. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        JanusGraphSourceConfigEntry → AnyRef → Any
                        -
                      18. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from ServerDataSourceConfigEntry

                      -
                      -

                      Inherited from DataSourceConfigEntry

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/KafkaSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/KafkaSourceConfigEntry.html deleted file mode 100644 index 8d53b17..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/KafkaSourceConfigEntry.html +++ /dev/null @@ -1,549 +0,0 @@ - - - - KafkaSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.KafkaSourceConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      KafkaSourceConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - KafkaSourceConfigEntry(category: SourceCategory.Value, intervalSeconds: Int, server: String, topic: String) extends StreamingDataSourceConfigEntry with Product with Serializable - -

                      - -

                      TODO: Support more config item about Kafka Consumer -

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, StreamingDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. KafkaSourceConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. StreamingDataSourceConfigEntry
                      7. DataSourceConfigEntry
                      8. AnyRef
                      9. Any
                      10. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - KafkaSourceConfigEntry(category: SourceCategory.Value, intervalSeconds: Int, server: String, topic: String) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - val - - - category: SourceCategory.Value - -

                        - - Permalink - - - -
                      6. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - val - - - intervalSeconds: Int - -

                        - - Permalink - - - -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - - val - - - server: String - -

                        - - Permalink - - - -
                      16. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        KafkaSourceConfigEntry → AnyRef → Any
                        -
                      18. - - -

                        - - - val - - - topic: String - -

                        - - Permalink - - - -
                      19. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from StreamingDataSourceConfigEntry

                      -
                      -

                      Inherited from DataSourceConfigEntry

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/MySQLSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/MySQLSourceConfigEntry.html deleted file mode 100644 index 9f4d4c7..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/MySQLSourceConfigEntry.html +++ /dev/null @@ -1,617 +0,0 @@ - - - - MySQLSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.MySQLSourceConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      MySQLSourceConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - MySQLSourceConfigEntry(category: SourceCategory.Value, host: String, port: Int, database: String, table: String, user: String, password: String, sentence: String) extends ServerDataSourceConfigEntry with Product with Serializable - -

                      - -

                      MySQLSourceConfigEntry -

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, ServerDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. MySQLSourceConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. ServerDataSourceConfigEntry
                      7. DataSourceConfigEntry
                      8. AnyRef
                      9. Any
                      10. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - MySQLSourceConfigEntry(category: SourceCategory.Value, host: String, port: Int, database: String, table: String, user: String, password: String, sentence: String) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - val - - - category: SourceCategory.Value - -

                        - - Permalink - - - -
                      6. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      7. - - -

                        - - - val - - - database: String - -

                        - - Permalink - - - -
                      8. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - val - - - host: String - -

                        - - Permalink - - - -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - val - - - password: String - -

                        - - Permalink - - - -
                      17. - - -

                        - - - val - - - port: Int - -

                        - - Permalink - - - -
                      18. - - -

                        - - - val - - - sentence: String - -

                        - - Permalink - - - -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - val - - - table: String - -

                        - - Permalink - - - -
                      21. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        MySQLSourceConfigEntry → AnyRef → Any
                        -
                      22. - - -

                        - - - val - - - user: String - -

                        - - Permalink - - - -
                      23. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      24. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      25. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from ServerDataSourceConfigEntry

                      -
                      -

                      Inherited from DataSourceConfigEntry

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/NebulaSinkConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/NebulaSinkConfigEntry.html deleted file mode 100644 index 2cf075c..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/NebulaSinkConfigEntry.html +++ /dev/null @@ -1,513 +0,0 @@ - - - - NebulaSinkConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.NebulaSinkConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      NebulaSinkConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - NebulaSinkConfigEntry(category: SinkCategory.Value, addresses: scala.List[String]) extends DataSinkConfigEntry with Product with Serializable - -

                      - -

                      NebulaSinkConfigEntry use to specified the nebula service's address. -

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, DataSinkConfigEntry, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. NebulaSinkConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. DataSinkConfigEntry
                      7. AnyRef
                      8. Any
                      9. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - NebulaSinkConfigEntry(category: SinkCategory.Value, addresses: scala.List[String]) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - - val - - - addresses: scala.List[String] - -

                        - - Permalink - - - -
                      5. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      6. - - -

                        - - - val - - - category: SinkCategory.Value - -

                        - - Permalink - - - -
                      7. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      8. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        NebulaSinkConfigEntry → AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from DataSinkConfigEntry

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Neo4JSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Neo4JSourceConfigEntry.html deleted file mode 100644 index 25b8647..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Neo4JSourceConfigEntry.html +++ /dev/null @@ -1,651 +0,0 @@ - - - - Neo4JSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.Neo4JSourceConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      Neo4JSourceConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - Neo4JSourceConfigEntry(category: SourceCategory.Value, sentence: String, name: String, server: String, user: String, password: String, database: Option[String], encryption: Boolean, parallel: Int, checkPointPath: Option[String]) extends ServerDataSourceConfigEntry with Product with Serializable - -

                      - -

                      Neo4JSourceConfigEntry -

                      checkPointPath

                      use save resume data dir path.

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, ServerDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. Neo4JSourceConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. ServerDataSourceConfigEntry
                      7. DataSourceConfigEntry
                      8. AnyRef
                      9. Any
                      10. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - Neo4JSourceConfigEntry(category: SourceCategory.Value, sentence: String, name: String, server: String, user: String, password: String, database: Option[String], encryption: Boolean, parallel: Int, checkPointPath: Option[String]) - -

                        - - Permalink - - -

                        checkPointPath

                        use save resume data dir path.

                        -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - val - - - category: SourceCategory.Value - -

                        - - Permalink - - - -
                      6. - - -

                        - - - val - - - checkPointPath: Option[String] - -

                        - - Permalink - - -

                        use save resume data dir path.

                        -
                      7. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      8. - - -

                        - - - val - - - database: Option[String] - -

                        - - Permalink - - - -
                      9. - - -

                        - - - val - - - encryption: Boolean - -

                        - - Permalink - - - -
                      10. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      11. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      12. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      13. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      14. - - -

                        - - - val - - - name: String - -

                        - - Permalink - - - -
                      15. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - - val - - - parallel: Int - -

                        - - Permalink - - - -
                      19. - - -

                        - - - val - - - password: String - -

                        - - Permalink - - - -
                      20. - - -

                        - - - val - - - sentence: String - -

                        - - Permalink - - - -
                      21. - - -

                        - - - val - - - server: String - -

                        - - Permalink - - - -
                      22. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      23. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        Neo4JSourceConfigEntry → AnyRef → Any
                        -
                      24. - - -

                        - - - val - - - user: String - -

                        - - Permalink - - - -
                      25. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      26. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      27. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from ServerDataSourceConfigEntry

                      -
                      -

                      Inherited from DataSourceConfigEntry

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/PulsarSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/PulsarSourceConfigEntry.html deleted file mode 100644 index 8c40c35..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/PulsarSourceConfigEntry.html +++ /dev/null @@ -1,566 +0,0 @@ - - - - PulsarSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.PulsarSourceConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      PulsarSourceConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - PulsarSourceConfigEntry(category: SourceCategory.Value, intervalSeconds: Int, serviceUrl: String, adminUrl: String, options: scala.Predef.Map[String, String]) extends StreamingDataSourceConfigEntry with Product with Serializable - -

                      - -

                      PulsarSourceConfigEntry -

                      adminUrl

                      use to get data schema.

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, StreamingDataSourceConfigEntry, DataSourceConfigEntry, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. PulsarSourceConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. StreamingDataSourceConfigEntry
                      7. DataSourceConfigEntry
                      8. AnyRef
                      9. Any
                      10. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - PulsarSourceConfigEntry(category: SourceCategory.Value, intervalSeconds: Int, serviceUrl: String, adminUrl: String, options: scala.Predef.Map[String, String]) - -

                        - - Permalink - - -

                        adminUrl

                        use to get data schema.

                        -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - - val - - - adminUrl: String - -

                        - - Permalink - - -

                        use to get data schema.

                        -
                      5. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      6. - - -

                        - - - val - - - category: SourceCategory.Value - -

                        - - Permalink - - - -
                      7. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      8. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - val - - - intervalSeconds: Int - -

                        - - Permalink - - - -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - val - - - options: scala.Predef.Map[String, String] - -

                        - - Permalink - - - -
                      17. - - -

                        - - - val - - - serviceUrl: String - -

                        - - Permalink - - - -
                      18. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        PulsarSourceConfigEntry → AnyRef → Any
                        -
                      20. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from StreamingDataSourceConfigEntry

                      -
                      -

                      Inherited from DataSourceConfigEntry

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/RateConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/RateConfigEntry.html deleted file mode 100644 index b2c4895..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/RateConfigEntry.html +++ /dev/null @@ -1,511 +0,0 @@ - - - - RateConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.RateConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      RateConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - RateConfigEntry(limit: Int, timeout: Int) extends Product with Serializable - -

                      - -

                      RateConfigEntry -

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. RateConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - RateConfigEntry(limit: Int, timeout: Int) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      8. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      10. - - -

                        - - - val - - - limit: Int - -

                        - - Permalink - - - -
                      11. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      12. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - - val - - - timeout: Int - -

                        - - Permalink - - - -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        RateConfigEntry → AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SchemaConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SchemaConfigEntry.html deleted file mode 100644 index 480bef8..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SchemaConfigEntry.html +++ /dev/null @@ -1,625 +0,0 @@ - - - - SchemaConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.SchemaConfigEntry - - - - - - - - - - - - - - - -
                      - Trait -

                      com.vesoft.nebula.tools.importer.config

                      -

                      SchemaConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - sealed - trait - - - SchemaConfigEntry extends AnyRef - -

                      - -

                      SchemaConfigEntry is tag/edge super class use to save some basic parameter for importer. -

                      - Linear Supertypes -
                      AnyRef, Any
                      -
                      - Known Subclasses - -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. SchemaConfigEntry
                      2. AnyRef
                      3. Any
                      4. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - -
                      -

                      Abstract Value Members

                      -
                      1. - - -

                        - - abstract - def - - - batch: Int - -

                        - - Permalink - - -

                        vertex or edge amount of one batch import

                        -
                      2. - - -

                        - - abstract - def - - - checkPointPath: Option[String] - -

                        - - Permalink - - -

                        check point path

                        -
                      3. - - -

                        - - abstract - def - - - dataSinkConfigEntry: DataSinkConfigEntry - -

                        - - Permalink - - -

                        seeDataSinkConfigEntry

                        -
                      4. - - -

                        - - abstract - def - - - dataSourceConfigEntry: DataSourceConfigEntry - -

                        - - Permalink - - -

                        seeDataSourceConfigEntry

                        -
                      5. - - -

                        - - abstract - def - - - fields: scala.List[String] - -

                        - - Permalink - - -

                        data source fields which are going to be import to nebula as properties

                        -
                      6. - - -

                        - - abstract - def - - - name: String - -

                        - - Permalink - - -

                        nebula tag or edge name

                        -
                      7. - - -

                        - - abstract - def - - - nebulaFields: scala.List[String] - -

                        - - Permalink - - -

                        nebula properties which are going to fill value with data source value

                        -
                      8. - - -

                        - - abstract - def - - - partition: Int - -

                        - - Permalink - - -

                        spark partition

                        -
                      -
                      - -
                      -

                      Concrete Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ServerDataSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ServerDataSourceConfigEntry.html deleted file mode 100644 index c7a2d42..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/ServerDataSourceConfigEntry.html +++ /dev/null @@ -1,524 +0,0 @@ - - - - ServerDataSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.ServerDataSourceConfigEntry - - - - - - - - - - - - - - - -
                      - Trait -

                      com.vesoft.nebula.tools.importer.config

                      -

                      ServerDataSourceConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - sealed - trait - - - ServerDataSourceConfigEntry extends DataSourceConfigEntry - -

                      - - - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. ServerDataSourceConfigEntry
                      2. DataSourceConfigEntry
                      3. AnyRef
                      4. Any
                      5. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - -
                      -

                      Abstract Value Members

                      -
                      1. - - -

                        - - abstract - def - - - category: SourceCategory.Value - -

                        - - Permalink - - -
                        Definition Classes
                        DataSourceConfigEntry
                        -
                      2. - - -

                        - - abstract - def - - - sentence: String - -

                        - - Permalink - - - -
                      -
                      - -
                      -

                      Concrete Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from DataSourceConfigEntry

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory$.html deleted file mode 100644 index bb3098b..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory$.html +++ /dev/null @@ -1,790 +0,0 @@ - - - - SinkCategory - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.SinkCategory - - - - - - - - - - - - - - - - - -

                      - - - object - - - SinkCategory extends Enumeration - -

                      - -

                      SinkCategory is used to expression the writer's type. -SST is not supported yet. -

                      - Linear Supertypes -
                      Enumeration, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. SinkCategory
                      2. Enumeration
                      3. Serializable
                      4. Serializable
                      5. AnyRef
                      6. Any
                      7. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - -
                      -

                      Type Members

                      -
                      1. - - -

                        - - - type - - - Type = Value - -

                        - - Permalink - - - -
                      2. - - -

                        - - - class - - - Val extends Value with Serializable - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        Annotations
                        - @SerialVersionUID() - -
                        -
                      3. - - -

                        - - abstract - class - - - Value extends Ordered[Value] with Serializable - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        Annotations
                        - @SerialVersionUID() - -
                        -
                      4. - - -

                        - - - class - - - ValueSet extends AbstractSet[Value] with SortedSet[Value] with SortedSetLike[Value, ValueSet] with Serializable - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      -
                      - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - - val - - - CLIENT: Value - -

                        - - Permalink - - - -
                      5. - - -

                        - - - val - - - SST: Value - -

                        - - Permalink - - - -
                      6. - - -

                        - - final - def - - - Value(i: Int, name: String): Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      7. - - -

                        - - final - def - - - Value(name: String): Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      8. - - -

                        - - final - def - - - Value(i: Int): Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      9. - - -

                        - - final - def - - - Value: Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      10. - - -

                        - - final - def - - - apply(x: Int): Value - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      11. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      13. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      15. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      16. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      17. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      18. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      19. - - -

                        - - final - def - - - maxId: Int - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      20. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      21. - - -

                        - - - var - - - nextId: Int - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      22. - - -

                        - - - var - - - nextName: Iterator[String] - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      23. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      24. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      25. - - -

                        - - - def - - - readResolve(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      26. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      27. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration → AnyRef → Any
                        -
                      28. - - -

                        - - - def - - - values: ValueSet - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      29. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      30. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      31. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      32. - - -

                        - - final - def - - - withName(s: String): Value - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Enumeration

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory.html deleted file mode 100644 index 75eadab..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SinkCategory.html +++ /dev/null @@ -1,504 +0,0 @@ - - - - SinkCategory - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.SinkCategory - - - - - - - - - - - - - - - - - -

                      - - - class - - - SinkCategory extends AnyRef - -

                      - -
                      - Linear Supertypes -
                      AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. SinkCategory
                      2. AnyRef
                      3. Any
                      4. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - SinkCategory() - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory$.html deleted file mode 100644 index 3d0b6ff..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory$.html +++ /dev/null @@ -1,976 +0,0 @@ - - - - SourceCategory - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.SourceCategory - - - - - - - - - - - - - - - - - -

                      - - - object - - - SourceCategory extends Enumeration - -

                      - -

                      Category use to explain the data source which the Spark application could reading. -

                      - Linear Supertypes -
                      Enumeration, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. SourceCategory
                      2. Enumeration
                      3. Serializable
                      4. Serializable
                      5. AnyRef
                      6. Any
                      7. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - -
                      -

                      Type Members

                      -
                      1. - - -

                        - - - type - - - Type = Value - -

                        - - Permalink - - - -
                      2. - - -

                        - - - class - - - Val extends Value with Serializable - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        Annotations
                        - @SerialVersionUID() - -
                        -
                      3. - - -

                        - - abstract - class - - - Value extends Ordered[Value] with Serializable - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        Annotations
                        - @SerialVersionUID() - -
                        -
                      4. - - -

                        - - - class - - - ValueSet extends AbstractSet[Value] with SortedSet[Value] with SortedSetLike[Value, ValueSet] with Serializable - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      -
                      - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - - val - - - CSV: Value - -

                        - - Permalink - - - -
                      5. - - -

                        - - - val - - - HBASE: Value - -

                        - - Permalink - - - -
                      6. - - -

                        - - - val - - - HIVE: Value - -

                        - - Permalink - - - -
                      7. - - -

                        - - - val - - - JANUS_GRAPH: Value - -

                        - - Permalink - - - -
                      8. - - -

                        - - - val - - - JSON: Value - -

                        - - Permalink - - - -
                      9. - - -

                        - - - val - - - KAFKA: Value - -

                        - - Permalink - - - -
                      10. - - -

                        - - - val - - - MYSQL: Value - -

                        - - Permalink - - - -
                      11. - - -

                        - - - val - - - NEO4J: Value - -

                        - - Permalink - - - -
                      12. - - -

                        - - - val - - - ORC: Value - -

                        - - Permalink - - - -
                      13. - - -

                        - - - val - - - PARQUET: Value - -

                        - - Permalink - - - -
                      14. - - -

                        - - - val - - - PULSAR: Value - -

                        - - Permalink - - - -
                      15. - - -

                        - - - val - - - SOCKET: Value - -

                        - - Permalink - - - -
                      16. - - -

                        - - - val - - - TEXT: Value - -

                        - - Permalink - - - -
                      17. - - -

                        - - final - def - - - Value(i: Int, name: String): Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      18. - - -

                        - - final - def - - - Value(name: String): Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      19. - - -

                        - - final - def - - - Value(i: Int): Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      20. - - -

                        - - final - def - - - Value: Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      21. - - -

                        - - final - def - - - apply(x: Int): Value - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      22. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      23. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      24. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      25. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      26. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      27. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      28. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      29. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      30. - - -

                        - - final - def - - - maxId: Int - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      31. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      32. - - -

                        - - - var - - - nextId: Int - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      33. - - -

                        - - - var - - - nextName: Iterator[String] - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      34. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      35. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      36. - - -

                        - - - def - - - readResolve(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      37. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      38. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration → AnyRef → Any
                        -
                      39. - - -

                        - - - def - - - values: ValueSet - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      40. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      41. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      42. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      43. - - -

                        - - final - def - - - withName(s: String): Value - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Enumeration

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory.html deleted file mode 100644 index 4b092c0..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SourceCategory.html +++ /dev/null @@ -1,504 +0,0 @@ - - - - SourceCategory - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.SourceCategory - - - - - - - - - - - - - - - - - -

                      - - - class - - - SourceCategory extends AnyRef - -

                      - -
                      - Linear Supertypes -
                      AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. SourceCategory
                      2. AnyRef
                      3. Any
                      4. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - SourceCategory() - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry$.html deleted file mode 100644 index eff2a11..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry$.html +++ /dev/null @@ -1,505 +0,0 @@ - - - - SparkConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.SparkConfigEntry - - - - - - - - - - - - - - - - - -

                      - - - object - - - SparkConfigEntry extends Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. SparkConfigEntry
                      2. Serializable
                      3. Serializable
                      4. AnyRef
                      5. Any
                      6. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - - def - - - apply(config: Config): SparkConfigEntry - -

                        - - Permalink - - - -
                      5. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      6. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      18. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry.html deleted file mode 100644 index e25615d..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/SparkConfigEntry.html +++ /dev/null @@ -1,496 +0,0 @@ - - - - SparkConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.SparkConfigEntry - - - - - - - - - - - - - - - - - -

                      - - - case class - - - SparkConfigEntry(map: scala.Predef.Map[String, String]) extends Product with Serializable - -

                      - -

                      SparkConfigEntry support key-value pairs for spark session. -

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. SparkConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - SparkConfigEntry(map: scala.Predef.Map[String, String]) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      8. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      10. - - -

                        - - - val - - - map: scala.Predef.Map[String, String] - -

                        - - Permalink - - - -
                      11. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      12. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        SparkConfigEntry → AnyRef → Any
                        -
                      16. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      17. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/StreamingDataSourceConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/StreamingDataSourceConfigEntry.html deleted file mode 100644 index b0093ad..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/StreamingDataSourceConfigEntry.html +++ /dev/null @@ -1,524 +0,0 @@ - - - - StreamingDataSourceConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.StreamingDataSourceConfigEntry - - - - - - - - - - - - - - - -
                      - Trait -

                      com.vesoft.nebula.tools.importer.config

                      -

                      StreamingDataSourceConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - sealed - trait - - - StreamingDataSourceConfigEntry extends DataSourceConfigEntry - -

                      - -
                      - Linear Supertypes - -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. StreamingDataSourceConfigEntry
                      2. DataSourceConfigEntry
                      3. AnyRef
                      4. Any
                      5. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - -
                      -

                      Abstract Value Members

                      -
                      1. - - -

                        - - abstract - def - - - category: SourceCategory.Value - -

                        - - Permalink - - -
                        Definition Classes
                        DataSourceConfigEntry
                        -
                      2. - - -

                        - - abstract - def - - - intervalSeconds: Int - -

                        - - Permalink - - - -
                      -
                      - -
                      -

                      Concrete Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from DataSourceConfigEntry

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/TagConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/TagConfigEntry.html deleted file mode 100644 index 4aa24e1..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/TagConfigEntry.html +++ /dev/null @@ -1,648 +0,0 @@ - - - - TagConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.TagConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      TagConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - TagConfigEntry(name: String, dataSourceConfigEntry: DataSourceConfigEntry, dataSinkConfigEntry: DataSinkConfigEntry, fields: scala.List[String], nebulaFields: scala.List[String], vertexField: String, vertexPolicy: Option[KeyPolicy.Value], batch: Int, partition: Int, checkPointPath: Option[String]) extends SchemaConfigEntry with Product with Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, SchemaConfigEntry, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. TagConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. SchemaConfigEntry
                      7. AnyRef
                      8. Any
                      9. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - TagConfigEntry(name: String, dataSourceConfigEntry: DataSourceConfigEntry, dataSinkConfigEntry: DataSinkConfigEntry, fields: scala.List[String], nebulaFields: scala.List[String], vertexField: String, vertexPolicy: Option[KeyPolicy.Value], batch: Int, partition: Int, checkPointPath: Option[String]) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - val - - - batch: Int - -

                        - - Permalink - - -

                        vertex or edge amount of one batch import

                        vertex or edge amount of one batch import

                        Definition Classes
                        TagConfigEntrySchemaConfigEntry
                        -
                      6. - - -

                        - - - val - - - checkPointPath: Option[String] - -

                        - - Permalink - - -

                        check point path

                        check point path

                        Definition Classes
                        TagConfigEntrySchemaConfigEntry
                        -
                      7. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      8. - - -

                        - - - val - - - dataSinkConfigEntry: DataSinkConfigEntry - -

                        - - Permalink - - -

                        seeDataSinkConfigEntry

                        -
                      9. - - -

                        - - - val - - - dataSourceConfigEntry: DataSourceConfigEntry - -

                        - - Permalink - - -

                        seeDataSourceConfigEntry

                        -
                      10. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      11. - - -

                        - - - val - - - fields: scala.List[String] - -

                        - - Permalink - - -

                        data source fields which are going to be import to nebula as properties

                        data source fields which are going to be import to nebula as properties

                        Definition Classes
                        TagConfigEntrySchemaConfigEntry
                        -
                      12. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      13. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      14. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      15. - - -

                        - - - val - - - name: String - -

                        - - Permalink - - -

                        nebula tag or edge name

                        nebula tag or edge name

                        Definition Classes
                        TagConfigEntrySchemaConfigEntry
                        -
                      16. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - - val - - - nebulaFields: scala.List[String] - -

                        - - Permalink - - -

                        nebula properties which are going to fill value with data source value

                        nebula properties which are going to fill value with data source value

                        Definition Classes
                        TagConfigEntrySchemaConfigEntry
                        -
                      18. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - val - - - partition: Int - -

                        - - Permalink - - -

                        spark partition

                        spark partition

                        Definition Classes
                        TagConfigEntrySchemaConfigEntry
                        -
                      21. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      22. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        TagConfigEntry → AnyRef → Any
                        -
                      23. - - -

                        - - - val - - - vertexField: String - -

                        - - Permalink - - - -
                      24. - - -

                        - - - val - - - vertexPolicy: Option[KeyPolicy.Value] - -

                        - - Permalink - - - -
                      25. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      26. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      27. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from SchemaConfigEntry

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Type$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Type$.html deleted file mode 100644 index 4514358..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/Type$.html +++ /dev/null @@ -1,786 +0,0 @@ - - - - Type - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.Type - - - - - - - - - - - - - - - -
                      - Object -

                      com.vesoft.nebula.tools.importer.config

                      -

                      Type

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - object - - - Type extends Enumeration - -

                      - -
                      - Linear Supertypes -
                      Enumeration, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. Type
                      2. Enumeration
                      3. Serializable
                      4. Serializable
                      5. AnyRef
                      6. Any
                      7. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - -
                      -

                      Type Members

                      -
                      1. - - -

                        - - - type - - - Type = Value - -

                        - - Permalink - - - -
                      2. - - -

                        - - - class - - - Val extends Value with Serializable - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        Annotations
                        - @SerialVersionUID() - -
                        -
                      3. - - -

                        - - abstract - class - - - Value extends Ordered[Value] with Serializable - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        Annotations
                        - @SerialVersionUID() - -
                        -
                      4. - - -

                        - - - class - - - ValueSet extends AbstractSet[Value] with SortedSet[Value] with SortedSetLike[Value, ValueSet] with Serializable - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      -
                      - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - - val - - - EDGE: Value - -

                        - - Permalink - - - -
                      5. - - -

                        - - - val - - - VERTEX: Value - -

                        - - Permalink - - - -
                      6. - - -

                        - - final - def - - - Value(i: Int, name: String): Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      7. - - -

                        - - final - def - - - Value(name: String): Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      8. - - -

                        - - final - def - - - Value(i: Int): Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      9. - - -

                        - - final - def - - - Value: Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      10. - - -

                        - - final - def - - - apply(x: Int): Value - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      11. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      13. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      15. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      16. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      17. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      18. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      19. - - -

                        - - final - def - - - maxId: Int - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      20. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      21. - - -

                        - - - var - - - nextId: Int - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      22. - - -

                        - - - var - - - nextName: Iterator[String] - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      23. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      24. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      25. - - -

                        - - - def - - - readResolve(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      26. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      27. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration → AnyRef → Any
                        -
                      28. - - -

                        - - - def - - - values: ValueSet - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      29. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      30. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      31. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      32. - - -

                        - - final - def - - - withName(s: String): Value - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Enumeration

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/UserConfigEntry.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/UserConfigEntry.html deleted file mode 100644 index 17fb308..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/UserConfigEntry.html +++ /dev/null @@ -1,511 +0,0 @@ - - - - UserConfigEntry - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config.UserConfigEntry - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.config

                      -

                      UserConfigEntry

                      Related Doc: - package config -

                      - - Permalink - - -
                      - -

                      - - - case class - - - UserConfigEntry(user: String, password: String) extends Product with Serializable - -

                      - -

                      UserConfigEntry is used when the client login the nebula graph service. -

                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. UserConfigEntry
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - UserConfigEntry(user: String, password: String) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      8. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      10. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      11. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      12. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - - val - - - password: String - -

                        - - Permalink - - - -
                      14. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        UserConfigEntry → AnyRef → Any
                        -
                      16. - - -

                        - - - val - - - user: String - -

                        - - Permalink - - - -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/package.html deleted file mode 100644 index b693879..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/config/package.html +++ /dev/null @@ -1,700 +0,0 @@ - - - - config - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.config - - - - - - - - - - - - - - - -
                      - Package -

                      com.vesoft.nebula.tools.importer

                      -

                      config

                      - - Permalink - - -
                      - -

                      - - - package - - - config - -

                      - -
                      - - -
                      -
                      - - -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - -
                      -

                      Type Members

                      -
                      1. - - -

                        - - - case class - - - Configs(databaseConfig: DataBaseConfigEntry, userConfig: UserConfigEntry, connectionConfig: ConnectionConfigEntry, executionConfig: ExecutionConfigEntry, errorConfig: ErrorConfigEntry, rateConfig: RateConfigEntry, sparkConfigEntry: SparkConfigEntry, tagsConfig: scala.List[TagConfigEntry], edgesConfig: scala.List[EdgeConfigEntry], hiveConfigEntry: Option[HiveConfigEntry] = None) extends Product with Serializable - -

                        - - Permalink - - -

                        Configs -

                        -
                      2. - - -

                        - - - case class - - - ConnectionConfigEntry(timeout: Int, retry: Int) extends Product with Serializable - -

                        - - Permalink - - -

                        ConnectionConfigEntry -

                        -
                      3. - - -

                        - - - case class - - - DataBaseConfigEntry(graphAddress: scala.List[String], space: String, metaAddresses: scala.List[String]) extends Product with Serializable - -

                        - - Permalink - - -

                        DataBaseConfigEntry describe the nebula cluster's address and which space will be used.

                        -
                      4. - - -

                        - - sealed - trait - - - DataSinkConfigEntry extends AnyRef - -

                        - - Permalink - - -

                        DataSinkConfigEntry -

                        -
                      5. - - -

                        - - sealed - trait - - - DataSourceConfigEntry extends AnyRef - -

                        - - Permalink - - -

                        DataSourceConfigEntry -

                        -
                      6. - - -

                        - - - case class - - - EdgeConfigEntry(name: String, dataSourceConfigEntry: DataSourceConfigEntry, dataSinkConfigEntry: DataSinkConfigEntry, fields: scala.List[String], nebulaFields: scala.List[String], sourceField: String, sourcePolicy: Option[KeyPolicy.Value], rankingField: Option[String], targetField: String, targetPolicy: Option[KeyPolicy.Value], isGeo: Boolean, latitude: Option[String], longitude: Option[String], batch: Int, partition: Int, checkPointPath: Option[String]) extends SchemaConfigEntry with Product with Serializable - -

                        - - Permalink - - -

                        -
                      7. - - -

                        - - - case class - - - ErrorConfigEntry(errorPath: String, errorMaxSize: Int) extends Product with Serializable - -

                        - - Permalink - - -

                        ErrorConfigEntry -

                        -
                      8. - - -

                        - - - case class - - - ExecutionConfigEntry(timeout: Int, retry: Int, interval: Int) extends Product with Serializable - -

                        - - Permalink - - -

                        ExecutionConfigEntry -

                        -
                      9. - - -

                        - - - case class - - - FileBaseSinkConfigEntry(category: SinkCategory.Value, localPath: String, remotePath: String) extends DataSinkConfigEntry with Product with Serializable - -

                        - - Permalink - - -

                        FileBaseSinkConfigEntry -

                        -
                      10. - - -

                        - - - case class - - - FileBaseSourceConfigEntry(category: SourceCategory.Value, path: String, separator: Option[String] = None, header: Option[Boolean] = None) extends FileDataSourceConfigEntry with Product with Serializable - -

                        - - Permalink - - -

                        FileBaseSourceConfigEntry -

                        -
                      11. - - -

                        - - sealed - trait - - - FileDataSourceConfigEntry extends DataSourceConfigEntry - -

                        - - Permalink - - - -
                      12. - - -

                        - - - case class - - - HBaseSourceConfigEntry(category: SourceCategory.Value, host: String, port: String, table: String, columnFamily: String, fields: scala.List[String]) extends ServerDataSourceConfigEntry with Product with Serializable - -

                        - - Permalink - - -

                        HBaseSourceConfigEntry

                        -
                      13. - - -

                        - - - case class - - - HiveConfigEntry(waredir: String, connectionURL: String, connectionDriverName: String, connectionUserName: String, connectionPassWord: String) extends Product with Serializable - -

                        - - Permalink - - - -
                      14. - - -

                        - - - case class - - - HiveSourceConfigEntry(category: SourceCategory.Value, sentence: String) extends ServerDataSourceConfigEntry with Product with Serializable - -

                        - - Permalink - - -

                        HiveSourceConfigEntry -

                        -
                      15. - - -

                        - - - case class - - - JanusGraphSourceConfigEntry(category: SourceCategory.Value, sentence: String, isEdge: Boolean) extends ServerDataSourceConfigEntry with Product with Serializable - -

                        - - Permalink - - - -
                      16. - - -

                        - - - case class - - - KafkaSourceConfigEntry(category: SourceCategory.Value, intervalSeconds: Int, server: String, topic: String) extends StreamingDataSourceConfigEntry with Product with Serializable - -

                        - - Permalink - - -

                        TODO: Support more config item about Kafka Consumer -

                        -
                      17. - - -

                        - - - case class - - - MySQLSourceConfigEntry(category: SourceCategory.Value, host: String, port: Int, database: String, table: String, user: String, password: String, sentence: String) extends ServerDataSourceConfigEntry with Product with Serializable - -

                        - - Permalink - - -

                        MySQLSourceConfigEntry -

                        -
                      18. - - -

                        - - - case class - - - NebulaSinkConfigEntry(category: SinkCategory.Value, addresses: scala.List[String]) extends DataSinkConfigEntry with Product with Serializable - -

                        - - Permalink - - -

                        NebulaSinkConfigEntry use to specified the nebula service's address.

                        -
                      19. - - -

                        - - - case class - - - Neo4JSourceConfigEntry(category: SourceCategory.Value, sentence: String, name: String, server: String, user: String, password: String, database: Option[String], encryption: Boolean, parallel: Int, checkPointPath: Option[String]) extends ServerDataSourceConfigEntry with Product with Serializable - -

                        - - Permalink - - -

                        Neo4JSourceConfigEntry -

                        Neo4JSourceConfigEntry -

                        checkPointPath

                        use save resume data dir path.

                        -
                      20. - - -

                        - - - case class - - - PulsarSourceConfigEntry(category: SourceCategory.Value, intervalSeconds: Int, serviceUrl: String, adminUrl: String, options: scala.Predef.Map[String, String]) extends StreamingDataSourceConfigEntry with Product with Serializable - -

                        - - Permalink - - -

                        PulsarSourceConfigEntry -

                        PulsarSourceConfigEntry -

                        adminUrl

                        use to get data schema.

                        -
                      21. - - -

                        - - - case class - - - RateConfigEntry(limit: Int, timeout: Int) extends Product with Serializable - -

                        - - Permalink - - -

                        RateConfigEntry -

                        -
                      22. - - -

                        - - sealed - trait - - - SchemaConfigEntry extends AnyRef - -

                        - - Permalink - - -

                        SchemaConfigEntry is tag/edge super class use to save some basic parameter for importer.

                        -
                      23. - - -

                        - - sealed - trait - - - ServerDataSourceConfigEntry extends DataSourceConfigEntry - -

                        - - Permalink - - - -
                      24. - - -

                        - - - class - - - SinkCategory extends AnyRef - -

                        - - Permalink - - - -
                      25. - - -

                        - - - class - - - SourceCategory extends AnyRef - -

                        - - Permalink - - - -
                      26. - - -

                        - - - case class - - - SparkConfigEntry(map: scala.Predef.Map[String, String]) extends Product with Serializable - -

                        - - Permalink - - -

                        SparkConfigEntry support key-value pairs for spark session.

                        -
                      27. - - -

                        - - sealed - trait - - - StreamingDataSourceConfigEntry extends DataSourceConfigEntry - -

                        - - Permalink - - - -
                      28. - - -

                        - - - case class - - - TagConfigEntry(name: String, dataSourceConfigEntry: DataSourceConfigEntry, dataSinkConfigEntry: DataSinkConfigEntry, fields: scala.List[String], nebulaFields: scala.List[String], vertexField: String, vertexPolicy: Option[KeyPolicy.Value], batch: Int, partition: Int, checkPointPath: Option[String]) extends SchemaConfigEntry with Product with Serializable - -

                        - - Permalink - - -

                        -
                      29. - - -

                        - - - case class - - - UserConfigEntry(user: String, password: String) extends Product with Serializable - -

                        - - Permalink - - -

                        UserConfigEntry is used when the client login the nebula graph service.

                        -
                      -
                      - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - - object - - - Configs extends Serializable - -

                        - - Permalink - - - -
                      2. - - -

                        - - - object - - - SinkCategory extends Enumeration - -

                        - - Permalink - - -

                        SinkCategory is used to expression the writer's type.

                        SinkCategory is used to expression the writer's type. -SST is not supported yet. -

                        -
                      3. - - -

                        - - - object - - - SourceCategory extends Enumeration - -

                        - - Permalink - - -

                        Category use to explain the data source which the Spark application could reading.

                        -
                      4. - - -

                        - - - object - - - SparkConfigEntry extends Serializable - -

                        - - Permalink - - -

                        -
                      5. - - -

                        - - - object - - - Type extends Enumeration - -

                        - - Permalink - - - -
                      -
                      - - - - -
                      - -
                      - - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edge.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edge.html deleted file mode 100644 index cf3c80b..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edge.html +++ /dev/null @@ -1,578 +0,0 @@ - - - - Edge - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.Edge - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer

                      -

                      Edge

                      Related Doc: - package importer -

                      - - Permalink - - -
                      - -

                      - - - case class - - - Edge(source: VertexIDSlice, destination: VertexIDSlice, ranking: Option[EdgeRank], values: PropertyValues) extends Product with Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. Edge
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - Edge(source: VertexIDSlice, destination: VertexIDSlice, values: PropertyValues) - -

                        - - Permalink - - - -
                      2. - - -

                        - - - new - - - Edge(source: VertexIDSlice, destination: VertexIDSlice, ranking: Option[EdgeRank], values: PropertyValues) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - val - - - destination: VertexIDSlice - -

                        - - Permalink - - - -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      11. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      12. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - - def - - - propertyValues: String - -

                        - - Permalink - - - -
                      15. - - -

                        - - - val - - - ranking: Option[EdgeRank] - -

                        - - Permalink - - - -
                      16. - - -

                        - - - val - - - source: VertexIDSlice - -

                        - - Permalink - - - -
                      17. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        Edge → AnyRef → Any
                        -
                      19. - - -

                        - - - val - - - values: PropertyValues - -

                        - - Permalink - - - -
                      20. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edges.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edges.html deleted file mode 100644 index b78bb5f..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Edges.html +++ /dev/null @@ -1,561 +0,0 @@ - - - - Edges - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.Edges - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer

                      -

                      Edges

                      Related Doc: - package importer -

                      - - Permalink - - -
                      - -

                      - - - case class - - - Edges(names: PropertyNames, values: scala.List[Edge], sourcePolicy: Option[KeyPolicy.Value] = None, targetPolicy: Option[KeyPolicy.Value] = None) extends Product with Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. Edges
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - Edges(names: PropertyNames, values: scala.List[Edge], sourcePolicy: Option[KeyPolicy.Value] = None, targetPolicy: Option[KeyPolicy.Value] = None) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      8. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      10. - - -

                        - - - val - - - names: PropertyNames - -

                        - - Permalink - - - -
                      11. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      12. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - - def - - - propertyNames: String - -

                        - - Permalink - - - -
                      15. - - -

                        - - - val - - - sourcePolicy: Option[KeyPolicy.Value] - -

                        - - Permalink - - - -
                      16. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - - val - - - targetPolicy: Option[KeyPolicy.Value] - -

                        - - Permalink - - - -
                      18. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        Edges → AnyRef → Any
                        -
                      19. - - -

                        - - - val - - - values: scala.List[Edge] - -

                        - - Permalink - - - -
                      20. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$KeyPolicy$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$KeyPolicy$.html deleted file mode 100644 index e50aaad..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$KeyPolicy$.html +++ /dev/null @@ -1,786 +0,0 @@ - - - - KeyPolicy - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.KeyPolicy - - - - - - - - - - - - - - - -
                      - Object -

                      com.vesoft.nebula.tools.importer

                      -

                      KeyPolicy

                      Related Doc: - package importer -

                      - - Permalink - - -
                      - -

                      - - - object - - - KeyPolicy extends Enumeration - -

                      - -
                      - Linear Supertypes -
                      Enumeration, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. KeyPolicy
                      2. Enumeration
                      3. Serializable
                      4. Serializable
                      5. AnyRef
                      6. Any
                      7. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - -
                      -

                      Type Members

                      -
                      1. - - -

                        - - - type - - - POLICY = Value - -

                        - - Permalink - - - -
                      2. - - -

                        - - - class - - - Val extends Value with Serializable - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        Annotations
                        - @SerialVersionUID() - -
                        -
                      3. - - -

                        - - abstract - class - - - Value extends Ordered[Value] with Serializable - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        Annotations
                        - @SerialVersionUID() - -
                        -
                      4. - - -

                        - - - class - - - ValueSet extends AbstractSet[Value] with SortedSet[Value] with SortedSetLike[Value, ValueSet] with Serializable - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      -
                      - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - - val - - - HASH: Value - -

                        - - Permalink - - - -
                      5. - - -

                        - - - val - - - UUID: Value - -

                        - - Permalink - - - -
                      6. - - -

                        - - final - def - - - Value(i: Int, name: String): Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      7. - - -

                        - - final - def - - - Value(name: String): Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      8. - - -

                        - - final - def - - - Value(i: Int): Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      9. - - -

                        - - final - def - - - Value: Value - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      10. - - -

                        - - final - def - - - apply(x: Int): Value - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      11. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      13. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      15. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      16. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      17. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      18. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      19. - - -

                        - - final - def - - - maxId: Int - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      20. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      21. - - -

                        - - - var - - - nextId: Int - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      22. - - -

                        - - - var - - - nextName: Iterator[String] - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      23. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      24. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      25. - - -

                        - - - def - - - readResolve(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected
                        Definition Classes
                        Enumeration
                        -
                      26. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      27. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration → AnyRef → Any
                        -
                      28. - - -

                        - - - def - - - values: ValueSet - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      29. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      30. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      31. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      32. - - -

                        - - final - def - - - withName(s: String): Value - -

                        - - Permalink - - -
                        Definition Classes
                        Enumeration
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Enumeration

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Offset.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Offset.html deleted file mode 100644 index 64cfd56..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Offset.html +++ /dev/null @@ -1,493 +0,0 @@ - - - - Offset - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.Offset - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer

                      -

                      Offset

                      Related Doc: - package importer -

                      - - Permalink - - -
                      - -

                      - - - case class - - - Offset(start: Long, size: Long) extends Product with Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. Offset
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - Offset(start: Long, size: Long) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      8. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      10. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      11. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      12. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - - val - - - size: Long - -

                        - - Permalink - - - -
                      14. - - -

                        - - - val - - - start: Long - -

                        - - Permalink - - - -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      17. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertex.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertex.html deleted file mode 100644 index 0f53ecb..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertex.html +++ /dev/null @@ -1,527 +0,0 @@ - - - - Vertex - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.Vertex - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer

                      -

                      Vertex

                      Related Doc: - package importer -

                      - - Permalink - - -
                      - -

                      - - - case class - - - Vertex(vertexID: VertexIDSlice, values: PropertyValues) extends Product with Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. Vertex
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - Vertex(vertexID: VertexIDSlice, values: PropertyValues) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      8. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      10. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      11. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      12. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - - def - - - propertyValues: String - -

                        - - Permalink - - - -
                      14. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        Vertex → AnyRef → Any
                        -
                      16. - - -

                        - - - val - - - values: PropertyValues - -

                        - - Permalink - - - -
                      17. - - -

                        - - - val - - - vertexID: VertexIDSlice - -

                        - - Permalink - - - -
                      18. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertices.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertices.html deleted file mode 100644 index 5f5ef6b..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package$$Vertices.html +++ /dev/null @@ -1,544 +0,0 @@ - - - - Vertices - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.Vertices - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer

                      -

                      Vertices

                      Related Doc: - package importer -

                      - - Permalink - - -
                      - -

                      - - - case class - - - Vertices(names: PropertyNames, values: scala.List[Vertex], policy: Option[KeyPolicy.Value] = None) extends Product with Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Serializable, Product, Equals, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. Vertices
                      2. Serializable
                      3. Serializable
                      4. Product
                      5. Equals
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - Vertices(names: PropertyNames, values: scala.List[Vertex], policy: Option[KeyPolicy.Value] = None) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      8. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      10. - - -

                        - - - val - - - names: PropertyNames - -

                        - - Permalink - - - -
                      11. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      12. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - - val - - - policy: Option[KeyPolicy.Value] - -

                        - - Permalink - - - -
                      15. - - -

                        - - - def - - - propertyNames: String - -

                        - - Permalink - - - -
                      16. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        Vertices → AnyRef → Any
                        -
                      18. - - -

                        - - - val - - - values: scala.List[Vertex] - -

                        - - Permalink - - - -
                      19. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Product

                      -
                      -

                      Inherited from Equals

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package.html deleted file mode 100644 index e784aa3..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/package.html +++ /dev/null @@ -1,709 +0,0 @@ - - - - importer - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer - - - - - - - - - - - - - - - -
                      - Package -

                      com.vesoft.nebula.tools

                      -

                      importer

                      - - Permalink - - -
                      - -

                      - - - package - - - importer - -

                      - -
                      - Linear Supertypes -
                      AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. importer
                      2. AnyRef
                      3. Any
                      4. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - -
                      -

                      Type Members

                      -
                      1. - - -

                        - - final - case class - - - Argument(config: File = new File("application.conf"), hive: Boolean = false, directly: Boolean = false, dry: Boolean = false, reload: String = "") extends Product with Serializable - -

                        - - Permalink - - - -
                      2. - - -

                        - - - case class - - - Edge(source: VertexIDSlice, destination: VertexIDSlice, ranking: Option[EdgeRank], values: PropertyValues) extends Product with Serializable - -

                        - - Permalink - - - -
                      3. - - -

                        - - - type - - - EdgeRank = Long - -

                        - - Permalink - - - -
                      4. - - -

                        - - - type - - - EdgeType = Int - -

                        - - Permalink - - - -
                      5. - - -

                        - - - type - - - EdgeVersion = Long - -

                        - - Permalink - - - -
                      6. - - -

                        - - - case class - - - Edges(names: PropertyNames, values: scala.List[Edge], sourcePolicy: Option[KeyPolicy.Value] = None, targetPolicy: Option[KeyPolicy.Value] = None) extends Product with Serializable - -

                        - - Permalink - - - -
                      7. - - -

                        - - - class - - - GraphProvider extends AutoCloseable with Serializable - -

                        - - Permalink - - -

                        -
                      8. - - -

                        - - - type - - - GraphSpaceID = Int - -

                        - - Permalink - - - -
                      9. - - -

                        - - - class - - - MetaProvider extends AutoCloseable with Serializable - -

                        - - Permalink - - -

                        MetaProvider provide nebula graph meta query operations.

                        -
                      10. - - -

                        - - - case class - - - Offset(start: Long, size: Long) extends Product with Serializable - -

                        - - Permalink - - - -
                      11. - - -

                        - - - type - - - PartitionID = Int - -

                        - - Permalink - - - -
                      12. - - -

                        - - - type - - - ProcessResult = ListBuffer[WriterResult] - -

                        - - Permalink - - - -
                      13. - - -

                        - - - type - - - PropertyNames = scala.collection.immutable.List[String] - -

                        - - Permalink - - - -
                      14. - - -

                        - - - type - - - PropertyValues = scala.collection.immutable.List[Any] - -

                        - - Permalink - - - -
                      15. - - -

                        - - - type - - - SchemaID = (TagID, EdgeType) - -

                        - - Permalink - - - -
                      16. - - -

                        - - - type - - - SchemaVersion = (TagVersion, EdgeVersion) - -

                        - - Permalink - - - -
                      17. - - -

                        - - - type - - - TagID = Int - -

                        - - Permalink - - - -
                      18. - - -

                        - - - type - - - TagVersion = Long - -

                        - - Permalink - - - -
                      19. - - -

                        - - final - case class - - - TooManyErrorsException(message: String) extends Exception with Product with Serializable - -

                        - - Permalink - - - -
                      20. - - -

                        - - - case class - - - Vertex(vertexID: VertexIDSlice, values: PropertyValues) extends Product with Serializable - -

                        - - Permalink - - - -
                      21. - - -

                        - - - type - - - VertexID = Long - -

                        - - Permalink - - - -
                      22. - - -

                        - - - type - - - VertexIDSlice = String - -

                        - - Permalink - - - -
                      23. - - -

                        - - - case class - - - Vertices(names: PropertyNames, values: scala.List[Vertex], policy: Option[KeyPolicy.Value] = None) extends Product with Serializable - -

                        - - Permalink - - - -
                      24. - - -

                        - - - type - - - WriterResult = ListenableFuture[Optional[Integer]] - -

                        - - Permalink - - - -
                      -
                      - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - - object - - - CheckPointHandler - -

                        - - Permalink - - -

                        CheckPointHandler handle the checkpoint files for Neo4j and Janusgraph -

                        -
                      2. - - -

                        - - - object - - - ErrorHandler - -

                        - - Permalink - - - -
                      3. - - -

                        - - - object - - - Exchange - -

                        - - Permalink - - -

                        SparkClientGenerator is a simple spark job used to write data into Nebula Graph parallel.

                        -
                      4. - - -

                        - - - object - - - KeyPolicy extends Enumeration - -

                        - - Permalink - - - -
                      5. - - -

                        - - - object - - - VidType extends Enumeration - -

                        - - Permalink - - - -
                      6. - - -

                        - - - package - - - config - -

                        - - Permalink - - - -
                      7. - - -

                        - - - package - - - processor - -

                        - - Permalink - - - -
                      8. - - -

                        - - - package - - - reader - -

                        - - Permalink - - - -
                      9. - - -

                        - - - package - - - utils - -

                        - - Permalink - - - -
                      10. - - -

                        - - - package - - - writer - -

                        - - Permalink - - - -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.html deleted file mode 100644 index e1e2959..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.html +++ /dev/null @@ -1,582 +0,0 @@ - - - - EdgeProcessor - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.processor.EdgeProcessor - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.processor

                      -

                      EdgeProcessor

                      Related Doc: - package processor -

                      - - Permalink - - -
                      - -

                      - - - class - - - EdgeProcessor extends Processor - -

                      - -
                      - Linear Supertypes -
                      Processor, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. EdgeProcessor
                      2. Processor
                      3. Serializable
                      4. Serializable
                      5. AnyRef
                      6. Any
                      7. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - EdgeProcessor(data: DataFrame, edgeConfig: EdgeConfigEntry, fieldKeys: scala.List[String], nebulaKeys: scala.List[String], config: Configs, batchSuccess: LongAccumulator, batchFailure: LongAccumulator) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - extraValue(row: org.apache.spark.sql.Row, field: String, fieldTypeMap: scala.Predef.Map[String, Int], toBytes: Boolean = false): Any - -

                        - - Permalink - - -

                        handle special types of attributes

                        handle special types of attributes

                        String type: add "" for attribute value, if value contains escape symbol,then keep it.

                        Date type: add date() function for attribute value. -eg: convert attribute value 2020-01-01 to date("2020-01-01")

                        Time type: add time() function for attribute value. -eg: convert attribute value 12:12:12:1111 to time("12:12:12:1111")

                        DataTime type: add datetime() function for attribute value. -eg: convert attribute value 2020-01-01T22:30:40 to datetime("2020-01-01T22:30:40") -

                        Definition Classes
                        Processor
                        -
                      9. - - -

                        - - - def - - - fetchOffset(path: String): Long - -

                        - - Permalink - - -
                        Definition Classes
                        Processor
                        -
                      10. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      11. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - - def - - - getLong(row: org.apache.spark.sql.Row, field: String): Long - -

                        - - Permalink - - -
                        Definition Classes
                        Processor
                        -
                      13. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      14. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      15. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - - def - - - process(): Unit - -

                        - - Permalink - - -

                        process dataframe to vertices or edges -

                        process dataframe to vertices or edges -

                        Definition Classes
                        EdgeProcessorProcessor
                        -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      21. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Processor

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/Processor.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/Processor.html deleted file mode 100644 index 110d7f7..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/Processor.html +++ /dev/null @@ -1,568 +0,0 @@ - - - - Processor - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.processor.Processor - - - - - - - - - - - - - - - -
                      - Trait -

                      com.vesoft.nebula.tools.importer.processor

                      -

                      Processor

                      Related Doc: - package processor -

                      - - Permalink - - -
                      - -

                      - - - trait - - - Processor extends Serializable - -

                      - -

                      processor is a converter. -It is responsible for converting the dataframe row data into Nebula Graph's vertex or edge, -and submit data to writer. -

                      - Linear Supertypes -
                      Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. Processor
                      2. Serializable
                      3. Serializable
                      4. AnyRef
                      5. Any
                      6. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - -
                      -

                      Abstract Value Members

                      -
                      1. - - -

                        - - abstract - def - - - process(): Unit - -

                        - - Permalink - - -

                        process dataframe to vertices or edges -

                        -
                      -
                      - -
                      -

                      Concrete Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - extraValue(row: org.apache.spark.sql.Row, field: String, fieldTypeMap: scala.Predef.Map[String, Int], toBytes: Boolean = false): Any - -

                        - - Permalink - - -

                        handle special types of attributes

                        handle special types of attributes

                        String type: add "" for attribute value, if value contains escape symbol,then keep it.

                        Date type: add date() function for attribute value. -eg: convert attribute value 2020-01-01 to date("2020-01-01")

                        Time type: add time() function for attribute value. -eg: convert attribute value 12:12:12:1111 to time("12:12:12:1111")

                        DataTime type: add datetime() function for attribute value. -eg: convert attribute value 2020-01-01T22:30:40 to datetime("2020-01-01T22:30:40") -

                        -
                      9. - - -

                        - - - def - - - fetchOffset(path: String): Long - -

                        - - Permalink - - - -
                      10. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      11. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - - def - - - getLong(row: org.apache.spark.sql.Row, field: String): Long - -

                        - - Permalink - - - -
                      13. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      14. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      15. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      20. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/ReloadProcessor.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/ReloadProcessor.html deleted file mode 100644 index 7048cd8..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/ReloadProcessor.html +++ /dev/null @@ -1,582 +0,0 @@ - - - - ReloadProcessor - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.processor.ReloadProcessor - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.processor

                      -

                      ReloadProcessor

                      Related Doc: - package processor -

                      - - Permalink - - -
                      - -

                      - - - class - - - ReloadProcessor extends Processor - -

                      - -
                      - Linear Supertypes -
                      Processor, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. ReloadProcessor
                      2. Processor
                      3. Serializable
                      4. Serializable
                      5. AnyRef
                      6. Any
                      7. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - ReloadProcessor(data: DataFrame, config: Configs, batchSuccess: LongAccumulator, batchFailure: LongAccumulator) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - extraValue(row: org.apache.spark.sql.Row, field: String, fieldTypeMap: scala.Predef.Map[String, Int], toBytes: Boolean = false): Any - -

                        - - Permalink - - -

                        handle special types of attributes

                        handle special types of attributes

                        String type: add "" for attribute value, if value contains escape symbol,then keep it.

                        Date type: add date() function for attribute value. -eg: convert attribute value 2020-01-01 to date("2020-01-01")

                        Time type: add time() function for attribute value. -eg: convert attribute value 12:12:12:1111 to time("12:12:12:1111")

                        DataTime type: add datetime() function for attribute value. -eg: convert attribute value 2020-01-01T22:30:40 to datetime("2020-01-01T22:30:40") -

                        Definition Classes
                        Processor
                        -
                      9. - - -

                        - - - def - - - fetchOffset(path: String): Long - -

                        - - Permalink - - -
                        Definition Classes
                        Processor
                        -
                      10. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      11. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - - def - - - getLong(row: org.apache.spark.sql.Row, field: String): Long - -

                        - - Permalink - - -
                        Definition Classes
                        Processor
                        -
                      13. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      14. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      15. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - - def - - - process(): Unit - -

                        - - Permalink - - -

                        process dataframe to vertices or edges -

                        process dataframe to vertices or edges -

                        Definition Classes
                        ReloadProcessorProcessor
                        -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      21. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Processor

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.html deleted file mode 100644 index f318e66..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.html +++ /dev/null @@ -1,582 +0,0 @@ - - - - VerticesProcessor - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.processor.VerticesProcessor - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.processor

                      -

                      VerticesProcessor

                      Related Doc: - package processor -

                      - - Permalink - - -
                      - -

                      - - - class - - - VerticesProcessor extends Processor - -

                      - -
                      - Linear Supertypes -
                      Processor, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. VerticesProcessor
                      2. Processor
                      3. Serializable
                      4. Serializable
                      5. AnyRef
                      6. Any
                      7. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - VerticesProcessor(data: DataFrame, tagConfig: TagConfigEntry, fieldKeys: scala.List[String], nebulaKeys: scala.List[String], config: Configs, batchSuccess: LongAccumulator, batchFailure: LongAccumulator) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - extraValue(row: org.apache.spark.sql.Row, field: String, fieldTypeMap: scala.Predef.Map[String, Int], toBytes: Boolean = false): Any - -

                        - - Permalink - - -

                        handle special types of attributes

                        handle special types of attributes

                        String type: add "" for attribute value, if value contains escape symbol,then keep it.

                        Date type: add date() function for attribute value. -eg: convert attribute value 2020-01-01 to date("2020-01-01")

                        Time type: add time() function for attribute value. -eg: convert attribute value 12:12:12:1111 to time("12:12:12:1111")

                        DataTime type: add datetime() function for attribute value. -eg: convert attribute value 2020-01-01T22:30:40 to datetime("2020-01-01T22:30:40") -

                        Definition Classes
                        Processor
                        -
                      9. - - -

                        - - - def - - - fetchOffset(path: String): Long - -

                        - - Permalink - - -
                        Definition Classes
                        Processor
                        -
                      10. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      11. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - - def - - - getLong(row: org.apache.spark.sql.Row, field: String): Long - -

                        - - Permalink - - -
                        Definition Classes
                        Processor
                        -
                      13. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      14. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      15. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - - def - - - process(): Unit - -

                        - - Permalink - - -

                        process dataframe to vertices or edges -

                        process dataframe to vertices or edges -

                        Definition Classes
                        VerticesProcessorProcessor
                        -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      21. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Processor

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/package.html deleted file mode 100644 index 44f07b4..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/processor/package.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - processor - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.processor - - - - - - - - - - - - - - - -
                      - Package -

                      com.vesoft.nebula.tools.importer

                      -

                      processor

                      - - Permalink - - -
                      - -

                      - - - package - - - processor - -

                      - -
                      - - -
                      -
                      - - -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - -
                      -

                      Type Members

                      -
                      1. - - -

                        - - - class - - - EdgeProcessor extends Processor - -

                        - - Permalink - - - -
                      2. - - -

                        - - - trait - - - Processor extends Serializable - -

                        - - Permalink - - -

                        processor is a converter.

                        processor is a converter. -It is responsible for converting the dataframe row data into Nebula Graph's vertex or edge, -and submit data to writer. -

                        -
                      3. - - -

                        - - - class - - - ReloadProcessor extends Processor - -

                        - - Permalink - - - -
                      4. - - -

                        - - - class - - - VerticesProcessor extends Processor - -

                        - - Permalink - - -

                        -
                      -
                      - - - - - - - - -
                      - -
                      - - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CSVReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CSVReader.html deleted file mode 100644 index cc0d17d..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CSVReader.html +++ /dev/null @@ -1,580 +0,0 @@ - - - - CSVReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.CSVReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      CSVReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - - class - - - CSVReader extends FileBaseReader - -

                      - -

                      The CSVReader extend the FileBaseReader and support read csv file from HDFS. -All types of the structure are StringType. -

                      - Linear Supertypes -
                      FileBaseReader, Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. CSVReader
                      2. FileBaseReader
                      3. Reader
                      4. Serializable
                      5. Serializable
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - CSVReader(session: SparkSession, csvConfig: FileBaseSourceConfigEntry) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        FileBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - val - - - path: String - -

                        - - Permalink - - -
                        Definition Classes
                        FileBaseReader
                        -
                      17. - - -

                        - - - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        CSVReaderReader
                        -
                      18. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        CSVReaderFileBaseReaderReader
                        -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      21. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from FileBaseReader

                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CheckPointSupport.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CheckPointSupport.html deleted file mode 100644 index 8576dc9..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CheckPointSupport.html +++ /dev/null @@ -1,506 +0,0 @@ - - - - CheckPointSupport - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.CheckPointSupport - - - - - - - - - - - - - - - -
                      - Trait -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      CheckPointSupport

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - - trait - - - CheckPointSupport extends Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Serializable, AnyRef, Any
                      -
                      - Known Subclasses - -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. CheckPointSupport
                      2. Serializable
                      3. Serializable
                      4. AnyRef
                      5. Any
                      6. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - getOffsets(totalCount: Long, parallel: Int, checkPointPath: Option[String], checkPointNamePrefix: String): scala.List[Offset] - -

                        - - Permalink - - - -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      18. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CustomReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CustomReader.html deleted file mode 100644 index 0e894b4..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/CustomReader.html +++ /dev/null @@ -1,581 +0,0 @@ - - - - CustomReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.CustomReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      CustomReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - abstract - class - - - CustomReader extends FileBaseReader - -

                      - -

                      The CustomReader extend the FileBaseReader and support read text file from HDFS. -Transformation is a function convert a line into Row. -The structure of the row should be specified. -

                      - Linear Supertypes -
                      FileBaseReader, Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. CustomReader
                      2. FileBaseReader
                      3. Reader
                      4. Serializable
                      5. Serializable
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - CustomReader(session: SparkSession, customConfig: FileBaseSourceConfigEntry, transformation: (String) ⇒ org.apache.spark.sql.Row, filter: (org.apache.spark.sql.Row) ⇒ Boolean, structType: StructType) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        FileBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - val - - - path: String - -

                        - - Permalink - - -
                        Definition Classes
                        FileBaseReader
                        -
                      17. - - -

                        - - - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        CustomReaderReader
                        -
                      18. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        CustomReaderFileBaseReaderReader
                        -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      21. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from FileBaseReader

                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/FileBaseReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/FileBaseReader.html deleted file mode 100644 index eab3944..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/FileBaseReader.html +++ /dev/null @@ -1,583 +0,0 @@ - - - - FileBaseReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.FileBaseReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      FileBaseReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - abstract - class - - - FileBaseReader extends Reader - -

                      - -

                      The FileBaseReader is the abstract class for HDFS file reader. -

                      - Linear Supertypes -
                      Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. FileBaseReader
                      2. Reader
                      3. Serializable
                      4. Serializable
                      5. AnyRef
                      6. Any
                      7. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - FileBaseReader(session: SparkSession, path: String) - -

                        - - Permalink - - - -
                      -
                      - - - -
                      -

                      Abstract Value Members

                      -
                      1. - - -

                        - - abstract - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        Reader
                        -
                      -
                      - -
                      -

                      Concrete Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        FileBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - val - - - path: String - -

                        - - Permalink - - - -
                      17. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        FileBaseReaderReader
                        -
                      18. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      20. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HBaseReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HBaseReader.html deleted file mode 100644 index eba5e1c..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HBaseReader.html +++ /dev/null @@ -1,578 +0,0 @@ - - - - HBaseReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.HBaseReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      HBaseReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - - class - - - HBaseReader extends ServerBaseReader - -

                      - -

                      HBaseReader extends ServerBaseReader

                      - Linear Supertypes -
                      ServerBaseReader, Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. HBaseReader
                      2. ServerBaseReader
                      3. Reader
                      4. Serializable
                      5. Serializable
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - HBaseReader(session: SparkSession, hbaseConfig: HBaseSourceConfigEntry) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        HBaseReaderReader
                        -
                      17. - - -

                        - - - val - - - sentence: String - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseReader
                        -
                      18. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        HBaseReaderServerBaseReaderReader
                        -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      21. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from ServerBaseReader

                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HiveReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HiveReader.html deleted file mode 100644 index 19061a6..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/HiveReader.html +++ /dev/null @@ -1,579 +0,0 @@ - - - - HiveReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.HiveReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      HiveReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - - class - - - HiveReader extends ServerBaseReader - -

                      - -

                      HiveReader extends the @{link ServerBaseReader}. -The HiveReader reading data from Apache Hive via sentence.

                      - Linear Supertypes -
                      ServerBaseReader, Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. HiveReader
                      2. ServerBaseReader
                      3. Reader
                      4. Serializable
                      5. Serializable
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - HiveReader(session: SparkSession, hiveConfig: HiveSourceConfigEntry) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        HiveReaderReader
                        -
                      17. - - -

                        - - - val - - - sentence: String - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseReader
                        -
                      18. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        HiveReaderServerBaseReaderReader
                        -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      21. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from ServerBaseReader

                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JSONReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JSONReader.html deleted file mode 100644 index 70fc6bb..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JSONReader.html +++ /dev/null @@ -1,579 +0,0 @@ - - - - JSONReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.JSONReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      JSONReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - - class - - - JSONReader extends FileBaseReader - -

                      - -

                      The JSONReader extend the FileBaseReader and support read json file from HDFS. -

                      - Linear Supertypes -
                      FileBaseReader, Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. JSONReader
                      2. FileBaseReader
                      3. Reader
                      4. Serializable
                      5. Serializable
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - JSONReader(session: SparkSession, jsonConfig: FileBaseSourceConfigEntry) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        FileBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - val - - - path: String - -

                        - - Permalink - - -
                        Definition Classes
                        FileBaseReader
                        -
                      17. - - -

                        - - - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        JSONReaderReader
                        -
                      18. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        JSONReaderFileBaseReaderReader
                        -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      21. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from FileBaseReader

                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JanusGraphReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JanusGraphReader.html deleted file mode 100644 index e020cbd..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/JanusGraphReader.html +++ /dev/null @@ -1,597 +0,0 @@ - - - - JanusGraphReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.JanusGraphReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      JanusGraphReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - - class - - - JanusGraphReader extends ServerBaseReader with CheckPointSupport - -

                      - -

                      JanusGraphReader extends the link ServerBaseReader

                      - Linear Supertypes -
                      CheckPointSupport, ServerBaseReader, Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. JanusGraphReader
                      2. CheckPointSupport
                      3. ServerBaseReader
                      4. Reader
                      5. Serializable
                      6. Serializable
                      7. AnyRef
                      8. Any
                      9. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - JanusGraphReader(session: SparkSession, janusGraphConfig: JanusGraphSourceConfigEntry) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - getOffsets(totalCount: Long, parallel: Int, checkPointPath: Option[String], checkPointNamePrefix: String): scala.List[Offset] - -

                        - - Permalink - - -
                        Definition Classes
                        CheckPointSupport
                        -
                      12. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      13. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      14. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        JanusGraphReaderReader
                        -
                      18. - - -

                        - - - val - - - sentence: String - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseReader
                        -
                      19. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        JanusGraphReaderServerBaseReaderReader
                        -
                      20. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      21. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      22. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      24. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from CheckPointSupport

                      -
                      -

                      Inherited from ServerBaseReader

                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/KafkaReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/KafkaReader.html deleted file mode 100644 index 57d5c27..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/KafkaReader.html +++ /dev/null @@ -1,561 +0,0 @@ - - - - KafkaReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.KafkaReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      KafkaReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - - class - - - KafkaReader extends StreamingBaseReader - -

                      - -
                      - Linear Supertypes -
                      StreamingBaseReader, Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. KafkaReader
                      2. StreamingBaseReader
                      3. Reader
                      4. Serializable
                      5. Serializable
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - KafkaReader(session: SparkSession, kafkaConfig: KafkaSourceConfigEntry) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        StreamingBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        KafkaReaderReader
                        -
                      17. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        KafkaReaderStreamingBaseReaderReader
                        -
                      18. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      20. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from StreamingBaseReader

                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/MySQLReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/MySQLReader.html deleted file mode 100644 index 7c0b6de..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/MySQLReader.html +++ /dev/null @@ -1,580 +0,0 @@ - - - - MySQLReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.MySQLReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      MySQLReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - - class - - - MySQLReader extends ServerBaseReader - -

                      - -

                      The MySQLReader extends the ServerBaseReader. -The MySQLReader reading data from MySQL via sentence. -

                      - Linear Supertypes -
                      ServerBaseReader, Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. MySQLReader
                      2. ServerBaseReader
                      3. Reader
                      4. Serializable
                      5. Serializable
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - MySQLReader(session: SparkSession, mysqlConfig: MySQLSourceConfigEntry) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        MySQLReaderReader
                        -
                      17. - - -

                        - - - val - - - sentence: String - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseReader
                        -
                      18. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        MySQLReaderServerBaseReaderReader
                        -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      21. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from ServerBaseReader

                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/NebulaReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/NebulaReader.html deleted file mode 100644 index 05e7cdd..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/NebulaReader.html +++ /dev/null @@ -1,578 +0,0 @@ - - - - NebulaReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.NebulaReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      NebulaReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - - class - - - NebulaReader extends ServerBaseReader - -

                      - -
                      - Linear Supertypes -
                      ServerBaseReader, Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. NebulaReader
                      2. ServerBaseReader
                      3. Reader
                      4. Serializable
                      5. Serializable
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - NebulaReader(session: SparkSession, nebulaConfig: ServerDataSourceConfigEntry) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        NebulaReaderReader
                        -
                      17. - - -

                        - - - val - - - sentence: String - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseReader
                        -
                      18. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        NebulaReaderServerBaseReaderReader
                        -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      21. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from ServerBaseReader

                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Neo4JReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Neo4JReader.html deleted file mode 100644 index c7d3101..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Neo4JReader.html +++ /dev/null @@ -1,598 +0,0 @@ - - - - Neo4JReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.Neo4JReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      Neo4JReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - - class - - - Neo4JReader extends ServerBaseReader with CheckPointSupport - -

                      - -

                      Neo4JReader extends the ServerBaseReader -this reader support checkpoint by sacrificing performance

                      - Linear Supertypes -
                      CheckPointSupport, ServerBaseReader, Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. Neo4JReader
                      2. CheckPointSupport
                      3. ServerBaseReader
                      4. Reader
                      5. Serializable
                      6. Serializable
                      7. AnyRef
                      8. Any
                      9. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - Neo4JReader(session: SparkSession, neo4jConfig: Neo4JSourceConfigEntry) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - getOffsets(totalCount: Long, parallel: Int, checkPointPath: Option[String], checkPointNamePrefix: String): scala.List[Offset] - -

                        - - Permalink - - -
                        Definition Classes
                        CheckPointSupport
                        -
                      12. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      13. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      14. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        Neo4JReaderReader
                        -
                      18. - - -

                        - - - val - - - sentence: String - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseReader
                        -
                      19. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        Neo4JReaderServerBaseReaderReader
                        -
                      20. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      21. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      22. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      24. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from CheckPointSupport

                      -
                      -

                      Inherited from ServerBaseReader

                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ORCReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ORCReader.html deleted file mode 100644 index 3e0aa3b..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ORCReader.html +++ /dev/null @@ -1,579 +0,0 @@ - - - - ORCReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.ORCReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      ORCReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - - class - - - ORCReader extends FileBaseReader - -

                      - -

                      The ORCReader extend the FileBaseReader and support read orc file from HDFS. -

                      - Linear Supertypes -
                      FileBaseReader, Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. ORCReader
                      2. FileBaseReader
                      3. Reader
                      4. Serializable
                      5. Serializable
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - ORCReader(session: SparkSession, orcConfig: FileBaseSourceConfigEntry) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        FileBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - val - - - path: String - -

                        - - Permalink - - -
                        Definition Classes
                        FileBaseReader
                        -
                      17. - - -

                        - - - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        ORCReaderReader
                        -
                      18. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        ORCReaderFileBaseReaderReader
                        -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      21. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from FileBaseReader

                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ParquetReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ParquetReader.html deleted file mode 100644 index 3ca9f40..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ParquetReader.html +++ /dev/null @@ -1,579 +0,0 @@ - - - - ParquetReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.ParquetReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      ParquetReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - - class - - - ParquetReader extends FileBaseReader - -

                      - -

                      The ParquetReader extend the FileBaseReader and support read parquet file from HDFS. -

                      - Linear Supertypes -
                      FileBaseReader, Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. ParquetReader
                      2. FileBaseReader
                      3. Reader
                      4. Serializable
                      5. Serializable
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - ParquetReader(session: SparkSession, parquetConfig: FileBaseSourceConfigEntry) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        FileBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - val - - - path: String - -

                        - - Permalink - - -
                        Definition Classes
                        FileBaseReader
                        -
                      17. - - -

                        - - - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        ParquetReaderReader
                        -
                      18. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        ParquetReaderFileBaseReaderReader
                        -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      21. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from FileBaseReader

                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/PulsarReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/PulsarReader.html deleted file mode 100644 index b903cc9..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/PulsarReader.html +++ /dev/null @@ -1,561 +0,0 @@ - - - - PulsarReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.PulsarReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      PulsarReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - - class - - - PulsarReader extends StreamingBaseReader - -

                      - -
                      - Linear Supertypes -
                      StreamingBaseReader, Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. PulsarReader
                      2. StreamingBaseReader
                      3. Reader
                      4. Serializable
                      5. Serializable
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - PulsarReader(session: SparkSession, pulsarConfig: PulsarSourceConfigEntry) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        StreamingBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        PulsarReaderReader
                        -
                      17. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        PulsarReaderStreamingBaseReaderReader
                        -
                      18. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      20. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from StreamingBaseReader

                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Reader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Reader.html deleted file mode 100644 index 89e021f..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/Reader.html +++ /dev/null @@ -1,544 +0,0 @@ - - - - Reader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.Reader - - - - - - - - - - - - - - - -
                      - Trait -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      Reader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - - trait - - - Reader extends Serializable - -

                      - -

                      The Reader is used for create a DataFrame from the source. Such as Hive or HDFS. -

                      - Linear Supertypes -
                      Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. Reader
                      2. Serializable
                      3. Serializable
                      4. AnyRef
                      5. Any
                      6. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - -
                      -

                      Abstract Value Members

                      -
                      1. - - -

                        - - abstract - def - - - close(): Unit - -

                        - - Permalink - - - -
                      2. - - -

                        - - abstract - def - - - read(): DataFrame - -

                        - - Permalink - - - -
                      3. - - -

                        - - abstract - def - - - session: SparkSession - -

                        - - Permalink - - - -
                      -
                      - -
                      -

                      Concrete Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ServerBaseReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ServerBaseReader.html deleted file mode 100644 index d4e39fc..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/ServerBaseReader.html +++ /dev/null @@ -1,583 +0,0 @@ - - - - ServerBaseReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.ServerBaseReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      ServerBaseReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - abstract - class - - - ServerBaseReader extends Reader - -

                      - -

                      ServerBaseReader is the abstract class of -It include a spark session and a sentence which will sent to service.

                      - Linear Supertypes -
                      Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. ServerBaseReader
                      2. Reader
                      3. Serializable
                      4. Serializable
                      5. AnyRef
                      6. Any
                      7. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - ServerBaseReader(session: SparkSession, sentence: String) - -

                        - - Permalink - - - -
                      -
                      - - - -
                      -

                      Abstract Value Members

                      -
                      1. - - -

                        - - abstract - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        Reader
                        -
                      -
                      - -
                      -

                      Concrete Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - val - - - sentence: String - -

                        - - Permalink - - - -
                      17. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseReaderReader
                        -
                      18. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      20. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/StreamingBaseReader.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/StreamingBaseReader.html deleted file mode 100644 index 6382ee1..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/StreamingBaseReader.html +++ /dev/null @@ -1,566 +0,0 @@ - - - - StreamingBaseReader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader.StreamingBaseReader - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.reader

                      -

                      StreamingBaseReader

                      Related Doc: - package reader -

                      - - Permalink - - -
                      - -

                      - - abstract - class - - - StreamingBaseReader extends Reader - -

                      - -

                      Spark Streaming -

                      - Linear Supertypes -
                      Reader, Serializable, Serializable, AnyRef, Any
                      -
                      - Known Subclasses - -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. StreamingBaseReader
                      2. Reader
                      3. Serializable
                      4. Serializable
                      5. AnyRef
                      6. Any
                      7. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - StreamingBaseReader(session: SparkSession) - -

                        - - Permalink - - - -
                      -
                      - - - -
                      -

                      Abstract Value Members

                      -
                      1. - - -

                        - - abstract - def - - - read(): DataFrame - -

                        - - Permalink - - -
                        Definition Classes
                        Reader
                        -
                      -
                      - -
                      -

                      Concrete Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        StreamingBaseReaderReader
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - val - - - session: SparkSession - -

                        - - Permalink - - -
                        Definition Classes
                        StreamingBaseReaderReader
                        -
                      17. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      19. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Reader

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/package.html deleted file mode 100644 index 7b3f8d4..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/reader/package.html +++ /dev/null @@ -1,419 +0,0 @@ - - - - reader - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.reader - - - - - - - - - - - - - - - -
                      - Package -

                      com.vesoft.nebula.tools.importer

                      -

                      reader

                      - - Permalink - - -
                      - -

                      - - - package - - - reader - -

                      - -
                      - - -
                      -
                      - - -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - -
                      -

                      Type Members

                      -
                      1. - - -

                        - - - class - - - CSVReader extends FileBaseReader - -

                        - - Permalink - - -

                        The CSVReader extend the FileBaseReader and support read csv file from HDFS.

                        The CSVReader extend the FileBaseReader and support read csv file from HDFS. -All types of the structure are StringType. -

                        -
                      2. - - -

                        - - - trait - - - CheckPointSupport extends Serializable - -

                        - - Permalink - - - -
                      3. - - -

                        - - abstract - class - - - CustomReader extends FileBaseReader - -

                        - - Permalink - - -

                        The CustomReader extend the FileBaseReader and support read text file from HDFS.

                        The CustomReader extend the FileBaseReader and support read text file from HDFS. -Transformation is a function convert a line into Row. -The structure of the row should be specified. -

                        -
                      4. - - -

                        - - abstract - class - - - FileBaseReader extends Reader - -

                        - - Permalink - - -

                        The FileBaseReader is the abstract class for HDFS file reader.

                        -
                      5. - - -

                        - - - class - - - HBaseReader extends ServerBaseReader - -

                        - - Permalink - - -

                        HBaseReader extends ServerBaseReader

                        -
                      6. - - -

                        - - - class - - - HiveReader extends ServerBaseReader - -

                        - - Permalink - - -

                        HiveReader extends the @{link ServerBaseReader}.

                        HiveReader extends the @{link ServerBaseReader}. -The HiveReader reading data from Apache Hive via sentence.

                        -
                      7. - - -

                        - - - class - - - JSONReader extends FileBaseReader - -

                        - - Permalink - - -

                        The JSONReader extend the FileBaseReader and support read json file from HDFS.

                        -
                      8. - - -

                        - - - class - - - JanusGraphReader extends ServerBaseReader with CheckPointSupport - -

                        - - Permalink - - -

                        JanusGraphReader extends the link ServerBaseReader

                        -
                      9. - - -

                        - - - class - - - KafkaReader extends StreamingBaseReader - -

                        - - Permalink - - -

                        -
                      10. - - -

                        - - - class - - - MySQLReader extends ServerBaseReader - -

                        - - Permalink - - -

                        The MySQLReader extends the ServerBaseReader.

                        The MySQLReader extends the ServerBaseReader. -The MySQLReader reading data from MySQL via sentence. -

                        -
                      11. - - -

                        - - - class - - - NebulaReader extends ServerBaseReader - -

                        - - Permalink - - -

                        -
                      12. - - -

                        - - - class - - - Neo4JReader extends ServerBaseReader with CheckPointSupport - -

                        - - Permalink - - -

                        Neo4JReader extends the ServerBaseReader -this reader support checkpoint by sacrificing performance

                        -
                      13. - - -

                        - - - class - - - ORCReader extends FileBaseReader - -

                        - - Permalink - - -

                        The ORCReader extend the FileBaseReader and support read orc file from HDFS.

                        -
                      14. - - -

                        - - - class - - - ParquetReader extends FileBaseReader - -

                        - - Permalink - - -

                        The ParquetReader extend the FileBaseReader and support read parquet file from HDFS.

                        -
                      15. - - -

                        - - - class - - - PulsarReader extends StreamingBaseReader - -

                        - - Permalink - - -

                        -
                      16. - - -

                        - - - trait - - - Reader extends Serializable - -

                        - - Permalink - - -

                        The Reader is used for create a DataFrame from the source.

                        The Reader is used for create a DataFrame from the source. Such as Hive or HDFS. -

                        -
                      17. - - -

                        - - abstract - class - - - ServerBaseReader extends Reader - -

                        - - Permalink - - -

                        ServerBaseReader is the abstract class of -It include a spark session and a sentence which will sent to service.

                        -
                      18. - - -

                        - - abstract - class - - - StreamingBaseReader extends Reader - -

                        - - Permalink - - -

                        Spark Streaming -

                        -
                      -
                      - - - - - - - - -
                      - -
                      - - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/HDFSUtils$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/HDFSUtils$.html deleted file mode 100644 index 91399b5..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/HDFSUtils$.html +++ /dev/null @@ -1,584 +0,0 @@ - - - - HDFSUtils - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.utils.HDFSUtils - - - - - - - - - - - - - - - -
                      - Object -

                      com.vesoft.nebula.tools.importer.utils

                      -

                      HDFSUtils

                      Related Doc: - package utils -

                      - - Permalink - - -
                      - -

                      - - - object - - - HDFSUtils - -

                      - -
                      - Linear Supertypes -
                      AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. HDFSUtils
                      2. AnyRef
                      3. Any
                      4. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - exists(path: String): Boolean - -

                        - - Permalink - - - -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - getContent(path: String): String - -

                        - - Permalink - - - -
                      12. - - -

                        - - - def - - - getFileSystem(): FileSystem - -

                        - - Permalink - - - -
                      13. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      14. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      15. - - -

                        - - - def - - - list(path: String): scala.List[String] - -

                        - - Permalink - - - -
                      16. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - - def - - - saveContent(path: String, content: String, charset: Charset = Charset.defaultCharset()): Unit - -

                        - - Permalink - - - -
                      20. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      21. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      22. - - -

                        - - - def - - - upload(localPath: String, remotePath: String): Unit - -

                        - - Permalink - - - -
                      23. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      24. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      25. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/KafkaUtils$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/KafkaUtils$.html deleted file mode 100644 index 6223ae3..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/KafkaUtils$.html +++ /dev/null @@ -1,516 +0,0 @@ - - - - KafkaUtils - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.utils.KafkaUtils - - - - - - - - - - - - - - - -
                      - Object -

                      com.vesoft.nebula.tools.importer.utils

                      -

                      KafkaUtils

                      Related Doc: - package utils -

                      - - Permalink - - -
                      - -

                      - - - object - - - KafkaUtils - -

                      - -
                      - Linear Supertypes -
                      AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. KafkaUtils
                      2. AnyRef
                      3. Any
                      4. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - - def - - - writeEdge(edges: Edge*): Unit - -

                        - - Permalink - - - -
                      21. - - -

                        - - - def - - - writeVertices(vertices: Vertex*): Unit - -

                        - - Permalink - - - -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/NebulaUtils$.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/NebulaUtils$.html deleted file mode 100644 index a432852..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/NebulaUtils$.html +++ /dev/null @@ -1,550 +0,0 @@ - - - - NebulaUtils - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.utils.NebulaUtils - - - - - - - - - - - - - - - -
                      - Object -

                      com.vesoft.nebula.tools.importer.utils

                      -

                      NebulaUtils

                      Related Doc: - package utils -

                      - - Permalink - - -
                      - -

                      - - - object - - - NebulaUtils - -

                      - -
                      - Linear Supertypes -
                      AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. NebulaUtils
                      2. AnyRef
                      3. Any
                      4. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - getDataFrameValue(value: String, dataType: DataType): Any - -

                        - - Permalink - - - -
                      11. - - -

                        - - - def - - - getDataSourceFieldType(sourceConfig: SchemaConfigEntry, space: String, metaProvider: MetaProvider): scala.Predef.Map[String, Int] - -

                        - - Permalink - - - -
                      12. - - -

                        - - - def - - - getDataType(clazz: Class[_]): DataType - -

                        - - Permalink - - - -
                      13. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      14. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      15. - - -

                        - - - def - - - isNumic(str: String): Boolean - -

                        - - Permalink - - - -
                      16. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      21. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/package.html deleted file mode 100644 index 70dddda..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/utils/package.html +++ /dev/null @@ -1,152 +0,0 @@ - - - - utils - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.utils - - - - - - - - - - - - - - - -
                      - Package -

                      com.vesoft.nebula.tools.importer

                      -

                      utils

                      - - Permalink - - -
                      - -

                      - - - package - - - utils - -

                      - -
                      - - -
                      -
                      - - -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - - object - - - HDFSUtils - -

                        - - Permalink - - - -
                      2. - - -

                        - - - object - - - KafkaUtils - -

                        - - Permalink - - - -
                      3. - - -

                        - - - object - - - NebulaUtils - -

                        - - Permalink - - - -
                      -
                      - - - - -
                      - -
                      - - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaGraphClientWriter.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaGraphClientWriter.html deleted file mode 100644 index 9b0ba02..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaGraphClientWriter.html +++ /dev/null @@ -1,646 +0,0 @@ - - - - NebulaGraphClientWriter - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.writer.NebulaGraphClientWriter - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.writer

                      -

                      NebulaGraphClientWriter

                      Related Doc: - package writer -

                      - - Permalink - - -
                      - -

                      - - - class - - - NebulaGraphClientWriter extends ServerBaseWriter - -

                      - -
                      - Linear Supertypes -
                      ServerBaseWriter, Writer, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. NebulaGraphClientWriter
                      2. ServerBaseWriter
                      3. Writer
                      4. Serializable
                      5. Serializable
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - NebulaGraphClientWriter(dataBaseConfigEntry: DataBaseConfigEntry, userConfigEntry: UserConfigEntry, connectionConfigEntry: ConnectionConfigEntry, executionRetry: Int, rateConfig: RateConfigEntry, config: SchemaConfigEntry, graphProvider: GraphProvider) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        NebulaGraphClientWriterWriter
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - prepare(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        NebulaGraphClientWriterWriter
                        -
                      17. - - -

                        - - - val - - - rateLimiter: RateLimiter - -

                        - - Permalink - - - -
                      18. - - -

                        - - - val - - - session: Session - -

                        - - Permalink - - - -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - def - - - toExecuteSentence(name: String, edges: Edges): String - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseWriter
                        -
                      21. - - -

                        - - - def - - - toExecuteSentence(name: String, vertices: Vertices): String - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseWriter
                        -
                      22. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      23. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      24. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      25. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      26. - - -

                        - - - def - - - writeEdges(edges: Edges): String - -

                        - - Permalink - - - -
                      27. - - -

                        - - - def - - - writeVertices(vertices: Vertices): String - -

                        - - Permalink - - - -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from ServerBaseWriter

                      -
                      -

                      Inherited from Writer

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaSSTWriter.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaSSTWriter.html deleted file mode 100644 index 62c34ea..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaSSTWriter.html +++ /dev/null @@ -1,610 +0,0 @@ - - - - NebulaSSTWriter - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.writer.NebulaSSTWriter - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.writer

                      -

                      NebulaSSTWriter

                      Related Doc: - package writer -

                      - - Permalink - - -
                      - -

                      - - - class - - - NebulaSSTWriter extends Writer - -

                      - -
                      - Linear Supertypes -
                      Writer, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. NebulaSSTWriter
                      2. Writer
                      3. Serializable
                      4. Serializable
                      5. AnyRef
                      6. Any
                      7. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - NebulaSSTWriter(path: String) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        NebulaSSTWriterWriter
                        -
                      7. - - -

                        - - - val - - - env: EnvOptions - -

                        - - Permalink - - - -
                      8. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      9. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      11. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      13. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      14. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      17. - - -

                        - - - val - - - options: Options - -

                        - - Permalink - - - -
                      18. - - -

                        - - - def - - - prepare(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        NebulaSSTWriterWriter
                        -
                      19. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      20. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      21. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      24. - - -

                        - - - def - - - write(key: Array[Byte], value: Array[Byte]): Unit - -

                        - - Permalink - - - -
                      25. - - -

                        - - - var - - - writer: SstFileWriter - -

                        - - Permalink - - - -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Writer

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaStorageClientWriter.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaStorageClientWriter.html deleted file mode 100644 index 44a2e96..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaStorageClientWriter.html +++ /dev/null @@ -1,629 +0,0 @@ - - - - NebulaStorageClientWriter - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.writer.NebulaStorageClientWriter - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.writer

                      -

                      NebulaStorageClientWriter

                      Related Doc: - package writer -

                      - - Permalink - - -
                      - -

                      - - - class - - - NebulaStorageClientWriter extends ServerBaseWriter - -

                      - -
                      - Linear Supertypes -
                      ServerBaseWriter, Writer, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. NebulaStorageClientWriter
                      2. ServerBaseWriter
                      3. Writer
                      4. Serializable
                      5. Serializable
                      6. AnyRef
                      7. Any
                      8. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - NebulaStorageClientWriter(host: String, port: Int, space: String) - -

                        - - Permalink - - - -
                      2. - - -

                        - - - new - - - NebulaStorageClientWriter(addresses: scala.List[(String, Int)], space: String) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        NebulaStorageClientWriterWriter
                        -
                      7. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      8. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      9. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      10. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      12. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      13. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - prepare(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        NebulaStorageClientWriterWriter
                        -
                      17. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - - def - - - toExecuteSentence(name: String, edges: Edges): String - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseWriter
                        -
                      19. - - -

                        - - - def - - - toExecuteSentence(name: String, vertices: Vertices): String - -

                        - - Permalink - - -
                        Definition Classes
                        ServerBaseWriter
                        -
                      20. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      21. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      22. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      23. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      24. - - -

                        - - - def - - - writeEdges(edges: Edges): String - -

                        - - Permalink - - - -
                      25. - - -

                        - - - def - - - writeVertices(vertices: Vertices): String - -

                        - - Permalink - - - -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from ServerBaseWriter

                      -
                      -

                      Inherited from Writer

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaWriterCallback.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaWriterCallback.html deleted file mode 100644 index 96ebbc7..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/NebulaWriterCallback.html +++ /dev/null @@ -1,538 +0,0 @@ - - - - NebulaWriterCallback - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.writer.NebulaWriterCallback - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.writer

                      -

                      NebulaWriterCallback

                      Related Doc: - package writer -

                      - - Permalink - - -
                      - -

                      - - - class - - - NebulaWriterCallback extends FutureCallback[java.util.List[Optional[Integer]]] - -

                      - -
                      - Linear Supertypes -
                      FutureCallback[java.util.List[Optional[Integer]]], AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. NebulaWriterCallback
                      2. FutureCallback
                      3. AnyRef
                      4. Any
                      5. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - NebulaWriterCallback(latch: CountDownLatch, batchSuccess: LongAccumulator, batchFailure: LongAccumulator, pathAndOffset: Option[(String, Long)]) - -

                        - - Permalink - - - -
                      -
                      - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - - def - - - onFailure(t: Throwable): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        NebulaWriterCallback → FutureCallback
                        -
                      16. - - -

                        - - - def - - - onSuccess(results: java.util.List[Optional[Integer]]): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        NebulaWriterCallback → FutureCallback
                        -
                      17. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      18. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      19. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from FutureCallback[java.util.List[Optional[Integer]]]

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.html deleted file mode 100644 index 22804b7..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.html +++ /dev/null @@ -1,616 +0,0 @@ - - - - ServerBaseWriter - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.writer.ServerBaseWriter - - - - - - - - - - - - - - - -
                      - Class -

                      com.vesoft.nebula.tools.importer.writer

                      -

                      ServerBaseWriter

                      Related Doc: - package writer -

                      - - Permalink - - -
                      - -

                      - - abstract - class - - - ServerBaseWriter extends Writer - -

                      - -
                      - Linear Supertypes -
                      Writer, Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. ServerBaseWriter
                      2. Writer
                      3. Serializable
                      4. Serializable
                      5. AnyRef
                      6. Any
                      7. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      -
                      -

                      Instance Constructors

                      -
                      1. - - -

                        - - - new - - - ServerBaseWriter() - -

                        - - Permalink - - - -
                      -
                      - - - -
                      -

                      Abstract Value Members

                      -
                      1. - - -

                        - - abstract - def - - - close(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        Writer
                        -
                      2. - - -

                        - - abstract - def - - - prepare(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        Writer
                        -
                      3. - - -

                        - - abstract - def - - - writeEdges(edges: Edges): String - -

                        - - Permalink - - - -
                      4. - - -

                        - - abstract - def - - - writeVertices(vertices: Vertices): String - -

                        - - Permalink - - - -
                      -
                      - -
                      -

                      Concrete Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - toExecuteSentence(name: String, edges: Edges): String - -

                        - - Permalink - - - -
                      17. - - -

                        - - - def - - - toExecuteSentence(name: String, vertices: Vertices): String - -

                        - - Permalink - - - -
                      18. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      19. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      20. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      21. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Writer

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/Writer.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/Writer.html deleted file mode 100644 index a97d214..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/Writer.html +++ /dev/null @@ -1,526 +0,0 @@ - - - - Writer - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.writer.Writer - - - - - - - - - - - - - - - -
                      - Trait -

                      com.vesoft.nebula.tools.importer.writer

                      -

                      Writer

                      Related Doc: - package writer -

                      - - Permalink - - -
                      - -

                      - - - trait - - - Writer extends Serializable - -

                      - -
                      - Linear Supertypes -
                      Serializable, Serializable, AnyRef, Any
                      -
                      - - -
                      -
                      -
                      - Ordering -
                        - -
                      1. Alphabetic
                      2. -
                      3. By Inheritance
                      4. -
                      -
                      -
                      - Inherited
                      -
                      -
                        -
                      1. Writer
                      2. Serializable
                      3. Serializable
                      4. AnyRef
                      5. Any
                      6. -
                      -
                      - -
                        -
                      1. Hide All
                      2. -
                      3. Show All
                      4. -
                      -
                      -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - -
                      -

                      Abstract Value Members

                      -
                      1. - - -

                        - - abstract - def - - - close(): Unit - -

                        - - Permalink - - - -
                      2. - - -

                        - - abstract - def - - - prepare(): Unit - -

                        - - Permalink - - - -
                      -
                      - -
                      -

                      Concrete Value Members

                      -
                      1. - - -

                        - - final - def - - - !=(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      2. - - -

                        - - final - def - - - ##(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      3. - - -

                        - - final - def - - - ==(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      4. - - -

                        - - final - def - - - asInstanceOf[T0]: T0 - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      5. - - -

                        - - - def - - - clone(): AnyRef - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      6. - - -

                        - - final - def - - - eq(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      7. - - -

                        - - - def - - - equals(arg0: Any): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      8. - - -

                        - - - def - - - finalize(): Unit - -

                        - - Permalink - - -
                        Attributes
                        protected[java.lang]
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - classOf[java.lang.Throwable] - ) - -
                        -
                      9. - - -

                        - - final - def - - - getClass(): Class[_] - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      10. - - -

                        - - - def - - - hashCode(): Int - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      11. - - -

                        - - final - def - - - isInstanceOf[T0]: Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        Any
                        -
                      12. - - -

                        - - final - def - - - ne(arg0: AnyRef): Boolean - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      13. - - -

                        - - final - def - - - notify(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      14. - - -

                        - - final - def - - - notifyAll(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      15. - - -

                        - - final - def - - - synchronized[T0](arg0: ⇒ T0): T0 - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        -
                      16. - - -

                        - - - def - - - toString(): String - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef → Any
                        -
                      17. - - -

                        - - final - def - - - wait(): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      18. - - -

                        - - final - def - - - wait(arg0: Long, arg1: Int): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      19. - - -

                        - - final - def - - - wait(arg0: Long): Unit - -

                        - - Permalink - - -
                        Definition Classes
                        AnyRef
                        Annotations
                        - @throws( - - ... - ) - -
                        -
                      -
                      - - - - -
                      - -
                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from Serializable

                      -
                      -

                      Inherited from AnyRef

                      -
                      -

                      Inherited from Any

                      -
                      - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/package.html deleted file mode 100644 index e53d1fa..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/importer/writer/package.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - writer - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools.importer.writer - - - - - - - - - - - - - - - -
                      - Package -

                      com.vesoft.nebula.tools.importer

                      -

                      writer

                      - - Permalink - - -
                      - -

                      - - - package - - - writer - -

                      - -
                      - - -
                      -
                      - - -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - -
                      -

                      Type Members

                      -
                      1. - - -

                        - - - class - - - NebulaGraphClientWriter extends ServerBaseWriter - -

                        - - Permalink - - -

                        -
                      2. - - -

                        - - - class - - - NebulaSSTWriter extends Writer - -

                        - - Permalink - - -

                        -
                      3. - - -

                        - - - class - - - NebulaStorageClientWriter extends ServerBaseWriter - -

                        - - Permalink - - -

                        -
                      4. - - -

                        - - - class - - - NebulaWriterCallback extends FutureCallback[java.util.List[Optional[Integer]]] - -

                        - - Permalink - - - -
                      5. - - -

                        - - abstract - class - - - ServerBaseWriter extends Writer - -

                        - - Permalink - - - -
                      6. - - -

                        - - - trait - - - Writer extends Serializable - -

                        - - Permalink - - -

                        -
                      -
                      - - - - - - - - -
                      - -
                      - - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/package.html deleted file mode 100644 index 2511f7f..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/nebula/tools/package.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - tools - nebula-exchange 2.0.0 API - com.vesoft.nebula.tools - - - - - - - - - - - - - - - -
                      - Package -

                      com.vesoft.nebula

                      -

                      tools

                      - - Permalink - - -
                      - -

                      - - - package - - - tools - -

                      - -
                      - - -
                      -
                      - - -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - - package - - - importer - -

                        - - Permalink - - - -
                      -
                      - - - - -
                      - -
                      - - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/com/vesoft/package.html b/nebula-exchange/target/site/scaladocs/com/vesoft/package.html deleted file mode 100644 index b7cbd41..0000000 --- a/nebula-exchange/target/site/scaladocs/com/vesoft/package.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - vesoft - nebula-exchange 2.0.0 API - com.vesoft - - - - - - - - - - - - - - - -
                      - Package -

                      com

                      -

                      vesoft

                      - - Permalink - - -
                      - -

                      - - - package - - - vesoft - -

                      - -
                      - - -
                      -
                      - - -
                      - Visibility -
                      1. Public
                      2. All
                      -
                      -
                      - -
                      -
                      - - - - - - -
                      -

                      Value Members

                      -
                      1. - - -

                        - - - package - - - nebula - -

                        - - Permalink - - - -
                      -
                      - - - - -
                      - -
                      - - -
                      - -
                      -
                      -

                      Ungrouped

                      - -
                      -
                      - -
                      - -
                      - - - - - - diff --git a/nebula-exchange/target/site/scaladocs/index.html b/nebula-exchange/target/site/scaladocs/index.html deleted file mode 100644 index 9775439..0000000 --- a/nebula-exchange/target/site/scaladocs/index.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - - - - - - -
                      - class icon - trait icon - trait icon - trait icon -
                      -
                      -
                      -
                      -
                      -
                      #ABCDEFGHIJKLMNOPQRSTUVWXYZdeprecated
                      -
                      -
                      - -
                        -
                        1. - com -
                            -
                            1. - com.vesoft -
                                -
                                1. - com.vesoft.nebula -
                                    -
                                    1. - com.vesoft.nebula.tools -
                                        -
                                        1. - com.vesoft.nebula.tools.importer -
                                          1. (case class)Argument
                                          2. (object)
                                            CheckPointHandler
                                          3. (case class)Edge
                                          4. (case class)Edges
                                          5. (object)
                                            ErrorHandler
                                          6. (object)
                                            Exchange
                                          7. (class)GraphProvider
                                          8. (object)
                                            KeyPolicy
                                          9. (class)MetaProvider
                                          10. (case class)Offset
                                          11. (case class)TooManyErrorsException
                                          12. (case class)Vertex
                                          13. (case class)Vertices
                                          14. (object)
                                            VidType
                                          -
                                          1. - com.vesoft.nebula.tools.importer.config -
                                            1. (object)(case class)Configs
                                            2. (case class)ConnectionConfigEntry
                                            3. (case class)DataBaseConfigEntry
                                            4. (trait)DataSinkConfigEntry
                                            5. (trait)DataSourceConfigEntry
                                            6. (case class)EdgeConfigEntry
                                            7. (case class)ErrorConfigEntry
                                            8. (case class)ExecutionConfigEntry
                                            9. (case class)FileBaseSinkConfigEntry
                                            10. (case class)FileBaseSourceConfigEntry
                                            11. (trait)FileDataSourceConfigEntry
                                            12. (case class)HBaseSourceConfigEntry
                                            13. (case class)HiveConfigEntry
                                            14. (case class)HiveSourceConfigEntry
                                            15. (case class)JanusGraphSourceConfigEntry
                                            16. (case class)KafkaSourceConfigEntry
                                            17. (case class)MySQLSourceConfigEntry
                                            18. (case class)NebulaSinkConfigEntry
                                            19. (case class)Neo4JSourceConfigEntry
                                            20. (case class)PulsarSourceConfigEntry
                                            21. (case class)RateConfigEntry
                                            22. (trait)SchemaConfigEntry
                                            23. (trait)ServerDataSourceConfigEntry
                                            24. (object)(class)SinkCategory
                                            25. (object)(class)SourceCategory
                                            26. (object)(case class)SparkConfigEntry
                                            27. (trait)StreamingDataSourceConfigEntry
                                            28. (case class)TagConfigEntry
                                            29. (object)
                                              Type
                                            30. (case class)UserConfigEntry
                                            -
                                            -
                                          2. - com.vesoft.nebula.tools.importer.processor -
                                            1. (class)EdgeProcessor
                                            2. (trait)Processor
                                            3. (class)ReloadProcessor
                                            4. (class)VerticesProcessor
                                            -
                                            -
                                          3. - com.vesoft.nebula.tools.importer.reader -
                                            1. (trait)CheckPointSupport
                                            2. (class)CSVReader
                                            3. (class)CustomReader
                                            4. (class)FileBaseReader
                                            5. (class)HBaseReader
                                            6. (class)HiveReader
                                            7. (class)JanusGraphReader
                                            8. (class)JSONReader
                                            9. (class)KafkaReader
                                            10. (class)MySQLReader
                                            11. (class)NebulaReader
                                            12. (class)Neo4JReader
                                            13. (class)ORCReader
                                            14. (class)ParquetReader
                                            15. (class)PulsarReader
                                            16. (trait)Reader
                                            17. (class)ServerBaseReader
                                            18. (class)StreamingBaseReader
                                            -
                                            -
                                          4. - com.vesoft.nebula.tools.importer.utils -
                                            1. (object)
                                              HDFSUtils
                                            2. (object)
                                              KafkaUtils
                                            3. (object)
                                              NebulaUtils
                                            -
                                            -
                                          5. - com.vesoft.nebula.tools.importer.writer -
                                            1. (class)NebulaGraphClientWriter
                                            2. (class)NebulaSSTWriter
                                            3. (class)NebulaStorageClientWriter
                                            4. (class)NebulaWriterCallback
                                            5. (class)ServerBaseWriter
                                            6. (trait)Writer
                                            -
                                            -
                                          -
                                        -
                                      -
                                    -
                                  -
                                -
                                -
                                -
                                - -
                                - - diff --git a/nebula-exchange/target/site/scaladocs/index.js b/nebula-exchange/target/site/scaladocs/index.js deleted file mode 100644 index e8cf3e3..0000000 --- a/nebula-exchange/target/site/scaladocs/index.js +++ /dev/null @@ -1 +0,0 @@ -Index.PACKAGES = {"com.vesoft.nebula" : [], "com.vesoft.nebula.tools.importer.reader" : [{"trait" : "com\/vesoft\/nebula\/tools\/importer\/reader\/CheckPointSupport.html", "name" : "com.vesoft.nebula.tools.importer.reader.CheckPointSupport"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/CSVReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.CSVReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/CustomReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.CustomReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/FileBaseReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.FileBaseReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/HBaseReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.HBaseReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/HiveReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.HiveReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/JanusGraphReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.JanusGraphReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/JSONReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.JSONReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/KafkaReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.KafkaReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/MySQLReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.MySQLReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/NebulaReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.NebulaReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/Neo4JReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.Neo4JReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/ORCReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.ORCReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/ParquetReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.ParquetReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/PulsarReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.PulsarReader"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/reader\/Reader.html", "name" : "com.vesoft.nebula.tools.importer.reader.Reader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/ServerBaseReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.ServerBaseReader"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/reader\/StreamingBaseReader.html", "name" : "com.vesoft.nebula.tools.importer.reader.StreamingBaseReader"}], "com.vesoft.nebula.tools.importer.utils" : [{"object" : "com\/vesoft\/nebula\/tools\/importer\/utils\/HDFSUtils$.html", "name" : "com.vesoft.nebula.tools.importer.utils.HDFSUtils"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/utils\/KafkaUtils$.html", "name" : "com.vesoft.nebula.tools.importer.utils.KafkaUtils"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/utils\/NebulaUtils$.html", "name" : "com.vesoft.nebula.tools.importer.utils.NebulaUtils"}], "com.vesoft.nebula.tools" : [], "com.vesoft.nebula.tools.importer.writer" : [{"class" : "com\/vesoft\/nebula\/tools\/importer\/writer\/NebulaGraphClientWriter.html", "name" : "com.vesoft.nebula.tools.importer.writer.NebulaGraphClientWriter"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/writer\/NebulaSSTWriter.html", "name" : "com.vesoft.nebula.tools.importer.writer.NebulaSSTWriter"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/writer\/NebulaStorageClientWriter.html", "name" : "com.vesoft.nebula.tools.importer.writer.NebulaStorageClientWriter"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/writer\/NebulaWriterCallback.html", "name" : "com.vesoft.nebula.tools.importer.writer.NebulaWriterCallback"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/writer\/ServerBaseWriter.html", "name" : "com.vesoft.nebula.tools.importer.writer.ServerBaseWriter"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/writer\/Writer.html", "name" : "com.vesoft.nebula.tools.importer.writer.Writer"}], "com.vesoft" : [], "com.vesoft.nebula.tools.importer.config" : [{"object" : "com\/vesoft\/nebula\/tools\/importer\/config\/Configs$.html", "case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/Configs.html", "name" : "com.vesoft.nebula.tools.importer.config.Configs"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/ConnectionConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.ConnectionConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/DataBaseConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.DataBaseConfigEntry"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/config\/DataSinkConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.DataSinkConfigEntry"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/config\/DataSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.DataSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/EdgeConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.EdgeConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/ErrorConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.ErrorConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/ExecutionConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.ExecutionConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/FileBaseSinkConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.FileBaseSinkConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/FileBaseSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.FileBaseSourceConfigEntry"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/config\/FileDataSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.FileDataSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/HBaseSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.HBaseSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/HiveConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.HiveConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/HiveSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.HiveSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/JanusGraphSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.JanusGraphSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/KafkaSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.KafkaSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/MySQLSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.MySQLSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/NebulaSinkConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.NebulaSinkConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/Neo4JSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.Neo4JSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/PulsarSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.PulsarSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/RateConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.RateConfigEntry"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/config\/SchemaConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.SchemaConfigEntry"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/config\/ServerDataSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.ServerDataSourceConfigEntry"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/config\/SinkCategory.html", "object" : "com\/vesoft\/nebula\/tools\/importer\/config\/SinkCategory$.html", "name" : "com.vesoft.nebula.tools.importer.config.SinkCategory"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/config\/SourceCategory.html", "object" : "com\/vesoft\/nebula\/tools\/importer\/config\/SourceCategory$.html", "name" : "com.vesoft.nebula.tools.importer.config.SourceCategory"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/SparkConfigEntry.html", "object" : "com\/vesoft\/nebula\/tools\/importer\/config\/SparkConfigEntry$.html", "name" : "com.vesoft.nebula.tools.importer.config.SparkConfigEntry"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/config\/StreamingDataSourceConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.StreamingDataSourceConfigEntry"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/TagConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.TagConfigEntry"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/config\/Type$.html", "name" : "com.vesoft.nebula.tools.importer.config.Type"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/config\/UserConfigEntry.html", "name" : "com.vesoft.nebula.tools.importer.config.UserConfigEntry"}], "com.vesoft.nebula.tools.importer.processor" : [{"class" : "com\/vesoft\/nebula\/tools\/importer\/processor\/EdgeProcessor.html", "name" : "com.vesoft.nebula.tools.importer.processor.EdgeProcessor"}, {"trait" : "com\/vesoft\/nebula\/tools\/importer\/processor\/Processor.html", "name" : "com.vesoft.nebula.tools.importer.processor.Processor"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/processor\/ReloadProcessor.html", "name" : "com.vesoft.nebula.tools.importer.processor.ReloadProcessor"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/processor\/VerticesProcessor.html", "name" : "com.vesoft.nebula.tools.importer.processor.VerticesProcessor"}], "com.vesoft.nebula.tools.importer" : [{"case class" : "com\/vesoft\/nebula\/tools\/importer\/Argument.html", "name" : "com.vesoft.nebula.tools.importer.Argument"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/CheckPointHandler$.html", "name" : "com.vesoft.nebula.tools.importer.CheckPointHandler"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/package$$Edge.html", "name" : "com.vesoft.nebula.tools.importer.Edge"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/package$$Edges.html", "name" : "com.vesoft.nebula.tools.importer.Edges"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/ErrorHandler$.html", "name" : "com.vesoft.nebula.tools.importer.ErrorHandler"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/Exchange$.html", "name" : "com.vesoft.nebula.tools.importer.Exchange"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/GraphProvider.html", "name" : "com.vesoft.nebula.tools.importer.GraphProvider"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/package$$KeyPolicy$.html", "name" : "com.vesoft.nebula.tools.importer.KeyPolicy"}, {"class" : "com\/vesoft\/nebula\/tools\/importer\/MetaProvider.html", "name" : "com.vesoft.nebula.tools.importer.MetaProvider"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/package$$Offset.html", "name" : "com.vesoft.nebula.tools.importer.Offset"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/TooManyErrorsException.html", "name" : "com.vesoft.nebula.tools.importer.TooManyErrorsException"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/package$$Vertex.html", "name" : "com.vesoft.nebula.tools.importer.Vertex"}, {"case class" : "com\/vesoft\/nebula\/tools\/importer\/package$$Vertices.html", "name" : "com.vesoft.nebula.tools.importer.Vertices"}, {"object" : "com\/vesoft\/nebula\/tools\/importer\/VidType$.html", "name" : "com.vesoft.nebula.tools.importer.VidType"}], "com" : []}; \ No newline at end of file diff --git a/nebula-exchange/target/site/scaladocs/index/index-a.html b/nebula-exchange/target/site/scaladocs/index/index-a.html deleted file mode 100644 index 0d07f2a..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-a.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                Argument
                                - -
                                -
                                address
                                - -
                                -
                                addresses
                                - -
                                -
                                adminUrl
                                - -
                                -
                                apply
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-b.html b/nebula-exchange/target/site/scaladocs/index/index-b.html deleted file mode 100644 index ac6eeec..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-b.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                batch
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-c.html b/nebula-exchange/target/site/scaladocs/index/index-c.html deleted file mode 100644 index d1bae90..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-c.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                CLIENT
                                - -
                                -
                                CSV
                                - -
                                -
                                CSVReader
                                - -
                                -
                                CheckPointHandler
                                - -
                                -
                                CheckPointSupport
                                - -
                                -
                                Configs
                                - -
                                -
                                ConnectionConfigEntry
                                - -
                                -
                                CustomReader
                                - -
                                -
                                category
                                - -
                                -
                                checkPointPath
                                - -
                                -
                                checkSupportResume
                                - -
                                -
                                close
                                - -
                                -
                                columnFamily
                                - -
                                -
                                com
                                - -
                                -
                                config
                                - -
                                -
                                connectionConfig
                                - -
                                -
                                connectionDriverName
                                - -
                                -
                                connectionPassWord
                                - -
                                -
                                connectionURL
                                - -
                                -
                                connectionUserName
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-d.html b/nebula-exchange/target/site/scaladocs/index/index-d.html deleted file mode 100644 index 332ea9d..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-d.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                DataBaseConfigEntry
                                - -
                                -
                                DataSinkConfigEntry
                                - -
                                -
                                DataSourceConfigEntry
                                - -
                                -
                                dataSinkConfigEntry
                                - -
                                -
                                dataSourceConfigEntry
                                - -
                                -
                                database
                                - -
                                -
                                databaseConfig
                                - -
                                -
                                destination
                                - -
                                -
                                directly
                                - -
                                -
                                dry
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-e.html b/nebula-exchange/target/site/scaladocs/index/index-e.html deleted file mode 100644 index a966b4b..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-e.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                EDGE
                                - -
                                -
                                Edge
                                - -
                                -
                                EdgeConfigEntry
                                - -
                                -
                                EdgeProcessor
                                - -
                                -
                                EdgeRank
                                - -
                                -
                                EdgeType
                                - -
                                -
                                EdgeVersion
                                - -
                                -
                                Edges
                                - -
                                -
                                ErrorConfigEntry
                                - -
                                -
                                ErrorHandler
                                - -
                                -
                                Exchange
                                - -
                                -
                                ExecutionConfigEntry
                                - -
                                -
                                edgesConfig
                                - -
                                -
                                encryption
                                - -
                                -
                                env
                                - -
                                -
                                errorConfig
                                - -
                                -
                                errorMaxSize
                                - -
                                -
                                errorPath
                                - -
                                -
                                executionConfig
                                - -
                                -
                                existError
                                - -
                                -
                                exists
                                - -
                                -
                                extraValue
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-f.html b/nebula-exchange/target/site/scaladocs/index/index-f.html deleted file mode 100644 index df34a36..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-f.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                FileBaseReader
                                - -
                                -
                                FileBaseSinkConfigEntry
                                - -
                                -
                                FileBaseSourceConfigEntry
                                - -
                                -
                                FileDataSourceConfigEntry
                                - -
                                -
                                fetchOffset
                                - -
                                -
                                fields
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-g.html b/nebula-exchange/target/site/scaladocs/index/index-g.html deleted file mode 100644 index 537d637..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-g.html +++ /dev/null @@ -1,74 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                GraphProvider
                                - -
                                -
                                GraphSpaceID
                                - -
                                -
                                getConfigOrNone
                                - -
                                -
                                getContent
                                - -
                                -
                                getDataFrameValue
                                - -
                                -
                                getDataSourceFieldType
                                - -
                                -
                                getDataType
                                - -
                                -
                                getEdgeSchema
                                - -
                                -
                                getFileSystem
                                - -
                                -
                                getGraphAddress
                                - -
                                -
                                getGraphClient
                                - -
                                -
                                getLabelType
                                - -
                                -
                                getLong
                                - -
                                -
                                getMetaAddress
                                - -
                                -
                                getOffsets
                                - -
                                -
                                getPartNumber
                                - -
                                -
                                getPathAndOffset
                                - -
                                -
                                getTagSchema
                                - -
                                -
                                getVidType
                                - -
                                -
                                graphAddress
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-h.html b/nebula-exchange/target/site/scaladocs/index/index-h.html deleted file mode 100644 index 769af3b..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-h.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                HASH
                                - -
                                -
                                HBASE
                                - -
                                -
                                HBaseReader
                                - -
                                -
                                HBaseSourceConfigEntry
                                - -
                                -
                                HDFSUtils
                                - -
                                -
                                HIVE
                                - -
                                -
                                HiveConfigEntry
                                - -
                                -
                                HiveReader
                                - -
                                -
                                HiveSourceConfigEntry
                                - -
                                -
                                header
                                - -
                                -
                                hive
                                - -
                                -
                                hiveConfigEntry
                                - -
                                -
                                host
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-i.html b/nebula-exchange/target/site/scaladocs/index/index-i.html deleted file mode 100644 index 0249970..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-i.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                INT
                                - -
                                -
                                importer
                                - -
                                -
                                interval
                                - -
                                -
                                intervalSeconds
                                - -
                                -
                                isEdge
                                - -
                                -
                                isGeo
                                - -
                                -
                                isNumic
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-j.html b/nebula-exchange/target/site/scaladocs/index/index-j.html deleted file mode 100644 index a786d08..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-j.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                JANUS_GRAPH
                                - -
                                -
                                JSON
                                - -
                                -
                                JSONReader
                                - -
                                -
                                JanusGraphReader
                                - -
                                -
                                JanusGraphSourceConfigEntry
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-k.html b/nebula-exchange/target/site/scaladocs/index/index-k.html deleted file mode 100644 index a8f0ccf..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-k.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                KAFKA
                                - -
                                -
                                KafkaReader
                                - -
                                -
                                KafkaSourceConfigEntry
                                - -
                                -
                                KafkaUtils
                                - -
                                -
                                KeyPolicy
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-l.html b/nebula-exchange/target/site/scaladocs/index/index-l.html deleted file mode 100644 index 6ecf261..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-l.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                latitude
                                - -
                                -
                                limit
                                - -
                                -
                                list
                                - -
                                -
                                localPath
                                - -
                                -
                                longitude
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-m.html b/nebula-exchange/target/site/scaladocs/index/index-m.html deleted file mode 100644 index 70ac5bd..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-m.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                MYSQL
                                - -
                                -
                                MetaProvider
                                - -
                                -
                                MySQLReader
                                - -
                                -
                                MySQLSourceConfigEntry
                                - -
                                -
                                main
                                - -
                                -
                                map
                                - -
                                -
                                metaAddresses
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-n.html b/nebula-exchange/target/site/scaladocs/index/index-n.html deleted file mode 100644 index a8c5fd5..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-n.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                NEO4J
                                - -
                                -
                                NebulaGraphClientWriter
                                - -
                                -
                                NebulaReader
                                - -
                                -
                                NebulaSSTWriter
                                - -
                                -
                                NebulaSinkConfigEntry
                                - -
                                -
                                NebulaStorageClientWriter
                                - -
                                -
                                NebulaUtils
                                - -
                                -
                                NebulaWriterCallback
                                - -
                                -
                                Neo4JReader
                                - -
                                -
                                Neo4JSourceConfigEntry
                                - -
                                -
                                name
                                - -
                                -
                                names
                                - -
                                -
                                nebula
                                - -
                                -
                                nebulaFields
                                - -
                                -
                                nebulaPoolConfig
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-o.html b/nebula-exchange/target/site/scaladocs/index/index-o.html deleted file mode 100644 index b3cbeec..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-o.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                ORC
                                - -
                                -
                                ORCReader
                                - -
                                -
                                Offset
                                - -
                                -
                                onFailure
                                - -
                                -
                                onSuccess
                                - -
                                -
                                options
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-p.html b/nebula-exchange/target/site/scaladocs/index/index-p.html deleted file mode 100644 index 497d775..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-p.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                PARQUET
                                - -
                                -
                                POLICY
                                - -
                                -
                                PULSAR
                                - -
                                -
                                ParquetReader
                                - -
                                -
                                PartitionID
                                - -
                                -
                                ProcessResult
                                - -
                                -
                                Processor
                                - -
                                -
                                PropertyNames
                                - -
                                -
                                PropertyValues
                                - -
                                -
                                PulsarReader
                                - -
                                -
                                PulsarSourceConfigEntry
                                - -
                                -
                                parallel
                                - -
                                -
                                parse
                                - -
                                -
                                parser
                                - -
                                -
                                partition
                                - -
                                -
                                password
                                - -
                                -
                                path
                                - -
                                -
                                policy
                                - -
                                -
                                pool
                                - -
                                -
                                port
                                - -
                                -
                                prepare
                                - -
                                -
                                process
                                - -
                                -
                                processor
                                - -
                                -
                                propertyNames
                                - -
                                -
                                propertyValues
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-r.html b/nebula-exchange/target/site/scaladocs/index/index-r.html deleted file mode 100644 index f9972f9..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-r.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                RateConfigEntry
                                - -
                                -
                                Reader
                                - -
                                -
                                ReloadProcessor
                                - -
                                -
                                ranking
                                - -
                                -
                                rankingField
                                - -
                                -
                                rateConfig
                                - -
                                -
                                rateLimiter
                                - -
                                -
                                read
                                - -
                                -
                                reader
                                - -
                                -
                                releaseGraphClient
                                - -
                                -
                                reload
                                - -
                                -
                                remotePath
                                - -
                                -
                                retry
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-s.html b/nebula-exchange/target/site/scaladocs/index/index-s.html deleted file mode 100644 index c320fa6..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-s.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                SOCKET
                                - -
                                -
                                SST
                                - -
                                -
                                STRING
                                - -
                                -
                                SchemaConfigEntry
                                - -
                                -
                                SchemaID
                                - -
                                -
                                SchemaVersion
                                - -
                                -
                                ServerBaseReader
                                - -
                                -
                                ServerBaseWriter
                                - -
                                -
                                ServerDataSourceConfigEntry
                                - -
                                -
                                SinkCategory
                                - -
                                -
                                SourceCategory
                                - -
                                -
                                SparkConfigEntry
                                - -
                                -
                                StreamingBaseReader
                                - -
                                -
                                StreamingDataSourceConfigEntry
                                - -
                                -
                                save
                                - -
                                -
                                saveContent
                                - -
                                -
                                sentence
                                - -
                                -
                                separator
                                - -
                                -
                                server
                                - -
                                -
                                serviceUrl
                                - -
                                -
                                session
                                - -
                                -
                                size
                                - -
                                -
                                source
                                - -
                                -
                                sourceField
                                - -
                                -
                                sourcePolicy
                                - -
                                -
                                space
                                - -
                                -
                                sparkConfigEntry
                                - -
                                -
                                start
                                - -
                                -
                                submit
                                - -
                                -
                                switchSpace
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-t.html b/nebula-exchange/target/site/scaladocs/index/index-t.html deleted file mode 100644 index cb5b6eb..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-t.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                TEXT
                                - -
                                -
                                TagConfigEntry
                                - -
                                -
                                TagID
                                - -
                                -
                                TagVersion
                                - -
                                -
                                TooManyErrorsException
                                - -
                                -
                                Type
                                - -
                                -
                                table
                                - -
                                -
                                tagsConfig
                                - -
                                -
                                targetField
                                - -
                                -
                                targetPolicy
                                - -
                                -
                                timeout
                                - -
                                -
                                toExecuteSentence
                                - -
                                -
                                toString
                                - -
                                -
                                tools
                                - -
                                -
                                topic
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-u.html b/nebula-exchange/target/site/scaladocs/index/index-u.html deleted file mode 100644 index 7c15e50..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-u.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                UUID
                                - -
                                -
                                UserConfigEntry
                                - -
                                -
                                upload
                                - -
                                -
                                user
                                - -
                                -
                                userConfig
                                - -
                                -
                                utils
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-v.html b/nebula-exchange/target/site/scaladocs/index/index-v.html deleted file mode 100644 index 1c1dbe9..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-v.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                VERTEX
                                - -
                                -
                                Vertex
                                - -
                                -
                                VertexID
                                - -
                                -
                                VertexIDSlice
                                - -
                                -
                                Vertices
                                - -
                                -
                                VerticesProcessor
                                - -
                                -
                                VidType
                                - -
                                -
                                values
                                - -
                                -
                                vertexField
                                - -
                                -
                                vertexID
                                - -
                                -
                                vertexPolicy
                                - -
                                -
                                vesoft
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/index/index-w.html b/nebula-exchange/target/site/scaladocs/index/index-w.html deleted file mode 100644 index 634b9b7..0000000 --- a/nebula-exchange/target/site/scaladocs/index/index-w.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - nebula-exchange 2.0.0 API - - - - - - - - -
                                -
                                Writer
                                - -
                                -
                                WriterResult
                                - -
                                -
                                waredir
                                - -
                                -
                                write
                                - -
                                -
                                writeEdge
                                - -
                                -
                                writeEdges
                                - -
                                -
                                writeVertices
                                - -
                                -
                                writer
                                - -
                                - diff --git a/nebula-exchange/target/site/scaladocs/lib/arrow-down.png b/nebula-exchange/target/site/scaladocs/lib/arrow-down.png deleted file mode 100644 index 7229603ae5b30ce0e0bd09863543b260085c8f2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6232 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 diff --git a/nebula-exchange/target/site/scaladocs/lib/class_big.png b/nebula-exchange/target/site/scaladocs/lib/class_big.png deleted file mode 100644 index cb1f638a585c50456f57b73c4d043c75762ff9a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7516 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
                                }cgT+sFDw4uMOU<91Pe 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 U==iC&s{jB107*qoM6N<$f-P8sEdT%j diff --git a/nebula-exchange/target/site/scaladocs/lib/constructorsbg.gif b/nebula-exchange/target/site/scaladocs/lib/constructorsbg.gif deleted file mode 100644 index 2e3f5ea53025f68e2636f9c65e5115a3aa1bb581..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1206 zcmZ?wbhEHbWMq(GIKseSZEam&UmqG8YHx4v?(P;76XWUWX=!Qc=j$685$WvY?CR?3 zAK)Jt7-V8%YG!5@8yjnDYwPIXsHUnK9v&VQ9TgWB=jiAd5*+O9?QL#hZftDKfCLo( zb4U0FD7Yk+Bm!w0`-+0ZZE`@j@w*YQzUa=n7J9^3ax%w4}1^R}1 z1|ToN6#Dw&SDKp(S6y5Zl!|aKR)dQ}DhpEegHnt0ON)|Ify$LZRuxz|7o{eaQ#zd*q`*i^wcF*!32#0RVQ^|kWMD=taQOHTE4u~h<^pqH7MVr61% z;AY@x;B0E?uBO)VrJ|N z)az`3RWB$hI zxnujbty?y4+PGo;y0vRouUffc`Ld-;7B5=3VE(+hb7s$)Ib-^?sZ%CTnmD1queYbW ztFxoMt+l1Osj;EHuC}JSsEZKEj1-MDKQ~FE;c4QDl#HG zEHorIC@{d^&)3J>%hSW%&DF)($Qx)!_Hn5)9TB4Am2f&=-p_kccyqPBfKGwUE!WRLZeY z&9_xAcF-<$)~j$)tu;5Sb~kMFG;Z}V?)EY6_cxj1Z!#mmbas&G!VuHNfk6*)|04m# ze}c|Msfi`2DGKG8B^e6tp1uJLIt)MnasUIXxWbl9$+AdMQ_qW!P0lP*Igu!GM1jSD HgTWdAVsJLn diff --git a/nebula-exchange/target/site/scaladocs/lib/defbg-blue.gif b/nebula-exchange/target/site/scaladocs/lib/defbg-blue.gif deleted file mode 100644 index 69038337a793be5ec04430183980b7e393113ea1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1544 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 availableWidth) - { - // resize diagram - var height = diagramHeight / diagramWidth * availableWidth; - $(".diagram svg", this).width(availableWidth); - $(".diagram svg", this).height(height); - - // register click event on whole div - $(".diagram", this).click(function() { - diagrams.popup($(this)); - }); - $(".diagram", this).addClass("magnifying"); - } - else - { - // restore full size of diagram - $(".diagram svg", this).width(diagramWidth); - $(".diagram svg", this).height(diagramHeight); - // don't show custom cursor any more - $(".diagram", this).removeClass("magnifying"); - } - }); -}; - -/** - * Shows or hides a diagram depending on its current state. - */ -diagrams.toggle = function(container, dontAnimate) -{ - // change class of link - $(".diagram-link", container).toggleClass("open"); - // get element to show / hide - var div = $(".diagram", container); - if (div.is(':visible')) - { - $(".diagram-help", container).hide(); - div.unbind("click"); - div.removeClass("magnifying"); - div.slideUp(100); - } - else - { - diagrams.resize(); - if(dontAnimate) - div.show(); - else - div.slideDown(100); - $(".diagram-help", container).show(); - } -}; - -/** - * Opens a popup containing a copy of a diagram. - */ -diagrams.windows = {}; -diagrams.popup = function(diagram) -{ - var id = diagram.attr("id"); - if(!diagrams.windows[id] || diagrams.windows[id].closed) { - var title = $(".symbol .name", $("#signature")).text(); - // cloning from parent window to popup somehow doesn't work in IE - // therefore include the SVG as a string into the HTML - var svgIE = jQuery.browser.msie ? $("
                                ").append(diagram.data("svg")).html() : ""; - var html = '' + - '\n' + - '\n' + - '\n' + - ' \n' + - ' ' + title + '\n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + - ' Close this window\n' + - ' ' + svgIE + '\n' + - ' \n' + - ''; - - var padding = 30; - var screenHeight = screen.availHeight; - var screenWidth = screen.availWidth; - var w = Math.min(screenWidth, diagram.data("width") + 2 * padding); - var h = Math.min(screenHeight, diagram.data("height") + 2 * padding); - var left = (screenWidth - w) / 2; - var top = (screenHeight - h) / 2; - var parameters = "height=" + h + ", width=" + w + ", left=" + left + ", top=" + top + ", scrollbars=yes, location=no, resizable=yes"; - var win = window.open("about:blank", "_blank", parameters); - win.document.open(); - win.document.write(html); - win.document.close(); - diagrams.windows[id] = win; - } - win.focus(); -}; - -/** - * This method is called from within the popup when a node is clicked. - */ -diagrams.redirectFromPopup = function(url) -{ - window.location = url; -}; - -/** - * Helper method that adds a class to a SVG element. - */ -diagrams.addClass = function(svgElem, newClass) { - newClass = newClass || "over"; - var classes = svgElem.attr("class"); - if ($.inArray(newClass, classes.split(/\s+/)) == -1) { - classes += (classes ? ' ' : '') + newClass; - svgElem.attr("class", classes); - } -}; - -/** - * Helper method that removes a class from a SVG element. - */ -diagrams.removeClass = function(svgElem, oldClass) { - oldClass = oldClass || "over"; - var classes = svgElem.attr("class"); - classes = $.grep(classes.split(/\s+/), function(n, i) { return n != oldClass; }).join(' '); - svgElem.attr("class", classes); -}; - diff --git a/nebula-exchange/target/site/scaladocs/lib/filter_box_left.png b/nebula-exchange/target/site/scaladocs/lib/filter_box_left.png deleted file mode 100644 index 0e8c893315e7955b02474d3a544b9145aafb15b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1692 zcmaJ?Yfuws6pg$rSOqBp3YKM~RV;Zz60;aJAs|tLX#yHS2bN@k3}iRiY$T*bRAg#9 zU=@FeD54a{@j+EkDTq>D1*#y5=}<;1FQtW2QWQm;)^1R+Kd|4-?)R8;&OP^jcW1wn zMQxbxvc!c#q0E;=h~?zGh0nhVLI8<$M9qZi_hoVG}vq!iJ%!WPy#m5Py=;ZL5vtw zxJE~4Fch#U!ikuX5P+o9Hz{a!GqR}RZJEe|F-)+I!J;#5DNO^V(*K8QwKHe~AxGZ% zomJQnouNY*a>RfcaTR%SNmN@X9TbWqFoEIG7?w6&MOg|)V1^V-2ZSm(fD~3~P}_bA zFO@=z7d?GMc8_g2)3)ShrtuM!>~@@N>+T&8M1C!960tDa)O{gFy2(fA zz3T<_SYuv{D)_EL=f;)y69e-Ky4|eHMud}d&8tpKdJXw|FA8wVks>d2E7RxJTpy%k& zkln?LUfbzg^RAqmv%e%NGORQBAW}-Td|p~VHijo;X8zsZ($X^6+uM6!J#g~Lon3o| z%yy6Q#l8#XZjX=8POAt4(SV9rv74$vZ!mQ7Ih=6>K^_l|jA(PbOJZ)7%FntjLr%)i zy2~xr+}{#jYpUxb&qZ$DoK;v{eCMdMAN4_|-e@%T^!4>EHE#RNqt*9tQPEOmTwHcp z8SUCPVvxz@I`!(h*bT?;AMpB?9IRY;6SepD?GM%LqlKtmzwpwk1RTGYUvT)Ehf9tw zE33A9!v5+(_aFQ91qB5O)j2tiU0q!X$!!raxvG}Ir~D;ZJ#daH$(+?g#+>uOcV@q9( zNA}J$hYc4tg?PB^X-m33JSql-TX}6aoBK0{#?8YKde>dG#XG8NY8+x>{FmgFM?ny@ z_lvcz0)e1s=k?TwO*EQAcHQALZe00KpIDBLpO!mctE_}kbiwl%FJKIFot&Jc+$f_8 z8oG+eBKkEqH`A|N(9~bzE0=fty7^4!Zl}xsijNe>*2c%iZiL<2FV|eD)ojQO;0pxH zS6iOl-NNi$#aFwY%o;pr{{mUu^Fwjf3l}ad*ZyPVIVyrIkPEX+>TMxn15Nd zav-ZrQP;=Um;C7y>q90w(zLCoZdruVQ63j}ETaFVxBMUOjizep$G*PA6TE6m?$RPx zmv)7uBXiNdkmBLz_4cmubG5#W6mXxF8k^TF<8E1SsNetIhE~5hP876f;&u1}p9{AC Ng(NIW{GBLa@4p#{lvn@& diff --git a/nebula-exchange/target/site/scaladocs/lib/filter_box_left2.gif b/nebula-exchange/target/site/scaladocs/lib/filter_box_left2.gif deleted file mode 100644 index b9b49076a6410112fd18b370bc661154bbab8f80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1462 zcmZ?wbhEHb6k!lyxN5?1>C&aRxVRrbe!P11>f*(Vt*xySCr_wV1o zw{PEm|Ni~!*RS{P-TU(8%b!1gZrr%>`t|GF+}z{Gk3W6-^z7NQ8#ZiMzkdCvPoHkz zz8w`6_44J*J9qAsmzV$k{ky2BXxFY?A3l8e`}gm(Y13k3V}U0q$LPMun}Zr!h6zgDka?cw3^9}E}>0mc8^5xxNmE{P?HK-$K>q98Fj zJGDe1DK$Ma&sORE?)^#%nJKnP;ikR@z6H*y8JQkcMXAA6ej&+K*~ykEO7?aNHWgMC zxdpkYC5Z|ZxjA{oRu#5Ni7EL>sa8NXNLXJ<0j#7X+g8aDB%uJZ(>cE=Rl!uxKsVXI z%s|1+P|wiV#N6CmN5ROz&_Lh7NZ-&%*U;R`*vQJjKmiJrfVLH-q*(>IxIyg#@@$nd zN=gc>^!0&3rdMvPmtT~wZ)j<02{OaTNEfI=x41H|B(Xv_uUHvof=g;~a#3bMNoIbY z0?5R~r2NtnTP2`NAzsKWfE$}vtOxdvUUGh}ennz|zM-B0$V)JVzP|XC=H|jx7ncO3 zBHWAB;NpiyW)Z+ZoqU2Pda%GTJ1y;^Qsfi`|MIrh5Ij~R+$jC3rFV4s>P;d@5 zRq#zr&ddYx!Rmc|tvvIJOA_;vQ$1a5m4GJbWoD*WS(v-I7@E3Rm|B{e7#g}7IJr4n zI=dQ~nOmATIhq)m!1TK0Czs}?=9R$orXciM;?xUD3b_S9n_W_iGRsm^+=}vZ6~JD$ z%Eav!Go0o@^`_uv@OxBG5|NZ^* z``6DO-@kqR^7+%p5AWZ-ee?R&%NNg|J$>@{(ZdJ#@7=v~`_|1H*RNf@a{1E53+K6ZM9qnzcEzM1h4fS=kHPuy>73F26CB;RB1^Ico zIoVm68R==MDalER3Gs2UG0{A;Cd`0selzKHgrQ9`0_gF3wJl4)%7oHr7^_ z7UpKACdNjp{}N?qO7E-ATK8?BP}HFfhW0S{OOhO#noZi%b`dsS#`djvo JU&f9M)&NKAH`@RJ diff --git a/nebula-exchange/target/site/scaladocs/lib/filter_box_right.png b/nebula-exchange/target/site/scaladocs/lib/filter_box_right.png deleted file mode 100644 index f127e35b48d39bd048fea2a8e98dd68fb5984601..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1803 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 diff --git a/nebula-exchange/target/site/scaladocs/lib/filterboxbg.gif b/nebula-exchange/target/site/scaladocs/lib/filterboxbg.gif deleted file mode 100644 index ae2f85823bbbd77d85a28d8348bfd75a1ec626ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1366 zcmaJ>d0^927|&$j+)$KD(Vht+jHR17kQ|Xk~>-G7(u~=+)csLf1#pCg4G#U&J1%shPBA!%LkH;I2 z#Q-f73I+oHOga+^12g3F`2nN9zdw;s)9KX6$Vez04h4f=k2jS{`~1FiCX-OrU@#aR zj;2yc5GN9eh9hAxhK7dXaj>aIB9TBKkVqu_e!s`#Nv4u1Ku)Kj9HV5UsKr$eJ4l5D z-^wbtNKze)0=F`4EN??Hd-ftQOWTlUvkP;HcBY+O+AA@Qy~~@Z-VVx2BUOvwN;l!= zM2=BN*v)nFGU2u%BrUWu1hBPb6oE$}N{0=p);3@*rd^O2*sRBN6jqMG;It~H;$H-2Ig?S|0ygt^@t4Gz{oyTp)+ATXZA1F zw+o6Ow+kX{Z#2U$l45zyAH};|L>(_HBu_DQ4jTd#^ejsg6&9z%V0M_yRFSl4tHPt5El;t`Es*7WICCjA`bIm!qS}SlOi0oh_b}d6YC4qxSOD5Rdx!^hV z#<+CuT#PxnC`bm?4)$LMom~RmqnYDv3!L%BXL!)<5@_qZk-z@@Zk3iy3q&o^Ix_2n0zAN=goPd@(W!w=pceDB?N-X3`C%{LCb zzJK4|*Is>P&+eCBdhvzlpL_P1T~F_PYR8lP+n;#+u}8N(^6*0sK5+ki_ug~&U3YHX za>wnr-FnN-n{T>t(+wN1zwX*=uHJCf`o1gIU2*wkmtNA_&!Ej)h%7(taaFHsux!+vQ;i5tQD4W zv&o2qE2YzH_B}#`-nO=9mf!3Ja$e73rto#dFaKXdXHZg3R;GHY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C$yM3OmMKd1b_zBX zRu#Dgxv3?I3Kh9IdBs*0wn~X9`AMl(KsHENUr7P1q$Jx`$q^)>0J76LzbI9~RL?*+ z*}%*|!OT$4(AdP>++0V&$iUD*-@r)U&`8(N+{)O<%D_MY3Y37h6{VzE1-ZCE?E>;_ zl`=|73as??%gf94%8m8%i_-NCEiElUW*8ai0#)c1SLT%@R_NvxE5l51Ni9w;$}A|! z%+FH*nV6WAUs__T1av9H3%LbwWAlpjz~0eI&d=4aNG#Ad)H48i38v837r)ZnT)67u zlAu(Cd$Af^98y`3svneEoL^d$oC;K~46>@g%DE^tu_V7JBtJg~7K#BG`6c$o&6x?nx#i>^x=oo!a#3DsBObD2IKumbD1#;jCKQ#}S+KYh6n(_a? zzkh!J`uXGgx36D5fBN|0{kyksUcY+z;`y_uPaZ#d_~8D%yLWEix_RUJwX0VyU%GhV z{JFDdPMZ`!zF{kpYlR z+RD .pre { - display: block; - position: absolute; - top: 0; - left: 0; - height: 23px; - width: 21px; - background: url("filter_box_left.png"); -} - -#textfilter > .input { - display: block; - position: absolute; - top: 0; - right: 20px; - left: 20px; -} - -#textfilter > .input > input { - height: 20px; - padding: 1px; - font-weight: bold; - color: #000000; - background: #ffffff url("filterboxbarbg.png") repeat-x bottom left; - width: 100%; -} - -#textfilter > .post { - display: block; - position: absolute; - top: 0; - right: 0; - height: 23px; - width: 21px; - background: url("filter_box_right.png"); -} - -/*#textfilter { - position: relative; - display: block; - height: 20px; - margin-bottom: 5px; -} - -#textfilter > .pre { - display: block; - position: absolute; - top: 0; - left: 0; - height: 20px; - width: 20px; - background: url("filter_box_left.png"); -} - -#textfilter > .input { - display: block; - position: absolute; - top: 0; - right: 20px; - left: 20px; -} - -#textfilter > .input > input { - height: 16px; - padding: 2px; - font-weight: bold; - color: darkblue; - background-color: white; - width: 100%; -} - -#textfilter > .post { - display: block; - position: absolute; - top: 0; - right: 0; - height: 20px; - width: 20px; - background: url("filter_box_right.png"); -}*/ - -#focusfilter { - position: relative; - text-align: center; - display: block; - padding: 5px; - background-color: #fffebd; /* light yellow*/ - text-shadow: #ffffff 0 1px 0; -} - -#focusfilter .focuscoll { - font-weight: bold; - text-shadow: #ffffff 0 1px 0; -} - -#focusfilter img { - bottom: -2px; - position: relative; -} - -#kindfilter { - position: relative; - display: block; - padding: 5px; -/* background-color: #999;*/ - text-align: center; -} - -#kindfilter > a { - color: black; -/* text-decoration: underline;*/ - text-shadow: #ffffff 0 1px 0; - -} - -#kindfilter > a:hover { - color: #4C4C4C; - text-decoration: none; - text-shadow: #ffffff 0 1px 0; -} - -#letters { - position: relative; - text-align: center; - padding-bottom: 5px; - border:1px solid #bbbbbb; - border-top:0; - border-left:0; - border-right:0; -} - -#letters > a, #letters > span { -/* font-family: monospace;*/ - color: #858484; - font-weight: bold; - font-size: 8pt; - text-shadow: #ffffff 0 1px 0; - padding-right: 2px; -} - -#letters > span { - color: #bbb; -} - -#tpl { - display: block; - position: fixed; - overflow: auto; - right: 0; - left: 0; - bottom: 0; - top: 5px; - position: absolute; - display: block; -} - -#tpl .packhide { - display: block; - float: right; - font-weight: normal; - color: white; -} - -#tpl .packfocus { - display: block; - float: right; - font-weight: normal; - color: white; -} - -#tpl .packages > ol { - background-color: #dadfe6; - /*margin-bottom: 5px;*/ -} - -/*#tpl .packages > ol > li { - margin-bottom: 1px; -}*/ - -#tpl .packages > li > a { - padding: 0px 5px; -} - -#tpl .packages > li > a.tplshow { - display: block; - color: white; - font-weight: bold; - display: block; - text-shadow: #000000 0 1px 0; -} - -#tpl ol > li.pack { - padding: 3px 5px; - background: url("packagesbg.gif"); - background-repeat:repeat-x; - min-height: 14px; - background-color: #6e808e; -} - -#tpl ol > li { - display: block; -} - -#tpl .templates > li { - padding-left: 5px; - min-height: 18px; -} - -#tpl ol > li .icon { - padding-right: 5px; - bottom: -2px; - position: relative; -} - -#tpl .templates div.placeholder { - padding-right: 5px; - width: 13px; - display: inline-block; -} - -#tpl .templates span.tplLink { - padding-left: 5px; -} - -#content { - border-left-width: 1px; - border-left-color: black; - border-left-style: white; - right: 0px; - left: 0px; - bottom: 0px; - top: 0px; - position: fixed; - margin-left: 300px; - display: block; - -webkit-overflow-scrolling: touch; -} - -#content > iframe { - display: block; - height: 100%; - width: 100%; -} - -.ui-layout-pane { - background: #FFF; - overflow: auto; -} - -.ui-layout-resizer { - background-image:url('filterbg.gif'); - background-repeat:repeat-x; - background-color: #ededee; /* light gray */ - border:1px solid #bbbbbb; - border-top:0; - border-bottom:0; - border-left: 0; -} - -.ui-layout-toggler { - background: #AAA; -} \ No newline at end of file diff --git a/nebula-exchange/target/site/scaladocs/lib/index.js b/nebula-exchange/target/site/scaladocs/lib/index.js deleted file mode 100644 index cf81f7f..0000000 --- a/nebula-exchange/target/site/scaladocs/lib/index.js +++ /dev/null @@ -1,577 +0,0 @@ -// © 2009–2010 EPFL/LAMP -// code by Gilles Dubochet with contributions by Johannes Rudolph, "spiros" and Marcin Kubala - -var topLevelTemplates = undefined; -var topLevelPackages = undefined; - -var scheduler = undefined; - -var kindFilterState = undefined; -var focusFilterState = undefined; - -var title = $(document).attr('title'); - -var lastFragment = ""; - -$(document).ready(function() { - $('body').layout({ - west__size: '20%', - center__maskContents: true - }); - $('#browser').layout({ - center__paneSelector: ".ui-west-center" - //,center__initClosed:true - ,north__paneSelector: ".ui-west-north" - }); - $('iframe').bind("load", function(){ - try { - var subtitle = $(this).contents().find('title').text(); - $(document).attr('title', (title ? title + " - " : "") + subtitle); - } catch (e) { - // Chrome doesn't allow reading the iframe's contents when - // used on the local file system. - } - setUrlFragmentFromFrameSrc(); - }); - - // workaround for IE's iframe sizing lack of smartness - if($.browser.msie) { - function fixIFrame() { - $('iframe').height($(window).height() ) - } - $('iframe').bind("load",fixIFrame) - $('iframe').bind("resize",fixIFrame) - } - - scheduler = new Scheduler(); - scheduler.addLabel("init", 1); - scheduler.addLabel("focus", 2); - scheduler.addLabel("filter", 4); - - prepareEntityList(); - - configureTextFilter(); - configureKindFilter(); - configureEntityList(); - - setFrameSrcFromUrlFragment(); - - // If the url fragment changes, adjust the src of iframe "template". - $(window).bind('hashchange', function() { - if(lastFragment != window.location.hash) { - lastFragment = window.location.hash; - setFrameSrcFromUrlFragment(); - } - }); -}); - -// Set the iframe's src according to the fragment of the current url. -// fragment = "#scala.Either" => iframe url = "scala/Either.html" -// fragment = "#scala.Either@isRight:Boolean" => iframe url = "scala/Either.html#isRight:Boolean" -// fragment = "#scalaz.iteratee.package@>@>[E,A]=scalaz.iteratee.package.Iteratee[E,A]" => iframe url = "scalaz/iteratee/package.html#>@>[E,A]=scalaz.iteratee.package.Iteratee[E,A]" -function setFrameSrcFromUrlFragment() { - - function extractLoc(fragment) { - var loc = fragment.split('@')[0].replace(/\./g, "/"); - if (loc.indexOf(".html") < 0) { - loc += ".html"; - } - return loc; - } - - function extractMemberSig(fragment) { - var splitIdx = fragment.indexOf('@'); - if (splitIdx < 0) { - return; - } - return fragment.substr(splitIdx + 1); - } - - var fragment = location.hash.slice(1); - if (fragment) { - var locWithMemeberSig = extractLoc(fragment); - var memberSig = extractMemberSig(fragment); - if (memberSig) { - locWithMemeberSig += "#" + memberSig; - } - frames["template"].location.replace(location.protocol + locWithMemeberSig); - } else { - console.log("empty fragment detected"); - frames["template"].location.replace("package.html"); - } -} - -// Set the url fragment according to the src of the iframe "template". -// iframe url = "scala/Either.html" => url fragment = "#scala.Either" -// iframe url = "scala/Either.html#isRight:Boolean" => url fragment = "#scala.Either@isRight:Boolean" -// iframe url = "scalaz/iteratee/package.html#>@>[E,A]=scalaz.iteratee.package.Iteratee[E,A]" => fragment = "#scalaz.iteratee.package@>@>[E,A]=scalaz.iteratee.package.Iteratee[E,A]" -function setUrlFragmentFromFrameSrc() { - try { - var commonLength = location.pathname.lastIndexOf("/"); - var frameLocation = frames["template"].location; - var relativePath = frameLocation.pathname.slice(commonLength + 1); - - if(!relativePath || frameLocation.pathname.indexOf("/") < 0) - return; - - // Add #, remove ".html" and replace "/" with "." - fragment = "#" + relativePath.replace(/\.html$/, "").replace(/\//g, "."); - - // Add the frame's hash after an @ - if(frameLocation.hash) fragment += ("@" + frameLocation.hash.slice(1)); - - // Use replace to not add history items - lastFragment = fragment; - location.replace(fragment); - } - catch(e) { - // Chrome doesn't allow reading the iframe's location when - // used on the local file system. - } -} - -var Index = {}; - -(function (ns) { - function openLink(t, type) { - var href; - if (type == 'object') { - href = t['object']; - } else { - href = t['class'] || t['trait'] || t['case class'] || t['type']; - } - return [ - '' - ].join(''); - } - - function createPackageHeader(pack) { - return [ - '
                              1. ', - 'focushide', - '', - pack, - '
                              2. ' - ].join(''); - }; - - function createListItem(template) { - var inner = ''; - - - if (template.object) { - inner += openLink(template, 'object'); - } - - if (template['class'] || template['trait'] || template['case class'] || template['type']) { - inner += (inner == '') ? - '
                                ' : ''; - inner += openLink(template, template['trait'] ? 'trait' : template['type'] ? 'type' : 'class'); - } else { - inner += '
                                '; - } - - return [ - '
                              3. ', - inner, - '', - template.name.replace(/^.*\./, ''), - '
                              4. ' - ].join(''); - } - - - ns.createPackageTree = function (pack, matched, focused) { - var html = $.map(matched, function (child, i) { - return createListItem(child); - }).join(''); - - var header; - if (focused && pack == focused) { - header = ''; - } else { - header = createPackageHeader(pack); - } - - return [ - '
                                  ', - header, - '
                                    ', - html, - '
                                ' - ].join(''); - } - - ns.keys = function (obj) { - var result = []; - var key; - for (key in obj) { - result.push(key); - } - return result; - } - - var hiddenPackages = {}; - - function subPackages(pack) { - return $.grep($('#tpl ol.packages'), function (element, index) { - var pack = $('li.pack > .tplshow', element).text(); - return pack.indexOf(pack + '.') == 0; - }); - } - - ns.hidePackage = function (ol) { - var selected = $('li.pack > .tplshow', ol).text(); - hiddenPackages[selected] = true; - - $('ol.templates', ol).hide(); - - $.each(subPackages(selected), function (index, element) { - $(element).hide(); - }); - } - - ns.showPackage = function (ol, state) { - var selected = $('li.pack > .tplshow', ol).text(); - hiddenPackages[selected] = false; - - $('ol.templates', ol).show(); - - $.each(subPackages(selected), function (index, element) { - $(element).show(); - - // When the filter is in "packs" state, - // we don't want to show the `.templates` - var key = $('li.pack > .tplshow', element).text(); - if (hiddenPackages[key] || state == 'packs') { - $('ol.templates', element).hide(); - } - }); - } - -})(Index); - -function configureEntityList() { - kindFilterSync(); - configureHideFilter(); - configureFocusFilter(); - textFilter(); -} - -/* Updates the list of entities (i.e. the content of the #tpl element) from the raw form generated by Scaladoc to a - form suitable for display. In particular, it adds class and object etc. icons, and it configures links to open in - the right frame. Furthermore, it sets the two reference top-level entities lists (topLevelTemplates and - topLevelPackages) to serve as reference for resetting the list when needed. - Be advised: this function should only be called once, on page load. */ -function prepareEntityList() { - var classIcon = $("#library > img.class"); - var traitIcon = $("#library > img.trait"); - var typeIcon = $("#library > img.type"); - var objectIcon = $("#library > img.object"); - var packageIcon = $("#library > img.package"); - - $('#tpl li.pack > a.tplshow').attr("target", "template"); - $('#tpl li.pack').each(function () { - $("span.class", this).each(function() { $(this).replaceWith(classIcon.clone()); }); - $("span.trait", this).each(function() { $(this).replaceWith(traitIcon.clone()); }); - $("span.type", this).each(function() { $(this).replaceWith(typeIcon.clone()); }); - $("span.object", this).each(function() { $(this).replaceWith(objectIcon.clone()); }); - $("span.package", this).each(function() { $(this).replaceWith(packageIcon.clone()); }); - }); - $('#tpl li.pack') - .prepend("hide") - .prepend("focus"); -} - -/* Handles all key presses while scrolling around with keyboard shortcuts in left panel */ -function keyboardScrolldownLeftPane() { - scheduler.add("init", function() { - $("#textfilter input").blur(); - var $items = $("#tpl li"); - $items.first().addClass('selected'); - - $(window).bind("keydown", function(e) { - var $old = $items.filter('.selected'), - $new; - - switch ( e.keyCode ) { - - case 9: // tab - $old.removeClass('selected'); - break; - - case 13: // enter - $old.removeClass('selected'); - var $url = $old.children().filter('a:last').attr('href'); - $("#template").attr("src",$url); - break; - - case 27: // escape - $old.removeClass('selected'); - $(window).unbind(e); - $("#textfilter input").focus(); - - break; - - case 38: // up - $new = $old.prev(); - - if (!$new.length) { - $new = $old.parent().prev(); - } - - if ($new.is('ol') && $new.children(':last').is('ol')) { - $new = $new.children().children(':last'); - } else if ($new.is('ol')) { - $new = $new.children(':last'); - } - - break; - - case 40: // down - $new = $old.next(); - if (!$new.length) { - $new = $old.parent().parent().next(); - } - if ($new.is('ol')) { - $new = $new.children(':first'); - } - break; - } - - if ($new.is('li')) { - $old.removeClass('selected'); - $new.addClass('selected'); - } else if (e.keyCode == 38) { - $(window).unbind(e); - $("#textfilter input").focus(); - } - }); - }); -} - -/* Configures the text filter */ -function configureTextFilter() { - scheduler.add("init", function() { - $("#textfilter").append(""); - var input = $("#textfilter input"); - resizeFilterBlock(); - input.bind('keyup', function(event) { - if (event.keyCode == 27) { // escape - input.attr("value", ""); - } - if (event.keyCode == 40) { // down arrow - $(window).unbind("keydown"); - keyboardScrolldownLeftPane(); - return false; - } - textFilter(); - }); - input.bind('keydown', function(event) { - if (event.keyCode == 9) { // tab - $("#template").contents().find("#mbrsel-input").focus(); - input.attr("value", ""); - return false; - } - textFilter(); - }); - input.focus(function(event) { input.select(); }); - }); - scheduler.add("init", function() { - $("#textfilter > .post").click(function(){ - $("#textfilter input").attr("value", ""); - textFilter(); - }); - }); -} - -function compilePattern(query) { - var escaped = query.replace(/([\.\*\+\?\|\(\)\[\]\\])/g, '\\$1'); - - if (query.toLowerCase() != query) { - // Regexp that matches CamelCase subbits: "BiSe" is - // "[a-z]*Bi[a-z]*Se" and matches "BitSet", "ABitSet", ... - return new RegExp(escaped.replace(/([A-Z])/g,"[a-z]*$1")); - } - else { // if query is all lower case make a normal case insensitive search - return new RegExp(escaped, "i"); - } -} - -// Filters all focused templates and packages. This function should be made less-blocking. -// @param query The string of the query -function textFilter() { - var query = $("#textfilter input").attr("value") || ''; - var queryRegExp = compilePattern(query); - - // if we are filtering on types, then we have to display types - // ("display packages only" is not possible when filtering) - if (query !== "") { - kindFilter("all"); - } - - // Three things trigger a reload of the left pane list: - // typeof textFilter.lastQuery === "undefined" <-- first load, there is nothing yet in the left pane - // textFilter.lastQuery !== query <-- the filter text has changed - // focusFilterState != null <-- a package has been "focused" - if ((typeof textFilter.lastQuery === "undefined") || (textFilter.lastQuery !== query) || (focusFilterState != null)) { - - textFilter.lastQuery = query; - - scheduler.clear("filter"); - - $('#tpl').html(''); - - var index = 0; - - var searchLoop = function () { - var packages = Index.keys(Index.PACKAGES).sort(); - - while (packages[index]) { - var pack = packages[index]; - var children = Index.PACKAGES[pack]; - index++; - - if (focusFilterState) { - if (pack == focusFilterState || - pack.indexOf(focusFilterState + '.') == 0) { - ; - } else { - continue; - } - } - - var matched = $.grep(children, function (child, i) { - return queryRegExp.test(child.name); - }); - - if (matched.length > 0) { - $('#tpl').append(Index.createPackageTree(pack, matched, - focusFilterState)); - scheduler.add('filter', searchLoop); - return; - } - } - - $('#tpl a.packfocus').click(function () { - focusFilter($(this).parent().parent()); - }); - configureHideFilter(); - }; - - scheduler.add('filter', searchLoop); - } -} - -/* Configures the hide tool by adding the hide link to all packages. */ -function configureHideFilter() { - $('#tpl li.pack a.packhide').click(function () { - var packhide = $(this) - var action = packhide.text(); - - var ol = $(this).parent().parent(); - - if (action == "hide") { - Index.hidePackage(ol); - packhide.text("show"); - } - else { - Index.showPackage(ol, kindFilterState); - packhide.text("hide"); - } - return false; - }); -} - -/* Configures the focus tool by adding the focus bar in the filter box (initially hidden), and by adding the focus - link to all packages. */ -function configureFocusFilter() { - scheduler.add("init", function() { - focusFilterState = null; - if ($("#focusfilter").length == 0) { - $("#filter").append("
                                focused on
                                "); - $("#focusfilter > .focusremove").click(function(event) { - textFilter(); - - $("#focusfilter").hide(); - $("#kindfilter").show(); - resizeFilterBlock(); - focusFilterState = null; - }); - $("#focusfilter").hide(); - resizeFilterBlock(); - } - }); - scheduler.add("init", function() { - $('#tpl li.pack a.packfocus').click(function () { - focusFilter($(this).parent()); - return false; - }); - }); -} - -/* Focuses the entity index on a specific package. To do so, it will copy the sub-templates and sub-packages of the - focuses package into the top-level templates and packages position of the index. The original top-level - @param package The
                              5. element that corresponds to the package in the entity index */ -function focusFilter(package) { - scheduler.clear("filter"); - - var currentFocus = $('li.pack > .tplshow', package).text(); - $("#focusfilter > .focuscoll").empty(); - $("#focusfilter > .focuscoll").append(currentFocus); - - $("#focusfilter").show(); - $("#kindfilter").hide(); - resizeFilterBlock(); - focusFilterState = currentFocus; - kindFilterSync(); - - textFilter(); -} - -function configureKindFilter() { - scheduler.add("init", function() { - kindFilterState = "all"; - $("#filter").append(""); - $("#kindfilter > a").click(function(event) { kindFilter("packs"); }); - resizeFilterBlock(); - }); -} - -function kindFilter(kind) { - if (kind == "packs") { - kindFilterState = "packs"; - kindFilterSync(); - $("#kindfilter > a").replaceWith("display all entities"); - $("#kindfilter > a").click(function(event) { kindFilter("all"); }); - } - else { - kindFilterState = "all"; - kindFilterSync(); - $("#kindfilter > a").replaceWith("display packages only"); - $("#kindfilter > a").click(function(event) { kindFilter("packs"); }); - } -} - -/* Applies the kind filter. */ -function kindFilterSync() { - if (kindFilterState == "all" || focusFilterState != null) { - $("#tpl a.packhide").text('hide'); - $("#tpl ol.templates").show(); - } else { - $("#tpl a.packhide").text('show'); - $("#tpl ol.templates").hide(); - } -} - -function resizeFilterBlock() { - $("#tpl").css("top", $("#filter").outerHeight(true)); -} diff --git a/nebula-exchange/target/site/scaladocs/lib/jquery-ui.js b/nebula-exchange/target/site/scaladocs/lib/jquery-ui.js deleted file mode 100644 index faab0cf..0000000 --- a/nebula-exchange/target/site/scaladocs/lib/jquery-ui.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! jQuery UI - v1.9.0 - 2012-10-05 -* http://jqueryui.com -* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.slider.js, jquery.ui.sortable.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js -* Copyright (c) 2012 jQuery Foundation and other contributors Licensed MIT */ - -(function(e,t){function i(t,n){var r,i,o,u=t.nodeName.toLowerCase();return"area"===u?(r=t.parentNode,i=r.name,!t.href||!i||r.nodeName.toLowerCase()!=="map"?!1:(o=e("img[usemap=#"+i+"]")[0],!!o&&s(o))):(/input|select|textarea|button|object/.test(u)?!t.disabled:"a"===u?t.href||n:n)&&s(t)}function s(t){return!e(t).parents().andSelf().filter(function(){return e.css(this,"visibility")==="hidden"||e.expr.filters.hidden(this)}).length}var n=0,r=/^ui-id-\d+$/;e.ui=e.ui||{};if(e.ui.version)return;e.extend(e.ui,{version:"1.9.0",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({_focus:e.fn.focus,focus:function(t,n){return typeof t=="number"?this.each(function(){var r=this;setTimeout(function(){e(r).focus(),n&&n.call(r)},t)}):this._focus.apply(this,arguments)},scrollParent:function(){var t;return e.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?t=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):t=this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(n){if(n!==t)return this.css("zIndex",n);if(this.length){var r=e(this[0]),i,s;while(r.length&&r[0]!==document){i=r.css("position");if(i==="absolute"||i==="relative"||i==="fixed"){s=parseInt(r.css("zIndex"),10);if(!isNaN(s)&&s!==0)return s}r=r.parent()}}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++n)})},removeUniqueId:function(){return this.each(function(){r.test(this.id)&&e(this).removeAttr("id")})}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(n,r){function u(t,n,r,s){return e.each(i,function(){n-=parseFloat(e.css(t,"padding"+this))||0,r&&(n-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(n-=parseFloat(e.css(t,"margin"+this))||0)}),n}var i=r==="Width"?["Left","Right"]:["Top","Bottom"],s=r.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+r]=function(n){return n===t?o["inner"+r].call(this):this.each(function(){e(this).css(s,u(this,n)+"px")})},e.fn["outer"+r]=function(t,n){return typeof t!="number"?o["outer"+r].call(this,t):this.each(function(){e(this).css(s,u(this,t,!0,n)+"px")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(n){return!!e.data(n,t)}}):function(t,n,r){return!!e.data(t,r[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),r=isNaN(n);return(r||n>=0)&&i(t,!r)}}),e(function(){var t=document.body,n=t.appendChild(n=document.createElement("div"));n.offsetHeight,e.extend(n.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),e.support.minHeight=n.offsetHeight===100,e.support.selectstart="onselectstart"in n,t.removeChild(n).style.display="none"}),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,n,r){var i,s=e.ui[t].prototype;for(i in r)s.plugins[i]=s.plugins[i]||[],s.plugins[i].push([n,r[i]])},call:function(e,t,n){var r,i=e.plugins[t];if(!i||!e.element[0].parentNode||e.element[0].parentNode.nodeType===11)return;for(r=0;r0?!0:(t[r]=1,i=t[r]>0,t[r]=0,i)},isOverAxis:function(e,t,n){return e>t&&e",options:{disabled:!1,create:null},_createWidget:function(t,r){r=e(r||this.defaultElement||this)[0],this.element=e(r),this.uuid=n++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),r!==this&&(e.data(r,this.widgetName,this),e.data(r,this.widgetFullName,this),this._on({remove:"destroy"}),this.document=e(r.style?r.ownerDocument:r.document||r),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(n,r){var i=n,s,o,u;if(arguments.length===0)return e.widget.extend({},this.options);if(typeof n=="string"){i={},s=n.split("."),n=s.shift();if(s.length){o=i[n]=e.widget.extend({},this.options[n]);for(u=0;u=9||!!t.button?this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted):this._mouseUp(t)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(e){return this.mouseDelayMet},_mouseStart:function(e){},_mouseDrag:function(e){},_mouseStop:function(e){},_mouseCapture:function(e){return!0}})})(jQuery);(function(e,t){function h(e,t,n){return[parseInt(e[0],10)*(l.test(e[0])?t/100:1),parseInt(e[1],10)*(l.test(e[1])?n/100:1)]}function p(t,n){return parseInt(e.css(t,n),10)||0}e.ui=e.ui||{};var n,r=Math.max,i=Math.abs,s=Math.round,o=/left|center|right/,u=/top|center|bottom/,a=/[\+\-]\d+%?/,f=/^\w+/,l=/%$/,c=e.fn.position;e.position={scrollbarWidth:function(){if(n!==t)return n;var r,i,s=e("
                                "),o=s.children()[0];return e("body").append(s),r=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,r===i&&(i=s[0].clientWidth),s.remove(),n=r-i},getScrollInfo:function(t){var n=t.isWindow?"":t.element.css("overflow-x"),r=t.isWindow?"":t.element.css("overflow-y"),i=n==="scroll"||n==="auto"&&t.width0?"right":"center",vertical:u<0?"top":o>0?"bottom":"middle"};lr(i(o),i(u))?h.important="horizontal":h.important="vertical",t.using.call(this,e,h)}),a.offset(e.extend(C,{using:u}))})},e.ui.position={fit:{left:function(e,t){var n=t.within,i=n.isWindow?n.scrollLeft:n.offset.left,s=n.width,o=e.left-t.collisionPosition.marginLeft,u=i-o,a=o+t.collisionWidth-s-i,f;t.collisionWidth>s?u>0&&a<=0?(f=e.left+u+t.collisionWidth-s-i,e.left+=u-f):a>0&&u<=0?e.left=i:u>a?e.left=i+s-t.collisionWidth:e.left=i:u>0?e.left+=u:a>0?e.left-=a:e.left=r(e.left-o,e.left)},top:function(e,t){var n=t.within,i=n.isWindow?n.scrollTop:n.offset.top,s=t.within.height,o=e.top-t.collisionPosition.marginTop,u=i-o,a=o+t.collisionHeight-s-i,f;t.collisionHeight>s?u>0&&a<=0?(f=e.top+u+t.collisionHeight-s-i,e.top+=u-f):a>0&&u<=0?e.top=i:u>a?e.top=i+s-t.collisionHeight:e.top=i:u>0?e.top+=u:a>0?e.top-=a:e.top=r(e.top-o,e.top)}},flip:{left:function(e,t){var n=t.within,r=n.offset.left+n.scrollLeft,s=n.width,o=n.isWindow?n.scrollLeft:n.offset.left,u=e.left-t.collisionPosition.marginLeft,a=u-o,f=u+t.collisionWidth-s-o,l=t.my[0]==="left"?-t.elemWidth:t.my[0]==="right"?t.elemWidth:0,c=t.at[0]==="left"?t.targetWidth:t.at[0]==="right"?-t.targetWidth:0,h=-2*t.offset[0],p,d;if(a<0){p=e.left+l+c+h+t.collisionWidth-s-r;if(p<0||p0){d=e.left-t.collisionPosition.marginLeft+l+c+h-o;if(d>0||i(d)a&&(v<0||v0&&(d=e.top-t.collisionPosition.marginTop+c+h+p-o,e.top+c+h+p>f&&(d>0||i(d)10&&i<11,t.innerHTML="",n.removeChild(t)}(),e.uiBackCompat!==!1&&function(e){var n=e.fn.position;e.fn.position=function(r){if(!r||!r.offset)return n.call(this,r);var i=r.offset.split(" "),s=r.at.split(" ");return i.length===1&&(i[1]=i[0]),/^\d/.test(i[0])&&(i[0]="+"+i[0]),/^\d/.test(i[1])&&(i[1]="+"+i[1]),s.length===1&&(/left|center|right/.test(s[0])?s[1]="center":(s[1]=s[0],s[0]="center")),n.call(this,e.extend(r,{at:s[0]+i[0]+" "+s[1]+i[1],offset:t}))}}(jQuery)})(jQuery);(function(e,t){var n=0,r={},i={};r.height=r.paddingTop=r.paddingBottom=r.borderTopWidth=r.borderBottomWidth="hide",i.height=i.paddingTop=i.paddingBottom=i.borderTopWidth=i.borderBottomWidth="show",e.widget("ui.accordion",{version:"1.9.0",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var t=this.accordionId="ui-accordion-"+(this.element.attr("id")||++n),r=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset"),this.headers=this.element.find(r.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this._hoverable(this.headers),this._focusable(this.headers),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").hide(),!r.collapsible&&r.active===!1&&(r.active=0),r.active<0&&(r.active+=this.headers.length),this.active=this._findActive(r.active).addClass("ui-accordion-header-active ui-state-active").toggleClass("ui-corner-all ui-corner-top"),this.active.next().addClass("ui-accordion-content-active").show(),this._createIcons(),this.originalHeight=this.element[0].style.height,this.refresh(),this.element.attr("role","tablist"),this.headers.attr("role","tab").each(function(n){var r=e(this),i=r.attr("id"),s=r.next(),o=s.attr("id");i||(i=t+"-header-"+n,r.attr("id",i)),o||(o=t+"-panel-"+n,s.attr("id",o)),r.attr("aria-controls",o),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false",tabIndex:-1}).next().attr({"aria-expanded":"false","aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true",tabIndex:0}).next().attr({"aria-expanded":"true","aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._on(this.headers,{keydown:"_keydown"}),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._setupEvents(r.event)},_getCreateEventData:function(){return{header:this.active,content:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),e=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this.options.heightStyle!=="content"&&(this.element.css("height",this.originalHeight),e.css("height",""))},_setOption:function(e,t){if(e==="active"){this._activate(t);return}e==="event"&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),e==="collapsible"&&!t&&this.options.active===!1&&this._activate(0),e==="icons"&&(this._destroyIcons(),t&&this._createIcons()),e==="disabled"&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)},_keydown:function(t){if(t.altKey||t.ctrlKey)return;var n=e.ui.keyCode,r=this.headers.length,i=this.headers.index(t.target),s=!1;switch(t.keyCode){case n.RIGHT:case n.DOWN:s=this.headers[(i+1)%r];break;case n.LEFT:case n.UP:s=this.headers[(i-1+r)%r];break;case n.SPACE:case n.ENTER:this._eventHandler(t);break;case n.HOME:s=this.headers[0];break;case n.END:s=this.headers[r-1]}s&&(e(t.target).attr("tabIndex",-1),e(s).attr("tabIndex",0),s.focus(),t.preventDefault())},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t,n,r=this.options.heightStyle,i=this.element.parent();this.element.css("height",this.originalHeight),r==="fill"?(e.support.minHeight||(n=i.css("overflow"),i.css("overflow","hidden")),t=i.height(),this.element.siblings(":visible").each(function(){var n=e(this),r=n.css("position");if(r==="absolute"||r==="fixed")return;t-=n.outerHeight(!0)}),n&&i.css("overflow",n),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):r==="auto"&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).height("").height())}).height(t)),r!=="content"&&this.element.height(this.element.height())},_activate:function(t){var n=this._findActive(t)[0];if(n===this.active[0])return;n=n||this.active[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return typeof t=="number"?this.headers.eq(t):e()},_setupEvents:function(t){var n={};if(!t)return;e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._on(this.headers,n)},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i[0]===r[0],o=s&&n.collapsible,u=o?e():i.next(),a=r.next(),f={oldHeader:r,oldPanel:a,newHeader:o?e():i,newPanel:u};t.preventDefault();if(s&&!n.collapsible||this._trigger("beforeActivate",t,f)===!1)return;n.active=o?!1:this.headers.index(i),this.active=s?e():i,this._toggle(f),r.removeClass("ui-accordion-header-active ui-state-active"),n.icons&&r.children(".ui-accordion-header-icon").removeClass(n.icons.activeHeader).addClass(n.icons.header),s||(i.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),n.icons&&i.children(".ui-accordion-header-icon").removeClass(n.icons.header).addClass(n.icons.activeHeader),i.next().addClass("ui-accordion-content-active"))},_toggle:function(t){var n=t.newPanel,r=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=n,this.prevHide=r,this.options.animate?this._animate(n,r,t):(r.hide(),n.show(),this._toggleComplete(t)),r.attr({"aria-expanded":"false","aria-hidden":"true"}),r.prev().attr("aria-selected","false"),n.length&&r.length?r.prev().attr("tabIndex",-1):n.length&&this.headers.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),n.attr({"aria-expanded":"true","aria-hidden":"false"}).prev().attr({"aria-selected":"true",tabIndex:0})},_animate:function(e,t,n){var s,o,u,a=this,f=0,l=e.length&&(!t.length||e.index()",options:{appendTo:"body",autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},pending:0,_create:function(){var t,n,r;this.isMultiLine=this._isMultiLine(),this.valueMethod=this.element[this.element.is("input,textarea")?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on({keydown:function(i){if(this.element.prop("readOnly")){t=!0,r=!0,n=!0;return}t=!1,r=!1,n=!1;var s=e.ui.keyCode;switch(i.keyCode){case s.PAGE_UP:t=!0,this._move("previousPage",i);break;case s.PAGE_DOWN:t=!0,this._move("nextPage",i);break;case s.UP:t=!0,this._keyEvent("previous",i);break;case s.DOWN:t=!0,this._keyEvent("next",i);break;case s.ENTER:case s.NUMPAD_ENTER:this.menu.active&&(t=!0,i.preventDefault(),this.menu.select(i));break;case s.TAB:this.menu.active&&this.menu.select(i);break;case s.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(i),i.preventDefault());break;default:n=!0,this._searchTimeout(i)}},keypress:function(r){if(t){t=!1,r.preventDefault();return}if(n)return;var i=e.ui.keyCode;switch(r.keyCode){case i.PAGE_UP:this._move("previousPage",r);break;case i.PAGE_DOWN:this._move("nextPage",r);break;case i.UP:this._keyEvent("previous",r);break;case i.DOWN:this._keyEvent("next",r)}},input:function(e){if(r){r=!1,e.preventDefault();return}this._searchTimeout(e)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}clearTimeout(this.searching),this.close(e),this._change(e)}}),this._initSource(),this.menu=e("
                              6. '+"";var z=N?'":"";for(var W=0;W<7;W++){var X=(W+T)%7;z+="=5?' class="ui-datepicker-week-end"':"")+">"+''+L[X]+""}U+=z+"";var V=this._getDaysInMonth(d,p);d==e.selectedYear&&p==e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,V));var J=(this._getFirstDayOfMonth(d,p)-T+7)%7,K=Math.ceil((J+V)/7),Q=f?this.maxRows>K?this.maxRows:K:K;this.maxRows=Q;var G=this._daylightSavingAdjust(new Date(d,p,1-J));for(var Y=0;Y";var Z=N?'":"";for(var W=0;W<7;W++){var et=M?M.apply(e.input?e.input[0]:null,[G]):[!0,""],tt=G.getMonth()!=p,nt=tt&&!D||!et[0]||c&&Gh;Z+='",G.setDate(G.getDate()+1),G=this._daylightSavingAdjust(G)}U+=Z+""}p++,p>11&&(p=0,d++),U+="
                                '+this._get(e,"weekHeader")+"
                                '+this._get(e,"calculateWeek")(G)+""+(tt&&!_?" ":nt?''+G.getDate()+"":''+G.getDate()+"")+"
                                "+(f?"
                                "+(o[0]>0&&I==o[1]-1?'
                                ':""):""),F+=U}B+=F}return B+=x+($.browser.msie&&parseInt($.browser.version,10)<7&&!e.inline?'':""),e._keyEvent=!1,B},_generateMonthYearHeader:function(e,t,n,r,i,s,o,u){var a=this._get(e,"changeMonth"),f=this._get(e,"changeYear"),l=this._get(e,"showMonthAfterYear"),c='
                                ',h="";if(s||!a)h+=''+o[t]+"";else{var p=r&&r.getFullYear()==n,d=i&&i.getFullYear()==n;h+='"}l||(c+=h+(s||!a||!f?" ":""));if(!e.yearshtml){e.yearshtml="";if(s||!f)c+=''+n+"";else{var m=this._get(e,"yearRange").split(":"),g=(new Date).getFullYear(),y=function(e){var t=e.match(/c[+-].*/)?n+parseInt(e.substring(1),10):e.match(/[+-].*/)?g+parseInt(e,10):parseInt(e,10);return isNaN(t)?g:t},b=y(m[0]),w=Math.max(b,y(m[1]||""));b=r?Math.max(b,r.getFullYear()):b,w=i?Math.min(w,i.getFullYear()):w,e.yearshtml+='",c+=e.yearshtml,e.yearshtml=null}}return c+=this._get(e,"yearSuffix"),l&&(c+=(s||!a||!f?" ":"")+h),c+="
                                ",c},_adjustInstDate:function(e,t,n){var r=e.drawYear+(n=="Y"?t:0),i=e.drawMonth+(n=="M"?t:0),s=Math.min(e.selectedDay,this._getDaysInMonth(r,i))+(n=="D"?t:0),o=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(r,i,s)));e.selectedDay=o.getDate(),e.drawMonth=e.selectedMonth=o.getMonth(),e.drawYear=e.selectedYear=o.getFullYear(),(n=="M"||n=="Y")&&this._notifyChange(e)},_restrictMinMax:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max"),i=n&&tr?r:i,i},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return t==null?[1,1]:typeof t=="number"?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return(new Date(e,t,1)).getDay()},_canAdjustMonth:function(e,t,n,r){var i=this._getNumberOfMonths(e),s=this._daylightSavingAdjust(new Date(n,r+(t<0?t:i[0]*i[1]),1));return t<0&&s.setDate(this._getDaysInMonth(s.getFullYear(),s.getMonth())),this._isInRange(e,s)},_isInRange:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max");return(!n||t.getTime()>=n.getTime())&&(!r||t.getTime()<=r.getTime())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t=typeof t!="string"?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,n,r){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var i=t?typeof t=="object"?t:this._daylightSavingAdjust(new Date(r,n,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),i,this._getFormatConfig(e))}}),$.fn.datepicker=function(e){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find(document.body).append($.datepicker.dpDiv),$.datepicker.initialized=!0);var t=Array.prototype.slice.call(arguments,1);return typeof e!="string"||e!="isDisabled"&&e!="getDate"&&e!="widget"?e=="option"&&arguments.length==2&&typeof arguments[1]=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t)):this.each(function(){typeof e=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this].concat(t)):$.datepicker._attachDatepicker(this,e)}):$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t))},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.9.0",window["DP_jQuery_"+dpuuid]=$})(jQuery);(function(e,t){var n="ui-dialog ui-widget ui-widget-content ui-corner-all ",r={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};e.widget("ui.dialog",{version:"1.9.0",options:{autoOpen:!0,buttons:{},closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:!1,maxWidth:!1,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var n=e(this).css(t).offset().top;n<0&&e(this).css("top",t.top-n)}},resizable:!0,show:null,stack:!0,title:"",width:300,zIndex:1e3},_create:function(){this.originalTitle=this.element.attr("title"),typeof this.originalTitle!="string"&&(this.originalTitle=""),this.oldPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.options.title=this.options.title||this.originalTitle;var t=this,r=this.options,i=r.title||" ",s=(this.uiDialog=e("
                                ")).addClass(n+r.dialogClass).css({display:"none",outline:0,zIndex:r.zIndex}).attr("tabIndex",-1).keydown(function(n){r.closeOnEscape&&!n.isDefaultPrevented()&&n.keyCode&&n.keyCode===e.ui.keyCode.ESCAPE&&(t.close(n),n.preventDefault())}).mousedown(function(e){t.moveToTop(!1,e)}).appendTo("body"),o=this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(s),u=(this.uiDialogTitlebar=e("
                                ")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(s),a=e("").addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").click(function(e){e.preventDefault(),t.close(e)}).appendTo(u),f=(this.uiDialogTitlebarCloseText=e("")).addClass("ui-icon ui-icon-closethick").text(r.closeText).appendTo(a),l=e("").uniqueId().addClass("ui-dialog-title").html(i).prependTo(u),c=(this.uiDialogButtonPane=e("
                                ")).addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),h=(this.uiButtonSet=e("
                                ")).addClass("ui-dialog-buttonset").appendTo(c);s.attr({role:"dialog","aria-labelledby":l.attr("id")}),u.find("*").add(u).disableSelection(),this._hoverable(a),this._focusable(a),r.draggable&&e.fn.draggable&&this._makeDraggable(),r.resizable&&e.fn.resizable&&this._makeResizable(),this._createButtons(r.buttons),this._isOpen=!1,e.fn.bgiframe&&s.bgiframe(),this._on(s,{keydown:function(t){if(!r.modal||t.keyCode!==e.ui.keyCode.TAB)return;var n=e(":tabbable",s),i=n.filter(":first"),o=n.filter(":last");if(t.target===o[0]&&!t.shiftKey)return i.focus(1),!1;if(t.target===i[0]&&t.shiftKey)return o.focus(1),!1}})},_init:function(){this.options.autoOpen&&this.open()},_destroy:function(){var e,t=this.oldPosition;this.overlay&&this.overlay.destroy(),this.uiDialog.hide(),this.element.removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"),this.uiDialog.remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},close:function(t){var n=this,r,i;if(!this._isOpen)return;if(!1===this._trigger("beforeClose",t))return;return this._isOpen=!1,this.overlay&&this.overlay.destroy(),this.options.hide?this.uiDialog.hide(this.options.hide,function(){n._trigger("close",t)}):(this.uiDialog.hide(),this._trigger("close",t)),e.ui.dialog.overlay.resize(),this.options.modal&&(r=0,e(".ui-dialog").each(function(){this!==n.uiDialog[0]&&(i=e(this).css("z-index"),isNaN(i)||(r=Math.max(r,i)))}),e.ui.dialog.maxZ=r),this},isOpen:function(){return this._isOpen},moveToTop:function(t,n){var r=this.options,i;return r.modal&&!t||!r.stack&&!r.modal?this._trigger("focus",n):(r.zIndex>e.ui.dialog.maxZ&&(e.ui.dialog.maxZ=r.zIndex),this.overlay&&(e.ui.dialog.maxZ+=1,e.ui.dialog.overlay.maxZ=e.ui.dialog.maxZ,this.overlay.$el.css("z-index",e.ui.dialog.overlay.maxZ)),i={scrollTop:this.element.scrollTop(),scrollLeft:this.element.scrollLeft()},e.ui.dialog.maxZ+=1,this.uiDialog.css("z-index",e.ui.dialog.maxZ),this.element.attr(i),this._trigger("focus",n),this)},open:function(){if(this._isOpen)return;var t,n=this.options,r=this.uiDialog;return this._size(),this._position(n.position),r.show(n.show),this.overlay=n.modal?new e.ui.dialog.overlay(this):null,this.moveToTop(!0),t=this.element.find(":tabbable"),t.length||(t=this.uiDialogButtonPane.find(":tabbable"),t.length||(t=r)),t.eq(0).focus(),this._isOpen=!0,this._trigger("open"),this},_createButtons:function(t){var n,r,i=this,s=!1;this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),typeof t=="object"&&t!==null&&e.each(t,function(){return!(s=!0)}),s?(e.each(t,function(t,n){n=e.isFunction(n)?{click:n,text:t}:n;var r=e("
                                ').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var n=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,n.cursorAt&&this._adjustOffsetFromHelper(n.cursorAt),n.containment&&this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,n){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute");if(!n){var r=this._uiHash();if(this._trigger("drag",t,r)===!1)return this._mouseUp({}),!1;this.position=r.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";return e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var n=!1;e.ui.ddmanager&&!this.options.dropBehaviour&&(n=e.ui.ddmanager.drop(this,t)),this.dropped&&(n=this.dropped,this.dropped=!1);var r=this.element[0],i=!1;while(r&&(r=r.parentNode))r==document&&(i=!0);if(!i&&this.options.helper==="original")return!1;if(this.options.revert=="invalid"&&!n||this.options.revert=="valid"&&n||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,n)){var s=this;e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){s._trigger("stop",t)!==!1&&s._clear()})}else this._trigger("stop",t)!==!1&&this._clear();return!1},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){var n=!this.options.handle||!e(this.options.handle,this.element).length?!0:!1;return e(this.options.handle,this.element).find("*").andSelf().each(function(){this==t.target&&(n=!0)}),n},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t])):n.helper=="clone"?this.element.clone().removeAttr("id"):this.element;return r.parents("body").length||r.appendTo(n.appendTo=="parent"?this.element[0].parentNode:n.appendTo),r[0]!=this.element[0]&&!/(fixed|absolute)/.test(r.css("position"))&&r.css("position","absolute"),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&e.browser.msie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t=this.options;t.containment=="parent"&&(t.containment=this.helper[0].parentNode);if(t.containment=="document"||t.containment=="window")this.containment=[t.containment=="document"?0:e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t.containment=="document"?0:e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(t.containment=="document"?0:e(window).scrollLeft())+e(t.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(t.containment=="document"?0:e(window).scrollTop())+(e(t.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(t.containment)&&t.containment.constructor!=Array){var n=e(t.containment),r=n[0];if(!r)return;var i=n.offset(),s=e(r).css("overflow")!="hidden";this.containment=[(parseInt(e(r).css("borderLeftWidth"),10)||0)+(parseInt(e(r).css("paddingLeft"),10)||0),(parseInt(e(r).css("borderTopWidth"),10)||0)+(parseInt(e(r).css("paddingTop"),10)||0),(s?Math.max(r.scrollWidth,r.offsetWidth):r.offsetWidth)-(parseInt(e(r).css("borderLeftWidth"),10)||0)-(parseInt(e(r).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(s?Math.max(r.scrollHeight,r.offsetHeight):r.offsetHeight)-(parseInt(e(r).css("borderTopWidth"),10)||0)-(parseInt(e(r).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=n}else t.containment.constructor==Array&&(this.containment=t.containment)},_convertPositionTo:function(t,n){n||(n=this.position);var r=t=="absolute"?1:-1,i=this.options,s=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(s[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():o?0:s.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():o?0:s.scrollLeft())*r}},_generatePosition:function(t){var n=this.options,r=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,i=/(html|body)/i.test(r[0].tagName),s=t.pageX,o=t.pageY;if(this.originalPosition){var u;if(this.containment){if(this.relative_container){var a=this.relative_container.offset();u=[this.containment[0]+a.left,this.containment[1]+a.top,this.containment[2]+a.left,this.containment[3]+a.top]}else u=this.containment;t.pageX-this.offset.click.leftu[2]&&(s=u[2]+this.offset.click.left),t.pageY-this.offset.click.top>u[3]&&(o=u[3]+this.offset.click.top)}if(n.grid){var f=n.grid[1]?this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1]:this.originalPageY;o=u?f-this.offset.click.topu[3]?f-this.offset.click.topu[2]?l-this.offset.click.left=0;l--){var c=r.snapElements[l].left,h=c+r.snapElements[l].width,p=r.snapElements[l].top,d=p+r.snapElements[l].height;if(!(c-s=l&&o<=c||u>=l&&u<=c||oc)&&(i>=a&&i<=f||s>=a&&s<=f||if);default:return!1}},e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,n){var r=e.ui.ddmanager.droppables[t.options.scope]||[],i=n?n.type:null,s=(t.currentItem||t.element).find(":data(droppable)").andSelf();e:for(var o=0;oe?0:r.max")[0],c,h=t.each;l.style.cssText="background-color:rgba(1,1,1,.5)",f.rgba=l.style.backgroundColor.indexOf("rgba")>-1,h(u,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),o.fn=t.extend(o.prototype,{parse:function(r,i,s,a){if(r===n)return this._rgba=[null,null,null,null],this;if(r.jquery||r.nodeType)r=t(r).css(i),i=n;var f=this,l=t.type(r),v=this._rgba=[],m;i!==n&&(r=[r,i,s,a],l="array");if(l==="string")return this.parse(d(r)||c._default);if(l==="array")return h(u.rgba.props,function(e,t){v[t.idx]=p(r[t.idx],t)}),this;if(l==="object")return r instanceof o?h(u,function(e,t){r[t.cache]&&(f[t.cache]=r[t.cache].slice())}):h(u,function(t,n){var i=n.cache;h(n.props,function(e,t){if(!f[i]&&n.to){if(e==="alpha"||r[e]==null)return;f[i]=n.to(f._rgba)}f[i][t.idx]=p(r[e],t,!0)}),f[i]&&e.inArray(null,f[i].slice(0,3))<0&&(f[i][3]=1,n.from&&(f._rgba=n.from(f[i])))}),this},is:function(e){var t=o(e),n=!0,r=this;return h(u,function(e,i){var s,o=t[i.cache];return o&&(s=r[i.cache]||i.to&&i.to(r._rgba)||[],h(i.props,function(e,t){if(o[t.idx]!=null)return n=o[t.idx]===s[t.idx],n})),n}),n},_space:function(){var e=[],t=this;return h(u,function(n,r){t[r.cache]&&e.push(n)}),e.pop()},transition:function(e,t){var n=o(e),r=n._space(),i=u[r],s=this.alpha()===0?o("transparent"):this,f=s[i.cache]||i.to(s._rgba),l=f.slice();return n=n[i.cache],h(i.props,function(e,r){var i=r.idx,s=f[i],o=n[i],u=a[r.type]||{};if(o===null)return;s===null?l[i]=o:(u.mod&&(o-s>u.mod/2?s+=u.mod:s-o>u.mod/2&&(s-=u.mod)),l[i]=p((o-s)*t+s,r))}),this[r](l)},blend:function(e){if(this._rgba[3]===1)return this;var n=this._rgba.slice(),r=n.pop(),i=o(e)._rgba;return o(t.map(n,function(e,t){return(1-r)*i[t]+r*e}))},toRgbaString:function(){var e="rgba(",n=t.map(this._rgba,function(e,t){return e==null?t>2?1:0:e});return n[3]===1&&(n.pop(),e="rgb("),e+n.join()+")"},toHslaString:function(){var e="hsla(",n=t.map(this.hsla(),function(e,t){return e==null&&(e=t>2?1:0),t&&t<3&&(e=Math.round(e*100)+"%"),e});return n[3]===1&&(n.pop(),e="hsl("),e+n.join()+")"},toHexString:function(e){var n=this._rgba.slice(),r=n.pop();return e&&n.push(~~(r*255)),"#"+t.map(n,function(e,t){return e=(e||0).toString(16),e.length===1?"0"+e:e}).join("")},toString:function(){return this._rgba[3]===0?"transparent":this.toRgbaString()}}),o.fn.parse.prototype=o.fn,u.hsla.to=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/255,n=e[1]/255,r=e[2]/255,i=e[3],s=Math.max(t,n,r),o=Math.min(t,n,r),u=s-o,a=s+o,f=a*.5,l,c;return o===s?l=0:t===s?l=60*(n-r)/u+360:n===s?l=60*(r-t)/u+120:l=60*(t-n)/u+240,f===0||f===1?c=f:f<=.5?c=u/a:c=u/(2-a),[Math.round(l)%360,c,f,i==null?1:i]},u.hsla.from=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/360,n=e[1],r=e[2],i=e[3],s=r<=.5?r*(1+n):r+n-r*n,o=2*r-s,u,a,f;return[Math.round(v(o,s,t+1/3)*255),Math.round(v(o,s,t)*255),Math.round(v(o,s,t-1/3)*255),i]},h(u,function(e,r){var s=r.props,u=r.cache,a=r.to,f=r.from;o.fn[e]=function(e){a&&!this[u]&&(this[u]=a(this._rgba));if(e===n)return this[u].slice();var r,i=t.type(e),l=i==="array"||i==="object"?e:arguments,c=this[u].slice();return h(s,function(e,t){var n=l[i==="object"?e:t.idx];n==null&&(n=c[t.idx]),c[t.idx]=p(n,t)}),f?(r=o(f(c)),r[u]=c,r):o(c)},h(s,function(n,r){if(o.fn[n])return;o.fn[n]=function(s){var o=t.type(s),u=n==="alpha"?this._hsla?"hsla":"rgba":e,a=this[u](),f=a[r.idx],l;return o==="undefined"?f:(o==="function"&&(s=s.call(this,f),o=t.type(s)),s==null&&r.empty?this:(o==="string"&&(l=i.exec(s),l&&(s=f+parseFloat(l[2])*(l[1]==="+"?1:-1))),a[r.idx]=s,this[u](a)))}})}),h(r,function(e,n){t.cssHooks[n]={set:function(e,r){var i,s,u="";if(t.type(r)!=="string"||(i=d(r))){r=o(i||r);if(!f.rgba&&r._rgba[3]!==1){s=n==="backgroundColor"?e.parentNode:e;while((u===""||u==="transparent")&&s&&s.style)try{u=t.css(s,"backgroundColor"),s=s.parentNode}catch(a){}r=r.blend(u&&u!=="transparent"?u:"_default")}r=r.toRgbaString()}try{e.style[n]=r}catch(r){}}},t.fx.step[n]=function(e){e.colorInit||(e.start=o(e.elem,n),e.end=o(e.end),e.colorInit=!0),t.cssHooks[n].set(e.elem,e.start.transition(e.end,e.pos))}}),t.cssHooks.borderColor={expand:function(e){var t={};return h(["Top","Right","Bottom","Left"],function(n,r){t["border"+r+"Color"]=e}),t}},c=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(){var t=this.ownerDocument.defaultView?this.ownerDocument.defaultView.getComputedStyle(this,null):this.currentStyle,n={},r,i,s;if(t&&t.length&&t[0]&&t[t[0]]){s=t.length;while(s--)r=t[s],typeof t[r]=="string"&&(n[e.camelCase(r)]=t[r])}else for(r in t)typeof t[r]=="string"&&(n[r]=t[r]);return n}function s(t,n){var i={},s,o;for(s in n)o=n[s],t[s]!==o&&!r[s]&&(e.fx.step[s]||!isNaN(parseFloat(o)))&&(i[s]=o);return i}var n=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,n){e.fx.step[n]=function(e){if(e.end!=="none"&&!e.setAttr||e.pos===1&&!e.setAttr)jQuery.style(e.elem,n,e.end),e.setAttr=!0}}),e.effects.animateClass=function(t,r,o,u){var a=e.speed(r,o,u);return this.queue(function(){var r=e(this),o=r.attr("class")||"",u,f=a.children?r.find("*").andSelf():r;f=f.map(function(){var t=e(this);return{el:t,start:i.call(this)}}),u=function(){e.each(n,function(e,n){t[n]&&r[n+"Class"](t[n])})},u(),f=f.map(function(){return this.end=i.call(this.el[0]),this.diff=s(this.start,this.end),this}),r.attr("class",o),f=f.map(function(){var t=this,n=e.Deferred(),r=jQuery.extend({},a,{queue:!1,complete:function(){n.resolve(t)}});return this.el.animate(this.diff,r),n.promise()}),e.when.apply(e,f.get()).done(function(){u(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),a.complete.call(r[0])})})},e.fn.extend({_addClass:e.fn.addClass,addClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{add:t},n,r,i):this._addClass(t)},_removeClass:e.fn.removeClass,removeClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{remove:t},n,r,i):this._removeClass(t)},_toggleClass:e.fn.toggleClass,toggleClass:function(n,r,i,s,o){return typeof r=="boolean"||r===t?i?e.effects.animateClass.call(this,r?{add:n}:{remove:n},i,s,o):this._toggleClass(n,r):e.effects.animateClass.call(this,{toggle:n},r,i,s)},switchClass:function(t,n,r,i,s){return e.effects.animateClass.call(this,{add:n,remove:t},r,i,s)}})}(),function(){function i(n,r,i,s){e.isPlainObject(n)&&(r=n,n=n.effect),n={effect:n},r===t&&(r={}),e.isFunction(r)&&(s=r,i=null,r={});if(typeof r=="number"||e.fx.speeds[r])s=i,i=r,r={};return e.isFunction(i)&&(s=i,i=null),r&&e.extend(n,r),i=i||r.duration,n.duration=e.fx.off?0:typeof i=="number"?i:i in e.fx.speeds?e.fx.speeds[i]:e.fx.speeds._default,n.complete=s||r.complete,n}function s(t){return!t||typeof t=="number"||e.fx.speeds[t]?!0:typeof t=="string"&&!e.effects.effect[t]?n&&e.effects[t]?!1:!0:!1}e.extend(e.effects,{version:"1.9.0",save:function(e,t){for(var n=0;n
                                ").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),i={width:t.width(),height:t.height()},s=document.activeElement;try{s.id}catch(o){s=document.body}return t.wrap(r),(t[0]===s||e.contains(t[0],s))&&e(s).focus(),r=t.parent(),t.css("position")==="static"?(r.css({position:"relative"}),t.css({position:"relative"})):(e.extend(n,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,r){n[r]=t.css(r),isNaN(parseInt(n[r],10))&&(n[r]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(i),r.css(n).show()},removeWrapper:function(t){var n=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===n||e.contains(t[0],n))&&e(n).focus()),t},setTransition:function(t,n,r,i){return i=i||{},e.each(n,function(e,n){var s=t.cssUnit(n);s[0]>0&&(i[n]=s[0]*r+s[1])}),i}}),e.fn.extend({effect:function(t,r,s,o){function h(t){function s(){e.isFunction(r)&&r.call(n[0]),e.isFunction(t)&&t()}var n=e(this),r=u.complete,i=u.mode;(n.is(":hidden")?i==="hide":i==="show")?s():l.call(n[0],u,s)}var u=i.apply(this,arguments),a=u.mode,f=u.queue,l=e.effects.effect[u.effect],c=!l&&n&&e.effects[u.effect];return e.fx.off||!l&&!c?a?this[a](u.duration,u.complete):this.each(function(){u.complete&&u.complete.call(this)}):l?f===!1?this.each(h):this.queue(f||"fx",h):c.call(this,{options:u,duration:u.duration,callback:u.complete,mode:u.mode})},_show:e.fn.show,show:function(e){if(s(e))return this._show.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="show",this.effect.call(this,t)},_hide:e.fn.hide,hide:function(e){if(s(e))return this._hide.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="hide",this.effect.call(this,t)},__toggle:e.fn.toggle,toggle:function(t){if(s(t)||typeof t=="boolean"||e.isFunction(t))return this.__toggle.apply(this,arguments);var n=i.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)},cssUnit:function(t){var n=this.css(t),r=[];return e.each(["em","px","%","pt"],function(e,t){n.indexOf(t)>0&&(r=[parseFloat(n),t])}),r}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,n){t[n]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return e===0||e===1?e:-Math.pow(2,8*(e-1))*Math.sin(((e-1)*80-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){var t,n=4;while(e<((t=Math.pow(2,--n))-1)/11);return 1/Math.pow(4,3-n)-7.5625*Math.pow((t*3-2)/22-e,2)}}),e.each(t,function(t,n){e.easing["easeIn"+t]=n,e.easing["easeOut"+t]=function(e){return 1-n(1-e)},e.easing["easeInOut"+t]=function(e){return e<.5?n(e*2)/2:1-n(e*-2+2)/2}})}()}(jQuery);(function(e,t){var n=/up|down|vertical/,r=/up|left|vertical|horizontal/;e.effects.effect.blind=function(t,i){var s=e(this),o=["position","top","bottom","left","right","height","width"],u=e.effects.setMode(s,t.mode||"hide"),a=t.direction||"up",f=n.test(a),l=f?"height":"width",c=f?"top":"left",h=r.test(a),p={},d=u==="show",v,m,g;s.parent().is(".ui-effects-wrapper")?e.effects.save(s.parent(),o):e.effects.save(s,o),s.show(),v=e.effects.createWrapper(s).css({overflow:"hidden"}),m=v[l](),g=parseFloat(v.css(c))||0,p[l]=d?m:0,h||(s.css(f?"bottom":"right",0).css(f?"top":"left","auto").css({position:"absolute"}),p[c]=d?g:m+g),d&&(v.css(l,0),h||v.css(c,g+m)),v.animate(p,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){u==="hide"&&s.hide(),e.effects.restore(s,o),e.effects.removeWrapper(s),i()}})}})(jQuery);(function(e,t){e.effects.effect.bounce=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=s==="hide",u=s==="show",a=t.direction||"up",f=t.distance,l=t.times||5,c=l*2+(u||o?1:0),h=t.duration/c,p=t.easing,d=a==="up"||a==="down"?"top":"left",v=a==="up"||a==="left",m,g,y,b=r.queue(),w=b.length;(u||o)&&i.push("opacity"),e.effects.save(r,i),r.show(),e.effects.createWrapper(r),f||(f=r[d==="top"?"outerHeight":"outerWidth"]()/3),u&&(y={opacity:1},y[d]=0,r.css("opacity",0).css(d,v?-f*2:f*2).animate(y,h,p)),o&&(f/=Math.pow(2,l-1)),y={},y[d]=0;for(m=0;m1&&b.splice.apply(b,[1,0].concat(b.splice(w,c+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.clip=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"vertical",a=u==="vertical",f=a?"height":"width",l=a?"top":"left",c={},h,p,d;e.effects.save(r,i),r.show(),h=e.effects.createWrapper(r).css({overflow:"hidden"}),p=r[0].tagName==="IMG"?h:r,d=p[f](),o&&(p.css(f,0),p.css(l,d/2)),c[f]=o?d:0,c[l]=o?0:d/2,p.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o||r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.drop=function(t,n){var r=e(this),i=["position","top","bottom","left","right","opacity","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left"?"pos":"neg",l={opacity:o?1:0},c;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),c=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0)/2,o&&r.css("opacity",0).css(a,f==="pos"?-c:c),l[a]=(o?f==="pos"?"+=":"-=":f==="pos"?"-=":"+=")+c,r.animate(l,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.explode=function(t,n){function y(){c.push(this),c.length===r*i&&b()}function b(){s.css({visibility:"visible"}),e(c).remove(),u||s.hide(),n()}var r=t.pieces?Math.round(Math.sqrt(t.pieces)):3,i=r,s=e(this),o=e.effects.setMode(s,t.mode||"hide"),u=o==="show",a=s.show().css("visibility","hidden").offset(),f=Math.ceil(s.outerWidth()/i),l=Math.ceil(s.outerHeight()/r),c=[],h,p,d,v,m,g;for(h=0;h
                                ").css({position:"absolute",visibility:"visible",left:-p*f,top:-h*l}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:f,height:l,left:d+(u?m*f:0),top:v+(u?g*l:0),opacity:u?0:1}).animate({left:d+(u?0:m*f),top:v+(u?0:g*l),opacity:u?1:0},t.duration||500,t.easing,y)}}})(jQuery);(function(e,t){e.effects.effect.fade=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"toggle");r.animate({opacity:i},{queue:!1,duration:t.duration,easing:t.easing,complete:n})}})(jQuery);(function(e,t){e.effects.effect.fold=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=s==="hide",a=t.size||15,f=/([0-9]+)%/.exec(a),l=!!t.horizFirst,c=o!==l,h=c?["width","height"]:["height","width"],p=t.duration/2,d,v,m={},g={};e.effects.save(r,i),r.show(),d=e.effects.createWrapper(r).css({overflow:"hidden"}),v=c?[d.width(),d.height()]:[d.height(),d.width()],f&&(a=parseInt(f[1],10)/100*v[u?0:1]),o&&d.css(l?{height:0,width:a}:{height:a,width:0}),m[h[0]]=o?v[0]:a,g[h[1]]=o?v[1]:0,d.animate(m,p,t.easing).animate(g,p,t.easing,function(){u&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()})}})(jQuery);(function(e,t){e.effects.effect.highlight=function(t,n){var r=e(this),i=["backgroundImage","backgroundColor","opacity"],s=e.effects.setMode(r,t.mode||"show"),o={backgroundColor:r.css("backgroundColor")};s==="hide"&&(o.opacity=0),e.effects.save(r,i),r.show().css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(o,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),n()}})}})(jQuery);(function(e,t){e.effects.effect.pulsate=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"show"),s=i==="show",o=i==="hide",u=s||i==="hide",a=(t.times||5)*2+(u?1:0),f=t.duration/a,l=0,c=r.queue(),h=c.length,p;if(s||!r.is(":visible"))r.css("opacity",0).show(),l=1;for(p=1;p1&&c.splice.apply(c,[1,0].concat(c.splice(h,a+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.puff=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"hide"),s=i==="hide",o=parseInt(t.percent,10)||150,u=o/100,a={height:r.height(),width:r.width()};e.extend(t,{effect:"scale",queue:!1,fade:!0,mode:i,complete:n,percent:s?o:100,from:s?a:{height:a.height*u,width:a.width*u}}),r.effect(t)},e.effects.effect.scale=function(t,n){var r=e(this),i=e.extend(!0,{},t),s=e.effects.setMode(r,t.mode||"effect"),o=parseInt(t.percent,10)||(parseInt(t.percent,10)===0?0:s==="hide"?0:100),u=t.direction||"both",a=t.origin,f={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()},l={y:u!=="horizontal"?o/100:1,x:u!=="vertical"?o/100:1};i.effect="size",i.queue=!1,i.complete=n,s!=="effect"&&(i.origin=a||["middle","center"],i.restore=!0),i.from=t.from||(s==="show"?{height:0,width:0}:f),i.to={height:f.height*l.y,width:f.width*l.x,outerHeight:f.outerHeight*l.y,outerWidth:f.outerWidth*l.x},i.fade&&(s==="show"&&(i.from.opacity=0,i.to.opacity=1),s==="hide"&&(i.from.opacity=1,i.to.opacity=0)),r.effect(i)},e.effects.effect.size=function(t,n){var r=e(this),i=["position","top","bottom","left","right","width","height","overflow","opacity"],s=["position","top","bottom","left","right","overflow","opacity"],o=["width","height","overflow"],u=["fontSize"],a=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],f=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],l=e.effects.setMode(r,t.mode||"effect"),c=t.restore||l!=="effect",h=t.scale||"both",p=t.origin||["middle","center"],d,v,m,g=r.css("position");l==="show"&&r.show(),d={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()},r.from=t.from||d,r.to=t.to||d,m={from:{y:r.from.height/d.height,x:r.from.width/d.width},to:{y:r.to.height/d.height,x:r.to.width/d.width}};if(h==="box"||h==="both")m.from.y!==m.to.y&&(i=i.concat(a),r.from=e.effects.setTransition(r,a,m.from.y,r.from),r.to=e.effects.setTransition(r,a,m.to.y,r.to)),m.from.x!==m.to.x&&(i=i.concat(f),r.from=e.effects.setTransition(r,f,m.from.x,r.from),r.to=e.effects.setTransition(r,f,m.to.x,r.to));(h==="content"||h==="both")&&m.from.y!==m.to.y&&(i=i.concat(u),r.from=e.effects.setTransition(r,u,m.from.y,r.from),r.to=e.effects.setTransition(r,u,m.to.y,r.to)),e.effects.save(r,c?i:s),r.show(),e.effects.createWrapper(r),r.css("overflow","hidden").css(r.from),p&&(v=e.effects.getBaseline(p,d),r.from.top=(d.outerHeight-r.outerHeight())*v.y,r.from.left=(d.outerWidth-r.outerWidth())*v.x,r.to.top=(d.outerHeight-r.to.outerHeight)*v.y,r.to.left=(d.outerWidth-r.to.outerWidth)*v.x),r.css(r.from);if(h==="content"||h==="both")a=a.concat(["marginTop","marginBottom"]).concat(u),f=f.concat(["marginLeft","marginRight"]),o=i.concat(a).concat(f),r.find("*[width]").each(function(){var n=e(this),r={height:n.height(),width:n.width()};c&&e.effects.save(n,o),n.from={height:r.height*m.from.y,width:r.width*m.from.x},n.to={height:r.height*m.to.y,width:r.width*m.to.x},m.from.y!==m.to.y&&(n.from=e.effects.setTransition(n,a,m.from.y,n.from),n.to=e.effects.setTransition(n,a,m.to.y,n.to)),m.from.x!==m.to.x&&(n.from=e.effects.setTransition(n,f,m.from.x,n.from),n.to=e.effects.setTransition(n,f,m.to.x,n.to)),n.css(n.from),n.animate(n.to,t.duration,t.easing,function(){c&&e.effects.restore(n,o)})});r.animate(r.to,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){r.to.opacity===0&&r.css("opacity",r.from.opacity),l==="hide"&&r.hide(),e.effects.restore(r,c?i:s),c||(g==="static"?r.css({position:"relative",top:r.to.top,left:r.to.left}):e.each(["top","left"],function(e,t){r.css(t,function(t,n){var i=parseInt(n,10),s=e?r.to.left:r.to.top;return n==="auto"?s+"px":i+s+"px"})})),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.shake=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=t.direction||"left",u=t.distance||20,a=t.times||3,f=a*2+1,l=Math.round(t.duration/f),c=o==="up"||o==="down"?"top":"left",h=o==="up"||o==="left",p={},d={},v={},m,g=r.queue(),y=g.length;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),p[c]=(h?"-=":"+=")+u,d[c]=(h?"+=":"-=")+u*2,v[c]=(h?"-=":"+=")+u*2,r.animate(p,l,t.easing);for(m=1;m1&&g.splice.apply(g,[1,0].concat(g.splice(y,f+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.slide=function(t,n){var r=e(this),i=["position","top","bottom","left","right","width","height"],s=e.effects.setMode(r,t.mode||"show"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left",l,c={};e.effects.save(r,i),r.show(),l=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0),e.effects.createWrapper(r).css({overflow:"hidden"}),o&&r.css(a,f?isNaN(l)?"-"+l:-l:l),c[a]=(o?f?"+=":"-=":f?"-=":"+=")+l,r.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.transfer=function(t,n){var r=e(this),i=e(t.to),s=i.css("position")==="fixed",o=e("body"),u=s?o.scrollTop():0,a=s?o.scrollLeft():0,f=i.offset(),l={top:f.top-u,left:f.left-a,height:i.innerHeight(),width:i.innerWidth()},c=r.offset(),h=e('
                                ').appendTo(document.body).addClass(t.className).css({top:c.top-u,left:c.left-a,height:r.innerHeight(),width:r.innerWidth(),position:s?"fixed":"absolute"}).animate(l,t.duration,t.easing,function(){h.remove(),n()})}})(jQuery);(function(e,t){var n=!1;e.widget("ui.menu",{version:"1.9.0",defaultElement:"
                                  ",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,e.proxy(function(e){this.options.disabled&&e.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(e){e.preventDefault()},"click .ui-state-disabled > a":function(e){e.preventDefault()},"click .ui-menu-item:has(a)":function(t){var r=e(t.target).closest(".ui-menu-item");!n&&r.not(".ui-state-disabled").length&&(n=!0,this.select(t),r.has(".ui-menu").length?this.expand(t):this.element.is(":focus")||(this.element.trigger("focus",[!0]),this.active&&this.active.parents(".ui-menu").length===1&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){var n=e(t.currentTarget);n.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(t,n)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var n=this.active||this.element.children(".ui-menu-item").eq(0);t||this.focus(e,n)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){e(t.target).closest(".ui-menu").length||this.collapseAll(t),n=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").andSelf().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){function a(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var n,r,i,s,o,u=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:u=!1,r=this.previousFilter||"",i=String.fromCharCode(t.keyCode),s=!1,clearTimeout(this.filterTimer),i===r?s=!0:i=r+i,o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())}),n=s&&n.index(this.active.next())!==-1?this.active.nextAll(".ui-menu-item"):n,n.length||(i=String.fromCharCode(t.keyCode),o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())})),n.length?(this.focus(t,n),n.length>1?(this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}u&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(e):this.select(e))},refresh:function(){var t,n=this.options.icons.submenu,r=this.element.find(this.options.menus+":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"});t=r.add(this.element),t.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),t.children(":not(.ui-menu-item)").each(function(){var t=e(this);/[^\-—–\s]/.test(t.text())||t.addClass("ui-widget-content ui-menu-divider")}),t.children(".ui-state-disabled").attr("aria-disabled","true"),r.each(function(){var t=e(this),r=t.prev("a"),i=e("").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);r.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",r.attr("id"))}),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},focus:function(e,t){var n,r;this.blur(e,e&&e.type==="focus"),this._scrollIntoView(t),this.active=t.first(),r=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",r.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),e&&e.type==="keydown"?this._close():this.timer=this._delay(function(){this._close()},this.delay),n=t.children(".ui-menu"),n.length&&/^mouse/.test(e.type)&&this._startOpening(n),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var n,r,i,s,o,u;this._hasScroll()&&(n=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,r=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,i=t.offset().top-this.activeMenu.offset().top-n-r,s=this.activeMenu.scrollTop(),o=this.activeMenu.height(),u=t.height(),i<0?this.activeMenu.scrollTop(s+i):i+u>o&&this.activeMenu.scrollTop(s+i-o+u))},blur:function(e,t){t||clearTimeout(this.timer);if(!this.active)return;this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active})},_startOpening:function(e){clearTimeout(this.timer);if(e.attr("aria-hidden")!=="true")return;this.timer=this._delay(function(){this._close(),this._open(e)},this.delay)},_open:function(t){var n=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(n)},collapseAll:function(t,n){clearTimeout(this.timer),this.timer=this._delay(function(){var r=n?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));r.length||(r=this.element),this._close(r),this.blur(t),this.activeMenu=r},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,n){var r;this.active&&(e==="first"||e==="last"?r=this.active[e==="first"?"prevAll":"nextAll"](".ui-menu-item").eq(-1):r=this.active[e+"All"](".ui-menu-item").eq(0));if(!r||!r.length||!this.active)r=this.activeMenu.children(".ui-menu-item")[t]();this.focus(n,r)},nextPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isLastItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r-i<0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())},previousPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isFirstItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r+i>0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item").first())},_hasScroll:function(){return this.element.outerHeight()
                                ").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(e){return e===t?this._value():(this._setOption("value",e),this)},_setOption:function(e,t){e==="value"&&(this.options.value=t,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),this._super(e,t)},_value:function(){var e=this.options.value;return typeof e!="number"&&(e=0),Math.min(this.options.max,Math.max(this.min,e))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var e=this.value(),t=this._percentage();this.oldValue!==e&&(this.oldValue=e,this._trigger("change")),this.valueDiv.toggle(e>this.min).toggleClass("ui-corner-right",e===this.options.max).width(t.toFixed(0)+"%"),this.element.attr("aria-valuenow",e)}})})(jQuery);(function(e,t){e.widget("ui.resizable",e.ui.mouse,{version:"1.9.0",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1e3},_create:function(){var t=this,n=this.options;this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!n.aspectRatio,aspectRatio:n.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:n.helper||n.ghost||n.animate?n.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e('
                                ').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data("resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=n.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne,nw");var r=this.handles.split(",");this.handles={};for(var i=0;i
                                ');u.css({zIndex:n.zIndex}),"se"==s&&u.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(u)}}this._renderAxis=function(t){t=t||this.element;for(var n in this.handles){this.handles[n].constructor==String&&(this.handles[n]=e(this.handles[n],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var r=e(this.handles[n],this.element),i=0;i=/sw|ne|nw|se|n|s/.test(n)?r.outerHeight():r.outerWidth();var s=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");t.css(s,i),this._proportionallyResize()}if(!e(this.handles[n]).length)continue}},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){if(!t.resizing){if(this.className)var e=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);t.axis=e&&e[1]?e[1]:"se"}}),n.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){if(n.disabled)return;e(this).removeClass("ui-resizable-autohide"),t._handles.show()}).mouseleave(function(){if(n.disabled)return;t.resizing||(e(this).addClass("ui-resizable-autohide"),t._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){t(this.element);var n=this.element;n.after(this.originalElement.css({position:n.css("position"),width:n.outerWidth(),height:n.outerHeight(),top:n.css("top"),left:n.css("left")})).remove()}return this.originalElement.css("resize",this.originalResizeStyle),t(this.originalElement),this},_mouseCapture:function(t){var n=!1;for(var r in this.handles)e(this.handles[r])[0]==t.target&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(t){var r=this.options,i=this.element.position(),s=this.element;this.resizing=!0,this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()},(s.is(".ui-draggable")||/absolute/.test(s.css("position")))&&s.css({position:"absolute",top:i.top,left:i.left}),this._renderProxy();var o=n(this.helper.css("left")),u=n(this.helper.css("top"));r.containment&&(o+=e(r.containment).scrollLeft()||0,u+=e(r.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:o,top:u},this.size=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalSize=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalPosition={left:o,top:u},this.sizeDiff={width:s.outerWidth()-s.width(),height:s.outerHeight()-s.height()},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio=typeof r.aspectRatio=="number"?r.aspectRatio:this.originalSize.width/this.originalSize.height||1;var a=e(".ui-resizable-"+this.axis).css("cursor");return e("body").css("cursor",a=="auto"?this.axis+"-resize":a),s.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(e){var t=this.helper,n=this.options,r={},i=this,s=this.originalMousePosition,o=this.axis,u=e.pageX-s.left||0,a=e.pageY-s.top||0,f=this._change[o];if(!f)return!1;var l=f.apply(this,[e,u,a]);this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey)l=this._updateRatio(l,e);return l=this._respectSize(l,e),this._propagate("resize",e),t.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigger("resize",e,this.ui()),!1},_mouseStop:function(t){this.resizing=!1;var n=this.options,r=this;if(this._helper){var i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),o=s&&e.ui.hasScroll(i[0],"left")?0:r.sizeDiff.height,u=s?0:r.sizeDiff.width,a={width:r.helper.width()-u,height:r.helper.height()-o},f=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,l=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;n.animate||this.element.css(e.extend(a,{top:l,left:f})),r.helper.height(r.size.height),r.helper.width(r.size.width),this._helper&&!n.animate&&this._proportionallyResize()}return e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t=this.options,n,i,s,o,u;u={minWidth:r(t.minWidth)?t.minWidth:0,maxWidth:r(t.maxWidth)?t.maxWidth:Infinity,minHeight:r(t.minHeight)?t.minHeight:0,maxHeight:r(t.maxHeight)?t.maxHeight:Infinity};if(this._aspectRatio||e)n=u.minHeight*this.aspectRatio,s=u.minWidth/this.aspectRatio,i=u.maxHeight*this.aspectRatio,o=u.maxWidth/this.aspectRatio,n>u.minWidth&&(u.minWidth=n),s>u.minHeight&&(u.minHeight=s),ie.width,l=r(e.height)&&i.minHeight&&i.minHeight>e.height;f&&(e.width=i.minWidth),l&&(e.height=i.minHeight),u&&(e.width=i.maxWidth),a&&(e.height=i.maxHeight);var c=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,p=/sw|nw|w/.test(o),d=/nw|ne|n/.test(o);f&&p&&(e.left=c-i.minWidth),u&&p&&(e.left=c-i.maxWidth),l&&d&&(e.top=h-i.minHeight),a&&d&&(e.top=h-i.maxHeight);var v=!e.width&&!e.height;return v&&!e.left&&e.top?e.top=null:v&&!e.top&&e.left&&(e.left=null),e},_proportionallyResize:function(){var t=this.options;if(!this._proportionallyResizeElements.length)return;var n=this.helper||this.element;for(var r=0;r
                                ');var r=e.browser.msie&&e.browser.version<7,i=r?1:0,s=r?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+s,height:this.element.outerHeight()+s,position:"absolute",left:this.elementOffset.left-i+"px",top:this.elementOffset.top-i+"px",zIndex:++n.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(e,t,n){return{width:this.originalSize.width+t}},w:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{top:s.top+n,height:i.height-n}},s:function(e,t,n){return{height:this.originalSize.height+n}},se:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},sw:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,n,r]))},ne:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},nw:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,n,r]))}},_propagate:function(t,n){e.ui.plugin.call(this,t,[n,this.ui()]),t!="resize"&&this._trigger(t,n,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","alsoResize",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=function(t){e(t).each(function(){var t=e(this);t.data("resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};typeof i.alsoResize=="object"&&!i.alsoResize.parentNode?i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)}):s(i.alsoResize)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.originalSize,o=r.originalPosition,u={height:r.size.height-s.height||0,width:r.size.width-s.width||0,top:r.position.top-o.top||0,left:r.position.left-o.left||0},a=function(t,r){e(t).each(function(){var t=e(this),i=e(this).data("resizable-alsoresize"),s={},o=r&&r.length?r:t.parents(n.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var n=(i[t]||0)+(u[t]||0);n&&n>=0&&(s[t]=n||null)}),t.css(s)})};typeof i.alsoResize=="object"&&!i.alsoResize.nodeType?e.each(i.alsoResize,function(e,t){a(e,t)}):a(i.alsoResize)},stop:function(t,n){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","animate",{stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r._proportionallyResizeElements,o=s.length&&/textarea/i.test(s[0].nodeName),u=o&&e.ui.hasScroll(s[0],"left")?0:r.sizeDiff.height,a=o?0:r.sizeDiff.width,f={width:r.size.width-a,height:r.size.height-u},l=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,c=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;r.element.animate(e.extend(f,c&&l?{top:c,left:l}:{}),{duration:i.animateDuration,easing:i.animateEasing,step:function(){var n={width:parseInt(r.element.css("width"),10),height:parseInt(r.element.css("height"),10),top:parseInt(r.element.css("top"),10),left:parseInt(r.element.css("left"),10)};s&&s.length&&e(s[0]).css({width:n.width,height:n.height}),r._updateCache(n),r._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(t,r){var i=e(this).data("resizable"),s=i.options,o=i.element,u=s.containment,a=u instanceof e?u.get(0):/parent/.test(u)?o.parent().get(0):u;if(!a)return;i.containerElement=e(a);if(/document/.test(u)||u==document)i.containerOffset={left:0,top:0},i.containerPosition={left:0,top:0},i.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight};else{var f=e(a),l=[];e(["Top","Right","Left","Bottom"]).each(function(e,t){l[e]=n(f.css("padding"+t))}),i.containerOffset=f.offset(),i.containerPosition=f.position(),i.containerSize={height:f.innerHeight()-l[3],width:f.innerWidth()-l[1]};var c=i.containerOffset,h=i.containerSize.height,p=i.containerSize.width,d=e.ui.hasScroll(a,"left")?a.scrollWidth:p,v=e.ui.hasScroll(a)?a.scrollHeight:h;i.parentData={element:a,left:c.left,top:c.top,width:d,height:v}}},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.containerSize,o=r.containerOffset,u=r.size,a=r.position,f=r._aspectRatio||t.shiftKey,l={top:0,left:0},c=r.containerElement;c[0]!=document&&/static/.test(c.css("position"))&&(l=o),a.left<(r._helper?o.left:0)&&(r.size.width=r.size.width+(r._helper?r.position.left-o.left:r.position.left-l.left),f&&(r.size.height=r.size.width/r.aspectRatio),r.position.left=i.helper?o.left:0),a.top<(r._helper?o.top:0)&&(r.size.height=r.size.height+(r._helper?r.position.top-o.top:r.position.top),f&&(r.size.width=r.size.height*r.aspectRatio),r.position.top=r._helper?o.top:0),r.offset.left=r.parentData.left+r.position.left,r.offset.top=r.parentData.top+r.position.top;var h=Math.abs((r._helper?r.offset.left-l.left:r.offset.left-l.left)+r.sizeDiff.width),p=Math.abs((r._helper?r.offset.top-l.top:r.offset.top-o.top)+r.sizeDiff.height),d=r.containerElement.get(0)==r.element.parent().get(0),v=/relative|absolute/.test(r.containerElement.css("position"));d&&v&&(h-=r.parentData.left),h+r.size.width>=r.parentData.width&&(r.size.width=r.parentData.width-h,f&&(r.size.height=r.size.width/r.aspectRatio)),p+r.size.height>=r.parentData.height&&(r.size.height=r.parentData.height-p,f&&(r.size.width=r.size.height*r.aspectRatio))},stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.position,o=r.containerOffset,u=r.containerPosition,a=r.containerElement,f=e(r.helper),l=f.offset(),c=f.outerWidth()-r.sizeDiff.width,h=f.outerHeight()-r.sizeDiff.height;r._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h}),r._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h})}}),e.ui.plugin.add("resizable","ghost",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size;r.ghost=r.originalElement.clone(),r.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:""),r.ghost.appendTo(r.helper)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.ghost.css({position:"relative",height:r.size.height,width:r.size.width})},stop:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.helper&&r.helper.get(0).removeChild(r.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size,o=r.originalSize,u=r.originalPosition,a=r.axis,f=i._aspectRatio||t.shiftKey;i.grid=typeof i.grid=="number"?[i.grid,i.grid]:i.grid;var l=Math.round((s.width-o.width)/(i.grid[0]||1))*(i.grid[0]||1),c=Math.round((s.height-o.height)/(i.grid[1]||1))*(i.grid[1]||1);/^(se|s|e)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c):/^(ne)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c):/^(sw)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.left=u.left-l):(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c,r.position.left=u.left-l)}});var n=function(e){return parseInt(e,10)||0},r=function(e){return!isNaN(parseInt(e,10))}})(jQuery);(function(e,t){e.widget("ui.selectable",e.ui.mouse,{version:"1.9.0",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch"},_create:function(){var t=this;this.element.addClass("ui-selectable"),this.dragged=!1;var n;this.refresh=function(){n=e(t.options.filter,t.element[0]),n.addClass("ui-selectee"),n.each(function(){var t=e(this),n=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:n.left,top:n.top,right:n.left+t.outerWidth(),bottom:n.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=n.addClass("ui-selectee"),this._mouseInit(),this.helper=e("
                                ")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var n=this;this.opos=[t.pageX,t.pageY];if(this.options.disabled)return;var r=this.options;this.selectees=e(r.filter,this.element[0]),this._trigger("start",t),e(r.appendTo).append(this.helper),this.helper.css({left:t.clientX,top:t.clientY,width:0,height:0}),r.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var r=e.data(this,"selectable-item");r.startselected=!0,!t.metaKey&&!t.ctrlKey&&(r.$element.removeClass("ui-selected"),r.selected=!1,r.$element.addClass("ui-unselecting"),r.unselecting=!0,n._trigger("unselecting",t,{unselecting:r.element}))}),e(t.target).parents().andSelf().each(function(){var r=e.data(this,"selectable-item");if(r){var i=!t.metaKey&&!t.ctrlKey||!r.$element.hasClass("ui-selected");return r.$element.removeClass(i?"ui-unselecting":"ui-selected").addClass(i?"ui-selecting":"ui-unselecting"),r.unselecting=!i,r.selecting=i,r.selected=i,i?n._trigger("selecting",t,{selecting:r.element}):n._trigger("unselecting",t,{unselecting:r.element}),!1}})},_mouseDrag:function(t){var n=this;this.dragged=!0;if(this.options.disabled)return;var r=this.options,i=this.opos[0],s=this.opos[1],o=t.pageX,u=t.pageY;if(i>o){var a=o;o=i,i=a}if(s>u){var a=u;u=s,s=a}return this.helper.css({left:i,top:s,width:o-i,height:u-s}),this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!a||a.element==n.element[0])return;var f=!1;r.tolerance=="touch"?f=!(a.left>o||a.rightu||a.bottomi&&a.rights&&a.bottom").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(r.range==="min"||r.range==="max"?" ui-slider-range-"+r.range:"")));for(t=i.length;tn&&(i=n,s=e(this),o=t)}),c.range===!0&&this.values(1)===c.min&&(o+=1,s=e(this.handles[o])),u=this._start(t,o),u===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,s.addClass("ui-state-active").focus(),a=s.offset(),f=!e(t.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=f?{left:0,top:0}:{left:t.pageX-a.left-s.width()/2,top:t.pageY-a.top-s.height()/2-(parseInt(s.css("borderTopWidth"),10)||0)-(parseInt(s.css("borderBottomWidth"),10)||0)+(parseInt(s.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(t,o,r),this._animateOff=!0,!0))},_mouseStart:function(e){return!0},_mouseDrag:function(e){var t={x:e.pageX,y:e.pageY},n=this._normValueFromMouse(t);return this._slide(e,this._handleIndex,n),!1},_mouseStop:function(e){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(e,this._handleIndex),this._change(e,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(e){var t,n,r,i,s;return this.orientation==="horizontal"?(t=this.elementSize.width,n=e.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(t=this.elementSize.height,n=e.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),r=n/t,r>1&&(r=1),r<0&&(r=0),this.orientation==="vertical"&&(r=1-r),i=this._valueMax()-this._valueMin(),s=this._valueMin()+r*i,this._trimAlignValue(s)},_start:function(e,t){var n={handle:this.handles[t],value:this.value()};return this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("start",e,n)},_slide:function(e,t,n){var r,i,s;this.options.values&&this.options.values.length?(r=this.values(t?0:1),this.options.values.length===2&&this.options.range===!0&&(t===0&&n>r||t===1&&n1){this.options.values[t]=this._trimAlignValue(n),this._refreshValue(),this._change(null,t);return}if(!arguments.length)return this._values();if(!e.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(t):this.value();r=this.options.values,i=arguments[0];for(s=0;s=this._valueMax())return this._valueMax();var t=this.options.step>0?this.options.step:1,n=(e-this._valueMin())%t,r=e-n;return Math.abs(n)*2>=t&&(r+=n>0?t:-t),parseFloat(r.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var t,n,r,i,s,o=this.options.range,u=this.options,a=this,f=this._animateOff?!1:u.animate,l={};this.options.values&&this.options.values.length?this.handles.each(function(r,i){n=(a.values(r)-a._valueMin())/(a._valueMax()-a._valueMin())*100,l[a.orientation==="horizontal"?"left":"bottom"]=n+"%",e(this).stop(1,1)[f?"animate":"css"](l,u.animate),a.options.range===!0&&(a.orientation==="horizontal"?(r===0&&a.range.stop(1,1)[f?"animate":"css"]({left:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({width:n-t+"%"},{queue:!1,duration:u.animate})):(r===0&&a.range.stop(1,1)[f?"animate":"css"]({bottom:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({height:n-t+"%"},{queue:!1,duration:u.animate}))),t=n}):(r=this.value(),i=this._valueMin(),s=this._valueMax(),n=s!==i?(r-i)/(s-i)*100:0,l[this.orientation==="horizontal"?"left":"bottom"]=n+"%",this.handle.stop(1,1)[f?"animate":"css"](l,u.animate),o==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[f?"animate":"css"]({width:n+"%"},u.animate),o==="max"&&this.orientation==="horizontal"&&this.range[f?"animate":"css"]({width:100-n+"%"},{queue:!1,duration:u.animate}),o==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[f?"animate":"css"]({height:n+"%"},u.animate),o==="max"&&this.orientation==="vertical"&&this.range[f?"animate":"css"]({height:100-n+"%"},{queue:!1,duration:u.animate}))}})})(jQuery);(function(e,t){e.widget("ui.sortable",e.ui.mouse,{version:"1.9.0",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?e.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_setOption:function(t,n){t==="disabled"?(this.options[t]=n,this.widget().toggleClass("ui-sortable-disabled",!!n)):e.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(t,n){var r=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(t);var i=null,s=e(t.target).parents().each(function(){if(e.data(this,r.widgetName+"-item")==r)return i=e(this),!1});e.data(t.target,r.widgetName+"-item")==r&&(i=e(t.target));if(!i)return!1;if(this.options.handle&&!n){var o=!1;e(this.options.handle,i).find("*").andSelf().each(function(){this==t.target&&(o=!0)});if(!o)return!1}return this.currentItem=i,this._removeCurrentsFromItems(),!0},_mouseStart:function(t,n,r){var i=this.options;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),i.containment&&this._setContainment(),i.cursor&&(e("body").css("cursor")&&(this._storedCursor=e("body").css("cursor")),e("body").css("cursor",i.cursor)),i.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",i.opacity)),i.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",i.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!r)for(var s=this.containers.length-1;s>=0;s--)this.containers[s]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var n=this.options,r=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY=0;i--){var s=this.items[i],o=s.item[0],u=this._intersectsWithPointer(s);if(!u)continue;if(s.instance!==this.currentContainer)continue;if(o!=this.currentItem[0]&&this.placeholder[u==1?"next":"prev"]()[0]!=o&&!e.contains(this.placeholder[0],o)&&(this.options.type=="semi-dynamic"?!e.contains(this.element[0],o):!0)){this.direction=u==1?"down":"up";if(this.options.tolerance!="pointer"&&!this._intersectsWithSides(s))break;this._rearrange(t,s),this._trigger("change",t,this._uiHash());break}}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,n){if(!t)return;e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t);if(this.options.revert){var r=this,i=this.placeholder.offset();this.reverting=!0,e(this.helper).animate({left:i.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:i.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){r._clear(t)})}else this._clear(t,n);return!1},cancel:function(){if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},e(n).each(function(){var n=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[-=_](.+)/);n&&r.push((t.key||n[1]+"[]")+"="+(t.key&&t.expression?n[1]:n[2]))}),!r.length&&t.key&&r.push(t.key+"="),r.join("&")},toArray:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},n.each(function(){r.push(e(t.item||this).attr(t.attribute||"id")||"")}),r},_intersectsWith:function(e){var t=this.positionAbs.left,n=t+this.helperProportions.width,r=this.positionAbs.top,i=r+this.helperProportions.height,s=e.left,o=s+e.width,u=e.top,a=u+e.height,f=this.offset.click.top,l=this.offset.click.left,c=r+f>u&&r+fs&&t+le[this.floating?"width":"height"]?c:s0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return e!=0&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor==String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){var n=[],r=[],i=this._connectWith();if(i&&t)for(var s=i.length-1;s>=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&r.push([e.isFunction(a.options.items)?a.options.items.call(a.element):e(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a])}}r.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var s=r.length-1;s>=0;s--)r[s][0].each(function(){n.push(this)});return e(n)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");for(var t=0;t=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&(r.push([e.isFunction(a.options.items)?a.options.items.call(a.element[0],t,{item:this.currentItem}):e(a.options.items,a.element),a]),this.containers.push(a))}}for(var s=r.length-1;s>=0;s--){var f=r[s][1],l=r[s][0];for(var u=0,c=l.length;u=0;n--){var r=this.items[n];if(r.instance!=this.currentContainer&&this.currentContainer&&r.item[0]!=this.currentItem[0])continue;var i=this.options.toleranceElement?e(this.options.toleranceElement,r.item):r.item;t||(r.width=i.outerWidth(),r.height=i.outerHeight());var s=i.offset();r.left=s.left,r.top=s.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var n=this.containers.length-1;n>=0;n--){var s=this.containers[n].element.offset();this.containers[n].containerCache.left=s.left,this.containers[n].containerCache.top=s.top,this.containers[n].containerCache.width=this.containers[n].element.outerWidth(),this.containers[n].containerCache.height=this.containers[n].element.outerHeight()}return this},_createPlaceholder:function(t){t=t||this;var n=t.options;if(!n.placeholder||n.placeholder.constructor==String){var r=n.placeholder;n.placeholder={element:function(){var n=e(document.createElement(t.currentItem[0].nodeName)).addClass(r||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return r||(n.style.visibility="hidden"),n},update:function(e,i){if(r&&!n.forcePlaceholderSize)return;i.height()||i.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),i.width()||i.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10))}}}t.placeholder=e(n.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),n.placeholder.update(t,t.placeholder)},_contactContainers:function(t){var n=null,r=null;for(var i=this.containers.length-1;i>=0;i--){if(e.contains(this.currentItem[0],this.containers[i].element[0]))continue;if(this._intersectsWith(this.containers[i].containerCache)){if(n&&e.contains(this.containers[i].element[0],n.element[0]))continue;n=this.containers[i],r=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",t,this._uiHash(this)),this.containers[i].containerCache.over=0)}if(!n)return;if(this.containers.length===1)this.containers[r]._trigger("over",t,this._uiHash(this)),this.containers[r].containerCache.over=1;else if(this.currentContainer!=this.containers[r]){var s=1e4,o=null,u=this.positionAbs[this.containers[r].floating?"left":"top"];for(var a=this.items.length-1;a>=0;a--){if(!e.contains(this.containers[r].element[0],this.items[a].item[0]))continue;var f=this.containers[r].floating?this.items[a].item.offset().left:this.items[a].item.offset().top;Math.abs(f-u)0?"down":"up")}if(!o&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[r],o?this._rearrange(t,o,null,!0):this._rearrange(t,null,this.containers[r].element,!0),this._trigger("change",t,this._uiHash()),this.containers[r]._trigger("change",t,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[r]._trigger("over",t,this._uiHash(this)),this.containers[r].containerCache.over=1}},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t,this.currentItem])):n.helper=="clone"?this.currentItem.clone():this.currentItem;return r.parents("body").length||e(n.appendTo!="parent"?n.appendTo:this.currentItem[0].parentNode)[0].appendChild(r[0]),r[0]==this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(r[0].style.width==""||n.forceHelperSize)&&r.width(this.currentItem.width()),(r[0].style.height==""||n.forceHelperSize)&&r.height(this.currentItem.height()),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&e.browser.msie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t=this.options;t.containment=="parent"&&(t.containment=this.helper[0].parentNode);if(t.containment=="document"||t.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,e(t.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(e(t.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(t.containment)){var n=e(t.containment)[0],r=e(t.containment).offset(),i=e(n).css("overflow")!="hidden";this.containment=[r.left+(parseInt(e(n).css("borderLeftWidth"),10)||0)+(parseInt(e(n).css("paddingLeft"),10)||0)-this.margins.left,r.top+(parseInt(e(n).css("borderTopWidth"),10)||0)+(parseInt(e(n).css("paddingTop"),10)||0)-this.margins.top,r.left+(i?Math.max(n.scrollWidth,n.offsetWidth):n.offsetWidth)-(parseInt(e(n).css("borderLeftWidth"),10)||0)-(parseInt(e(n).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,r.top+(i?Math.max(n.scrollHeight,n.offsetHeight):n.offsetHeight)-(parseInt(e(n).css("borderTopWidth"),10)||0)-(parseInt(e(n).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(t,n){n||(n=this.position);var r=t=="absolute"?1:-1,i=this.options,s=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(s[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():o?0:s.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():o?0:s.scrollLeft())*r}},_generatePosition:function(t){var n=this.options,r=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,i=/(html|body)/i.test(r[0].tagName);this.cssPosition=="relative"&&(this.scrollParent[0]==document||this.scrollParent[0]==this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset());var s=t.pageX,o=t.pageY;if(this.originalPosition){this.containment&&(t.pageX-this.offset.click.leftthis.containment[2]&&(s=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top));if(n.grid){var u=this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1];o=this.containment?u-this.offset.click.topthis.containment[3]?u-this.offset.click.topthis.containment[2]?a-this.offset.click.left=0;i--)n||r.push(function(e){return function(t){e._trigger("deactivate",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over&&(r.push(function(e){return function(t){e._trigger("out",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over=0);this._storedCursor&&e("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!n){this._trigger("beforeStop",t,this._uiHash());for(var i=0;i",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var t={},n=this.element;return e.each(["min","max","step"],function(e,r){var i=n.attr(r);i!==undefined&&i.length&&(t[r]=i)}),t},_events:{keydown:function(e){this._start(e)&&this._keydown(e)&&e.preventDefault()},keyup:"_stop",focus:function(){this.uiSpinner.addClass("ui-state-active"),this.previous=this.element.val()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}this._refresh(),this.uiSpinner.removeClass("ui-state-active"),this.previous!==this.element.val()&&this._trigger("change",e)},mousewheel:function(e,t){if(!t)return;if(!this.spinning&&!this._start(e))return!1;this._spin((t>0?1:-1)*this.options.step,e),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(e)},100),e.preventDefault()},"mousedown .ui-spinner-button":function(t){function r(){var e=this.element[0]===this.document[0].activeElement;e||(this.element.focus(),this.previous=n,this._delay(function(){this.previous=n}))}var n;n=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),t.preventDefault(),r.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,r.call(this)});if(this._start(t)===!1)return;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(t){if(!e(t.currentTarget).hasClass("ui-state-active"))return;if(this._start(t)===!1)return!1;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var e=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this._hoverable(e),this.element.attr("role","spinbutton"),this.buttons=e.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(e.height()*.5)&&e.height()>0&&e.height(e.height()),this.options.disabled&&this.disable()},_keydown:function(t){var n=this.options,r=e.ui.keyCode;switch(t.keyCode){case r.UP:return this._repeat(null,1,t),!0;case r.DOWN:return this._repeat(null,-1,t),!0;case r.PAGE_UP:return this._repeat(null,n.page,t),!0;case r.PAGE_DOWN:return this._repeat(null,-n.page,t),!0}return!1},_uiSpinnerHtml:function(){return""},_buttonHtml:function(){return""+""+""+""+""},_start:function(e){return!this.spinning&&this._trigger("start",e)===!1?!1:(this.counter||(this.counter=1),this.spinning=!0,!0)},_repeat:function(e,t,n){e=e||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,t,n)},e),this._spin(t*this.options.step,n)},_spin:function(e,t){var n=this.value()||0;this.counter||(this.counter=1),n=this._adjustValue(n+e*this._increment(this.counter));if(!this.spinning||this._trigger("spin",t,{value:n})!==!1)this._value(n),this.counter++},_increment:function(t){var n=this.options.incremental;return n?e.isFunction(n)?n(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var e=this._precisionOf(this.options.step);return this.options.min!==null&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=e.toString(),n=t.indexOf(".");return n===-1?0:t.length-n-1},_adjustValue:function(e){var t,n,r=this.options;return t=r.min!==null?r.min:0,n=e-t,n=Math.round(n/r.step)*r.step,e=t+n,e=parseFloat(e.toFixed(this._precision())),r.max!==null&&e>r.max?r.max:r.min!==null&&e1&&e.href.replace(r,"")===location.href.replace(r,"")}var n=0,r=/#.*$/;e.widget("ui.tabs",{version:"1.9.0",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var t,n=this,r=this.options,i=r.active;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",r.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs();if(i===null){location.hash&&this.anchors.each(function(e,t){if(t.hash===location.hash)return i=e,!1}),i===null&&(i=this.tabs.filter(".ui-tabs-active").index());if(i===null||i===-1)i=this.tabs.length?0:!1}i!==!1&&(i=this.tabs.index(this.tabs.eq(i)),i===-1&&(i=r.collapsible?!1:0)),r.active=i,!r.collapsible&&r.active===!1&&this.anchors.length&&(r.active=0),e.isArray(r.disabled)&&(r.disabled=e.unique(r.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return n.tabs.index(e)}))).sort()),this.options.active!==!1&&this.anchors.length?this.active=this._findActive(this.options.active):this.active=e(),this._refresh(),this.active.length&&this.load(r.active)},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var n=e(this.document[0].activeElement).closest("li"),r=this.tabs.index(n),i=!0;if(this._handlePageNav(t))return;switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:r++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:i=!1,r--;break;case e.ui.keyCode.END:r=this.anchors.length-1;break;case e.ui.keyCode.HOME:r=0;break;case e.ui.keyCode.SPACE:t.preventDefault(),clearTimeout(this.activating),this._activate(r);return;case e.ui.keyCode.ENTER:t.preventDefault(),clearTimeout(this.activating),this._activate(r===this.options.active?!1:r);return;default:return}t.preventDefault(),clearTimeout(this.activating),r=this._focusNextTab(r,i),t.ctrlKey||(n.attr("aria-selected","false"),this.tabs.eq(r).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",r)},this.delay))},_panelKeydown:function(t){if(this._handlePageNav(t))return;t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP)return this._activate(this._focusNextTab(this.options.active-1,!1)),!0;if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN)return this._activate(this._focusNextTab(this.options.active+1,!0)),!0},_findNextTab:function(t,n){function i(){return t>r&&(t=0),t<0&&(t=r),t}var r=this.tabs.length-1;while(e.inArray(i(),this.options.disabled)!==-1)t=n?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){if(e==="active"){this._activate(t);return}if(e==="disabled"){this._setupDisabled(t);return}this._super(e,t),e==="collapsible"&&(this.element.toggleClass("ui-tabs-collapsible",t),!t&&this.options.active===!1&&this._activate(0)),e==="event"&&this._setupEvents(t),e==="heightStyle"&&this._setupHeightStyle(t)},_tabId:function(e){return e.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t,n=this.options,r=this.tablist.children(":has(a[href])");n.disabled=e.map(r.filter(".ui-state-disabled"),function(e){return r.index(e)}),this._processTabs(),n.active===!1||!this.anchors.length?(n.active=!1,this.active=e()):this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===n.disabled.length?(n.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,n.active-1),!1)):n.active=this.tabs.index(this.active),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(n,r){var i,o,u,a=e(r).uniqueId().attr("id"),f=e(r).closest("li"),l=f.attr("aria-controls");s(r)?(i=r.hash,o=t.element.find(t._sanitizeSelector(i))):(u=t._tabId(f),i="#"+u,o=t.element.find(i),o.length||(o=t._createPanel(u),o.insertAfter(t.panels[n-1]||t.tablist)),o.attr("aria-live","polite")),o.length&&(t.panels=t.panels.add(o)),l&&f.data("ui-tabs-aria-controls",l),f.attr({"aria-controls":i.substring(1),"aria-labelledby":a}),o.attr("aria-labelledby",a)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("
                                ").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var n=0,r;r=this.tabs[n];n++)t===!0||e.inArray(n,t)!==-1?e(r).addClass("ui-state-disabled").attr("aria-disabled","true"):e(r).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var n={click:function(e){e.preventDefault()}};t&&e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,n),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var n,r,i=this.element.parent();t==="fill"?(e.support.minHeight||(r=i.css("overflow"),i.css("overflow","hidden")),n=i.height(),this.element.siblings(":visible").each(function(){var t=e(this),r=t.css("position");if(r==="absolute"||r==="fixed")return;n-=t.outerHeight(!0)}),r&&i.css("overflow",r),this.element.children().not(this.panels).each(function(){n-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,n-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):t==="auto"&&(n=0,this.panels.each(function(){n=Math.max(n,e(this).height("").height())}).height(n))},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i.closest("li"),o=s[0]===r[0],u=o&&n.collapsible,a=u?e():this._getPanelForTab(s),f=r.length?this._getPanelForTab(r):e(),l={oldTab:r,oldPanel:f,newTab:u?e():s,newPanel:a};t.preventDefault();if(s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||o&&!n.collapsible||this._trigger("beforeActivate",t,l)===!1)return;n.active=u?!1:this.tabs.index(s),this.active=o?e():s,this.xhr&&this.xhr.abort(),!f.length&&!a.length&&e.error("jQuery UI Tabs: Mismatching fragment identifier."),a.length&&this.load(this.tabs.index(s),t),this._toggle(t,l)},_toggle:function(t,n){function o(){r.running=!1,r._trigger("activate",t,n)}function u(){n.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),i.length&&r.options.show?r._show(i,r.options.show,o):(i.show(),o())}var r=this,i=n.newPanel,s=n.oldPanel;this.running=!0,s.length&&this.options.hide?this._hide(s,this.options.hide,function(){n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),s.hide(),u()),s.attr({"aria-expanded":"false","aria-hidden":"true"}),n.oldTab.attr("aria-selected","false"),i.length&&s.length?n.oldTab.attr("tabIndex",-1):i.length&&this.tabs.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),i.attr({"aria-expanded":"true","aria-hidden":"false"}),n.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(t){var n,r=this._findActive(t);if(r[0]===this.active[0])return;r.length||(r=this.active),n=r.find(".ui-tabs-anchor")[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return typeof e=="string"&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeData("href.tabs").removeData("load.tabs").removeUniqueId(),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),n=t.data("ui-tabs-aria-controls");n?t.attr("aria-controls",n):t.removeAttr("aria-controls")}),this.options.heightStyle!=="content"&&this.panels.css("height","")},enable:function(n){var r=this.options.disabled;if(r===!1)return;n===t?r=!1:(n=this._getIndex(n),e.isArray(r)?r=e.map(r,function(e){return e!==n?e:null}):r=e.map(this.tabs,function(e,t){return t!==n?t:null})),this._setupDisabled(r)},disable:function(n){var r=this.options.disabled;if(r===!0)return;if(n===t)r=!0;else{n=this._getIndex(n);if(e.inArray(n,r)!==-1)return;e.isArray(r)?r=e.merge([n],r).sort():r=[n]}this._setupDisabled(r)},load:function(t,n){t=this._getIndex(t);var r=this,i=this.tabs.eq(t),o=i.find(".ui-tabs-anchor"),u=this._getPanelForTab(i),a={tab:i,panel:u};if(s(o[0]))return;this.xhr=e.ajax(this._ajaxSettings(o,n,a)),this.xhr&&this.xhr.statusText!=="canceled"&&(i.addClass("ui-tabs-loading"),u.attr("aria-busy","true"),this.xhr.success(function(e){setTimeout(function(){u.html(e),r._trigger("load",n,a)},1)}).complete(function(e,t){setTimeout(function(){t==="abort"&&r.panels.stop(!1,!0),i.removeClass("ui-tabs-loading"),u.removeAttr("aria-busy"),e===r.xhr&&delete r.xhr},1)}))},_ajaxSettings:function(t,n,r){var i=this;return{url:t.attr("href"),beforeSend:function(t,s){return i._trigger("beforeLoad",n,e.extend({jqXHR:t,ajaxSettings:s},r))}}},_getPanelForTab:function(t){var n=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+n))}}),e.uiBackCompat!==!1&&(e.ui.tabs.prototype._ui=function(e,t){return{tab:e,panel:t,index:this.anchors.index(e)}},e.widget("ui.tabs",e.ui.tabs,{url:function(e,t){this.anchors.eq(e).attr("href",t)}}),e.widget("ui.tabs",e.ui.tabs,{options:{ajaxOptions:null,cache:!1},_create:function(){this._super();var t=this;this._on({tabsbeforeload:function(n,r){if(e.data(r.tab[0],"cache.tabs")){n.preventDefault();return}r.jqXHR.success(function(){t.options.cache&&e.data(r.tab[0],"cache.tabs",!0)})}})},_ajaxSettings:function(t,n,r){var i=this.options.ajaxOptions;return e.extend({},i,{error:function(e,t,n){try{i.error(e,t,r.tab.closest("li").index(),r.tab[0])}catch(n){}}},this._superApply(arguments))},_setOption:function(e,t){e==="cache"&&t===!1&&this.anchors.removeData("cache.tabs"),this._super(e,t)},_destroy:function(){this.anchors.removeData("cache.tabs"),this._super()},url:function(e,t){this.anchors.eq(e).removeData("cache.tabs"),this._superApply(arguments)}}),e.widget("ui.tabs",e.ui.tabs,{abort:function(){this.xhr&&this.xhr.abort()}}),e.widget("ui.tabs",e.ui.tabs,{options:{spinner:"Loading…"},_create:function(){this._super(),this._on({tabsbeforeload:function(e,t){if(e.target!==this.element[0]||!this.options.spinner)return;var n=t.tab.find("span"),r=n.html();n.html(this.options.spinner),t.jqXHR.complete(function(){n.html(r)})}})}}),e.widget("ui.tabs",e.ui.tabs,{options:{enable:null,disable:null},enable:function(t){var n=this.options,r;if(t&&n.disabled===!0||e.isArray(n.disabled)&&e.inArray(t,n.disabled)!==-1)r=!0;this._superApply(arguments),r&&this._trigger("enable",null,this._ui(this.anchors[t],this.panels[t]))},disable:function(t){var n=this.options,r;if(t&&n.disabled===!1||e.isArray(n.disabled)&&e.inArray(t,n.disabled)===-1)r=!0;this._superApply(arguments),r&&this._trigger("disable",null,this._ui(this.anchors[t],this.panels[t]))}}),e.widget("ui.tabs",e.ui.tabs,{options:{add:null,remove:null,tabTemplate:"
                              7. #{label}
                              8. "},add:function(n,r,i){i===t&&(i=this.anchors.length);var s,o,u=this.options,a=e(u.tabTemplate.replace(/#\{href\}/g,n).replace(/#\{label\}/g,r)),f=n.indexOf("#")?this._tabId(a):n.replace("#","");return a.addClass("ui-state-default ui-corner-top").data("ui-tabs-destroy",!0),a.attr("aria-controls",f),s=i>=this.tabs.length,o=this.element.find("#"+f),o.length||(o=this._createPanel(f),s?i>0?o.insertAfter(this.panels.eq(-1)):o.appendTo(this.element):o.insertBefore(this.panels[i])),o.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").hide(),s?a.appendTo(this.tablist):a.insertBefore(this.tabs[i]),u.disabled=e.map(u.disabled,function(e){return e>=i?++e:e}),this.refresh(),this.tabs.length===1&&u.active===!1&&this.option("active",0),this._trigger("add",null,this._ui(this.anchors[i],this.panels[i])),this},remove:function(t){t=this._getIndex(t);var n=this.options,r=this.tabs.eq(t).remove(),i=this._getPanelForTab(r).remove();return r.hasClass("ui-tabs-active")&&this.anchors.length>2&&this._activate(t+(t+1=t?--e:e}),this.refresh(),this._trigger("remove",null,this._ui(r.find("a")[0],i[0])),this}}),e.widget("ui.tabs",e.ui.tabs,{length:function(){return this.anchors.length}}),e.widget("ui.tabs",e.ui.tabs,{options:{idPrefix:"ui-tabs-"},_tabId:function(t){var n=t.is("li")?t.find("a[href]"):t;return n=n[0],e(n).closest("li").attr("aria-controls")||n.title&&n.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF\-]/g,"")||this.options.idPrefix+i()}}),e.widget("ui.tabs",e.ui.tabs,{options:{panelTemplate:"
                                "},_createPanel:function(t){return e(this.options.panelTemplate).attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)}}),e.widget("ui.tabs",e.ui.tabs,{_create:function(){var e=this.options;e.active===null&&e.selected!==t&&(e.active=e.selected===-1?!1:e.selected),this._super(),e.selected=e.active,e.selected===!1&&(e.selected=-1)},_setOption:function(e,t){if(e!=="selected")return this._super(e,t);var n=this.options;this._super("active",t===-1?!1:t),n.selected=n.active,n.selected===!1&&(n.selected=-1)},_eventHandler:function(e){this._superApply(arguments),this.options.selected=this.options.active,this.options.selected===!1&&(this.options.selected=-1)}}),e.widget("ui.tabs",e.ui.tabs,{options:{show:null,select:null},_create:function(){this._super(),this.options.active!==!1&&this._trigger("show",null,this._ui(this.active.find(".ui-tabs-anchor")[0],this._getPanelForTab(this.active)[0]))},_trigger:function(e,t,n){var r=this._superApply(arguments);return r?(e==="beforeActivate"&&n.newTab.length?r=this._super("select",t,{tab:n.newTab.find(".ui-tabs-anchor")[0],panel:n.newPanel[0],index:n.newTab.closest("li").index()}):e==="activate"&&n.newTab.length&&(r=this._super("show",t,{tab:n.newTab.find(".ui-tabs-anchor")[0],panel:n.newPanel[0],index:n.newTab.closest("li").index()})),r):!1}}),e.widget("ui.tabs",e.ui.tabs,{select:function(e){e=this._getIndex(e);if(e===-1){if(!this.options.collapsible||this.options.selected===-1)return;e=this.options.selected}this.anchors.eq(e).trigger(this.options.event+this.eventNamespace)}}),function(){var t=0;e.widget("ui.tabs",e.ui.tabs,{options:{cookie:null},_create:function(){var e=this.options,t;e.active==null&&e.cookie&&(t=parseInt(this._cookie(),10),t===-1&&(t=!1),e.active=t),this._super()},_cookie:function(n){var r=[this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+ ++t)];return arguments.length&&(r.push(n===!1?-1:n),r.push(this.options.cookie)),e.cookie.apply(null,r)},_refresh:function(){this._super(),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_eventHandler:function(e){this._superApply(arguments),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_destroy:function(){this._super(),this.options.cookie&&this._cookie(null,this.options.cookie)}})}(),e.widget("ui.tabs",e.ui.tabs,{_trigger:function(t,n,r){var i=e.extend({},r);return t==="load"&&(i.panel=i.panel[0],i.tab=i.tab.find(".ui-tabs-anchor")[0]),this._super(t,n,i)}}),e.widget("ui.tabs",e.ui.tabs,{options:{fx:null},_getFx:function(){var t,n,r=this.options.fx;return r&&(e.isArray(r)?(t=r[0],n=r[1]):t=n=r),r?{show:n,hide:t}:null},_toggle:function(e,t){function o(){n.running=!1,n._trigger("activate",e,t)}function u(){t.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),r.length&&s.show?r.animate(s.show,s.show.duration,function(){o()}):(r.show(),o())}var n=this,r=t.newPanel,i=t.oldPanel,s=this._getFx();if(!s)return this._super(e,t);n.running=!0,i.length&&s.hide?i.animate(s.hide,s.hide.duration,function(){t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),i.hide(),u())}}))})(jQuery);(function(e){function n(t,n){var r=(t.attr("aria-describedby")||"").split(/\s+/);r.push(n),t.data("ui-tooltip-id",n).attr("aria-describedby",e.trim(r.join(" ")))}function r(t){var n=t.data("ui-tooltip-id"),r=(t.attr("aria-describedby")||"").split(/\s+/),i=e.inArray(n,r);i!==-1&&r.splice(i,1),t.removeData("ui-tooltip-id"),r=e.trim(r.join(" ")),r?t.attr("aria-describedby",r):t.removeAttr("aria-describedby")}var t=0;e.widget("ui.tooltip",{version:"1.9.0",options:{content:function(){return e(this).attr("title")},hide:!0,items:"[title]",position:{my:"left+15 center",at:"right center",collision:"flipfit flipfit"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={}},_setOption:function(t,n){var r=this;if(t==="disabled"){this[n?"_disable":"_enable"](),this.options[t]=n;return}this._super(t,n),t==="content"&&e.each(this.tooltips,function(e,t){r._updateContent(t)})},_disable:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0)}),this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.is("[title]")&&t.data("ui-tooltip-title",t.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))})},open:function(t){var n=e(t?t.target:this.element).closest(this.options.items);if(!n.length)return;if(this.options.track&&n.data("ui-tooltip-id")){this._find(n).position(e.extend({of:n},this.options.position)),this._off(this.document,"mousemove");return}n.attr("title")&&n.data("ui-tooltip-title",n.attr("title")),n.data("tooltip-open",!0),this._updateContent(n,t)},_updateContent:function(e,t){var n,r=this.options.content,i=this;if(typeof r=="string")return this._open(t,e,r);n=r.call(e[0],function(n){if(!e.data("tooltip-open"))return;i._delay(function(){this._open(t,e,n)})}),n&&this._open(t,e,n)},_open:function(t,r,i){function u(e){o.of=e,s.position(o)}var s,o;if(!i)return;s=this._find(r);if(s.length){s.find(".ui-tooltip-content").html(i);return}r.is("[title]")&&(t&&t.type==="mouseover"?r.attr("title",""):r.removeAttr("title")),s=this._tooltip(r),n(r,s.attr("id")),s.find(".ui-tooltip-content").html(i),this.options.track&&t&&/^mouse/.test(t.originalEvent.type)?(o=e.extend({},this.options.position),this._on(this.document,{mousemove:u}),u(t)):s.position(e.extend({of:r},this.options.position)),s.hide(),this._show(s,this.options.show),this._trigger("open",t,{tooltip:s}),this._on(r,{mouseleave:"close",focusout:"close",keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var n=e.Event(t);n.currentTarget=r[0],this.close(n,!0)}}})},close:function(t,n){var i=this,s=e(t?t.currentTarget:this.element),o=this._find(s);if(this.closing)return;if(!n&&t&&t.type!=="focusout"&&this.document[0].activeElement===s[0])return;s.data("ui-tooltip-title")&&s.attr("title",s.data("ui-tooltip-title")),r(s),o.stop(!0),this._hide(o,this.options.hide,function(){e(this).remove(),delete i.tooltips[this.id]}),s.removeData("tooltip-open"),this._off(s,"mouseleave focusout keyup"),this._off(this.document,"mousemove"),this.closing=!0,this._trigger("close",t,{tooltip:o}),this.closing=!1},_tooltip:function(n){var r="ui-tooltip-"+t++,i=e("
                                ").attr({id:r,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return e("
                                ").addClass("ui-tooltip-content").appendTo(i),i.appendTo(this.document[0].body),e.fn.bgiframe&&i.bgiframe(),this.tooltips[r]=n,i},_find:function(t){var n=t.data("ui-tooltip-id");return n?e("#"+n):e()},_destroy:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0),e("#"+n).remove(),r.data("ui-tooltip-title")&&(r.attr("title",r.data("ui-tooltip-title")),r.removeData("ui-tooltip-title"))})}})})(jQuery); \ No newline at end of file diff --git a/nebula-exchange/target/site/scaladocs/lib/jquery.js b/nebula-exchange/target/site/scaladocs/lib/jquery.js deleted file mode 100644 index bc3fbc8..0000000 --- a/nebula-exchange/target/site/scaladocs/lib/jquery.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v1.8.2 jquery.com | jquery.org/license */ -(function(a,b){function G(a){var b=F[a]={};return p.each(a.split(s),function(a,c){b[c]=!0}),b}function J(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(I,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:+d+""===d?+d:H.test(d)?p.parseJSON(d):d}catch(f){}p.data(a,c,d)}else d=b}return d}function K(a){var b;for(b in a){if(b==="data"&&p.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function ba(){return!1}function bb(){return!0}function bh(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function bi(a,b){do a=a[b];while(a&&a.nodeType!==1);return a}function bj(a,b,c){b=b||0;if(p.isFunction(b))return p.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return p.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=p.grep(a,function(a){return a.nodeType===1});if(be.test(b))return p.filter(b,d,!c);b=p.filter(b,d)}return p.grep(a,function(a,d){return p.inArray(a,b)>=0===c})}function bk(a){var b=bl.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function bC(a,b){return a.getElementsByTagName(b)[0]||a.appendChild(a.ownerDocument.createElement(b))}function bD(a,b){if(b.nodeType!==1||!p.hasData(a))return;var c,d,e,f=p._data(a),g=p._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;d").appendTo(e.body),c=b.css("display");b.remove();if(c==="none"||c===""){bI=e.body.appendChild(bI||p.extend(e.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!bJ||!bI.createElement)bJ=(bI.contentWindow||bI.contentDocument).document,bJ.write(""),bJ.close();b=bJ.body.appendChild(bJ.createElement(a)),c=bH(b,"display"),e.body.removeChild(bI)}return bS[a]=c,c}function ci(a,b,c,d){var e;if(p.isArray(b))p.each(b,function(b,e){c||ce.test(a)?d(a,e):ci(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&p.type(b)==="object")for(e in b)ci(a+"["+e+"]",b[e],c,d);else d(a,b)}function cz(a){return function(b,c){typeof b!="string"&&(c=b,b="*");var d,e,f,g=b.toLowerCase().split(s),h=0,i=g.length;if(p.isFunction(c))for(;h)[^>]*$|#([\w\-]*)$)/,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,y=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,z=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,A=/^-ms-/,B=/-([\da-z])/gi,C=function(a,b){return(b+"").toUpperCase()},D=function(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",D,!1),p.ready()):e.readyState==="complete"&&(e.detachEvent("onreadystatechange",D),p.ready())},E={};p.fn=p.prototype={constructor:p,init:function(a,c,d){var f,g,h,i;if(!a)return this;if(a.nodeType)return this.context=this[0]=a,this.length=1,this;if(typeof a=="string"){a.charAt(0)==="<"&&a.charAt(a.length-1)===">"&&a.length>=3?f=[null,a,null]:f=u.exec(a);if(f&&(f[1]||!c)){if(f[1])return c=c instanceof p?c[0]:c,i=c&&c.nodeType?c.ownerDocument||c:e,a=p.parseHTML(f[1],i,!0),v.test(f[1])&&p.isPlainObject(c)&&this.attr.call(a,c,!0),p.merge(this,a);g=e.getElementById(f[2]);if(g&&g.parentNode){if(g.id!==f[2])return d.find(a);this.length=1,this[0]=g}return this.context=e,this.selector=a,this}return!c||c.jquery?(c||d).find(a):this.constructor(c).find(a)}return p.isFunction(a)?d.ready(a):(a.selector!==b&&(this.selector=a.selector,this.context=a.context),p.makeArray(a,this))},selector:"",jquery:"1.8.2",length:0,size:function(){return this.length},toArray:function(){return k.call(this)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=p.merge(this.constructor(),a);return d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")"),d},each:function(a,b){return p.each(this,a,b)},ready:function(a){return p.ready.promise().done(a),this},eq:function(a){return a=+a,a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(k.apply(this,arguments),"slice",k.call(arguments).join(","))},map:function(a){return this.pushStack(p.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:j,sort:[].sort,splice:[].splice},p.fn.init.prototype=p.fn,p.extend=p.fn.extend=function(){var a,c,d,e,f,g,h=arguments[0]||{},i=1,j=arguments.length,k=!1;typeof h=="boolean"&&(k=h,h=arguments[1]||{},i=2),typeof h!="object"&&!p.isFunction(h)&&(h={}),j===i&&(h=this,--i);for(;i0)return;d.resolveWith(e,[p]),p.fn.trigger&&p(e).trigger("ready").off("ready")},isFunction:function(a){return p.type(a)==="function"},isArray:Array.isArray||function(a){return p.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):E[m.call(a)]||"object"},isPlainObject:function(a){if(!a||p.type(a)!=="object"||a.nodeType||p.isWindow(a))return!1;try{if(a.constructor&&!n.call(a,"constructor")&&!n.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||n.call(a,d)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},error:function(a){throw new Error(a)},parseHTML:function(a,b,c){var d;return!a||typeof a!="string"?null:(typeof b=="boolean"&&(c=b,b=0),b=b||e,(d=v.exec(a))?[b.createElement(d[1])]:(d=p.buildFragment([a],b,c?null:[]),p.merge([],(d.cacheable?p.clone(d.fragment):d.fragment).childNodes)))},parseJSON:function(b){if(!b||typeof b!="string")return null;b=p.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(w.test(b.replace(y,"@").replace(z,"]").replace(x,"")))return(new Function("return "+b))();p.error("Invalid JSON: "+b)},parseXML:function(c){var d,e;if(!c||typeof c!="string")return null;try{a.DOMParser?(e=new DOMParser,d=e.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(f){d=b}return(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&p.error("Invalid XML: "+c),d},noop:function(){},globalEval:function(b){b&&r.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(A,"ms-").replace(B,C)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,c,d){var e,f=0,g=a.length,h=g===b||p.isFunction(a);if(d){if(h){for(e in a)if(c.apply(a[e],d)===!1)break}else for(;f0&&a[0]&&a[i-1]||i===0||p.isArray(a));if(j)for(;h-1)i.splice(c,1),e&&(c<=g&&g--,c<=h&&h--)}),this},has:function(a){return p.inArray(a,i)>-1},empty:function(){return i=[],this},disable:function(){return i=j=c=b,this},disabled:function(){return!i},lock:function(){return j=b,c||l.disable(),this},locked:function(){return!j},fireWith:function(a,b){return b=b||[],b=[a,b.slice?b.slice():b],i&&(!d||j)&&(e?j.push(b):k(b)),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!d}};return l},p.extend({Deferred:function(a){var b=[["resolve","done",p.Callbacks("once memory"),"resolved"],["reject","fail",p.Callbacks("once memory"),"rejected"],["notify","progress",p.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return p.Deferred(function(c){p.each(b,function(b,d){var f=d[0],g=a[b];e[d[1]](p.isFunction(g)?function(){var a=g.apply(this,arguments);a&&p.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f+"With"](this===e?c:this,[a])}:c[f])}),a=null}).promise()},promise:function(a){return a!=null?p.extend(a,d):d}},e={};return d.pipe=d.then,p.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[a^1][2].disable,b[2][2].lock),e[f[0]]=g.fire,e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=k.call(arguments),d=c.length,e=d!==1||a&&p.isFunction(a.promise)?d:0,f=e===1?a:p.Deferred(),g=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?k.call(arguments):d,c===h?f.notifyWith(b,c):--e||f.resolveWith(b,c)}},h,i,j;if(d>1){h=new Array(d),i=new Array(d),j=new Array(d);for(;b
                                a",c=n.getElementsByTagName("*"),d=n.getElementsByTagName("a")[0],d.style.cssText="top:1px;float:left;opacity:.5";if(!c||!c.length)return{};f=e.createElement("select"),g=f.appendChild(e.createElement("option")),h=n.getElementsByTagName("input")[0],b={leadingWhitespace:n.firstChild.nodeType===3,tbody:!n.getElementsByTagName("tbody").length,htmlSerialize:!!n.getElementsByTagName("link").length,style:/top/.test(d.getAttribute("style")),hrefNormalized:d.getAttribute("href")==="/a",opacity:/^0.5/.test(d.style.opacity),cssFloat:!!d.style.cssFloat,checkOn:h.value==="on",optSelected:g.selected,getSetAttribute:n.className!=="t",enctype:!!e.createElement("form").enctype,html5Clone:e.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:e.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},h.checked=!0,b.noCloneChecked=h.cloneNode(!0).checked,f.disabled=!0,b.optDisabled=!g.disabled;try{delete n.test}catch(o){b.deleteExpando=!1}!n.addEventListener&&n.attachEvent&&n.fireEvent&&(n.attachEvent("onclick",m=function(){b.noCloneEvent=!1}),n.cloneNode(!0).fireEvent("onclick"),n.detachEvent("onclick",m)),h=e.createElement("input"),h.value="t",h.setAttribute("type","radio"),b.radioValue=h.value==="t",h.setAttribute("checked","checked"),h.setAttribute("name","t"),n.appendChild(h),i=e.createDocumentFragment(),i.appendChild(n.lastChild),b.checkClone=i.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=h.checked,i.removeChild(h),i.appendChild(n);if(n.attachEvent)for(k in{submit:!0,change:!0,focusin:!0})j="on"+k,l=j in n,l||(n.setAttribute(j,"return;"),l=typeof n[j]=="function"),b[k+"Bubbles"]=l;return p(function(){var c,d,f,g,h="padding:0;margin:0;border:0;display:block;overflow:hidden;",i=e.getElementsByTagName("body")[0];if(!i)return;c=e.createElement("div"),c.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",i.insertBefore(c,i.firstChild),d=e.createElement("div"),c.appendChild(d),d.innerHTML="
                                t
                                ",f=d.getElementsByTagName("td"),f[0].style.cssText="padding:0;margin:0;border:0;display:none",l=f[0].offsetHeight===0,f[0].style.display="",f[1].style.display="none",b.reliableHiddenOffsets=l&&f[0].offsetHeight===0,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",b.boxSizing=d.offsetWidth===4,b.doesNotIncludeMarginInBodyOffset=i.offsetTop!==1,a.getComputedStyle&&(b.pixelPosition=(a.getComputedStyle(d,null)||{}).top!=="1%",b.boxSizingReliable=(a.getComputedStyle(d,null)||{width:"4px"}).width==="4px",g=e.createElement("div"),g.style.cssText=d.style.cssText=h,g.style.marginRight=g.style.width="0",d.style.width="1px",d.appendChild(g),b.reliableMarginRight=!parseFloat((a.getComputedStyle(g,null)||{}).marginRight)),typeof d.style.zoom!="undefined"&&(d.innerHTML="",d.style.cssText=h+"width:1px;padding:1px;display:inline;zoom:1",b.inlineBlockNeedsLayout=d.offsetWidth===3,d.style.display="block",d.style.overflow="visible",d.innerHTML="
                                ",d.firstChild.style.width="5px",b.shrinkWrapBlocks=d.offsetWidth!==3,c.style.zoom=1),i.removeChild(c),c=d=f=g=null}),i.removeChild(n),c=d=f=g=h=i=n=null,b}();var H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,I=/([A-Z])/g;p.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(p.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){return a=a.nodeType?p.cache[a[p.expando]]:a[p.expando],!!a&&!K(a)},data:function(a,c,d,e){if(!p.acceptData(a))return;var f,g,h=p.expando,i=typeof c=="string",j=a.nodeType,k=j?p.cache:a,l=j?a[h]:a[h]&&h;if((!l||!k[l]||!e&&!k[l].data)&&i&&d===b)return;l||(j?a[h]=l=p.deletedIds.pop()||p.guid++:l=h),k[l]||(k[l]={},j||(k[l].toJSON=p.noop));if(typeof c=="object"||typeof c=="function")e?k[l]=p.extend(k[l],c):k[l].data=p.extend(k[l].data,c);return f=k[l],e||(f.data||(f.data={}),f=f.data),d!==b&&(f[p.camelCase(c)]=d),i?(g=f[c],g==null&&(g=f[p.camelCase(c)])):g=f,g},removeData:function(a,b,c){if(!p.acceptData(a))return;var d,e,f,g=a.nodeType,h=g?p.cache:a,i=g?a[p.expando]:p.expando;if(!h[i])return;if(b){d=c?h[i]:h[i].data;if(d){p.isArray(b)||(b in d?b=[b]:(b=p.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,f=b.length;e1,null,!1))},removeData:function(a){return this.each(function(){p.removeData(this,a)})}}),p.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=p._data(a,b),c&&(!d||p.isArray(c)?d=p._data(a,b,p.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=p.queue(a,b),d=c.length,e=c.shift(),f=p._queueHooks(a,b),g=function(){p.dequeue(a,b)};e==="inprogress"&&(e=c.shift(),d--),e&&(b==="fx"&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return p._data(a,c)||p._data(a,c,{empty:p.Callbacks("once memory").add(function(){p.removeData(a,b+"queue",!0),p.removeData(a,c,!0)})})}}),p.fn.extend({queue:function(a,c){var d=2;return typeof a!="string"&&(c=a,a="fx",d--),arguments.length1)},removeAttr:function(a){return this.each(function(){p.removeAttr(this,a)})},prop:function(a,b){return p.access(this,p.prop,a,b,arguments.length>1)},removeProp:function(a){return a=p.propFix[a]||a,this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,f,g,h;if(p.isFunction(a))return this.each(function(b){p(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(s);for(c=0,d=this.length;c=0)d=d.replace(" "+c[f]+" "," ");e.className=a?p.trim(d):""}}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";return p.isFunction(a)?this.each(function(c){p(this).toggleClass(a.call(this,c,this.className,b),b)}):this.each(function(){if(c==="string"){var e,f=0,g=p(this),h=b,i=a.split(s);while(e=i[f++])h=d?h:!g.hasClass(e),g[h?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&p._data(this,"__className__",this.className),this.className=this.className||a===!1?"":p._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c=0)return!0;return!1},val:function(a){var c,d,e,f=this[0];if(!arguments.length){if(f)return c=p.valHooks[f.type]||p.valHooks[f.nodeName.toLowerCase()],c&&"get"in c&&(d=c.get(f,"value"))!==b?d:(d=f.value,typeof d=="string"?d.replace(P,""):d==null?"":d);return}return e=p.isFunction(a),this.each(function(d){var f,g=p(this);if(this.nodeType!==1)return;e?f=a.call(this,d,g.val()):f=a,f==null?f="":typeof f=="number"?f+="":p.isArray(f)&&(f=p.map(f,function(a){return a==null?"":a+""})),c=p.valHooks[this.type]||p.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,f,"value")===b)this.value=f})}}),p.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,f=a.selectedIndex,g=[],h=a.options,i=a.type==="select-one";if(f<0)return null;c=i?f:0,d=i?f+1:h.length;for(;c=0}),c.length||(a.selectedIndex=-1),c}}},attrFn:{},attr:function(a,c,d,e){var f,g,h,i=a.nodeType;if(!a||i===3||i===8||i===2)return;if(e&&p.isFunction(p.fn[c]))return p(a)[c](d);if(typeof a.getAttribute=="undefined")return p.prop(a,c,d);h=i!==1||!p.isXMLDoc(a),h&&(c=c.toLowerCase(),g=p.attrHooks[c]||(T.test(c)?M:L));if(d!==b){if(d===null){p.removeAttr(a,c);return}return g&&"set"in g&&h&&(f=g.set(a,d,c))!==b?f:(a.setAttribute(c,d+""),d)}return g&&"get"in g&&h&&(f=g.get(a,c))!==null?f:(f=a.getAttribute(c),f===null?b:f)},removeAttr:function(a,b){var c,d,e,f,g=0;if(b&&a.nodeType===1){d=b.split(s);for(;g=0}})});var V=/^(?:textarea|input|select)$/i,W=/^([^\.]*|)(?:\.(.+)|)$/,X=/(?:^|\s)hover(\.\S+|)\b/,Y=/^key/,Z=/^(?:mouse|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=function(a){return p.event.special.hover?a:a.replace(X,"mouseenter$1 mouseleave$1")};p.event={add:function(a,c,d,e,f){var g,h,i,j,k,l,m,n,o,q,r;if(a.nodeType===3||a.nodeType===8||!c||!d||!(g=p._data(a)))return;d.handler&&(o=d,d=o.handler,f=o.selector),d.guid||(d.guid=p.guid++),i=g.events,i||(g.events=i={}),h=g.handle,h||(g.handle=h=function(a){return typeof p!="undefined"&&(!a||p.event.triggered!==a.type)?p.event.dispatch.apply(h.elem,arguments):b},h.elem=a),c=p.trim(_(c)).split(" ");for(j=0;j=0&&(s=s.slice(0,-1),i=!0),s.indexOf(".")>=0&&(t=s.split("."),s=t.shift(),t.sort());if((!f||p.event.customEvent[s])&&!p.event.global[s])return;c=typeof c=="object"?c[p.expando]?c:new p.Event(s,c):new p.Event(s),c.type=s,c.isTrigger=!0,c.exclusive=i,c.namespace=t.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+t.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,m=s.indexOf(":")<0?"on"+s:"";if(!f){h=p.cache;for(j in h)h[j].events&&h[j].events[s]&&p.event.trigger(c,d,h[j].handle.elem,!0);return}c.result=b,c.target||(c.target=f),d=d!=null?p.makeArray(d):[],d.unshift(c),n=p.event.special[s]||{};if(n.trigger&&n.trigger.apply(f,d)===!1)return;q=[[f,n.bindType||s]];if(!g&&!n.noBubble&&!p.isWindow(f)){r=n.delegateType||s,k=$.test(r+s)?f:f.parentNode;for(l=f;k;k=k.parentNode)q.push([k,r]),l=k;l===(f.ownerDocument||e)&&q.push([l.defaultView||l.parentWindow||a,r])}for(j=0;j=0:p.find(m,this,null,[f]).length),h[m]&&j.push(l);j.length&&u.push({elem:f,matches:j})}o.length>q&&u.push({elem:this,matches:o.slice(q)});for(d=0;d0?this.on(b,null,a,c):this.trigger(b)},Y.test(b)&&(p.event.fixHooks[b]=p.event.keyHooks),Z.test(b)&&(p.event.fixHooks[b]=p.event.mouseHooks)}),function(a,b){function bc(a,b,c,d){c=c||[],b=b||r;var e,f,i,j,k=b.nodeType;if(!a||typeof a!="string")return c;if(k!==1&&k!==9)return[];i=g(b);if(!i&&!d)if(e=P.exec(a))if(j=e[1]){if(k===9){f=b.getElementById(j);if(!f||!f.parentNode)return c;if(f.id===j)return c.push(f),c}else if(b.ownerDocument&&(f=b.ownerDocument.getElementById(j))&&h(b,f)&&f.id===j)return c.push(f),c}else{if(e[2])return w.apply(c,x.call(b.getElementsByTagName(a),0)),c;if((j=e[3])&&_&&b.getElementsByClassName)return w.apply(c,x.call(b.getElementsByClassName(j),0)),c}return bp(a.replace(L,"$1"),b,c,d,i)}function bd(a){return function(b){var c=b.nodeName.toLowerCase();return c==="input"&&b.type===a}}function be(a){return function(b){var c=b.nodeName.toLowerCase();return(c==="input"||c==="button")&&b.type===a}}function bf(a){return z(function(b){return b=+b,z(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function bg(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}function bh(a,b){var c,d,f,g,h,i,j,k=C[o][a];if(k)return b?0:k.slice(0);h=a,i=[],j=e.preFilter;while(h){if(!c||(d=M.exec(h)))d&&(h=h.slice(d[0].length)),i.push(f=[]);c=!1;if(d=N.exec(h))f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=d[0].replace(L," ");for(g in e.filter)(d=W[g].exec(h))&&(!j[g]||(d=j[g](d,r,!0)))&&(f.push(c=new q(d.shift())),h=h.slice(c.length),c.type=g,c.matches=d);if(!c)break}return b?h.length:h?bc.error(a):C(a,i).slice(0)}function bi(a,b,d){var e=b.dir,f=d&&b.dir==="parentNode",g=u++;return b.first?function(b,c,d){while(b=b[e])if(f||b.nodeType===1)return a(b,c,d)}:function(b,d,h){if(!h){var i,j=t+" "+g+" ",k=j+c;while(b=b[e])if(f||b.nodeType===1){if((i=b[o])===k)return b.sizset;if(typeof i=="string"&&i.indexOf(j)===0){if(b.sizset)return b}else{b[o]=k;if(a(b,d,h))return b.sizset=!0,b;b.sizset=!1}}}else while(b=b[e])if(f||b.nodeType===1)if(a(b,d,h))return b}}function bj(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function bk(a,b,c,d,e){var f,g=[],h=0,i=a.length,j=b!=null;for(;h-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==l)||((b=c).nodeType?j(a,c,d):k(a,c,d))}];for(;i1&&bj(m),i>1&&a.slice(0,i-1).join("").replace(L,"$1"),c,i0,f=a.length>0,g=function(h,i,j,k,m){var n,o,p,q=[],s=0,u="0",x=h&&[],y=m!=null,z=l,A=h||f&&e.find.TAG("*",m&&i.parentNode||i),B=t+=z==null?1:Math.E;y&&(l=i!==r&&i,c=g.el);for(;(n=A[u])!=null;u++){if(f&&n){for(o=0;p=a[o];o++)if(p(n,i,j)){k.push(n);break}y&&(t=B,c=++g.el)}d&&((n=!p&&n)&&s--,h&&x.push(n))}s+=u;if(d&&u!==s){for(o=0;p=b[o];o++)p(x,q,i,j);if(h){if(s>0)while(u--)!x[u]&&!q[u]&&(q[u]=v.call(k));q=bk(q)}w.apply(k,q),y&&!h&&q.length>0&&s+b.length>1&&bc.uniqueSort(k)}return y&&(t=B,l=z),x};return g.el=0,d?z(g):g}function bo(a,b,c,d){var e=0,f=b.length;for(;e2&&(j=h[0]).type==="ID"&&b.nodeType===9&&!f&&e.relative[h[1].type]){b=e.find.ID(j.matches[0].replace(V,""),b,f)[0];if(!b)return c;a=a.slice(h.shift().length)}for(g=W.POS.test(a)?-1:h.length-1;g>=0;g--){j=h[g];if(e.relative[k=j.type])break;if(l=e.find[k])if(d=l(j.matches[0].replace(V,""),R.test(h[0].type)&&b.parentNode||b,f)){h.splice(g,1),a=d.length&&h.join("");if(!a)return w.apply(c,x.call(d,0)),c;break}}}return i(a,m)(d,b,f,c,R.test(a)),c}function bq(){}var c,d,e,f,g,h,i,j,k,l,m=!0,n="undefined",o=("sizcache"+Math.random()).replace(".",""),q=String,r=a.document,s=r.documentElement,t=0,u=0,v=[].pop,w=[].push,x=[].slice,y=[].indexOf||function(a){var b=0,c=this.length;for(;be.cacheLength&&delete a[b.shift()],a[c]=d},a)},B=A(),C=A(),D=A(),E="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",G=F.replace("w","w#"),H="([*^$|!~]?=)",I="\\["+E+"*("+F+")"+E+"*(?:"+H+E+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+G+")|)|)"+E+"*\\]",J=":("+F+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+I+")|[^:]|\\\\.)*|.*))\\)|)",K=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+E+"*((?:-\\d)?\\d*)"+E+"*\\)|)(?=[^-]|$)",L=new RegExp("^"+E+"+|((?:^|[^\\\\])(?:\\\\.)*)"+E+"+$","g"),M=new RegExp("^"+E+"*,"+E+"*"),N=new RegExp("^"+E+"*([\\x20\\t\\r\\n\\f>+~])"+E+"*"),O=new RegExp(J),P=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,Q=/^:not/,R=/[\x20\t\r\n\f]*[+~]/,S=/:not\($/,T=/h\d/i,U=/input|select|textarea|button/i,V=/\\(?!\\)/g,W={ID:new RegExp("^#("+F+")"),CLASS:new RegExp("^\\.("+F+")"),NAME:new RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:new RegExp("^("+F.replace("w","w*")+")"),ATTR:new RegExp("^"+I),PSEUDO:new RegExp("^"+J),POS:new RegExp(K,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+E+"*(even|odd|(([+-]|)(\\d*)n|)"+E+"*(?:([+-]|)"+E+"*(\\d+)|))"+E+"*\\)|)","i"),needsContext:new RegExp("^"+E+"*[>+~]|"+K,"i")},X=function(a){var b=r.createElement("div");try{return a(b)}catch(c){return!1}finally{b=null}},Y=X(function(a){return a.appendChild(r.createComment("")),!a.getElementsByTagName("*").length}),Z=X(function(a){return a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!==n&&a.firstChild.getAttribute("href")==="#"}),$=X(function(a){a.innerHTML="";var b=typeof a.lastChild.getAttribute("multiple");return b!=="boolean"&&b!=="string"}),_=X(function(a){return a.innerHTML="",!a.getElementsByClassName||!a.getElementsByClassName("e").length?!1:(a.lastChild.className="e",a.getElementsByClassName("e").length===2)}),ba=X(function(a){a.id=o+0,a.innerHTML="
                                ",s.insertBefore(a,s.firstChild);var b=r.getElementsByName&&r.getElementsByName(o).length===2+r.getElementsByName(o+0).length;return d=!r.getElementById(o),s.removeChild(a),b});try{x.call(s.childNodes,0)[0].nodeType}catch(bb){x=function(a){var b,c=[];for(;b=this[a];a++)c.push(b);return c}}bc.matches=function(a,b){return bc(a,null,null,b)},bc.matchesSelector=function(a,b){return bc(b,null,null,[a]).length>0},f=bc.getText=function(a){var b,c="",d=0,e=a.nodeType;if(e){if(e===1||e===9||e===11){if(typeof a.textContent=="string")return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=f(a)}else if(e===3||e===4)return a.nodeValue}else for(;b=a[d];d++)c+=f(b);return c},g=bc.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?b.nodeName!=="HTML":!1},h=bc.contains=s.contains?function(a,b){var c=a.nodeType===9?a.documentElement:a,d=b&&b.parentNode;return a===d||!!(d&&d.nodeType===1&&c.contains&&c.contains(d))}:s.compareDocumentPosition?function(a,b){return b&&!!(a.compareDocumentPosition(b)&16)}:function(a,b){while(b=b.parentNode)if(b===a)return!0;return!1},bc.attr=function(a,b){var c,d=g(a);return d||(b=b.toLowerCase()),(c=e.attrHandle[b])?c(a):d||$?a.getAttribute(b):(c=a.getAttributeNode(b),c?typeof a[b]=="boolean"?a[b]?b:null:c.specified?c.value:null:null)},e=bc.selectors={cacheLength:50,createPseudo:z,match:W,attrHandle:Z?{}:{href:function(a){return a.getAttribute("href",2)},type:function(a){return a.getAttribute("type")}},find:{ID:d?function(a,b,c){if(typeof b.getElementById!==n&&!c){var d=b.getElementById(a);return d&&d.parentNode?[d]:[]}}:function(a,c,d){if(typeof c.getElementById!==n&&!d){var e=c.getElementById(a);return e?e.id===a||typeof e.getAttributeNode!==n&&e.getAttributeNode("id").value===a?[e]:b:[]}},TAG:Y?function(a,b){if(typeof b.getElementsByTagName!==n)return b.getElementsByTagName(a)}:function(a,b){var c=b.getElementsByTagName(a);if(a==="*"){var d,e=[],f=0;for(;d=c[f];f++)d.nodeType===1&&e.push(d);return e}return c},NAME:ba&&function(a,b){if(typeof b.getElementsByName!==n)return b.getElementsByName(name)},CLASS:_&&function(a,b,c){if(typeof b.getElementsByClassName!==n&&!c)return b.getElementsByClassName(a)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(V,""),a[3]=(a[4]||a[5]||"").replace(V,""),a[2]==="~="&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),a[1]==="nth"?(a[2]||bc.error(a[0]),a[3]=+(a[3]?a[4]+(a[5]||1):2*(a[2]==="even"||a[2]==="odd")),a[4]=+(a[6]+a[7]||a[2]==="odd")):a[2]&&bc.error(a[0]),a},PSEUDO:function(a){var b,c;if(W.CHILD.test(a[0]))return null;if(a[3])a[2]=a[3];else if(b=a[4])O.test(b)&&(c=bh(b,!0))&&(c=b.indexOf(")",b.length-c)-b.length)&&(b=b.slice(0,c),a[0]=a[0].slice(0,c)),a[2]=b;return a.slice(0,3)}},filter:{ID:d?function(a){return a=a.replace(V,""),function(b){return b.getAttribute("id")===a}}:function(a){return a=a.replace(V,""),function(b){var c=typeof b.getAttributeNode!==n&&b.getAttributeNode("id");return c&&c.value===a}},TAG:function(a){return a==="*"?function(){return!0}:(a=a.replace(V,"").toLowerCase(),function(b){return b.nodeName&&b.nodeName.toLowerCase()===a})},CLASS:function(a){var b=B[o][a];return b||(b=B(a,new RegExp("(^|"+E+")"+a+"("+E+"|$)"))),function(a){return b.test(a.className||typeof a.getAttribute!==n&&a.getAttribute("class")||"")}},ATTR:function(a,b,c){return function(d,e){var f=bc.attr(d,a);return f==null?b==="!=":b?(f+="",b==="="?f===c:b==="!="?f!==c:b==="^="?c&&f.indexOf(c)===0:b==="*="?c&&f.indexOf(c)>-1:b==="$="?c&&f.substr(f.length-c.length)===c:b==="~="?(" "+f+" ").indexOf(c)>-1:b==="|="?f===c||f.substr(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d){return a==="nth"?function(a){var b,e,f=a.parentNode;if(c===1&&d===0)return!0;if(f){e=0;for(b=f.firstChild;b;b=b.nextSibling)if(b.nodeType===1){e++;if(a===b)break}}return e-=d,e===c||e%c===0&&e/c>=0}:function(b){var c=b;switch(a){case"only":case"first":while(c=c.previousSibling)if(c.nodeType===1)return!1;if(a==="first")return!0;c=b;case"last":while(c=c.nextSibling)if(c.nodeType===1)return!1;return!0}}},PSEUDO:function(a,b){var c,d=e.pseudos[a]||e.setFilters[a.toLowerCase()]||bc.error("unsupported pseudo: "+a);return d[o]?d(b):d.length>1?(c=[a,a,"",b],e.setFilters.hasOwnProperty(a.toLowerCase())?z(function(a,c){var e,f=d(a,b),g=f.length;while(g--)e=y.call(a,f[g]),a[e]=!(c[e]=f[g])}):function(a){return d(a,0,c)}):d}},pseudos:{not:z(function(a){var b=[],c=[],d=i(a.replace(L,"$1"));return d[o]?z(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)if(f=g[h])a[h]=!(b[h]=f)}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:z(function(a){return function(b){return bc(a,b).length>0}}),contains:z(function(a){return function(b){return(b.textContent||b.innerText||f(b)).indexOf(a)>-1}}),enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&!!a.checked||b==="option"&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},parent:function(a){return!e.pseudos.empty(a)},empty:function(a){var b;a=a.firstChild;while(a){if(a.nodeName>"@"||(b=a.nodeType)===3||b===4)return!1;a=a.nextSibling}return!0},header:function(a){return T.test(a.nodeName)},text:function(a){var b,c;return a.nodeName.toLowerCase()==="input"&&(b=a.type)==="text"&&((c=a.getAttribute("type"))==null||c.toLowerCase()===b)},radio:bd("radio"),checkbox:bd("checkbox"),file:bd("file"),password:bd("password"),image:bd("image"),submit:be("submit"),reset:be("reset"),button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&a.type==="button"||b==="button"},input:function(a){return U.test(a.nodeName)},focus:function(a){var b=a.ownerDocument;return a===b.activeElement&&(!b.hasFocus||b.hasFocus())&&(!!a.type||!!a.href)},active:function(a){return a===a.ownerDocument.activeElement},first:bf(function(a,b,c){return[0]}),last:bf(function(a,b,c){return[b-1]}),eq:bf(function(a,b,c){return[c<0?c+b:c]}),even:bf(function(a,b,c){for(var d=0;d=0;)a.push(d);return a}),gt:bf(function(a,b,c){for(var d=c<0?c+b:c;++d",a.querySelectorAll("[selected]").length||e.push("\\["+E+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),a.querySelectorAll(":checked").length||e.push(":checked")}),X(function(a){a.innerHTML="

                                ",a.querySelectorAll("[test^='']").length&&e.push("[*^$]="+E+"*(?:\"\"|'')"),a.innerHTML="",a.querySelectorAll(":enabled").length||e.push(":enabled",":disabled")}),e=new RegExp(e.join("|")),bp=function(a,d,f,g,h){if(!g&&!h&&(!e||!e.test(a))){var i,j,k=!0,l=o,m=d,n=d.nodeType===9&&a;if(d.nodeType===1&&d.nodeName.toLowerCase()!=="object"){i=bh(a),(k=d.getAttribute("id"))?l=k.replace(c,"\\$&"):d.setAttribute("id",l),l="[id='"+l+"'] ",j=i.length;while(j--)i[j]=l+i[j].join("");m=R.test(a)&&d.parentNode||d,n=i.join(",")}if(n)try{return w.apply(f,x.call(m.querySelectorAll(n),0)),f}catch(p){}finally{k||d.removeAttribute("id")}}return b(a,d,f,g,h)},h&&(X(function(b){a=h.call(b,"div");try{h.call(b,"[test!='']:sizzle"),f.push("!=",J)}catch(c){}}),f=new RegExp(f.join("|")),bc.matchesSelector=function(b,c){c=c.replace(d,"='$1']");if(!g(b)&&!f.test(c)&&(!e||!e.test(c)))try{var i=h.call(b,c);if(i||a||b.document&&b.document.nodeType!==11)return i}catch(j){}return bc(c,null,null,[b]).length>0})}(),e.pseudos.nth=e.pseudos.eq,e.filters=bq.prototype=e.pseudos,e.setFilters=new bq,bc.attr=p.attr,p.find=bc,p.expr=bc.selectors,p.expr[":"]=p.expr.pseudos,p.unique=bc.uniqueSort,p.text=bc.getText,p.isXMLDoc=bc.isXML,p.contains=bc.contains}(a);var bc=/Until$/,bd=/^(?:parents|prev(?:Until|All))/,be=/^.[^:#\[\.,]*$/,bf=p.expr.match.needsContext,bg={children:!0,contents:!0,next:!0,prev:!0};p.fn.extend({find:function(a){var b,c,d,e,f,g,h=this;if(typeof a!="string")return p(a).filter(function(){for(b=0,c=h.length;b0)for(e=d;e=0:p.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c,d=0,e=this.length,f=[],g=bf.test(a)||typeof a!="string"?p(a,b||this.context):0;for(;d-1:p.find.matchesSelector(c,a)){f.push(c);break}c=c.parentNode}}return f=f.length>1?p.unique(f):f,this.pushStack(f,"closest",a)},index:function(a){return a?typeof a=="string"?p.inArray(this[0],p(a)):p.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(a,b){var c=typeof a=="string"?p(a,b):p.makeArray(a&&a.nodeType?[a]:a),d=p.merge(this.get(),c);return this.pushStack(bh(c[0])||bh(d[0])?d:p.unique(d))},addBack:function(a){return this.add(a==null?this.prevObject:this.prevObject.filter(a))}}),p.fn.andSelf=p.fn.addBack,p.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return p.dir(a,"parentNode")},parentsUntil:function(a,b,c){return p.dir(a,"parentNode",c)},next:function(a){return bi(a,"nextSibling")},prev:function(a){return bi(a,"previousSibling")},nextAll:function(a){return p.dir(a,"nextSibling")},prevAll:function(a){return p.dir(a,"previousSibling")},nextUntil:function(a,b,c){return p.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return p.dir(a,"previousSibling",c)},siblings:function(a){return p.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return p.sibling(a.firstChild)},contents:function(a){return p.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:p.merge([],a.childNodes)}},function(a,b){p.fn[a]=function(c,d){var e=p.map(this,b,c);return bc.test(a)||(d=c),d&&typeof d=="string"&&(e=p.filter(d,e)),e=this.length>1&&!bg[a]?p.unique(e):e,this.length>1&&bd.test(a)&&(e=e.reverse()),this.pushStack(e,a,k.call(arguments).join(","))}}),p.extend({filter:function(a,b,c){return c&&(a=":not("+a+")"),b.length===1?p.find.matchesSelector(b[0],a)?[b[0]]:[]:p.find.matches(a,b)},dir:function(a,c,d){var e=[],f=a[c];while(f&&f.nodeType!==9&&(d===b||f.nodeType!==1||!p(f).is(d)))f.nodeType===1&&e.push(f),f=f[c];return e},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var bl="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",bm=/ jQuery\d+="(?:null|\d+)"/g,bn=/^\s+/,bo=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bp=/<([\w:]+)/,bq=/]","i"),bv=/^(?:checkbox|radio)$/,bw=/checked\s*(?:[^=]|=\s*.checked.)/i,bx=/\/(java|ecma)script/i,by=/^\s*\s*$/g,bz={option:[1,""],legend:[1,"
                                ","
                                "],thead:[1,"","
                                "],tr:[2,"","
                                "],td:[3,"","
                                "],col:[2,"","
                                "],area:[1,"",""],_default:[0,"",""]},bA=bk(e),bB=bA.appendChild(e.createElement("div"));bz.optgroup=bz.option,bz.tbody=bz.tfoot=bz.colgroup=bz.caption=bz.thead,bz.th=bz.td,p.support.htmlSerialize||(bz._default=[1,"X
                                ","
                                "]),p.fn.extend({text:function(a){return p.access(this,function(a){return a===b?p.text(this):this.empty().append((this[0]&&this[0].ownerDocument||e).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(p.isFunction(a))return this.each(function(b){p(this).wrapAll(a.call(this,b))});if(this[0]){var b=p(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return p.isFunction(a)?this.each(function(b){p(this).wrapInner(a.call(this,b))}):this.each(function(){var b=p(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=p.isFunction(a);return this.each(function(c){p(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){p.nodeName(this,"body")||p(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(a,this.firstChild)})},before:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(a,this),"before",this.selector)}},after:function(){if(!bh(this[0]))return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=p.clean(arguments);return this.pushStack(p.merge(this,a),"after",this.selector)}},remove:function(a,b){var c,d=0;for(;(c=this[d])!=null;d++)if(!a||p.filter(a,[c]).length)!b&&c.nodeType===1&&(p.cleanData(c.getElementsByTagName("*")),p.cleanData([c])),c.parentNode&&c.parentNode.removeChild(c);return this},empty:function(){var a,b=0;for(;(a=this[b])!=null;b++){a.nodeType===1&&p.cleanData(a.getElementsByTagName("*"));while(a.firstChild)a.removeChild(a.firstChild)}return this},clone:function(a,b){return a=a==null?!1:a,b=b==null?a:b,this.map(function(){return p.clone(this,a,b)})},html:function(a){return p.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(bm,""):b;if(typeof a=="string"&&!bs.test(a)&&(p.support.htmlSerialize||!bu.test(a))&&(p.support.leadingWhitespace||!bn.test(a))&&!bz[(bp.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(bo,"<$1>");try{for(;d1&&typeof j=="string"&&bw.test(j))return this.each(function(){p(this).domManip(a,c,d)});if(p.isFunction(j))return this.each(function(e){var f=p(this);a[0]=j.call(this,e,c?f.html():b),f.domManip(a,c,d)});if(this[0]){e=p.buildFragment(a,this,k),g=e.fragment,f=g.firstChild,g.childNodes.length===1&&(g=f);if(f){c=c&&p.nodeName(f,"tr");for(h=e.cacheable||l-1;i0?this.clone(!0):this).get(),p(g[e])[b](d),f=f.concat(d);return this.pushStack(f,a,g.selector)}}),p.extend({clone:function(a,b,c){var d,e,f,g;p.support.html5Clone||p.isXMLDoc(a)||!bu.test("<"+a.nodeName+">")?g=a.cloneNode(!0):(bB.innerHTML=a.outerHTML,bB.removeChild(g=bB.firstChild));if((!p.support.noCloneEvent||!p.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!p.isXMLDoc(a)){bE(a,g),d=bF(a),e=bF(g);for(f=0;d[f];++f)e[f]&&bE(d[f],e[f])}if(b){bD(a,g);if(c){d=bF(a),e=bF(g);for(f=0;d[f];++f)bD(d[f],e[f])}}return d=e=null,g},clean:function(a,b,c,d){var f,g,h,i,j,k,l,m,n,o,q,r,s=b===e&&bA,t=[];if(!b||typeof b.createDocumentFragment=="undefined")b=e;for(f=0;(h=a[f])!=null;f++){typeof h=="number"&&(h+="");if(!h)continue;if(typeof h=="string")if(!br.test(h))h=b.createTextNode(h);else{s=s||bk(b),l=b.createElement("div"),s.appendChild(l),h=h.replace(bo,"<$1>"),i=(bp.exec(h)||["",""])[1].toLowerCase(),j=bz[i]||bz._default,k=j[0],l.innerHTML=j[1]+h+j[2];while(k--)l=l.lastChild;if(!p.support.tbody){m=bq.test(h),n=i==="table"&&!m?l.firstChild&&l.firstChild.childNodes:j[1]===""&&!m?l.childNodes:[];for(g=n.length-1;g>=0;--g)p.nodeName(n[g],"tbody")&&!n[g].childNodes.length&&n[g].parentNode.removeChild(n[g])}!p.support.leadingWhitespace&&bn.test(h)&&l.insertBefore(b.createTextNode(bn.exec(h)[0]),l.firstChild),h=l.childNodes,l.parentNode.removeChild(l)}h.nodeType?t.push(h):p.merge(t,h)}l&&(h=l=s=null);if(!p.support.appendChecked)for(f=0;(h=t[f])!=null;f++)p.nodeName(h,"input")?bG(h):typeof h.getElementsByTagName!="undefined"&&p.grep(h.getElementsByTagName("input"),bG);if(c){q=function(a){if(!a.type||bx.test(a.type))return d?d.push(a.parentNode?a.parentNode.removeChild(a):a):c.appendChild(a)};for(f=0;(h=t[f])!=null;f++)if(!p.nodeName(h,"script")||!q(h))c.appendChild(h),typeof h.getElementsByTagName!="undefined"&&(r=p.grep(p.merge([],h.getElementsByTagName("script")),q),t.splice.apply(t,[f+1,0].concat(r)),f+=r.length)}return t},cleanData:function(a,b){var c,d,e,f,g=0,h=p.expando,i=p.cache,j=p.support.deleteExpando,k=p.event.special;for(;(e=a[g])!=null;g++)if(b||p.acceptData(e)){d=e[h],c=d&&i[d];if(c){if(c.events)for(f in c.events)k[f]?p.event.remove(e,f):p.removeEvent(e,f,c.handle);i[d]&&(delete i[d],j?delete e[h]:e.removeAttribute?e.removeAttribute(h):e[h]=null,p.deletedIds.push(d))}}}}),function(){var a,b;p.uaMatch=function(a){a=a.toLowerCase();var b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},a=p.uaMatch(g.userAgent),b={},a.browser&&(b[a.browser]=!0,b.version=a.version),b.chrome?b.webkit=!0:b.webkit&&(b.safari=!0),p.browser=b,p.sub=function(){function a(b,c){return new a.fn.init(b,c)}p.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function c(c,d){return d&&d instanceof p&&!(d instanceof a)&&(d=a(d)),p.fn.init.call(this,c,d,b)},a.fn.init.prototype=a.fn;var b=a(e);return a}}();var bH,bI,bJ,bK=/alpha\([^)]*\)/i,bL=/opacity=([^)]*)/,bM=/^(top|right|bottom|left)$/,bN=/^(none|table(?!-c[ea]).+)/,bO=/^margin/,bP=new RegExp("^("+q+")(.*)$","i"),bQ=new RegExp("^("+q+")(?!px)[a-z%]+$","i"),bR=new RegExp("^([-+])=("+q+")","i"),bS={},bT={position:"absolute",visibility:"hidden",display:"block"},bU={letterSpacing:0,fontWeight:400},bV=["Top","Right","Bottom","Left"],bW=["Webkit","O","Moz","ms"],bX=p.fn.toggle;p.fn.extend({css:function(a,c){return p.access(this,function(a,c,d){return d!==b?p.style(a,c,d):p.css(a,c)},a,c,arguments.length>1)},show:function(){return b$(this,!0)},hide:function(){return b$(this)},toggle:function(a,b){var c=typeof a=="boolean";return p.isFunction(a)&&p.isFunction(b)?bX.apply(this,arguments):this.each(function(){(c?a:bZ(this))?p(this).show():p(this).hide()})}}),p.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bH(a,"opacity");return c===""?"1":c}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":p.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!a||a.nodeType===3||a.nodeType===8||!a.style)return;var f,g,h,i=p.camelCase(c),j=a.style;c=p.cssProps[i]||(p.cssProps[i]=bY(j,i)),h=p.cssHooks[c]||p.cssHooks[i];if(d===b)return h&&"get"in h&&(f=h.get(a,!1,e))!==b?f:j[c];g=typeof d,g==="string"&&(f=bR.exec(d))&&(d=(f[1]+1)*f[2]+parseFloat(p.css(a,c)),g="number");if(d==null||g==="number"&&isNaN(d))return;g==="number"&&!p.cssNumber[i]&&(d+="px");if(!h||!("set"in h)||(d=h.set(a,d,e))!==b)try{j[c]=d}catch(k){}},css:function(a,c,d,e){var f,g,h,i=p.camelCase(c);return c=p.cssProps[i]||(p.cssProps[i]=bY(a.style,i)),h=p.cssHooks[c]||p.cssHooks[i],h&&"get"in h&&(f=h.get(a,!0,e)),f===b&&(f=bH(a,c)),f==="normal"&&c in bU&&(f=bU[c]),d||e!==b?(g=parseFloat(f),d||p.isNumeric(g)?g||0:f):f},swap:function(a,b,c){var d,e,f={};for(e in b)f[e]=a.style[e],a.style[e]=b[e];d=c.call(a);for(e in b)a.style[e]=f[e];return d}}),a.getComputedStyle?bH=function(b,c){var d,e,f,g,h=a.getComputedStyle(b,null),i=b.style;return h&&(d=h[c],d===""&&!p.contains(b.ownerDocument,b)&&(d=p.style(b,c)),bQ.test(d)&&bO.test(c)&&(e=i.width,f=i.minWidth,g=i.maxWidth,i.minWidth=i.maxWidth=i.width=d,d=h.width,i.width=e,i.minWidth=f,i.maxWidth=g)),d}:e.documentElement.currentStyle&&(bH=function(a,b){var c,d,e=a.currentStyle&&a.currentStyle[b],f=a.style;return e==null&&f&&f[b]&&(e=f[b]),bQ.test(e)&&!bM.test(b)&&(c=f.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":e,e=f.pixelLeft+"px",f.left=c,d&&(a.runtimeStyle.left=d)),e===""?"auto":e}),p.each(["height","width"],function(a,b){p.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth===0&&bN.test(bH(a,"display"))?p.swap(a,bT,function(){return cb(a,b,d)}):cb(a,b,d)},set:function(a,c,d){return b_(a,c,d?ca(a,b,d,p.support.boxSizing&&p.css(a,"boxSizing")==="border-box"):0)}}}),p.support.opacity||(p.cssHooks.opacity={get:function(a,b){return bL.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=p.isNumeric(b)?"alpha(opacity="+b*100+")":"",f=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&p.trim(f.replace(bK,""))===""&&c.removeAttribute){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bK.test(f)?f.replace(bK,e):f+" "+e}}),p(function(){p.support.reliableMarginRight||(p.cssHooks.marginRight={get:function(a,b){return p.swap(a,{display:"inline-block"},function(){if(b)return bH(a,"marginRight")})}}),!p.support.pixelPosition&&p.fn.position&&p.each(["top","left"],function(a,b){p.cssHooks[b]={get:function(a,c){if(c){var d=bH(a,b);return bQ.test(d)?p(a).position()[b]+"px":d}}}})}),p.expr&&p.expr.filters&&(p.expr.filters.hidden=function(a){return a.offsetWidth===0&&a.offsetHeight===0||!p.support.reliableHiddenOffsets&&(a.style&&a.style.display||bH(a,"display"))==="none"},p.expr.filters.visible=function(a){return!p.expr.filters.hidden(a)}),p.each({margin:"",padding:"",border:"Width"},function(a,b){p.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bV[d]+b]=e[d]||e[d-2]||e[0];return f}},bO.test(a)||(p.cssHooks[a+b].set=b_)});var cd=/%20/g,ce=/\[\]$/,cf=/\r?\n/g,cg=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ch=/^(?:select|textarea)/i;p.fn.extend({serialize:function(){return p.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?p.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ch.test(this.nodeName)||cg.test(this.type))}).map(function(a,b){var c=p(this).val();return c==null?null:p.isArray(c)?p.map(c,function(a,c){return{name:b.name,value:a.replace(cf,"\r\n")}}):{name:b.name,value:c.replace(cf,"\r\n")}}).get()}}),p.param=function(a,c){var d,e=[],f=function(a,b){b=p.isFunction(b)?b():b==null?"":b,e[e.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=p.ajaxSettings&&p.ajaxSettings.traditional);if(p.isArray(a)||a.jquery&&!p.isPlainObject(a))p.each(a,function(){f(this.name,this.value)});else for(d in a)ci(d,a[d],c,f);return e.join("&").replace(cd,"+")};var cj,ck,cl=/#.*$/,cm=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,cn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,co=/^(?:GET|HEAD)$/,cp=/^\/\//,cq=/\?/,cr=/)<[^<]*)*<\/script>/gi,cs=/([?&])_=[^&]*/,ct=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,cu=p.fn.load,cv={},cw={},cx=["*/"]+["*"];try{ck=f.href}catch(cy){ck=e.createElement("a"),ck.href="",ck=ck.href}cj=ct.exec(ck.toLowerCase())||[],p.fn.load=function(a,c,d){if(typeof a!="string"&&cu)return cu.apply(this,arguments);if(!this.length)return this;var e,f,g,h=this,i=a.indexOf(" ");return i>=0&&(e=a.slice(i,a.length),a=a.slice(0,i)),p.isFunction(c)?(d=c,c=b):c&&typeof c=="object"&&(f="POST"),p.ajax({url:a,type:f,dataType:"html",data:c,complete:function(a,b){d&&h.each(d,g||[a.responseText,b,a])}}).done(function(a){g=arguments,h.html(e?p("
                                ").append(a.replace(cr,"")).find(e):a)}),this},p.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){p.fn[b]=function(a){return this.on(b,a)}}),p.each(["get","post"],function(a,c){p[c]=function(a,d,e,f){return p.isFunction(d)&&(f=f||e,e=d,d=b),p.ajax({type:c,url:a,data:d,success:e,dataType:f})}}),p.extend({getScript:function(a,c){return p.get(a,b,c,"script")},getJSON:function(a,b,c){return p.get(a,b,c,"json")},ajaxSetup:function(a,b){return b?cB(a,p.ajaxSettings):(b=a,a=p.ajaxSettings),cB(a,b),a},ajaxSettings:{url:ck,isLocal:cn.test(cj[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":cx},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":p.parseJSON,"text xml":p.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:cz(cv),ajaxTransport:cz(cw),ajax:function(a,c){function y(a,c,f,i){var k,s,t,u,w,y=c;if(v===2)return;v=2,h&&clearTimeout(h),g=b,e=i||"",x.readyState=a>0?4:0,f&&(u=cC(l,x,f));if(a>=200&&a<300||a===304)l.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(p.lastModified[d]=w),w=x.getResponseHeader("Etag"),w&&(p.etag[d]=w)),a===304?(y="notmodified",k=!0):(k=cD(l,u),y=k.state,s=k.data,t=k.error,k=!t);else{t=y;if(!y||a)y="error",a<0&&(a=0)}x.status=a,x.statusText=(c||y)+"",k?o.resolveWith(m,[s,y,x]):o.rejectWith(m,[x,y,t]),x.statusCode(r),r=b,j&&n.trigger("ajax"+(k?"Success":"Error"),[x,l,k?s:t]),q.fireWith(m,[x,y]),j&&(n.trigger("ajaxComplete",[x,l]),--p.active||p.event.trigger("ajaxStop"))}typeof a=="object"&&(c=a,a=b),c=c||{};var d,e,f,g,h,i,j,k,l=p.ajaxSetup({},c),m=l.context||l,n=m!==l&&(m.nodeType||m instanceof p)?p(m):p.event,o=p.Deferred(),q=p.Callbacks("once memory"),r=l.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,setRequestHeader:function(a,b){if(!v){var c=a.toLowerCase();a=u[c]=u[c]||a,t[a]=b}return this},getAllResponseHeaders:function(){return v===2?e:null},getResponseHeader:function(a){var c;if(v===2){if(!f){f={};while(c=cm.exec(e))f[c[1].toLowerCase()]=c[2]}c=f[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){return v||(l.mimeType=a),this},abort:function(a){return a=a||w,g&&g.abort(a),y(0,a),this}};o.promise(x),x.success=x.done,x.error=x.fail,x.complete=q.add,x.statusCode=function(a){if(a){var b;if(v<2)for(b in a)r[b]=[r[b],a[b]];else b=a[x.status],x.always(b)}return this},l.url=((a||l.url)+"").replace(cl,"").replace(cp,cj[1]+"//"),l.dataTypes=p.trim(l.dataType||"*").toLowerCase().split(s),l.crossDomain==null&&(i=ct.exec(l.url.toLowerCase())||!1,l.crossDomain=i&&i.join(":")+(i[3]?"":i[1]==="http:"?80:443)!==cj.join(":")+(cj[3]?"":cj[1]==="http:"?80:443)),l.data&&l.processData&&typeof l.data!="string"&&(l.data=p.param(l.data,l.traditional)),cA(cv,l,c,x);if(v===2)return x;j=l.global,l.type=l.type.toUpperCase(),l.hasContent=!co.test(l.type),j&&p.active++===0&&p.event.trigger("ajaxStart");if(!l.hasContent){l.data&&(l.url+=(cq.test(l.url)?"&":"?")+l.data,delete l.data),d=l.url;if(l.cache===!1){var z=p.now(),A=l.url.replace(cs,"$1_="+z);l.url=A+(A===l.url?(cq.test(l.url)?"&":"?")+"_="+z:"")}}(l.data&&l.hasContent&&l.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",l.contentType),l.ifModified&&(d=d||l.url,p.lastModified[d]&&x.setRequestHeader("If-Modified-Since",p.lastModified[d]),p.etag[d]&&x.setRequestHeader("If-None-Match",p.etag[d])),x.setRequestHeader("Accept",l.dataTypes[0]&&l.accepts[l.dataTypes[0]]?l.accepts[l.dataTypes[0]]+(l.dataTypes[0]!=="*"?", "+cx+"; q=0.01":""):l.accepts["*"]);for(k in l.headers)x.setRequestHeader(k,l.headers[k]);if(!l.beforeSend||l.beforeSend.call(m,x,l)!==!1&&v!==2){w="abort";for(k in{success:1,error:1,complete:1})x[k](l[k]);g=cA(cw,l,c,x);if(!g)y(-1,"No Transport");else{x.readyState=1,j&&n.trigger("ajaxSend",[x,l]),l.async&&l.timeout>0&&(h=setTimeout(function(){x.abort("timeout")},l.timeout));try{v=1,g.send(t,y)}catch(B){if(v<2)y(-1,B);else throw B}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var cE=[],cF=/\?/,cG=/(=)\?(?=&|$)|\?\?/,cH=p.now();p.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=cE.pop()||p.expando+"_"+cH++;return this[a]=!0,a}}),p.ajaxPrefilter("json jsonp",function(c,d,e){var f,g,h,i=c.data,j=c.url,k=c.jsonp!==!1,l=k&&cG.test(j),m=k&&!l&&typeof i=="string"&&!(c.contentType||"").indexOf("application/x-www-form-urlencoded")&&cG.test(i);if(c.dataTypes[0]==="jsonp"||l||m)return f=c.jsonpCallback=p.isFunction(c.jsonpCallback)?c.jsonpCallback():c.jsonpCallback,g=a[f],l?c.url=j.replace(cG,"$1"+f):m?c.data=i.replace(cG,"$1"+f):k&&(c.url+=(cF.test(j)?"&":"?")+c.jsonp+"="+f),c.converters["script json"]=function(){return h||p.error(f+" was not called"),h[0]},c.dataTypes[0]="json",a[f]=function(){h=arguments},e.always(function(){a[f]=g,c[f]&&(c.jsonpCallback=d.jsonpCallback,cE.push(f)),h&&p.isFunction(g)&&g(h[0]),h=g=b}),"script"}),p.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){return p.globalEval(a),a}}}),p.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),p.ajaxTransport("script",function(a){if(a.crossDomain){var c,d=e.head||e.getElementsByTagName("head")[0]||e.documentElement;return{send:function(f,g){c=e.createElement("script"),c.async="async",a.scriptCharset&&(c.charset=a.scriptCharset),c.src=a.url,c.onload=c.onreadystatechange=function(a,e){if(e||!c.readyState||/loaded|complete/.test(c.readyState))c.onload=c.onreadystatechange=null,d&&c.parentNode&&d.removeChild(c),c=b,e||g(200,"success")},d.insertBefore(c,d.firstChild)},abort:function(){c&&c.onload(0,1)}}}});var cI,cJ=a.ActiveXObject?function(){for(var a in cI)cI[a](0,1)}:!1,cK=0;p.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&cL()||cM()}:cL,function(a){p.extend(p.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(p.ajaxSettings.xhr()),p.support.ajax&&p.ajaxTransport(function(c){if(!c.crossDomain||p.support.cors){var d;return{send:function(e,f){var g,h,i=c.xhr();c.username?i.open(c.type,c.url,c.async,c.username,c.password):i.open(c.type,c.url,c.async);if(c.xhrFields)for(h in c.xhrFields)i[h]=c.xhrFields[h];c.mimeType&&i.overrideMimeType&&i.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(h in e)i.setRequestHeader(h,e[h])}catch(j){}i.send(c.hasContent&&c.data||null),d=function(a,e){var h,j,k,l,m;try{if(d&&(e||i.readyState===4)){d=b,g&&(i.onreadystatechange=p.noop,cJ&&delete cI[g]);if(e)i.readyState!==4&&i.abort();else{h=i.status,k=i.getAllResponseHeaders(),l={},m=i.responseXML,m&&m.documentElement&&(l.xml=m);try{l.text=i.responseText}catch(a){}try{j=i.statusText}catch(n){j=""}!h&&c.isLocal&&!c.crossDomain?h=l.text?200:404:h===1223&&(h=204)}}}catch(o){e||f(-1,o)}l&&f(h,j,l,k)},c.async?i.readyState===4?setTimeout(d,0):(g=++cK,cJ&&(cI||(cI={},p(a).unload(cJ)),cI[g]=d),i.onreadystatechange=d):d()},abort:function(){d&&d(0,1)}}}});var cN,cO,cP=/^(?:toggle|show|hide)$/,cQ=new RegExp("^(?:([-+])=|)("+q+")([a-z%]*)$","i"),cR=/queueHooks$/,cS=[cY],cT={"*":[function(a,b){var c,d,e=this.createTween(a,b),f=cQ.exec(b),g=e.cur(),h=+g||0,i=1,j=20;if(f){c=+f[2],d=f[3]||(p.cssNumber[a]?"":"px");if(d!=="px"&&h){h=p.css(e.elem,a,!0)||c||1;do i=i||".5",h=h/i,p.style(e.elem,a,h+d);while(i!==(i=e.cur()/g)&&i!==1&&--j)}e.unit=d,e.start=h,e.end=f[1]?h+(f[1]+1)*c:c}return e}]};p.Animation=p.extend(cW,{tweener:function(a,b){p.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");var c,d=0,e=a.length;for(;d-1,j={},k={},l,m;i?(k=e.position(),l=k.top,m=k.left):(l=parseFloat(g)||0,m=parseFloat(h)||0),p.isFunction(b)&&(b=b.call(a,c,f)),b.top!=null&&(j.top=b.top-f.top+l),b.left!=null&&(j.left=b.left-f.left+m),"using"in b?b.using.call(a,j):e.css(j)}},p.fn.extend({position:function(){if(!this[0])return;var a=this[0],b=this.offsetParent(),c=this.offset(),d=c_.test(b[0].nodeName)?{top:0,left:0}:b.offset();return c.top-=parseFloat(p.css(a,"marginTop"))||0,c.left-=parseFloat(p.css(a,"marginLeft"))||0,d.top+=parseFloat(p.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(p.css(b[0],"borderLeftWidth"))||0,{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||e.body;while(a&&!c_.test(a.nodeName)&&p.css(a,"position")==="static")a=a.offsetParent;return a||e.body})}}),p.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);p.fn[a]=function(e){return p.access(this,function(a,e,f){var g=da(a);if(f===b)return g?c in g?g[c]:g.document.documentElement[e]:a[e];g?g.scrollTo(d?p(g).scrollLeft():f,d?f:p(g).scrollTop()):a[e]=f},a,e,arguments.length,null)}}),p.each({Height:"height",Width:"width"},function(a,c){p.each({padding:"inner"+a,content:c,"":"outer"+a},function(d,e){p.fn[e]=function(e,f){var g=arguments.length&&(d||typeof e!="boolean"),h=d||(e===!0||f===!0?"margin":"border");return p.access(this,function(c,d,e){var f;return p.isWindow(c)?c.document.documentElement["client"+a]:c.nodeType===9?(f=c.documentElement,Math.max(c.body["scroll"+a],f["scroll"+a],c.body["offset"+a],f["offset"+a],f["client"+a])):e===b?p.css(c,d,e,h):p.style(c,d,e,h)},c,g?e:b,g,null)}})}),a.jQuery=a.$=p,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return p})})(window); \ No newline at end of file diff --git a/nebula-exchange/target/site/scaladocs/lib/jquery.layout.js b/nebula-exchange/target/site/scaladocs/lib/jquery.layout.js deleted file mode 100644 index d5e008d..0000000 --- a/nebula-exchange/target/site/scaladocs/lib/jquery.layout.js +++ /dev/null @@ -1,5486 +0,0 @@ -/** - * @preserve jquery.layout 1.3.0 - Release Candidate 30.62 - * $Date: 2012-08-04 08:00:00 (Thu, 23 Aug 2012) $ - * $Rev: 303006 $ - * - * Copyright (c) 2012 - * Fabrizio Balliano (http://www.fabrizioballiano.net) - * Kevin Dalman (http://allpro.net) - * - * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html) - * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses. - * - * Changelog: http://layout.jquery-dev.net/changelog.cfm#1.3.0.rc30.62 - * NOTE: This is a short-term release to patch a couple of bugs. - * These bugs are listed as officially fixed in RC30.7, which will be released shortly. - * - * Docs: http://layout.jquery-dev.net/documentation.html - * Tips: http://layout.jquery-dev.net/tips.html - * Help: http://groups.google.com/group/jquery-ui-layout - */ - -/* JavaDoc Info: http://code.google.com/closure/compiler/docs/js-for-compiler.html - * {!Object} non-nullable type (never NULL) - * {?string} nullable type (sometimes NULL) - default for {Object} - * {number=} optional parameter - * {*} ALL types - */ - -// NOTE: For best readability, view with a fixed-width font and tabs equal to 4-chars - -;(function ($) { - -// alias Math methods - used a lot! -var min = Math.min -, max = Math.max -, round = Math.floor - -, isStr = function (v) { return $.type(v) === "string"; } - -, runPluginCallbacks = function (Instance, a_fn) { - if ($.isArray(a_fn)) - for (var i=0, c=a_fn.length; i
                                ').appendTo("body"); - var d = { width: $c.width() - $c[0].clientWidth, height: $c.height() - $c[0].clientHeight }; - $c.remove(); - window.scrollbarWidth = d.width; - window.scrollbarHeight = d.height; - return dim.match(/^(width|height)$/) ? d[dim] : d; - } - - - /** - * Returns hash container 'display' and 'visibility' - * - * @see $.swap() - swaps CSS, runs callback, resets CSS - */ -, showInvisibly: function ($E, force) { - if ($E && $E.length && (force || $E.css('display') === "none")) { // only if not *already hidden* - var s = $E[0].style - // save ONLY the 'style' props because that is what we must restore - , CSS = { display: s.display || '', visibility: s.visibility || '' }; - // show element 'invisibly' so can be measured - $E.css({ display: "block", visibility: "hidden" }); - return CSS; - } - return {}; - } - - /** - * Returns data for setting size of an element (container or a pane). - * - * @see _create(), onWindowResize() for container, plus others for pane - * @return JSON Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc - */ -, getElementDimensions: function ($E) { - var - d = {} // dimensions hash - , x = d.css = {} // CSS hash - , i = {} // TEMP insets - , b, p // TEMP border, padding - , N = $.layout.cssNum - , off = $E.offset() - ; - d.offsetLeft = off.left; - d.offsetTop = off.top; - - $.each("Left,Right,Top,Bottom".split(","), function (idx, e) { // e = edge - b = x["border" + e] = $.layout.borderWidth($E, e); - p = x["padding"+ e] = $.layout.cssNum($E, "padding"+e); - i[e] = b + p; // total offset of content from outer side - d["inset"+ e] = p; // eg: insetLeft = paddingLeft - }); - - d.offsetWidth = $E.innerWidth(); // offsetWidth is used in calc when doing manual resize - d.offsetHeight = $E.innerHeight(); // ditto - d.outerWidth = $E.outerWidth(); - d.outerHeight = $E.outerHeight(); - d.innerWidth = max(0, d.outerWidth - i.Left - i.Right); - d.innerHeight = max(0, d.outerHeight - i.Top - i.Bottom); - - x.width = $E.width(); - x.height = $E.height(); - x.top = N($E,"top",true); - x.bottom = N($E,"bottom",true); - x.left = N($E,"left",true); - x.right = N($E,"right",true); - - //d.visible = $E.is(":visible");// && x.width > 0 && x.height > 0; - - return d; - } - -, getElementCSS: function ($E, list) { - var - CSS = {} - , style = $E[0].style - , props = list.split(",") - , sides = "Top,Bottom,Left,Right".split(",") - , attrs = "Color,Style,Width".split(",") - , p, s, a, i, j, k - ; - for (i=0; i < props.length; i++) { - p = props[i]; - if (p.match(/(border|padding|margin)$/)) - for (j=0; j < 4; j++) { - s = sides[j]; - if (p === "border") - for (k=0; k < 3; k++) { - a = attrs[k]; - CSS[p+s+a] = style[p+s+a]; - } - else - CSS[p+s] = style[p+s]; - } - else - CSS[p] = style[p]; - }; - return CSS - } - - /** - * Return the innerWidth for the current browser/doctype - * - * @see initPanes(), sizeMidPanes(), initHandles(), sizeHandles() - * @param {Array.} $E Must pass a jQuery object - first element is processed - * @param {number=} outerWidth (optional) Can pass a width, allowing calculations BEFORE element is resized - * @return {number} Returns the innerWidth of the elem by subtracting padding and borders - */ -, cssWidth: function ($E, outerWidth) { - // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed - if (outerWidth <= 0) return 0; - - if (!$.layout.browser.boxModel) return outerWidth; - - // strip border and padding from outerWidth to get CSS Width - var b = $.layout.borderWidth - , n = $.layout.cssNum - , W = outerWidth - - b($E, "Left") - - b($E, "Right") - - n($E, "paddingLeft") - - n($E, "paddingRight"); - - return max(0,W); - } - - /** - * Return the innerHeight for the current browser/doctype - * - * @see initPanes(), sizeMidPanes(), initHandles(), sizeHandles() - * @param {Array.} $E Must pass a jQuery object - first element is processed - * @param {number=} outerHeight (optional) Can pass a width, allowing calculations BEFORE element is resized - * @return {number} Returns the innerHeight of the elem by subtracting padding and borders - */ -, cssHeight: function ($E, outerHeight) { - // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed - if (outerHeight <= 0) return 0; - - if (!$.layout.browser.boxModel) return outerHeight; - - // strip border and padding from outerHeight to get CSS Height - var b = $.layout.borderWidth - , n = $.layout.cssNum - , H = outerHeight - - b($E, "Top") - - b($E, "Bottom") - - n($E, "paddingTop") - - n($E, "paddingBottom"); - - return max(0,H); - } - - /** - * Returns the 'current CSS numeric value' for a CSS property - 0 if property does not exist - * - * @see Called by many methods - * @param {Array.} $E Must pass a jQuery object - first element is processed - * @param {string} prop The name of the CSS property, eg: top, width, etc. - * @param {boolean=} [allowAuto=false] true = return 'auto' if that is value; false = return 0 - * @return {(string|number)} Usually used to get an integer value for position (top, left) or size (height, width) - */ -, cssNum: function ($E, prop, allowAuto) { - if (!$E.jquery) $E = $($E); - var CSS = $.layout.showInvisibly($E) - , p = $.css($E[0], prop, true) - , v = allowAuto && p=="auto" ? p : (parseInt(p, 10) || 0); - $E.css( CSS ); // RESET - return v; - } - -, borderWidth: function (el, side) { - if (el.jquery) el = el[0]; - var b = "border"+ side.substr(0,1).toUpperCase() + side.substr(1); // left => Left - return $.css(el, b+"Style", true) === "none" ? 0 : (parseInt($.css(el, b+"Width", true), 10) || 0); - } - - /** - * Mouse-tracking utility - FUTURE REFERENCE - * - * init: if (!window.mouse) { - * window.mouse = { x: 0, y: 0 }; - * $(document).mousemove( $.layout.trackMouse ); - * } - * - * @param {Object} evt - * -, trackMouse: function (evt) { - window.mouse = { x: evt.clientX, y: evt.clientY }; - } - */ - - /** - * SUBROUTINE for preventPrematureSlideClose option - * - * @param {Object} evt - * @param {Object=} el - */ -, isMouseOverElem: function (evt, el) { - var - $E = $(el || this) - , d = $E.offset() - , T = d.top - , L = d.left - , R = L + $E.outerWidth() - , B = T + $E.outerHeight() - , x = evt.pageX // evt.clientX ? - , y = evt.pageY // evt.clientY ? - ; - // if X & Y are < 0, probably means is over an open SELECT - return ($.layout.browser.msie && x < 0 && y < 0) || ((x >= L && x <= R) && (y >= T && y <= B)); - } - - /** - * Message/Logging Utility - * - * @example $.layout.msg("My message"); // log text - * @example $.layout.msg("My message", true); // alert text - * @example $.layout.msg({ foo: "bar" }, "Title"); // log hash-data, with custom title - * @example $.layout.msg({ foo: "bar" }, true, "Title", { sort: false }); -OR- - * @example $.layout.msg({ foo: "bar" }, "Title", { sort: false, display: true }); // alert hash-data - * - * @param {(Object|string)} info String message OR Hash/Array - * @param {(Boolean|string|Object)=} [popup=false] True means alert-box - can be skipped - * @param {(Object|string)=} [debugTitle=""] Title for Hash data - can be skipped - * @param {Object=} [debugOpts] Extra options for debug output - */ -, msg: function (info, popup, debugTitle, debugOpts) { - if ($.isPlainObject(info) && window.debugData) { - if (typeof popup === "string") { - debugOpts = debugTitle; - debugTitle = popup; - } - else if (typeof debugTitle === "object") { - debugOpts = debugTitle; - debugTitle = null; - } - var t = debugTitle || "log( )" - , o = $.extend({ sort: false, returnHTML: false, display: false }, debugOpts); - if (popup === true || o.display) - debugData( info, t, o ); - else if (window.console) - console.log(debugData( info, t, o )); - } - else if (popup) - alert(info); - else if (window.console) - console.log(info); - else { - var id = "#layoutLogger" - , $l = $(id); - if (!$l.length) - $l = createLog(); - $l.children("ul").append('
                              9. '+ info.replace(/\/g,">") +'
                              10. '); - } - - function createLog () { - var pos = $.support.fixedPosition ? 'fixed' : 'absolute' - , $e = $('
                                ' - + '
                                ' - + 'XLayout console.log
                                ' - + '
                                  ' - + '
                                  ' - ).appendTo("body"); - $e.css('left', $(window).width() - $e.outerWidth() - 5) - if ($.ui.draggable) $e.draggable({ handle: ':first-child' }); - return $e; - }; - } - -}; - -// DEFAULT OPTIONS -$.layout.defaults = { -/* - * LAYOUT & LAYOUT-CONTAINER OPTIONS - * - none of these options are applicable to individual panes - */ - name: "" // Not required, but useful for buttons and used for the state-cookie -, containerSelector: "" // ONLY used when specifying a childOptions - to find container-element that is NOT directly-nested -, containerClass: "ui-layout-container" // layout-container element -, scrollToBookmarkOnLoad: true // after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark) -, resizeWithWindow: true // bind thisLayout.resizeAll() to the window.resize event -, resizeWithWindowDelay: 200 // delay calling resizeAll because makes window resizing very jerky -, resizeWithWindowMaxDelay: 0 // 0 = none - force resize every XX ms while window is being resized -, onresizeall_start: null // CALLBACK when resizeAll() STARTS - NOT pane-specific -, onresizeall_end: null // CALLBACK when resizeAll() ENDS - NOT pane-specific -, onload_start: null // CALLBACK when Layout inits - after options initialized, but before elements -, onload_end: null // CALLBACK when Layout inits - after EVERYTHING has been initialized -, onunload_start: null // CALLBACK when Layout is destroyed OR onWindowUnload -, onunload_end: null // CALLBACK when Layout is destroyed OR onWindowUnload -, initPanes: true // false = DO NOT initialize the panes onLoad - will init later -, showErrorMessages: true // enables fatal error messages to warn developers of common errors -, showDebugMessages: false // display console-and-alert debug msgs - IF this Layout version _has_ debugging code! -// Changing this zIndex value will cause other zIndex values to automatically change -, zIndex: null // the PANE zIndex - resizers and masks will be +1 -// DO NOT CHANGE the zIndex values below unless you clearly understand their relationships -, zIndexes: { // set _default_ z-index values here... - pane_normal: 0 // normal z-index for panes - , content_mask: 1 // applied to overlays used to mask content INSIDE panes during resizing - , resizer_normal: 2 // normal z-index for resizer-bars - , pane_sliding: 100 // applied to *BOTH* the pane and its resizer when a pane is 'slid open' - , pane_animate: 1000 // applied to the pane when being animated - not applied to the resizer - , resizer_drag: 10000 // applied to the CLONED resizer-bar when being 'dragged' - } -, errors: { - pane: "pane" // description of "layout pane element" - used only in error messages - , selector: "selector" // description of "jQuery-selector" - used only in error messages - , addButtonError: "Error Adding Button \n\nInvalid " - , containerMissing: "UI Layout Initialization Error\n\nThe specified layout-container does not exist." - , centerPaneMissing: "UI Layout Initialization Error\n\nThe center-pane element does not exist.\n\nThe center-pane is a required element." - , noContainerHeight: "UI Layout Initialization Warning\n\nThe layout-container \"CONTAINER\" has no height.\n\nTherefore the layout is 0-height and hence 'invisible'!" - , callbackError: "UI Layout Callback Error\n\nThe EVENT callback is not a valid function." - } -/* - * PANE DEFAULT SETTINGS - * - settings under the 'panes' key become the default settings for *all panes* - * - ALL pane-options can also be set specifically for each panes, which will override these 'default values' - */ -, panes: { // default options for 'all panes' - will be overridden by 'per-pane settings' - applyDemoStyles: false // NOTE: renamed from applyDefaultStyles for clarity - , closable: true // pane can open & close - , resizable: true // when open, pane can be resized - , slidable: true // when closed, pane can 'slide open' over other panes - closes on mouse-out - , initClosed: false // true = init pane as 'closed' - , initHidden: false // true = init pane as 'hidden' - no resizer-bar/spacing - // SELECTORS - //, paneSelector: "" // MUST be pane-specific - jQuery selector for pane - , contentSelector: ".ui-layout-content" // INNER div/element to auto-size so only it scrolls, not the entire pane! - , contentIgnoreSelector: ".ui-layout-ignore" // element(s) to 'ignore' when measuring 'content' - , findNestedContent: false // true = $P.find(contentSelector), false = $P.children(contentSelector) - // GENERIC ROOT-CLASSES - for auto-generated classNames - , paneClass: "ui-layout-pane" // Layout Pane - , resizerClass: "ui-layout-resizer" // Resizer Bar - , togglerClass: "ui-layout-toggler" // Toggler Button - , buttonClass: "ui-layout-button" // CUSTOM Buttons - eg: '[ui-layout-button]-toggle/-open/-close/-pin' - // ELEMENT SIZE & SPACING - //, size: 100 // MUST be pane-specific -initial size of pane - , minSize: 0 // when manually resizing a pane - , maxSize: 0 // ditto, 0 = no limit - , spacing_open: 6 // space between pane and adjacent panes - when pane is 'open' - , spacing_closed: 6 // ditto - when pane is 'closed' - , togglerLength_open: 50 // Length = WIDTH of toggler button on north/south sides - HEIGHT on east/west sides - , togglerLength_closed: 50 // 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden' - , togglerAlign_open: "center" // top/left, bottom/right, center, OR... - , togglerAlign_closed: "center" // 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right - , togglerContent_open: "" // text or HTML to put INSIDE the toggler - , togglerContent_closed: "" // ditto - // RESIZING OPTIONS - , resizerDblClickToggle: true // - , autoResize: true // IF size is 'auto' or a percentage, then recalc 'pixel size' whenever the layout resizes - , autoReopen: true // IF a pane was auto-closed due to noRoom, reopen it when there is room? False = leave it closed - , resizerDragOpacity: 1 // option for ui.draggable - //, resizerCursor: "" // MUST be pane-specific - cursor when over resizer-bar - , maskContents: false // true = add DIV-mask over-or-inside this pane so can 'drag' over IFRAMES - , maskObjects: false // true = add IFRAME-mask over-or-inside this pane to cover objects/applets - content-mask will overlay this mask - , maskZindex: null // will override zIndexes.content_mask if specified - not applicable to iframe-panes - , resizingGrid: false // grid size that the resizers will snap-to during resizing, eg: [20,20] - , livePaneResizing: false // true = LIVE Resizing as resizer is dragged - , liveContentResizing: false // true = re-measure header/footer heights as resizer is dragged - , liveResizingTolerance: 1 // how many px change before pane resizes, to control performance - // SLIDING OPTIONS - , sliderCursor: "pointer" // cursor when resizer-bar will trigger 'sliding' - , slideTrigger_open: "click" // click, dblclick, mouseenter - , slideTrigger_close: "mouseleave"// click, mouseleave - , slideDelay_open: 300 // applies only for mouseenter event - 0 = instant open - , slideDelay_close: 300 // applies only for mouseleave event (300ms is the minimum!) - , hideTogglerOnSlide: false // when pane is slid-open, should the toggler show? - , preventQuickSlideClose: $.layout.browser.webkit // Chrome triggers slideClosed as it is opening - , preventPrematureSlideClose: false // handle incorrect mouseleave trigger, like when over a SELECT-list in IE - // PANE-SPECIFIC TIPS & MESSAGES - , tips: { - Open: "Open" // eg: "Open Pane" - , Close: "Close" - , Resize: "Resize" - , Slide: "Slide Open" - , Pin: "Pin" - , Unpin: "Un-Pin" - , noRoomToOpen: "Not enough room to show this panel." // alert if user tries to open a pane that cannot - , minSizeWarning: "Panel has reached its minimum size" // displays in browser statusbar - , maxSizeWarning: "Panel has reached its maximum size" // ditto - } - // HOT-KEYS & MISC - , showOverflowOnHover: false // will bind allowOverflow() utility to pane.onMouseOver - , enableCursorHotkey: true // enabled 'cursor' hotkeys - //, customHotkey: "" // MUST be pane-specific - EITHER a charCode OR a character - , customHotkeyModifier: "SHIFT" // either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT' - // PANE ANIMATION - // NOTE: fxSss_open, fxSss_close & fxSss_size options (eg: fxName_open) are auto-generated if not passed - , fxName: "slide" // ('none' or blank), slide, drop, scale -- only relevant to 'open' & 'close', NOT 'size' - , fxSpeed: null // slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration - , fxSettings: {} // can be passed, eg: { easing: "easeOutBounce", duration: 1500 } - , fxOpacityFix: true // tries to fix opacity in IE to restore anti-aliasing after animation - , animatePaneSizing: false // true = animate resizing after dragging resizer-bar OR sizePane() is called - /* NOTE: Action-specific FX options are auto-generated from the options above if not specifically set: - fxName_open: "slide" // 'Open' pane animation - fnName_close: "slide" // 'Close' pane animation - fxName_size: "slide" // 'Size' pane animation - when animatePaneSizing = true - fxSpeed_open: null - fxSpeed_close: null - fxSpeed_size: null - fxSettings_open: {} - fxSettings_close: {} - fxSettings_size: {} - */ - // CHILD/NESTED LAYOUTS - , childOptions: null // Layout-options for nested/child layout - even {} is valid as options - , initChildLayout: true // true = child layout will be created as soon as _this_ layout completes initialization - , destroyChildLayout: true // true = destroy child-layout if this pane is destroyed - , resizeChildLayout: true // true = trigger child-layout.resizeAll() when this pane is resized - // EVENT TRIGGERING - , triggerEventsOnLoad: false // true = trigger onopen OR onclose callbacks when layout initializes - , triggerEventsDuringLiveResize: true // true = trigger onresize callback REPEATEDLY if livePaneResizing==true - // PANE CALLBACKS - , onshow_start: null // CALLBACK when pane STARTS to Show - BEFORE onopen/onhide_start - , onshow_end: null // CALLBACK when pane ENDS being Shown - AFTER onopen/onhide_end - , onhide_start: null // CALLBACK when pane STARTS to Close - BEFORE onclose_start - , onhide_end: null // CALLBACK when pane ENDS being Closed - AFTER onclose_end - , onopen_start: null // CALLBACK when pane STARTS to Open - , onopen_end: null // CALLBACK when pane ENDS being Opened - , onclose_start: null // CALLBACK when pane STARTS to Close - , onclose_end: null // CALLBACK when pane ENDS being Closed - , onresize_start: null // CALLBACK when pane STARTS being Resized ***FOR ANY REASON*** - , onresize_end: null // CALLBACK when pane ENDS being Resized ***FOR ANY REASON*** - , onsizecontent_start: null // CALLBACK when sizing of content-element STARTS - , onsizecontent_end: null // CALLBACK when sizing of content-element ENDS - , onswap_start: null // CALLBACK when pane STARTS to Swap - , onswap_end: null // CALLBACK when pane ENDS being Swapped - , ondrag_start: null // CALLBACK when pane STARTS being ***MANUALLY*** Resized - , ondrag_end: null // CALLBACK when pane ENDS being ***MANUALLY*** Resized - } -/* - * PANE-SPECIFIC SETTINGS - * - options listed below MUST be specified per-pane - they CANNOT be set under 'panes' - * - all options under the 'panes' key can also be set specifically for any pane - * - most options under the 'panes' key apply only to 'border-panes' - NOT the center-pane - */ -, north: { - paneSelector: ".ui-layout-north" - , size: "auto" // eg: "auto", "30%", .30, 200 - , resizerCursor: "n-resize" // custom = url(myCursor.cur) - , customHotkey: "" // EITHER a charCode (43) OR a character ("o") - } -, south: { - paneSelector: ".ui-layout-south" - , size: "auto" - , resizerCursor: "s-resize" - , customHotkey: "" - } -, east: { - paneSelector: ".ui-layout-east" - , size: 200 - , resizerCursor: "e-resize" - , customHotkey: "" - } -, west: { - paneSelector: ".ui-layout-west" - , size: 200 - , resizerCursor: "w-resize" - , customHotkey: "" - } -, center: { - paneSelector: ".ui-layout-center" - , minWidth: 0 - , minHeight: 0 - } -}; - -$.layout.optionsMap = { - // layout/global options - NOT pane-options - layout: ("stateManagement,effects,zIndexes,errors," - + "name,zIndex,scrollToBookmarkOnLoad,showErrorMessages," - + "resizeWithWindow,resizeWithWindowDelay,resizeWithWindowMaxDelay," - + "onresizeall,onresizeall_start,onresizeall_end,onload,onunload").split(",") -// borderPanes: [ ALL options that are NOT specified as 'layout' ] - // default.panes options that apply to the center-pane (most options apply _only_ to border-panes) -, center: ("paneClass,contentSelector,contentIgnoreSelector,findNestedContent,applyDemoStyles,triggerEventsOnLoad," - + "showOverflowOnHover,maskContents,maskObjects,liveContentResizing," - + "childOptions,initChildLayout,resizeChildLayout,destroyChildLayout," - + "onresize,onresize_start,onresize_end,onsizecontent,onsizecontent_start,onsizecontent_end").split(",") - // options that MUST be specifically set 'per-pane' - CANNOT set in the panes (defaults) key -, noDefault: ("paneSelector,resizerCursor,customHotkey").split(",") -}; - -/** - * Processes options passed in converts flat-format data into subkey (JSON) format - * In flat-format, subkeys are _currently_ separated with 2 underscores, like north__optName - * Plugins may also call this method so they can transform their own data - * - * @param {!Object} hash Data/options passed by user - may be a single level or nested levels - * @return {Object} Returns hash of minWidth & minHeight - */ -$.layout.transformData = function (hash) { - var json = { panes: {}, center: {} } // init return object - , data, branch, optKey, keys, key, val, i, c; - - if (typeof hash !== "object") return json; // no options passed - - // convert all 'flat-keys' to 'sub-key' format - for (optKey in hash) { - branch = json; - data = $.layout.optionsMap.layout; - val = hash[ optKey ]; - keys = optKey.split("__"); // eg: west__size or north__fxSettings__duration - c = keys.length - 1; - // convert underscore-delimited to subkeys - for (i=0; i <= c; i++) { - key = keys[i]; - if (i === c) - branch[key] = val; - else if (!branch[key]) - branch[key] = {}; // create the subkey - // recurse to sub-key for next loop - if not done - branch = branch[key]; - } - } - - return json; -}; - -// INTERNAL CONFIG DATA - DO NOT CHANGE THIS! -$.layout.backwardCompatibility = { - // data used by renameOldOptions() - map: { - // OLD Option Name: NEW Option Name - applyDefaultStyles: "applyDemoStyles" - , resizeNestedLayout: "resizeChildLayout" - , resizeWhileDragging: "livePaneResizing" - , resizeContentWhileDragging: "liveContentResizing" - , triggerEventsWhileDragging: "triggerEventsDuringLiveResize" - , maskIframesOnResize: "maskContents" - , useStateCookie: "stateManagement.enabled" - , "cookie.autoLoad": "stateManagement.autoLoad" - , "cookie.autoSave": "stateManagement.autoSave" - , "cookie.keys": "stateManagement.stateKeys" - , "cookie.name": "stateManagement.cookie.name" - , "cookie.domain": "stateManagement.cookie.domain" - , "cookie.path": "stateManagement.cookie.path" - , "cookie.expires": "stateManagement.cookie.expires" - , "cookie.secure": "stateManagement.cookie.secure" - // OLD Language options - , noRoomToOpenTip: "tips.noRoomToOpen" - , togglerTip_open: "tips.Close" // open = Close - , togglerTip_closed: "tips.Open" // closed = Open - , resizerTip: "tips.Resize" - , sliderTip: "tips.Slide" - } - -/** -* @param {Object} opts -*/ -, renameOptions: function (opts) { - var map = $.layout.backwardCompatibility.map - , oldData, newData, value - ; - for (var itemPath in map) { - oldData = getBranch( itemPath ); - value = oldData.branch[ oldData.key ]; - if (value !== undefined) { - newData = getBranch( map[itemPath], true ); - newData.branch[ newData.key ] = value; - delete oldData.branch[ oldData.key ]; - } - } - - /** - * @param {string} path - * @param {boolean=} [create=false] Create path if does not exist - */ - function getBranch (path, create) { - var a = path.split(".") // split keys into array - , c = a.length - 1 - , D = { branch: opts, key: a[c] } // init branch at top & set key (last item) - , i = 0, k, undef; - for (; i 0) { - if (autoHide && $E.data('autoHidden') && $E.innerHeight() > 0) { - $E.show().data('autoHidden', false); - if (!browser.mozilla) // FireFox refreshes iframes - IE does not - // make hidden, then visible to 'refresh' display after animation - $E.css(_c.hidden).css(_c.visible); - } - } - else if (autoHide && !$E.data('autoHidden')) - $E.hide().data('autoHidden', true); - } - - /** - * @param {(string|!Object)} el - * @param {number=} outerHeight - * @param {boolean=} [autoHide=false] - */ -, setOuterHeight = function (el, outerHeight, autoHide) { - var $E = el, h; - if (isStr(el)) $E = $Ps[el]; // west - else if (!el.jquery) $E = $(el); - h = cssH($E, outerHeight); - $E.css({ height: h, visibility: "visible" }); // may have been 'hidden' by sizeContent - if (h > 0 && $E.innerWidth() > 0) { - if (autoHide && $E.data('autoHidden')) { - $E.show().data('autoHidden', false); - if (!browser.mozilla) // FireFox refreshes iframes - IE does not - $E.css(_c.hidden).css(_c.visible); - } - } - else if (autoHide && !$E.data('autoHidden')) - $E.hide().data('autoHidden', true); - } - - /** - * @param {(string|!Object)} el - * @param {number=} outerSize - * @param {boolean=} [autoHide=false] - */ -, setOuterSize = function (el, outerSize, autoHide) { - if (_c[pane].dir=="horz") // pane = north or south - setOuterHeight(el, outerSize, autoHide); - else // pane = east or west - setOuterWidth(el, outerSize, autoHide); - } - - - /** - * Converts any 'size' params to a pixel/integer size, if not already - * If 'auto' or a decimal/percentage is passed as 'size', a pixel-size is calculated - * - /** - * @param {string} pane - * @param {(string|number)=} size - * @param {string=} [dir] - * @return {number} - */ -, _parseSize = function (pane, size, dir) { - if (!dir) dir = _c[pane].dir; - - if (isStr(size) && size.match(/%/)) - size = (size === '100%') ? -1 : parseInt(size, 10) / 100; // convert % to decimal - - if (size === 0) - return 0; - else if (size >= 1) - return parseInt(size, 10); - - var o = options, avail = 0; - if (dir=="horz") // north or south or center.minHeight - avail = sC.innerHeight - ($Ps.north ? o.north.spacing_open : 0) - ($Ps.south ? o.south.spacing_open : 0); - else if (dir=="vert") // east or west or center.minWidth - avail = sC.innerWidth - ($Ps.west ? o.west.spacing_open : 0) - ($Ps.east ? o.east.spacing_open : 0); - - if (size === -1) // -1 == 100% - return avail; - else if (size > 0) // percentage, eg: .25 - return round(avail * size); - else if (pane=="center") - return 0; - else { // size < 0 || size=='auto' || size==Missing || size==Invalid - // auto-size the pane - var dim = (dir === "horz" ? "height" : "width") - , $P = $Ps[pane] - , $C = dim === 'height' ? $Cs[pane] : false - , vis = $.layout.showInvisibly($P) // show pane invisibly if hidden - , szP = $P.css(dim) // SAVE current pane size - , szC = $C ? $C.css(dim) : 0 // SAVE current content size - ; - $P.css(dim, "auto"); - if ($C) $C.css(dim, "auto"); - size = (dim === "height") ? $P.outerHeight() : $P.outerWidth(); // MEASURE - $P.css(dim, szP).css(vis); // RESET size & visibility - if ($C) $C.css(dim, szC); - return size; - } - } - - /** - * Calculates current 'size' (outer-width or outer-height) of a border-pane - optionally with 'pane-spacing' added - * - * @param {(string|!Object)} pane - * @param {boolean=} [inclSpace=false] - * @return {number} Returns EITHER Width for east/west panes OR Height for north/south panes - */ -, getPaneSize = function (pane, inclSpace) { - var - $P = $Ps[pane] - , o = options[pane] - , s = state[pane] - , oSp = (inclSpace ? o.spacing_open : 0) - , cSp = (inclSpace ? o.spacing_closed : 0) - ; - if (!$P || s.isHidden) - return 0; - else if (s.isClosed || (s.isSliding && inclSpace)) - return cSp; - else if (_c[pane].dir === "horz") - return $P.outerHeight() + oSp; - else // dir === "vert" - return $P.outerWidth() + oSp; - } - - /** - * Calculate min/max pane dimensions and limits for resizing - * - * @param {string} pane - * @param {boolean=} [slide=false] - */ -, setSizeLimits = function (pane, slide) { - if (!isInitialized()) return; - var - o = options[pane] - , s = state[pane] - , c = _c[pane] - , dir = c.dir - , side = c.side.toLowerCase() - , type = c.sizeType.toLowerCase() - , isSliding = (slide != undefined ? slide : s.isSliding) // only open() passes 'slide' param - , $P = $Ps[pane] - , paneSpacing = o.spacing_open - // measure the pane on the *opposite side* from this pane - , altPane = _c.oppositeEdge[pane] - , altS = state[altPane] - , $altP = $Ps[altPane] - , altPaneSize = (!$altP || altS.isVisible===false || altS.isSliding ? 0 : (dir=="horz" ? $altP.outerHeight() : $altP.outerWidth())) - , altPaneSpacing = ((!$altP || altS.isHidden ? 0 : options[altPane][ altS.isClosed !== false ? "spacing_closed" : "spacing_open" ]) || 0) - // limitSize prevents this pane from 'overlapping' opposite pane - , containerSize = (dir=="horz" ? sC.innerHeight : sC.innerWidth) - , minCenterDims = cssMinDims("center") - , minCenterSize = dir=="horz" ? max(options.center.minHeight, minCenterDims.minHeight) : max(options.center.minWidth, minCenterDims.minWidth) - // if pane is 'sliding', then ignore center and alt-pane sizes - because 'overlays' them - , limitSize = (containerSize - paneSpacing - (isSliding ? 0 : (_parseSize("center", minCenterSize, dir) + altPaneSize + altPaneSpacing))) - , minSize = s.minSize = max( _parseSize(pane, o.minSize), cssMinDims(pane).minSize ) - , maxSize = s.maxSize = min( (o.maxSize ? _parseSize(pane, o.maxSize) : 100000), limitSize ) - , r = s.resizerPosition = {} // used to set resizing limits - , top = sC.insetTop - , left = sC.insetLeft - , W = sC.innerWidth - , H = sC.innerHeight - , rW = o.spacing_open // subtract resizer-width to get top/left position for south/east - ; - switch (pane) { - case "north": r.min = top + minSize; - r.max = top + maxSize; - break; - case "west": r.min = left + minSize; - r.max = left + maxSize; - break; - case "south": r.min = top + H - maxSize - rW; - r.max = top + H - minSize - rW; - break; - case "east": r.min = left + W - maxSize - rW; - r.max = left + W - minSize - rW; - break; - }; - } - - /** - * Returns data for setting the size/position of center pane. Also used to set Height for east/west panes - * - * @return JSON Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height - */ -, calcNewCenterPaneDims = function () { - var d = { - top: getPaneSize("north", true) // true = include 'spacing' value for pane - , bottom: getPaneSize("south", true) - , left: getPaneSize("west", true) - , right: getPaneSize("east", true) - , width: 0 - , height: 0 - }; - - // NOTE: sC = state.container - // calc center-pane outer dimensions - d.width = sC.innerWidth - d.left - d.right; // outerWidth - d.height = sC.innerHeight - d.bottom - d.top; // outerHeight - // add the 'container border/padding' to get final positions relative to the container - d.top += sC.insetTop; - d.bottom += sC.insetBottom; - d.left += sC.insetLeft; - d.right += sC.insetRight; - - return d; - } - - - /** - * @param {!Object} el - * @param {boolean=} [allStates=false] - */ -, getHoverClasses = function (el, allStates) { - var - $El = $(el) - , type = $El.data("layoutRole") - , pane = $El.data("layoutEdge") - , o = options[pane] - , root = o[type +"Class"] - , _pane = "-"+ pane // eg: "-west" - , _open = "-open" - , _closed = "-closed" - , _slide = "-sliding" - , _hover = "-hover " // NOTE the trailing space - , _state = $El.hasClass(root+_closed) ? _closed : _open - , _alt = _state === _closed ? _open : _closed - , classes = (root+_hover) + (root+_pane+_hover) + (root+_state+_hover) + (root+_pane+_state+_hover) - ; - if (allStates) // when 'removing' classes, also remove alternate-state classes - classes += (root+_alt+_hover) + (root+_pane+_alt+_hover); - - if (type=="resizer" && $El.hasClass(root+_slide)) - classes += (root+_slide+_hover) + (root+_pane+_slide+_hover); - - return $.trim(classes); - } -, addHover = function (evt, el) { - var $E = $(el || this); - if (evt && $E.data("layoutRole") === "toggler") - evt.stopPropagation(); // prevent triggering 'slide' on Resizer-bar - $E.addClass( getHoverClasses($E) ); - } -, removeHover = function (evt, el) { - var $E = $(el || this); - $E.removeClass( getHoverClasses($E, true) ); - } - -, onResizerEnter = function (evt) { // ALSO called by toggler.mouseenter - if ($.fn.disableSelection) - $("body").disableSelection(); - } -, onResizerLeave = function (evt, el) { - var - e = el || this // el is only passed when called by the timer - , pane = $(e).data("layoutEdge") - , name = pane +"ResizerLeave" - ; - timer.clear(pane+"_openSlider"); // cancel slideOpen timer, if set - timer.clear(name); // cancel enableSelection timer - may re/set below - // this method calls itself on a timer because it needs to allow - // enough time for dragging to kick-in and set the isResizing flag - // dragging has a 100ms delay set, so this delay must be >100 - if (!el) // 1st call - mouseleave event - timer.set(name, function(){ onResizerLeave(evt, e); }, 200); - // if user is resizing, then dragStop will enableSelection(), so can skip it here - else if (!state[pane].isResizing && $.fn.enableSelection) // 2nd call - by timer - $("body").enableSelection(); - } - -/* - * ########################### - * INITIALIZATION METHODS - * ########################### - */ - - /** - * Initialize the layout - called automatically whenever an instance of layout is created - * - * @see none - triggered onInit - * @return mixed true = fully initialized | false = panes not initialized (yet) | 'cancel' = abort - */ -, _create = function () { - // initialize config/options - initOptions(); - var o = options; - - // TEMP state so isInitialized returns true during init process - state.creatingLayout = true; - - // init plugins for this layout, if there are any (eg: stateManagement) - runPluginCallbacks( Instance, $.layout.onCreate ); - - // options & state have been initialized, so now run beforeLoad callback - // onload will CANCEL layout creation if it returns false - if (false === _runCallbacks("onload_start")) - return 'cancel'; - - // initialize the container element - _initContainer(); - - // bind hotkey function - keyDown - if required - initHotkeys(); - - // bind window.onunload - $(window).bind("unload."+ sID, unload); - - // init plugins for this layout, if there are any (eg: customButtons) - runPluginCallbacks( Instance, $.layout.onLoad ); - - // if layout elements are hidden, then layout WILL NOT complete initialization! - // initLayoutElements will set initialized=true and run the onload callback IF successful - if (o.initPanes) _initLayoutElements(); - - delete state.creatingLayout; - - return state.initialized; - } - - /** - * Initialize the layout IF not already - * - * @see All methods in Instance run this test - * @return boolean true = layoutElements have been initialized | false = panes are not initialized (yet) - */ -, isInitialized = function () { - if (state.initialized || state.creatingLayout) return true; // already initialized - else return _initLayoutElements(); // try to init panes NOW - } - - /** - * Initialize the layout - called automatically whenever an instance of layout is created - * - * @see _create() & isInitialized - * @return An object pointer to the instance created - */ -, _initLayoutElements = function (retry) { - // initialize config/options - var o = options; - - // CANNOT init panes inside a hidden container! - if (!$N.is(":visible")) { - // handle Chrome bug where popup window 'has no height' - // if layout is BODY element, try again in 50ms - // SEE: http://layout.jquery-dev.net/samples/test_popup_window.html - if ( !retry && browser.webkit && $N[0].tagName === "BODY" ) - setTimeout(function(){ _initLayoutElements(true); }, 50); - return false; - } - - // a center pane is required, so make sure it exists - if (!getPane("center").length) { - return _log( o.errors.centerPaneMissing ); - } - - // TEMP state so isInitialized returns true during init process - state.creatingLayout = true; - - // update Container dims - $.extend(sC, elDims( $N )); - - // initialize all layout elements - initPanes(); // size & position panes - calls initHandles() - which calls initResizable() - - if (o.scrollToBookmarkOnLoad) { - var l = self.location; - if (l.hash) l.replace( l.hash ); // scrollTo Bookmark - } - - // check to see if this layout 'nested' inside a pane - if (Instance.hasParentLayout) - o.resizeWithWindow = false; - // bind resizeAll() for 'this layout instance' to window.resize event - else if (o.resizeWithWindow) - $(window).bind("resize."+ sID, windowResize); - - delete state.creatingLayout; - state.initialized = true; - - // init plugins for this layout, if there are any - runPluginCallbacks( Instance, $.layout.onReady ); - - // now run the onload callback, if exists - _runCallbacks("onload_end"); - - return true; // elements initialized successfully - } - - /** - * Initialize nested layouts - called when _initLayoutElements completes - * - * NOT CURRENTLY USED - * - * @see _initLayoutElements - * @return An object pointer to the instance created - */ -, _initChildLayouts = function () { - $.each(_c.allPanes, function (idx, pane) { - if (options[pane].initChildLayout) - createChildLayout( pane ); - }); - } - - /** - * Initialize nested layouts for a specific pane - can optionally pass layout-options - * - * @see _initChildLayouts - * @param {string|Object} evt_or_pane The pane being opened, ie: north, south, east, or west - * @param {Object=} [opts] Layout-options - if passed, will OVERRRIDE options[pane].childOptions - * @return An object pointer to the layout instance created - or null - */ -, createChildLayout = function (evt_or_pane, opts) { - var pane = evtPane.call(this, evt_or_pane) - , $P = $Ps[pane] - , C = children - ; - if ($P) { - var $C = $Cs[pane] - , o = opts || options[pane].childOptions - , d = "layout" - // determine which element is supposed to be the 'child container' - // if pane has a 'containerSelector' OR a 'content-div', use those instead of the pane - , $Cont = o.containerSelector ? $P.find( o.containerSelector ) : ($C || $P) - , containerFound = $Cont.length - // see if a child-layout ALREADY exists on this element - , child = containerFound ? (C[pane] = $Cont.data(d) || null) : null - ; - // if no layout exists, but childOptions are set, try to create the layout now - if (!child && containerFound && o) - child = C[pane] = $Cont.eq(0).layout(o) || null; - if (child) - child.hasParentLayout = true; // set parent-flag in child - } - Instance[pane].child = C[pane]; // ALWAYS set pane-object pointer, even if null - } - -, windowResize = function () { - var delay = Number(options.resizeWithWindowDelay); - if (delay < 10) delay = 100; // MUST have a delay! - // resizing uses a delay-loop because the resize event fires repeatly - except in FF, but delay anyway - timer.clear("winResize"); // if already running - timer.set("winResize", function(){ - timer.clear("winResize"); - timer.clear("winResizeRepeater"); - var dims = elDims( $N ); - // only trigger resizeAll() if container has changed size - if (dims.innerWidth !== sC.innerWidth || dims.innerHeight !== sC.innerHeight) - resizeAll(); - }, delay); - // ALSO set fixed-delay timer, if not already running - if (!timer.data["winResizeRepeater"]) setWindowResizeRepeater(); - } - -, setWindowResizeRepeater = function () { - var delay = Number(options.resizeWithWindowMaxDelay); - if (delay > 0) - timer.set("winResizeRepeater", function(){ setWindowResizeRepeater(); resizeAll(); }, delay); - } - -, unload = function () { - var o = options; - - _runCallbacks("onunload_start"); - - // trigger plugin callabacks for this layout (eg: stateManagement) - runPluginCallbacks( Instance, $.layout.onUnload ); - - _runCallbacks("onunload_end"); - } - - /** - * Validate and initialize container CSS and events - * - * @see _create() - */ -, _initContainer = function () { - var - N = $N[0] - , tag = sC.tagName = N.tagName - , id = sC.id = N.id - , cls = sC.className = N.className - , o = options - , name = o.name - , fullPage= (tag === "BODY") - , props = "overflow,position,margin,padding,border" - , css = "layoutCSS" - , CSS = {} - , hid = "hidden" // used A LOT! - // see if this container is a 'pane' inside an outer-layout - , parent = $N.data("parentLayout") // parent-layout Instance - , pane = $N.data("layoutEdge") // pane-name in parent-layout - , isChild = parent && pane - ; - // sC -> state.container - sC.selector = $N.selector.split(".slice")[0]; - sC.ref = (o.name ? o.name +' layout / ' : '') + tag + (id ? "#"+id : cls ? '.['+cls+']' : ''); // used in messages - - $N .data({ - layout: Instance - , layoutContainer: sID // FLAG to indicate this is a layout-container - contains unique internal ID - }) - .addClass(o.containerClass) - ; - var layoutMethods = { - destroy: '' - , initPanes: '' - , resizeAll: 'resizeAll' - , resize: 'resizeAll' - }; - // loop hash and bind all methods - include layoutID namespacing - for (name in layoutMethods) { - $N.bind("layout"+ name.toLowerCase() +"."+ sID, Instance[ layoutMethods[name] || name ]); - } - - // if this container is another layout's 'pane', then set child/parent pointers - if (isChild) { - // update parent flag - Instance.hasParentLayout = true; - // set pointers to THIS child-layout (Instance) in parent-layout - // NOTE: parent.PANE.child is an ALIAS to parent.children.PANE - parent[pane].child = parent.children[pane] = $N.data("layout"); - } - - // SAVE original container CSS for use in destroy() - if (!$N.data(css)) { - // handle props like overflow different for BODY & HTML - has 'system default' values - if (fullPage) { - CSS = $.extend( elCSS($N, props), { - height: $N.css("height") - , overflow: $N.css("overflow") - , overflowX: $N.css("overflowX") - , overflowY: $N.css("overflowY") - }); - // ALSO SAVE CSS - var $H = $("html"); - $H.data(css, { - height: "auto" // FF would return a fixed px-size! - , overflow: $H.css("overflow") - , overflowX: $H.css("overflowX") - , overflowY: $H.css("overflowY") - }); - } - else // handle props normally for non-body elements - CSS = elCSS($N, props+",top,bottom,left,right,width,height,overflow,overflowX,overflowY"); - - $N.data(css, CSS); - } - - try { // format html/body if this is a full page layout - if (fullPage) { - $("html").css({ - height: "100%" - , overflow: hid - , overflowX: hid - , overflowY: hid - }); - $("body").css({ - position: "relative" - , height: "100%" - , overflow: hid - , overflowX: hid - , overflowY: hid - , margin: 0 - , padding: 0 // TODO: test whether body-padding could be handled? - , border: "none" // a body-border creates problems because it cannot be measured! - }); - - // set current layout-container dimensions - $.extend(sC, elDims( $N )); - } - else { // set required CSS for overflow and position - // ENSURE container will not 'scroll' - CSS = { overflow: hid, overflowX: hid, overflowY: hid } - var - p = $N.css("position") - , h = $N.css("height") - ; - // if this is a NESTED layout, then container/outer-pane ALREADY has position and height - if (!isChild) { - if (!p || !p.match(/fixed|absolute|relative/)) - CSS.position = "relative"; // container MUST have a 'position' - /* - if (!h || h=="auto") - CSS.height = "100%"; // container MUST have a 'height' - */ - } - $N.css( CSS ); - - // set current layout-container dimensions - if ( $N.is(":visible") ) { - $.extend(sC, elDims( $N )); - if (sC.innerHeight < 1) - _log( o.errors.noContainerHeight.replace(/CONTAINER/, sC.ref) ); - } - } - } catch (ex) {} - } - - /** - * Bind layout hotkeys - if options enabled - * - * @see _create() and addPane() - * @param {string=} [panes=""] The edge(s) to process - */ -, initHotkeys = function (panes) { - panes = panes ? panes.split(",") : _c.borderPanes; - // bind keyDown to capture hotkeys, if option enabled for ANY pane - $.each(panes, function (i, pane) { - var o = options[pane]; - if (o.enableCursorHotkey || o.customHotkey) { - $(document).bind("keydown."+ sID, keyDown); // only need to bind this ONCE - return false; // BREAK - binding was done - } - }); - } - - /** - * Build final OPTIONS data - * - * @see _create() - */ -, initOptions = function () { - var data, d, pane, key, val, i, c, o; - - // reprocess user's layout-options to have correct options sub-key structure - opts = $.layout.transformData( opts ); // panes = default subkey - - // auto-rename old options for backward compatibility - opts = $.layout.backwardCompatibility.renameAllOptions( opts ); - - // if user-options has 'panes' key (pane-defaults), clean it... - if (!$.isEmptyObject(opts.panes)) { - // REMOVE any pane-defaults that MUST be set per-pane - data = $.layout.optionsMap.noDefault; - for (i=0, c=data.length; i 0) { - z.pane_normal = zo; - z.content_mask = max(zo+1, z.content_mask); // MIN = +1 - z.resizer_normal = max(zo+2, z.resizer_normal); // MIN = +2 - } - - // DELETE 'panes' key now that we are done - values were copied to EACH pane - delete options.panes; - - - function createFxOptions ( pane ) { - var o = options[pane] - , d = options.panes; - // ensure fxSettings key to avoid errors - if (!o.fxSettings) o.fxSettings = {}; - if (!d.fxSettings) d.fxSettings = {}; - - $.each(["_open","_close","_size"], function (i,n) { - var - sName = "fxName"+ n - , sSpeed = "fxSpeed"+ n - , sSettings = "fxSettings"+ n - // recalculate fxName according to specificity rules - , fxName = o[sName] = - o[sName] // options.west.fxName_open - || d[sName] // options.panes.fxName_open - || o.fxName // options.west.fxName - || d.fxName // options.panes.fxName - || "none" // MEANS $.layout.defaults.panes.fxName == "" || false || null || 0 - ; - // validate fxName to ensure is valid effect - MUST have effect-config data in options.effects - if (fxName === "none" || !$.effects || !$.effects[fxName] || !options.effects[fxName]) - fxName = o[sName] = "none"; // effect not loaded OR unrecognized fxName - - // set vars for effects subkeys to simplify logic - var fx = options.effects[fxName] || {} // effects.slide - , fx_all = fx.all || null // effects.slide.all - , fx_pane = fx[pane] || null // effects.slide.west - ; - // create fxSpeed[_open|_close|_size] - o[sSpeed] = - o[sSpeed] // options.west.fxSpeed_open - || d[sSpeed] // options.west.fxSpeed_open - || o.fxSpeed // options.west.fxSpeed - || d.fxSpeed // options.panes.fxSpeed - || null // DEFAULT - let fxSetting.duration control speed - ; - // create fxSettings[_open|_close|_size] - o[sSettings] = $.extend( - true - , {} - , fx_all // effects.slide.all - , fx_pane // effects.slide.west - , d.fxSettings // options.panes.fxSettings - , o.fxSettings // options.west.fxSettings - , d[sSettings] // options.panes.fxSettings_open - , o[sSettings] // options.west.fxSettings_open - ); - }); - - // DONE creating action-specific-settings for this pane, - // so DELETE generic options - are no longer meaningful - delete o.fxName; - delete o.fxSpeed; - delete o.fxSettings; - } - } - - /** - * Initialize module objects, styling, size and position for all panes - * - * @see _initElements() - * @param {string} pane The pane to process - */ -, getPane = function (pane) { - var sel = options[pane].paneSelector - if (sel.substr(0,1)==="#") // ID selector - // NOTE: elements selected 'by ID' DO NOT have to be 'children' - return $N.find(sel).eq(0); - else { // class or other selector - var $P = $N.children(sel).eq(0); - // look for the pane nested inside a 'form' element - return $P.length ? $P : $N.children("form:first").children(sel).eq(0); - } - } - -, initPanes = function (evt) { - // stopPropagation if called by trigger("layoutinitpanes") - use evtPane utility - evtPane(evt); - - // NOTE: do north & south FIRST so we can measure their height - do center LAST - $.each(_c.allPanes, function (idx, pane) { - addPane( pane, true ); - }); - - // init the pane-handles NOW in case we have to hide or close the pane below - initHandles(); - - // now that all panes have been initialized and initially-sized, - // make sure there is really enough space available for each pane - $.each(_c.borderPanes, function (i, pane) { - if ($Ps[pane] && state[pane].isVisible) { // pane is OPEN - setSizeLimits(pane); - makePaneFit(pane); // pane may be Closed, Hidden or Resized by makePaneFit() - } - }); - // size center-pane AGAIN in case we 'closed' a border-pane in loop above - sizeMidPanes("center"); - - // Chrome/Webkit sometimes fires callbacks BEFORE it completes resizing! - // Before RC30.3, there was a 10ms delay here, but that caused layout - // to load asynchrously, which is BAD, so try skipping delay for now - - // process pane contents and callbacks, and init/resize child-layout if exists - $.each(_c.allPanes, function (i, pane) { - var o = options[pane]; - if ($Ps[pane]) { - if (state[pane].isVisible) { // pane is OPEN - sizeContent(pane); - // trigger pane.onResize if triggerEventsOnLoad = true - if (o.triggerEventsOnLoad) - _runCallbacks("onresize_end", pane); - else // automatic if onresize called, otherwise call it specifically - // resize child - IF inner-layout already exists (created before this layout) - resizeChildLayout(pane); - } - // init childLayout - even if pane is not visible - if (o.initChildLayout && o.childOptions) - createChildLayout(pane); - } - }); - } - - /** - * Add a pane to the layout - subroutine of initPanes() - * - * @see initPanes() - * @param {string} pane The pane to process - * @param {boolean=} [force=false] Size content after init - */ -, addPane = function (pane, force) { - if (!force && !isInitialized()) return; - var - o = options[pane] - , s = state[pane] - , c = _c[pane] - , fx = s.fx - , dir = c.dir - , spacing = o.spacing_open || 0 - , isCenter = (pane === "center") - , CSS = {} - , $P = $Ps[pane] - , size, minSize, maxSize - ; - // if pane-pointer already exists, remove the old one first - if ($P) - removePane( pane, false, true, false ); - else - $Cs[pane] = false; // init - - $P = $Ps[pane] = getPane(pane); - if (!$P.length) { - $Ps[pane] = false; // logic - return; - } - - // SAVE original Pane CSS - if (!$P.data("layoutCSS")) { - var props = "position,top,left,bottom,right,width,height,overflow,zIndex,display,backgroundColor,padding,margin,border"; - $P.data("layoutCSS", elCSS($P, props)); - } - - // create alias for pane data in Instance - initHandles will add more - Instance[pane] = { name: pane, pane: $Ps[pane], content: $Cs[pane], options: options[pane], state: state[pane], child: children[pane] }; - - // add classes, attributes & events - $P .data({ - parentLayout: Instance // pointer to Layout Instance - , layoutPane: Instance[pane] // NEW pointer to pane-alias-object - , layoutEdge: pane - , layoutRole: "pane" - }) - .css(c.cssReq).css("zIndex", options.zIndexes.pane_normal) - .css(o.applyDemoStyles ? c.cssDemo : {}) // demo styles - .addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector' - .bind("mouseenter."+ sID, addHover ) - .bind("mouseleave."+ sID, removeHover ) - ; - var paneMethods = { - hide: '' - , show: '' - , toggle: '' - , close: '' - , open: '' - , slideOpen: '' - , slideClose: '' - , slideToggle: '' - , size: 'sizePane' - , sizePane: 'sizePane' - , sizeContent: '' - , sizeHandles: '' - , enableClosable: '' - , disableClosable: '' - , enableSlideable: '' - , disableSlideable: '' - , enableResizable: '' - , disableResizable: '' - , swapPanes: 'swapPanes' - , swap: 'swapPanes' - , move: 'swapPanes' - , removePane: 'removePane' - , remove: 'removePane' - , createChildLayout: '' - , resizeChildLayout: '' - , resizeAll: 'resizeAll' - , resizeLayout: 'resizeAll' - } - , name; - // loop hash and bind all methods - include layoutID namespacing - for (name in paneMethods) { - $P.bind("layoutpane"+ name.toLowerCase() +"."+ sID, Instance[ paneMethods[name] || name ]); - } - - // see if this pane has a 'scrolling-content element' - initContent(pane, false); // false = do NOT sizeContent() - called later - - if (!isCenter) { - // call _parseSize AFTER applying pane classes & styles - but before making visible (if hidden) - // if o.size is auto or not valid, then MEASURE the pane and use that as its 'size' - size = s.size = _parseSize(pane, o.size); - minSize = _parseSize(pane,o.minSize) || 1; - maxSize = _parseSize(pane,o.maxSize) || 100000; - if (size > 0) size = max(min(size, maxSize), minSize); - - // state for border-panes - s.isClosed = false; // true = pane is closed - s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes - s.isResizing= false; // true = pane is in process of being resized - s.isHidden = false; // true = pane is hidden - no spacing, resizer or toggler is visible! - - // array for 'pin buttons' whose classNames are auto-updated on pane-open/-close - if (!s.pins) s.pins = []; - } - // states common to ALL panes - s.tagName = $P[0].tagName; - s.edge = pane; // useful if pane is (or about to be) 'swapped' - easy find out where it is (or is going) - s.noRoom = false; // true = pane 'automatically' hidden due to insufficient room - will unhide automatically - s.isVisible = true; // false = pane is invisible - closed OR hidden - simplify logic - - // set css-position to account for container borders & padding - switch (pane) { - case "north": CSS.top = sC.insetTop; - CSS.left = sC.insetLeft; - CSS.right = sC.insetRight; - break; - case "south": CSS.bottom = sC.insetBottom; - CSS.left = sC.insetLeft; - CSS.right = sC.insetRight; - break; - case "west": CSS.left = sC.insetLeft; // top, bottom & height set by sizeMidPanes() - break; - case "east": CSS.right = sC.insetRight; // ditto - break; - case "center": // top, left, width & height set by sizeMidPanes() - } - - if (dir === "horz") // north or south pane - CSS.height = cssH($P, size); - else if (dir === "vert") // east or west pane - CSS.width = cssW($P, size); - //else if (isCenter) {} - - $P.css(CSS); // apply size -- top, bottom & height will be set by sizeMidPanes - if (dir != "horz") sizeMidPanes(pane, true); // true = skipCallback - - // close or hide the pane if specified in settings - if (o.initClosed && o.closable && !o.initHidden) - close(pane, true, true); // true, true = force, noAnimation - else if (o.initHidden || o.initClosed) - hide(pane); // will be completely invisible - no resizer or spacing - else if (!s.noRoom) - // make the pane visible - in case was initially hidden - $P.css("display","block"); - // ELSE setAsOpen() - called later by initHandles() - - // RESET visibility now - pane will appear IF display:block - $P.css("visibility","visible"); - - // check option for auto-handling of pop-ups & drop-downs - if (o.showOverflowOnHover) - $P.hover( allowOverflow, resetOverflow ); - - // if manually adding a pane AFTER layout initialization, then... - if (state.initialized) { - initHandles( pane ); - initHotkeys( pane ); - resizeAll(); // will sizeContent if pane is visible - if (s.isVisible) { // pane is OPEN - if (o.triggerEventsOnLoad) - _runCallbacks("onresize_end", pane); - else // automatic if onresize called, otherwise call it specifically - // resize child - IF inner-layout already exists (created before this layout) - resizeChildLayout(pane); // a previously existing childLayout - } - if (o.initChildLayout && o.childOptions) - createChildLayout(pane); - } - } - - /** - * Initialize module objects, styling, size and position for all resize bars and toggler buttons - * - * @see _create() - * @param {string=} [panes=""] The edge(s) to process - */ -, initHandles = function (panes) { - panes = panes ? panes.split(",") : _c.borderPanes; - - // create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV - $.each(panes, function (i, pane) { - var $P = $Ps[pane]; - $Rs[pane] = false; // INIT - $Ts[pane] = false; - if (!$P) return; // pane does not exist - skip - - var - o = options[pane] - , s = state[pane] - , c = _c[pane] - , paneId = o.paneSelector.substr(0,1) === "#" ? o.paneSelector.substr(1) : "" - , rClass = o.resizerClass - , tClass = o.togglerClass - , side = c.side.toLowerCase() - , spacing = (s.isVisible ? o.spacing_open : o.spacing_closed) - , _pane = "-"+ pane // used for classNames - , _state = (s.isVisible ? "-open" : "-closed") // used for classNames - , I = Instance[pane] - // INIT RESIZER BAR - , $R = I.resizer = $Rs[pane] = $("
                                  ") - // INIT TOGGLER BUTTON - , $T = I.toggler = (o.closable ? $Ts[pane] = $("
                                  ") : false) - ; - - //if (s.isVisible && o.resizable) ... handled by initResizable - if (!s.isVisible && o.slidable) - $R.attr("title", o.tips.Slide).css("cursor", o.sliderCursor); - - $R // if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer" - .attr("id", paneId ? paneId +"-resizer" : "" ) - .data({ - parentLayout: Instance - , layoutPane: Instance[pane] // NEW pointer to pane-alias-object - , layoutEdge: pane - , layoutRole: "resizer" - }) - .css(_c.resizers.cssReq).css("zIndex", options.zIndexes.resizer_normal) - .css(o.applyDemoStyles ? _c.resizers.cssDemo : {}) // add demo styles - .addClass(rClass +" "+ rClass+_pane) - .hover(addHover, removeHover) // ALWAYS add hover-classes, even if resizing is not enabled - handle with CSS instead - .hover(onResizerEnter, onResizerLeave) // ALWAYS NEED resizer.mouseleave to balance toggler.mouseenter - .appendTo($N) // append DIV to container - ; - - if ($T) { - $T // if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "#paneLeft-toggler" - .attr("id", paneId ? paneId +"-toggler" : "" ) - .data({ - parentLayout: Instance - , layoutPane: Instance[pane] // NEW pointer to pane-alias-object - , layoutEdge: pane - , layoutRole: "toggler" - }) - .css(_c.togglers.cssReq) // add base/required styles - .css(o.applyDemoStyles ? _c.togglers.cssDemo : {}) // add demo styles - .addClass(tClass +" "+ tClass+_pane) - .hover(addHover, removeHover) // ALWAYS add hover-classes, even if toggling is not enabled - handle with CSS instead - .bind("mouseenter", onResizerEnter) // NEED toggler.mouseenter because mouseenter MAY NOT fire on resizer - .appendTo($R) // append SPAN to resizer DIV - ; - // ADD INNER-SPANS TO TOGGLER - if (o.togglerContent_open) // ui-layout-open - $(""+ o.togglerContent_open +"") - .data({ - layoutEdge: pane - , layoutRole: "togglerContent" - }) - .data("layoutRole", "togglerContent") - .data("layoutEdge", pane) - .addClass("content content-open") - .css("display","none") - .appendTo( $T ) - //.hover( addHover, removeHover ) // use ui-layout-toggler-west-hover .content-open instead! - ; - if (o.togglerContent_closed) // ui-layout-closed - $(""+ o.togglerContent_closed +"") - .data({ - layoutEdge: pane - , layoutRole: "togglerContent" - }) - .addClass("content content-closed") - .css("display","none") - .appendTo( $T ) - //.hover( addHover, removeHover ) // use ui-layout-toggler-west-hover .content-closed instead! - ; - // ADD TOGGLER.click/.hover - enableClosable(pane); - } - - // add Draggable events - initResizable(pane); - - // ADD CLASSNAMES & SLIDE-BINDINGS - eg: class="resizer resizer-west resizer-open" - if (s.isVisible) - setAsOpen(pane); // onOpen will be called, but NOT onResize - else { - setAsClosed(pane); // onClose will be called - bindStartSlidingEvent(pane, true); // will enable events IF option is set - } - - }); - - // SET ALL HANDLE DIMENSIONS - sizeHandles(); - } - - - /** - * Initialize scrolling ui-layout-content div - if exists - * - * @see initPane() - or externally after an Ajax injection - * @param {string} [pane] The pane to process - * @param {boolean=} [resize=true] Size content after init - */ -, initContent = function (pane, resize) { - if (!isInitialized()) return; - var - o = options[pane] - , sel = o.contentSelector - , I = Instance[pane] - , $P = $Ps[pane] - , $C - ; - if (sel) $C = I.content = $Cs[pane] = (o.findNestedContent) - ? $P.find(sel).eq(0) // match 1-element only - : $P.children(sel).eq(0) - ; - if ($C && $C.length) { - $C.data("layoutRole", "content"); - // SAVE original Pane CSS - if (!$C.data("layoutCSS")) - $C.data("layoutCSS", elCSS($C, "height")); - $C.css( _c.content.cssReq ); - if (o.applyDemoStyles) { - $C.css( _c.content.cssDemo ); // add padding & overflow: auto to content-div - $P.css( _c.content.cssDemoPane ); // REMOVE padding/scrolling from pane - } - state[pane].content = {}; // init content state - if (resize !== false) sizeContent(pane); - // sizeContent() is called AFTER init of all elements - } - else - I.content = $Cs[pane] = false; - } - - - /** - * Add resize-bars to all panes that specify it in options - * -dependancy: $.fn.resizable - will skip if not found - * - * @see _create() - * @param {string=} [panes=""] The edge(s) to process - */ -, initResizable = function (panes) { - var draggingAvailable = $.layout.plugins.draggable - , side // set in start() - ; - panes = panes ? panes.split(",") : _c.borderPanes; - - $.each(panes, function (idx, pane) { - var o = options[pane]; - if (!draggingAvailable || !$Ps[pane] || !o.resizable) { - o.resizable = false; - return true; // skip to next - } - - var s = state[pane] - , z = options.zIndexes - , c = _c[pane] - , side = c.dir=="horz" ? "top" : "left" - , opEdge = _c.oppositeEdge[pane] - , masks = pane +",center,"+ opEdge + (c.dir=="horz" ? ",west,east" : "") - , $P = $Ps[pane] - , $R = $Rs[pane] - , base = o.resizerClass - , lastPos = 0 // used when live-resizing - , r, live // set in start because may change - // 'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process - , resizerClass = base+"-drag" // resizer-drag - , resizerPaneClass = base+"-"+pane+"-drag" // resizer-north-drag - // 'helper' class is applied to the CLONED resizer-bar while it is being dragged - , helperClass = base+"-dragging" // resizer-dragging - , helperPaneClass = base+"-"+pane+"-dragging" // resizer-north-dragging - , helperLimitClass = base+"-dragging-limit" // resizer-drag - , helperPaneLimitClass = base+"-"+pane+"-dragging-limit" // resizer-north-drag - , helperClassesSet = false // logic var - ; - - if (!s.isClosed) - $R.attr("title", o.tips.Resize) - .css("cursor", o.resizerCursor); // n-resize, s-resize, etc - - $R.draggable({ - containment: $N[0] // limit resizing to layout container - , axis: (c.dir=="horz" ? "y" : "x") // limit resizing to horz or vert axis - , delay: 0 - , distance: 1 - , grid: o.resizingGrid - // basic format for helper - style it using class: .ui-draggable-dragging - , helper: "clone" - , opacity: o.resizerDragOpacity - , addClasses: false // avoid ui-state-disabled class when disabled - //, iframeFix: o.draggableIframeFix // TODO: consider using when bug is fixed - , zIndex: z.resizer_drag - - , start: function (e, ui) { - // REFRESH options & state pointers in case we used swapPanes - o = options[pane]; - s = state[pane]; - // re-read options - live = o.livePaneResizing; - - // ondrag_start callback - will CANCEL hide if returns false - // TODO: dragging CANNOT be cancelled like this, so see if there is a way? - if (false === _runCallbacks("ondrag_start", pane)) return false; - - s.isResizing = true; // prevent pane from closing while resizing - timer.clear(pane+"_closeSlider"); // just in case already triggered - - // SET RESIZER LIMITS - used in drag() - setSizeLimits(pane); // update pane/resizer state - r = s.resizerPosition; - lastPos = ui.position[ side ] - - $R.addClass( resizerClass +" "+ resizerPaneClass ); // add drag classes - helperClassesSet = false; // reset logic var - see drag() - - // DISABLE TEXT SELECTION (probably already done by resizer.mouseOver) - $('body').disableSelection(); - - // MASK PANES CONTAINING IFRAMES, APPLETS OR OTHER TROUBLESOME ELEMENTS - showMasks( masks ); - } - - , drag: function (e, ui) { - if (!helperClassesSet) { // can only add classes after clone has been added to the DOM - //$(".ui-draggable-dragging") - ui.helper - .addClass( helperClass +" "+ helperPaneClass ) // add helper classes - .css({ right: "auto", bottom: "auto" }) // fix dir="rtl" issue - .children().css("visibility","hidden") // hide toggler inside dragged resizer-bar - ; - helperClassesSet = true; - // draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane! - if (s.isSliding) $Ps[pane].css("zIndex", z.pane_sliding); - } - // CONTAIN RESIZER-BAR TO RESIZING LIMITS - var limit = 0; - if (ui.position[side] < r.min) { - ui.position[side] = r.min; - limit = -1; - } - else if (ui.position[side] > r.max) { - ui.position[side] = r.max; - limit = 1; - } - // ADD/REMOVE dragging-limit CLASS - if (limit) { - ui.helper.addClass( helperLimitClass +" "+ helperPaneLimitClass ); // at dragging-limit - window.defaultStatus = (limit>0 && pane.match(/(north|west)/)) || (limit<0 && pane.match(/(south|east)/)) ? o.tips.maxSizeWarning : o.tips.minSizeWarning; - } - else { - ui.helper.removeClass( helperLimitClass +" "+ helperPaneLimitClass ); // not at dragging-limit - window.defaultStatus = ""; - } - // DYNAMICALLY RESIZE PANES IF OPTION ENABLED - // won't trigger unless resizer has actually moved! - if (live && Math.abs(ui.position[side] - lastPos) >= o.liveResizingTolerance) { - lastPos = ui.position[side]; - resizePanes(e, ui, pane) - } - } - - , stop: function (e, ui) { - $('body').enableSelection(); // RE-ENABLE TEXT SELECTION - window.defaultStatus = ""; // clear 'resizing limit' message from statusbar - $R.removeClass( resizerClass +" "+ resizerPaneClass ); // remove drag classes from Resizer - s.isResizing = false; - resizePanes(e, ui, pane, true, masks); // true = resizingDone - } - - }); - }); - - /** - * resizePanes - * - * Sub-routine called from stop() - and drag() if livePaneResizing - * - * @param {!Object} evt - * @param {!Object} ui - * @param {string} pane - * @param {boolean=} [resizingDone=false] - */ - var resizePanes = function (evt, ui, pane, resizingDone, masks) { - var dragPos = ui.position - , c = _c[pane] - , o = options[pane] - , s = state[pane] - , resizerPos - ; - switch (pane) { - case "north": resizerPos = dragPos.top; break; - case "west": resizerPos = dragPos.left; break; - case "south": resizerPos = sC.offsetHeight - dragPos.top - o.spacing_open; break; - case "east": resizerPos = sC.offsetWidth - dragPos.left - o.spacing_open; break; - }; - // remove container margin from resizer position to get the pane size - var newSize = resizerPos - sC["inset"+ c.side]; - - // Disable OR Resize Mask(s) created in drag.start - if (!resizingDone) { - // ensure we meet liveResizingTolerance criteria - if (Math.abs(newSize - s.size) < o.liveResizingTolerance) - return; // SKIP resize this time - // resize the pane - manualSizePane(pane, newSize, false, true); // true = noAnimation - sizeMasks(); // resize all visible masks - } - else { // resizingDone - // ondrag_end callback - if (false !== _runCallbacks("ondrag_end", pane)) - manualSizePane(pane, newSize, false, true); // true = noAnimation - hideMasks(); // hide all masks, which include panes with 'content/iframe-masks' - if (s.isSliding && masks) // RE-SHOW only 'object-masks' so objects won't show through sliding pane - showMasks( masks, true ); // true = onlyForObjects - } - }; - } - - /** - * sizeMask - * - * Needed to overlay a DIV over an IFRAME-pane because mask CANNOT be *inside* the pane - * Called when mask created, and during livePaneResizing - */ -, sizeMask = function () { - var $M = $(this) - , pane = $M.data("layoutMask") // eg: "west" - , s = state[pane] - ; - // only masks over an IFRAME-pane need manual resizing - if (s.tagName == "IFRAME" && s.isVisible) // no need to mask closed/hidden panes - $M.css({ - top: s.offsetTop - , left: s.offsetLeft - , width: s.outerWidth - , height: s.outerHeight - }); - /* ALT Method... - var $P = $Ps[pane]; - $M.css( $P.position() ).css({ width: $P[0].offsetWidth, height: $P[0].offsetHeight }); - */ - } -, sizeMasks = function () { - $Ms.each( sizeMask ); // resize all 'visible' masks - } - -, showMasks = function (panes, onlyForObjects) { - var a = panes ? panes.split(",") : $.layout.config.allPanes - , z = options.zIndexes - , o, s; - $.each(a, function(i,p){ - s = state[p]; - o = options[p]; - if (s.isVisible && ( (!onlyForObjects && o.maskContents) || o.maskObjects )) { - getMasks(p).each(function(){ - sizeMask.call(this); - this.style.zIndex = s.isSliding ? z.pane_sliding+1 : z.pane_normal+1 - this.style.display = "block"; - }); - } - }); - } - -, hideMasks = function () { - // ensure no pane is resizing - could be a timing issue - var skip; - $.each( $.layout.config.borderPanes, function(i,p){ - if (state[p].isResizing) { - skip = true; - return false; // BREAK - } - }); - if (!skip) - $Ms.hide(); // hide ALL masks - } - -, getMasks = function (pane) { - var $Masks = $([]) - , $M, i = 0, c = $Ms.length - ; - for (; i CSS - if (sC.tagName === "BODY" && ($N = $("html")).data(css)) // RESET CSS - $N.css( $N.data(css) ).removeData(css); - - // trigger plugins for this layout, if there are any - runPluginCallbacks( Instance, $.layout.onDestroy ); - - // trigger state-management and onunload callback - unload(); - - // clear the Instance of everything except for container & options (so could recreate) - // RE-CREATE: myLayout = myLayout.container.layout( myLayout.options ); - for (n in Instance) - if (!n.match(/^(container|options)$/)) delete Instance[ n ]; - // add a 'destroyed' flag to make it easy to check - Instance.destroyed = true; - - // if this is a child layout, CLEAR the child-pointer in the parent - /* for now the pointer REMAINS, but with only container, options and destroyed keys - if (parentPane) { - var layout = parentPane.pane.data("parentLayout"); - parentPane.child = layout.children[ parentPane.name ] = null; - } - */ - - return Instance; // for coding convenience - } - - /** - * Remove a pane from the layout - subroutine of destroy() - * - * @see destroy() - * @param {string|Object} evt_or_pane The pane to process - * @param {boolean=} [remove=false] Remove the DOM element? - * @param {boolean=} [skipResize=false] Skip calling resizeAll()? - * @param {boolean=} [destroyChild=true] Destroy Child-layouts? If not passed, obeys options setting - */ -, removePane = function (evt_or_pane, remove, skipResize, destroyChild) { - if (!isInitialized()) return; - var pane = evtPane.call(this, evt_or_pane) - , $P = $Ps[pane] - , $C = $Cs[pane] - , $R = $Rs[pane] - , $T = $Ts[pane] - ; - // NOTE: elements can still exist even after remove() - // so check for missing data(), which is cleared by removed() - if ($P && $.isEmptyObject( $P.data() )) $P = false; - if ($C && $.isEmptyObject( $C.data() )) $C = false; - if ($R && $.isEmptyObject( $R.data() )) $R = false; - if ($T && $.isEmptyObject( $T.data() )) $T = false; - - if ($P) $P.stop(true, true); - - // check for a child layout - var o = options[pane] - , s = state[pane] - , d = "layout" - , css = "layoutCSS" - , child = children[pane] || ($P ? $P.data(d) : 0) || ($C ? $C.data(d) : 0) || null - , destroy = destroyChild !== undefined ? destroyChild : o.destroyChildLayout - ; - - // FIRST destroy the child-layout(s) - if (destroy && child && !child.destroyed) { - child.destroy(true); // tell child-layout to destroy ALL its child-layouts too - if (child.destroyed) // destroy was successful - child = null; // clear pointer for logic below - } - - if ($P && remove && !child) - $P.remove(); - else if ($P && $P[0]) { - // create list of ALL pane-classes that need to be removed - var root = o.paneClass // default="ui-layout-pane" - , pRoot = root +"-"+ pane // eg: "ui-layout-pane-west" - , _open = "-open" - , _sliding= "-sliding" - , _closed = "-closed" - , classes = [ root, root+_open, root+_closed, root+_sliding, // generic classes - pRoot, pRoot+_open, pRoot+_closed, pRoot+_sliding ] // pane-specific classes - ; - $.merge(classes, getHoverClasses($P, true)); // ADD hover-classes - // remove all Layout classes from pane-element - $P .removeClass( classes.join(" ") ) // remove ALL pane-classes - .removeData("parentLayout") - .removeData("layoutPane") - .removeData("layoutRole") - .removeData("layoutEdge") - .removeData("autoHidden") // in case set - .unbind("."+ sID) // remove ALL Layout events - // TODO: remove these extra unbind commands when jQuery is fixed - //.unbind("mouseenter"+ sID) - //.unbind("mouseleave"+ sID) - ; - // do NOT reset CSS if this pane/content is STILL the container of a nested layout! - // the nested layout will reset its 'container' CSS when/if it is destroyed - if ($C && $C.data(d)) { - // a content-div may not have a specific width, so give it one to contain the Layout - $C.width( $C.width() ); - child.resizeAll(); // now resize the Layout - } - else if ($C) - $C.css( $C.data(css) ).removeData(css).removeData("layoutRole"); - // remove pane AFTER content in case there was a nested layout - if (!$P.data(d)) - $P.css( $P.data(css) ).removeData(css); - } - - // REMOVE pane resizer and toggler elements - if ($T) $T.remove(); - if ($R) $R.remove(); - - // CLEAR all pointers and state data - Instance[pane] = $Ps[pane] = $Cs[pane] = $Rs[pane] = $Ts[pane] = children[pane] = false; - s = { removed: true }; - - if (!skipResize) - resizeAll(); - } - - -/* - * ########################### - * ACTION METHODS - * ########################### - */ - -, _hidePane = function (pane) { - var $P = $Ps[pane] - , o = options[pane] - , s = $P[0].style - ; - if (o.useOffscreenClose) { - if (!$P.data(_c.offscreenReset)) - $P.data(_c.offscreenReset, { left: s.left, right: s.right }); - $P.css( _c.offscreenCSS ); - } - else - $P.hide().removeData(_c.offscreenReset); - } - -, _showPane = function (pane) { - var $P = $Ps[pane] - , o = options[pane] - , off = _c.offscreenCSS - , old = $P.data(_c.offscreenReset) - , s = $P[0].style - ; - $P .show() // ALWAYS show, just in case - .removeData(_c.offscreenReset); - if (o.useOffscreenClose && old) { - if (s.left == off.left) - s.left = old.left; - if (s.right == off.right) - s.right = old.right; - } - } - - - /** - * Completely 'hides' a pane, including its spacing - as if it does not exist - * The pane is not actually 'removed' from the source, so can use 'show' to un-hide it - * - * @param {string|Object} evt_or_pane The pane being hidden, ie: north, south, east, or west - * @param {boolean=} [noAnimation=false] - */ -, hide = function (evt_or_pane, noAnimation) { - if (!isInitialized()) return; - var pane = evtPane.call(this, evt_or_pane) - , o = options[pane] - , s = state[pane] - , $P = $Ps[pane] - , $R = $Rs[pane] - ; - if (!$P || s.isHidden) return; // pane does not exist OR is already hidden - - // onhide_start callback - will CANCEL hide if returns false - if (state.initialized && false === _runCallbacks("onhide_start", pane)) return; - - s.isSliding = false; // just in case - - // now hide the elements - if ($R) $R.hide(); // hide resizer-bar - if (!state.initialized || s.isClosed) { - s.isClosed = true; // to trigger open-animation on show() - s.isHidden = true; - s.isVisible = false; - if (!state.initialized) - _hidePane(pane); // no animation when loading page - sizeMidPanes(_c[pane].dir === "horz" ? "" : "center"); - if (state.initialized || o.triggerEventsOnLoad) - _runCallbacks("onhide_end", pane); - } - else { - s.isHiding = true; // used by onclose - close(pane, false, noAnimation); // adjust all panes to fit - } - } - - /** - * Show a hidden pane - show as 'closed' by default unless openPane = true - * - * @param {string|Object} evt_or_pane The pane being opened, ie: north, south, east, or west - * @param {boolean=} [openPane=false] - * @param {boolean=} [noAnimation=false] - * @param {boolean=} [noAlert=false] - */ -, show = function (evt_or_pane, openPane, noAnimation, noAlert) { - if (!isInitialized()) return; - var pane = evtPane.call(this, evt_or_pane) - , o = options[pane] - , s = state[pane] - , $P = $Ps[pane] - , $R = $Rs[pane] - ; - if (!$P || !s.isHidden) return; // pane does not exist OR is not hidden - - // onshow_start callback - will CANCEL show if returns false - if (false === _runCallbacks("onshow_start", pane)) return; - - s.isSliding = false; // just in case - s.isShowing = true; // used by onopen/onclose - //s.isHidden = false; - will be set by open/close - if not cancelled - - // now show the elements - //if ($R) $R.show(); - will be shown by open/close - if (openPane === false) - close(pane, true); // true = force - else - open(pane, false, noAnimation, noAlert); // adjust all panes to fit - } - - - /** - * Toggles a pane open/closed by calling either open or close - * - * @param {string|Object} evt_or_pane The pane being toggled, ie: north, south, east, or west - * @param {boolean=} [slide=false] - */ -, toggle = function (evt_or_pane, slide) { - if (!isInitialized()) return; - var evt = evtObj(evt_or_pane) - , pane = evtPane.call(this, evt_or_pane) - , s = state[pane] - ; - if (evt) // called from to $R.dblclick OR triggerPaneEvent - evt.stopImmediatePropagation(); - if (s.isHidden) - show(pane); // will call 'open' after unhiding it - else if (s.isClosed) - open(pane, !!slide); - else - close(pane); - } - - - /** - * Utility method used during init or other auto-processes - * - * @param {string} pane The pane being closed - * @param {boolean=} [setHandles=false] - */ -, _closePane = function (pane, setHandles) { - var - $P = $Ps[pane] - , s = state[pane] - ; - _hidePane(pane); - s.isClosed = true; - s.isVisible = false; - // UNUSED: if (setHandles) setAsClosed(pane, true); // true = force - } - - /** - * Close the specified pane (animation optional), and resize all other panes as needed - * - * @param {string|Object} evt_or_pane The pane being closed, ie: north, south, east, or west - * @param {boolean=} [force=false] - * @param {boolean=} [noAnimation=false] - * @param {boolean=} [skipCallback=false] - */ -, close = function (evt_or_pane, force, noAnimation, skipCallback) { - var pane = evtPane.call(this, evt_or_pane); - // if pane has been initialized, but NOT the complete layout, close pane instantly - if (!state.initialized && $Ps[pane]) { - _closePane(pane); // INIT pane as closed - return; - } - if (!isInitialized()) return; - - var - $P = $Ps[pane] - , $R = $Rs[pane] - , $T = $Ts[pane] - , o = options[pane] - , s = state[pane] - , c = _c[pane] - , doFX, isShowing, isHiding, wasSliding; - - // QUEUE in case another action/animation is in progress - $N.queue(function( queueNext ){ - - if ( !$P - || (!o.closable && !s.isShowing && !s.isHiding) // invalid request // (!o.resizable && !o.closable) ??? - || (!force && s.isClosed && !s.isShowing) // already closed - ) return queueNext(); - - // onclose_start callback - will CANCEL hide if returns false - // SKIP if just 'showing' a hidden pane as 'closed' - var abort = !s.isShowing && false === _runCallbacks("onclose_start", pane); - - // transfer logic vars to temp vars - isShowing = s.isShowing; - isHiding = s.isHiding; - wasSliding = s.isSliding; - // now clear the logic vars (REQUIRED before aborting) - delete s.isShowing; - delete s.isHiding; - - if (abort) return queueNext(); - - doFX = !noAnimation && !s.isClosed && (o.fxName_close != "none"); - s.isMoving = true; - s.isClosed = true; - s.isVisible = false; - // update isHidden BEFORE sizing panes - if (isHiding) s.isHidden = true; - else if (isShowing) s.isHidden = false; - - if (s.isSliding) // pane is being closed, so UNBIND trigger events - bindStopSlidingEvents(pane, false); // will set isSliding=false - else // resize panes adjacent to this one - sizeMidPanes(_c[pane].dir === "horz" ? "" : "center", false); // false = NOT skipCallback - - // if this pane has a resizer bar, move it NOW - before animation - setAsClosed(pane); - - // CLOSE THE PANE - if (doFX) { // animate the close - // mask panes with objects - var masks = "center"+ (c.dir=="horz" ? ",west,east" : ""); - showMasks( masks, true ); // true = ONLY mask panes with maskObjects=true - lockPaneForFX(pane, true); // need to set left/top so animation will work - $P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () { - lockPaneForFX(pane, false); // undo - if (s.isClosed) close_2(); - queueNext(); - }); - } - else { // hide the pane without animation - _hidePane(pane); - close_2(); - queueNext(); - }; - }); - - // SUBROUTINE - function close_2 () { - s.isMoving = false; - bindStartSlidingEvent(pane, true); // will enable if o.slidable = true - - // if opposite-pane was autoClosed, see if it can be autoOpened now - var altPane = _c.oppositeEdge[pane]; - if (state[ altPane ].noRoom) { - setSizeLimits( altPane ); - makePaneFit( altPane ); - } - - // hide any masks shown while closing - hideMasks(); - - if (!skipCallback && (state.initialized || o.triggerEventsOnLoad)) { - // onclose callback - UNLESS just 'showing' a hidden pane as 'closed' - if (!isShowing) _runCallbacks("onclose_end", pane); - // onhide OR onshow callback - if (isShowing) _runCallbacks("onshow_end", pane); - if (isHiding) _runCallbacks("onhide_end", pane); - } - } - } - - /** - * @param {string} pane The pane just closed, ie: north, south, east, or west - */ -, setAsClosed = function (pane) { - var - $P = $Ps[pane] - , $R = $Rs[pane] - , $T = $Ts[pane] - , o = options[pane] - , s = state[pane] - , side = _c[pane].side.toLowerCase() - , inset = "inset"+ _c[pane].side - , rClass = o.resizerClass - , tClass = o.togglerClass - , _pane = "-"+ pane // used for classNames - , _open = "-open" - , _sliding= "-sliding" - , _closed = "-closed" - ; - $R - .css(side, sC[inset]) // move the resizer - .removeClass( rClass+_open +" "+ rClass+_pane+_open ) - .removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding ) - .addClass( rClass+_closed +" "+ rClass+_pane+_closed ) - .unbind("dblclick."+ sID) - ; - // DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvent? - if (o.resizable && $.layout.plugins.draggable) - $R - .draggable("disable") - .removeClass("ui-state-disabled") // do NOT apply disabled styling - not suitable here - .css("cursor", "default") - .attr("title","") - ; - - // if pane has a toggler button, adjust that too - if ($T) { - $T - .removeClass( tClass+_open +" "+ tClass+_pane+_open ) - .addClass( tClass+_closed +" "+ tClass+_pane+_closed ) - .attr("title", o.tips.Open) // may be blank - ; - // toggler-content - if exists - $T.children(".content-open").hide(); - $T.children(".content-closed").css("display","block"); - } - - // sync any 'pin buttons' - syncPinBtns(pane, false); - - if (state.initialized) { - // resize 'length' and position togglers for adjacent panes - sizeHandles(); - } - } - - /** - * Open the specified pane (animation optional), and resize all other panes as needed - * - * @param {string|Object} evt_or_pane The pane being opened, ie: north, south, east, or west - * @param {boolean=} [slide=false] - * @param {boolean=} [noAnimation=false] - * @param {boolean=} [noAlert=false] - */ -, open = function (evt_or_pane, slide, noAnimation, noAlert) { - if (!isInitialized()) return; - var pane = evtPane.call(this, evt_or_pane) - , $P = $Ps[pane] - , $R = $Rs[pane] - , $T = $Ts[pane] - , o = options[pane] - , s = state[pane] - , c = _c[pane] - , doFX, isShowing - ; - // QUEUE in case another action/animation is in progress - $N.queue(function( queueNext ){ - - if ( !$P - || (!o.resizable && !o.closable && !s.isShowing) // invalid request - || (s.isVisible && !s.isSliding) // already open - ) return queueNext(); - - // pane can ALSO be unhidden by just calling show(), so handle this scenario - if (s.isHidden && !s.isShowing) { - queueNext(); // call before show() because it needs the queue free - show(pane, true); - return; - } - - if (o.autoResize && s.size != o.size) // resize pane to original size set in options - sizePane(pane, o.size, true, true, true); // true=skipCallback/forceResize/noAnimation - else - // make sure there is enough space available to open the pane - setSizeLimits(pane, slide); - - // onopen_start callback - will CANCEL open if returns false - var cbReturn = _runCallbacks("onopen_start", pane); - - if (cbReturn === "abort") - return queueNext(); - - // update pane-state again in case options were changed in onopen_start - if (cbReturn !== "NC") // NC = "No Callback" - setSizeLimits(pane, slide); - - if (s.minSize > s.maxSize) { // INSUFFICIENT ROOM FOR PANE TO OPEN! - syncPinBtns(pane, false); // make sure pin-buttons are reset - if (!noAlert && o.tips.noRoomToOpen) - alert(o.tips.noRoomToOpen); - return queueNext(); // ABORT - } - - if (slide) // START Sliding - will set isSliding=true - bindStopSlidingEvents(pane, true); // BIND trigger events to close sliding-pane - else if (s.isSliding) // PIN PANE (stop sliding) - open pane 'normally' instead - bindStopSlidingEvents(pane, false); // UNBIND trigger events - will set isSliding=false - else if (o.slidable) - bindStartSlidingEvent(pane, false); // UNBIND trigger events - - s.noRoom = false; // will be reset by makePaneFit if 'noRoom' - makePaneFit(pane); - - // transfer logic var to temp var - isShowing = s.isShowing; - // now clear the logic var - delete s.isShowing; - - doFX = !noAnimation && s.isClosed && (o.fxName_open != "none"); - s.isMoving = true; - s.isVisible = true; - s.isClosed = false; - // update isHidden BEFORE sizing panes - WHY??? Old? - if (isShowing) s.isHidden = false; - - if (doFX) { // ANIMATE - // mask panes with objects - var masks = "center"+ (c.dir=="horz" ? ",west,east" : ""); - if (s.isSliding) masks += ","+ _c.oppositeEdge[pane]; - showMasks( masks, true ); // true = ONLY mask panes with maskObjects=true - lockPaneForFX(pane, true); // need to set left/top so animation will work - $P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() { - lockPaneForFX(pane, false); // undo - if (s.isVisible) open_2(); // continue - queueNext(); - }); - } - else { // no animation - _showPane(pane);// just show pane and... - open_2(); // continue - queueNext(); - }; - }); - - // SUBROUTINE - function open_2 () { - s.isMoving = false; - - // cure iframe display issues - _fixIframe(pane); - - // NOTE: if isSliding, then other panes are NOT 'resized' - if (!s.isSliding) { // resize all panes adjacent to this one - hideMasks(); // remove any masks shown while opening - sizeMidPanes(_c[pane].dir=="vert" ? "center" : "", false); // false = NOT skipCallback - } - - // set classes, position handles and execute callbacks... - setAsOpen(pane); - }; - - } - - /** - * @param {string} pane The pane just opened, ie: north, south, east, or west - * @param {boolean=} [skipCallback=false] - */ -, setAsOpen = function (pane, skipCallback) { - var - $P = $Ps[pane] - , $R = $Rs[pane] - , $T = $Ts[pane] - , o = options[pane] - , s = state[pane] - , side = _c[pane].side.toLowerCase() - , inset = "inset"+ _c[pane].side - , rClass = o.resizerClass - , tClass = o.togglerClass - , _pane = "-"+ pane // used for classNames - , _open = "-open" - , _closed = "-closed" - , _sliding= "-sliding" - ; - $R - .css(side, sC[inset] + getPaneSize(pane)) // move the resizer - .removeClass( rClass+_closed +" "+ rClass+_pane+_closed ) - .addClass( rClass+_open +" "+ rClass+_pane+_open ) - ; - if (s.isSliding) - $R.addClass( rClass+_sliding +" "+ rClass+_pane+_sliding ) - else // in case 'was sliding' - $R.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding ) - - if (o.resizerDblClickToggle) - $R.bind("dblclick", toggle ); - removeHover( 0, $R ); // remove hover classes - if (o.resizable && $.layout.plugins.draggable) - $R .draggable("enable") - .css("cursor", o.resizerCursor) - .attr("title", o.tips.Resize); - else if (!s.isSliding) - $R.css("cursor", "default"); // n-resize, s-resize, etc - - // if pane also has a toggler button, adjust that too - if ($T) { - $T .removeClass( tClass+_closed +" "+ tClass+_pane+_closed ) - .addClass( tClass+_open +" "+ tClass+_pane+_open ) - .attr("title", o.tips.Close); // may be blank - removeHover( 0, $T ); // remove hover classes - // toggler-content - if exists - $T.children(".content-closed").hide(); - $T.children(".content-open").css("display","block"); - } - - // sync any 'pin buttons' - syncPinBtns(pane, !s.isSliding); - - // update pane-state dimensions - BEFORE resizing content - $.extend(s, elDims($P)); - - if (state.initialized) { - // resize resizer & toggler sizes for all panes - sizeHandles(); - // resize content every time pane opens - to be sure - sizeContent(pane, true); // true = remeasure headers/footers, even if 'pane.isMoving' - } - - if (!skipCallback && (state.initialized || o.triggerEventsOnLoad) && $P.is(":visible")) { - // onopen callback - _runCallbacks("onopen_end", pane); - // onshow callback - TODO: should this be here? - if (s.isShowing) _runCallbacks("onshow_end", pane); - - // ALSO call onresize because layout-size *may* have changed while pane was closed - if (state.initialized) - _runCallbacks("onresize_end", pane); - } - - // TODO: Somehow sizePane("north") is being called after this point??? - } - - - /** - * slideOpen / slideClose / slideToggle - * - * Pass-though methods for sliding - */ -, slideOpen = function (evt_or_pane) { - if (!isInitialized()) return; - var evt = evtObj(evt_or_pane) - , pane = evtPane.call(this, evt_or_pane) - , s = state[pane] - , delay = options[pane].slideDelay_open - ; - // prevent event from triggering on NEW resizer binding created below - if (evt) evt.stopImmediatePropagation(); - - if (s.isClosed && evt && evt.type === "mouseenter" && delay > 0) - // trigger = mouseenter - use a delay - timer.set(pane+"_openSlider", open_NOW, delay); - else - open_NOW(); // will unbind events if is already open - - /** - * SUBROUTINE for timed open - */ - function open_NOW () { - if (!s.isClosed) // skip if no longer closed! - bindStopSlidingEvents(pane, true); // BIND trigger events to close sliding-pane - else if (!s.isMoving) - open(pane, true); // true = slide - open() will handle binding - }; - } - -, slideClose = function (evt_or_pane) { - if (!isInitialized()) return; - var evt = evtObj(evt_or_pane) - , pane = evtPane.call(this, evt_or_pane) - , o = options[pane] - , s = state[pane] - , delay = s.isMoving ? 1000 : 300 // MINIMUM delay - option may override - ; - if (s.isClosed || s.isResizing) - return; // skip if already closed OR in process of resizing - else if (o.slideTrigger_close === "click") - close_NOW(); // close immediately onClick - else if (o.preventQuickSlideClose && s.isMoving) - return; // handle Chrome quick-close on slide-open - else if (o.preventPrematureSlideClose && evt && $.layout.isMouseOverElem(evt, $Ps[pane])) - return; // handle incorrect mouseleave trigger, like when over a SELECT-list in IE - else if (evt) // trigger = mouseleave - use a delay - // 1 sec delay if 'opening', else .3 sec - timer.set(pane+"_closeSlider", close_NOW, max(o.slideDelay_close, delay)); - else // called programically - close_NOW(); - - /** - * SUBROUTINE for timed close - */ - function close_NOW () { - if (s.isClosed) // skip 'close' if already closed! - bindStopSlidingEvents(pane, false); // UNBIND trigger events - TODO: is this needed here? - else if (!s.isMoving) - close(pane); // close will handle unbinding - }; - } - - /** - * @param {string|Object} evt_or_pane The pane being opened, ie: north, south, east, or west - */ -, slideToggle = function (evt_or_pane) { - var pane = evtPane.call(this, evt_or_pane); - toggle(pane, true); - } - - - /** - * Must set left/top on East/South panes so animation will work properly - * - * @param {string} pane The pane to lock, 'east' or 'south' - any other is ignored! - * @param {boolean} doLock true = set left/top, false = remove - */ -, lockPaneForFX = function (pane, doLock) { - var $P = $Ps[pane] - , s = state[pane] - , o = options[pane] - , z = options.zIndexes - ; - if (doLock) { - $P.css({ zIndex: z.pane_animate }); // overlay all elements during animation - if (pane=="south") - $P.css({ top: sC.insetTop + sC.innerHeight - $P.outerHeight() }); - else if (pane=="east") - $P.css({ left: sC.insetLeft + sC.innerWidth - $P.outerWidth() }); - } - else { // animation DONE - RESET CSS - // TODO: see if this can be deleted. It causes a quick-close when sliding in Chrome - $P.css({ zIndex: (s.isSliding ? z.pane_sliding : z.pane_normal) }); - if (pane=="south") - $P.css({ top: "auto" }); - // if pane is positioned 'off-screen', then DO NOT screw with it! - else if (pane=="east" && !$P.css("left").match(/\-99999/)) - $P.css({ left: "auto" }); - // fix anti-aliasing in IE - only needed for animations that change opacity - if (browser.msie && o.fxOpacityFix && o.fxName_open != "slide" && $P.css("filter") && $P.css("opacity") == 1) - $P[0].style.removeAttribute('filter'); - } - } - - - /** - * Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger - * - * @see open(), close() - * @param {string} pane The pane to enable/disable, 'north', 'south', etc. - * @param {boolean} enable Enable or Disable sliding? - */ -, bindStartSlidingEvent = function (pane, enable) { - var o = options[pane] - , $P = $Ps[pane] - , $R = $Rs[pane] - , evtName = o.slideTrigger_open.toLowerCase() - ; - if (!$R || (enable && !o.slidable)) return; - - // make sure we have a valid event - if (evtName.match(/mouseover/)) - evtName = o.slideTrigger_open = "mouseenter"; - else if (!evtName.match(/(click|dblclick|mouseenter)/)) - evtName = o.slideTrigger_open = "click"; - - $R - // add or remove event - [enable ? "bind" : "unbind"](evtName +'.'+ sID, slideOpen) - // set the appropriate cursor & title/tip - .css("cursor", enable ? o.sliderCursor : "default") - .attr("title", enable ? o.tips.Slide : "") - ; - } - - /** - * Add or remove 'mouseleave' events to 'slide close' when pane is 'sliding' open or closed - * Also increases zIndex when pane is sliding open - * See bindStartSlidingEvent for code to control 'slide open' - * - * @see slideOpen(), slideClose() - * @param {string} pane The pane to process, 'north', 'south', etc. - * @param {boolean} enable Enable or Disable events? - */ -, bindStopSlidingEvents = function (pane, enable) { - var o = options[pane] - , s = state[pane] - , c = _c[pane] - , z = options.zIndexes - , evtName = o.slideTrigger_close.toLowerCase() - , action = (enable ? "bind" : "unbind") - , $P = $Ps[pane] - , $R = $Rs[pane] - ; - s.isSliding = enable; // logic - timer.clear(pane+"_closeSlider"); // just in case - - // remove 'slideOpen' event from resizer - // ALSO will raise the zIndex of the pane & resizer - if (enable) bindStartSlidingEvent(pane, false); - - // RE/SET zIndex - increases when pane is sliding-open, resets to normal when not - $P.css("zIndex", enable ? z.pane_sliding : z.pane_normal); - $R.css("zIndex", enable ? z.pane_sliding+2 : z.resizer_normal); // NOTE: mask = pane_sliding+1 - - // make sure we have a valid event - if (!evtName.match(/(click|mouseleave)/)) - evtName = o.slideTrigger_close = "mouseleave"; // also catches 'mouseout' - - // add/remove slide triggers - $R[action](evtName, slideClose); // base event on resize - // need extra events for mouseleave - if (evtName === "mouseleave") { - // also close on pane.mouseleave - $P[action]("mouseleave."+ sID, slideClose); - // cancel timer when mouse moves between 'pane' and 'resizer' - $R[action]("mouseenter."+ sID, cancelMouseOut); - $P[action]("mouseenter."+ sID, cancelMouseOut); - } - - if (!enable) - timer.clear(pane+"_closeSlider"); - else if (evtName === "click" && !o.resizable) { - // IF pane is not resizable (which already has a cursor and tip) - // then set the a cursor & title/tip on resizer when sliding - $R.css("cursor", enable ? o.sliderCursor : "default"); - $R.attr("title", enable ? o.tips.Close : ""); // use Toggler-tip, eg: "Close Pane" - } - - // SUBROUTINE for mouseleave timer clearing - function cancelMouseOut (evt) { - timer.clear(pane+"_closeSlider"); - evt.stopPropagation(); - } - } - - - /** - * Hides/closes a pane if there is insufficient room - reverses this when there is room again - * MUST have already called setSizeLimits() before calling this method - * - * @param {string} pane The pane being resized - * @param {boolean=} [isOpening=false] Called from onOpen? - * @param {boolean=} [skipCallback=false] Should the onresize callback be run? - * @param {boolean=} [force=false] - */ -, makePaneFit = function (pane, isOpening, skipCallback, force) { - var - o = options[pane] - , s = state[pane] - , c = _c[pane] - , $P = $Ps[pane] - , $R = $Rs[pane] - , isSidePane = c.dir==="vert" - , hasRoom = false - ; - // special handling for center & east/west panes - if (pane === "center" || (isSidePane && s.noVerticalRoom)) { - // see if there is enough room to display the pane - // ERROR: hasRoom = s.minHeight <= s.maxHeight && (isSidePane || s.minWidth <= s.maxWidth); - hasRoom = (s.maxHeight >= 0); - if (hasRoom && s.noRoom) { // previously hidden due to noRoom, so show now - _showPane(pane); - if ($R) $R.show(); - s.isVisible = true; - s.noRoom = false; - if (isSidePane) s.noVerticalRoom = false; - _fixIframe(pane); - } - else if (!hasRoom && !s.noRoom) { // not currently hidden, so hide now - _hidePane(pane); - if ($R) $R.hide(); - s.isVisible = false; - s.noRoom = true; - } - } - - // see if there is enough room to fit the border-pane - if (pane === "center") { - // ignore center in this block - } - else if (s.minSize <= s.maxSize) { // pane CAN fit - hasRoom = true; - if (s.size > s.maxSize) // pane is too big - shrink it - sizePane(pane, s.maxSize, skipCallback, force, true); // true = noAnimation - else if (s.size < s.minSize) // pane is too small - enlarge it - sizePane(pane, s.minSize, skipCallback, force, true); - // need s.isVisible because new pseudoClose method keeps pane visible, but off-screen - else if ($R && s.isVisible && $P.is(":visible")) { - // make sure resizer-bar is positioned correctly - // handles situation where nested layout was 'hidden' when initialized - var side = c.side.toLowerCase() - , pos = s.size + sC["inset"+ c.side] - ; - if ($.layout.cssNum($R, side) != pos) $R.css( side, pos ); - } - - // if was previously hidden due to noRoom, then RESET because NOW there is room - if (s.noRoom) { - // s.noRoom state will be set by open or show - if (s.wasOpen && o.closable) { - if (o.autoReopen) - open(pane, false, true, true); // true = noAnimation, true = noAlert - else // leave the pane closed, so just update state - s.noRoom = false; - } - else - show(pane, s.wasOpen, true, true); // true = noAnimation, true = noAlert - } - } - else { // !hasRoom - pane CANNOT fit - if (!s.noRoom) { // pane not set as noRoom yet, so hide or close it now... - s.noRoom = true; // update state - s.wasOpen = !s.isClosed && !s.isSliding; - if (s.isClosed){} // SKIP - else if (o.closable) // 'close' if possible - close(pane, true, true); // true = force, true = noAnimation - else // 'hide' pane if cannot just be closed - hide(pane, true); // true = noAnimation - } - } - } - - - /** - * sizePane / manualSizePane - * sizePane is called only by internal methods whenever a pane needs to be resized - * manualSizePane is an exposed flow-through method allowing extra code when pane is 'manually resized' - * - * @param {string|Object} evt_or_pane The pane being resized - * @param {number} size The *desired* new size for this pane - will be validated - * @param {boolean=} [skipCallback=false] Should the onresize callback be run? - * @param {boolean=} [noAnimation=false] - */ -, manualSizePane = function (evt_or_pane, size, skipCallback, noAnimation) { - if (!isInitialized()) return; - var pane = evtPane.call(this, evt_or_pane) - , o = options[pane] - , s = state[pane] - // if resizing callbacks have been delayed and resizing is now DONE, force resizing to complete... - , forceResize = o.livePaneResizing && !s.isResizing - ; - // ANY call to manualSizePane disables autoResize - ie, percentage sizing - o.autoResize = false; - // flow-through... - sizePane(pane, size, skipCallback, forceResize, noAnimation); // will animate resize if option enabled - } - - /** - * @param {string|Object} evt_or_pane The pane being resized - * @param {number} size The *desired* new size for this pane - will be validated - * @param {boolean=} [skipCallback=false] Should the onresize callback be run? - * @param {boolean=} [force=false] Force resizing even if does not seem necessary - * @param {boolean=} [noAnimation=false] - */ -, sizePane = function (evt_or_pane, size, skipCallback, force, noAnimation) { - if (!isInitialized()) return; - var pane = evtPane.call(this, evt_or_pane) // probably NEVER called from event? - , o = options[pane] - , s = state[pane] - , $P = $Ps[pane] - , $R = $Rs[pane] - , side = _c[pane].side.toLowerCase() - , dimName = _c[pane].sizeType.toLowerCase() - , inset = "inset"+ _c[pane].side - , skipResizeWhileDragging = s.isResizing && !o.triggerEventsDuringLiveResize - , doFX = noAnimation !== true && o.animatePaneSizing - , oldSize, newSize - ; - // QUEUE in case another action/animation is in progress - $N.queue(function( queueNext ){ - // calculate 'current' min/max sizes - setSizeLimits(pane); // update pane-state - oldSize = s.size; - size = _parseSize(pane, size); // handle percentages & auto - size = max(size, _parseSize(pane, o.minSize)); - size = min(size, s.maxSize); - if (size < s.minSize) { // not enough room for pane! - queueNext(); // call before makePaneFit() because it needs the queue free - makePaneFit(pane, false, skipCallback); // will hide or close pane - return; - } - - // IF newSize is same as oldSize, then nothing to do - abort - if (!force && size === oldSize) - return queueNext(); - - // onresize_start callback CANNOT cancel resizing because this would break the layout! - if (!skipCallback && state.initialized && s.isVisible) - _runCallbacks("onresize_start", pane); - - // resize the pane, and make sure its visible - newSize = cssSize(pane, size); - - if (doFX && $P.is(":visible")) { // ANIMATE - var fx = $.layout.effects.size[pane] || $.layout.effects.size.all - , easing = o.fxSettings_size.easing || fx.easing - , z = options.zIndexes - , props = {}; - props[ dimName ] = newSize +'px'; - s.isMoving = true; - // overlay all elements during animation - $P.css({ zIndex: z.pane_animate }) - .show().animate( props, o.fxSpeed_size, easing, function(){ - // reset zIndex after animation - $P.css({ zIndex: (s.isSliding ? z.pane_sliding : z.pane_normal) }); - s.isMoving = false; - sizePane_2(); // continue - queueNext(); - }); - } - else { // no animation - $P.css( dimName, newSize ); // resize pane - // if pane is visible, then - if ($P.is(":visible")) - sizePane_2(); // continue - else { - // pane is NOT VISIBLE, so just update state data... - // when pane is *next opened*, it will have the new size - s.size = size; // update state.size - $.extend(s, elDims($P)); // update state dimensions - } - queueNext(); - }; - - }); - - // SUBROUTINE - function sizePane_2 () { - /* Panes are sometimes not sized precisely in some browsers!? - * This code will resize the pane up to 3 times to nudge the pane to the correct size - */ - var actual = dimName==='width' ? $P.outerWidth() : $P.outerHeight() - , tries = [{ - pane: pane - , count: 1 - , target: size - , actual: actual - , correct: (size === actual) - , attempt: size - , cssSize: newSize - }] - , lastTry = tries[0] - , thisTry = {} - , msg = 'Inaccurate size after resizing the '+ pane +'-pane.' - ; - while ( !lastTry.correct ) { - thisTry = { pane: pane, count: lastTry.count+1, target: size }; - - if (lastTry.actual > size) - thisTry.attempt = max(0, lastTry.attempt - (lastTry.actual - size)); - else // lastTry.actual < size - thisTry.attempt = max(0, lastTry.attempt + (size - lastTry.actual)); - - thisTry.cssSize = cssSize(pane, thisTry.attempt); - $P.css( dimName, thisTry.cssSize ); - - thisTry.actual = dimName=='width' ? $P.outerWidth() : $P.outerHeight(); - thisTry.correct = (size === thisTry.actual); - - // log attempts and alert the user of this *non-fatal error* (if showDebugMessages) - if ( tries.length === 1) { - _log(msg, false, true); - _log(lastTry, false, true); - } - _log(thisTry, false, true); - // after 4 tries, is as close as its gonna get! - if (tries.length > 3) break; - - tries.push( thisTry ); - lastTry = tries[ tries.length - 1 ]; - } - // END TESTING CODE - - // update pane-state dimensions - s.size = size; - $.extend(s, elDims($P)); - - if (s.isVisible && $P.is(":visible")) { - // reposition the resizer-bar - if ($R) $R.css( side, size + sC[inset] ); - // resize the content-div - sizeContent(pane); - } - - if (!skipCallback && !skipResizeWhileDragging && state.initialized && s.isVisible) - _runCallbacks("onresize_end", pane); - - // resize all the adjacent panes, and adjust their toggler buttons - // when skipCallback passed, it means the controlling method will handle 'other panes' - if (!skipCallback) { - // also no callback if live-resize is in progress and NOT triggerEventsDuringLiveResize - if (!s.isSliding) sizeMidPanes(_c[pane].dir=="horz" ? "" : "center", skipResizeWhileDragging, force); - sizeHandles(); - } - - // if opposite-pane was autoClosed, see if it can be autoOpened now - var altPane = _c.oppositeEdge[pane]; - if (size < oldSize && state[ altPane ].noRoom) { - setSizeLimits( altPane ); - makePaneFit( altPane, false, skipCallback ); - } - - // DEBUG - ALERT user/developer so they know there was a sizing problem - if (tries.length > 1) - _log(msg +'\nSee the Error Console for details.', true, true); - } - } - - /** - * @see initPanes(), sizePane(), resizeAll(), open(), close(), hide() - * @param {Array.|string} panes The pane(s) being resized, comma-delmited string - * @param {boolean=} [skipCallback=false] Should the onresize callback be run? - * @param {boolean=} [force=false] - */ -, sizeMidPanes = function (panes, skipCallback, force) { - panes = (panes ? panes : "east,west,center").split(","); - - $.each(panes, function (i, pane) { - if (!$Ps[pane]) return; // NO PANE - skip - var - o = options[pane] - , s = state[pane] - , $P = $Ps[pane] - , $R = $Rs[pane] - , isCenter= (pane=="center") - , hasRoom = true - , CSS = {} - , newCenter = calcNewCenterPaneDims() - ; - // update pane-state dimensions - $.extend(s, elDims($P)); - - if (pane === "center") { - if (!force && s.isVisible && newCenter.width === s.outerWidth && newCenter.height === s.outerHeight) - return true; // SKIP - pane already the correct size - // set state for makePaneFit() logic - $.extend(s, cssMinDims(pane), { - maxWidth: newCenter.width - , maxHeight: newCenter.height - }); - CSS = newCenter; - // convert OUTER width/height to CSS width/height - CSS.width = cssW($P, CSS.width); - // NEW - allow pane to extend 'below' visible area rather than hide it - CSS.height = cssH($P, CSS.height); - hasRoom = CSS.width >= 0 && CSS.height >= 0; // height >= 0 = ALWAYS TRUE NOW - // during layout init, try to shrink east/west panes to make room for center - if (!state.initialized && o.minWidth > s.outerWidth) { - var - reqPx = o.minWidth - s.outerWidth - , minE = options.east.minSize || 0 - , minW = options.west.minSize || 0 - , sizeE = state.east.size - , sizeW = state.west.size - , newE = sizeE - , newW = sizeW - ; - if (reqPx > 0 && state.east.isVisible && sizeE > minE) { - newE = max( sizeE-minE, sizeE-reqPx ); - reqPx -= sizeE-newE; - } - if (reqPx > 0 && state.west.isVisible && sizeW > minW) { - newW = max( sizeW-minW, sizeW-reqPx ); - reqPx -= sizeW-newW; - } - // IF we found enough extra space, then resize the border panes as calculated - if (reqPx === 0) { - if (sizeE && sizeE != minE) - sizePane('east', newE, true, force, true); // true = skipCallback/noAnimation - initPanes will handle when done - if (sizeW && sizeW != minW) - sizePane('west', newW, true, force, true); - // now start over! - sizeMidPanes('center', skipCallback, force); - return; // abort this loop - } - } - } - else { // for east and west, set only the height, which is same as center height - // set state.min/maxWidth/Height for makePaneFit() logic - if (s.isVisible && !s.noVerticalRoom) - $.extend(s, elDims($P), cssMinDims(pane)) - if (!force && !s.noVerticalRoom && newCenter.height === s.outerHeight) - return true; // SKIP - pane already the correct size - // east/west have same top, bottom & height as center - CSS.top = newCenter.top; - CSS.bottom = newCenter.bottom; - // NEW - allow pane to extend 'below' visible area rather than hide it - CSS.height = cssH($P, newCenter.height); - s.maxHeight = CSS.height; - hasRoom = (s.maxHeight >= 0); // ALWAYS TRUE NOW - if (!hasRoom) s.noVerticalRoom = true; // makePaneFit() logic - } - - if (hasRoom) { - // resizeAll passes skipCallback because it triggers callbacks after ALL panes are resized - if (!skipCallback && state.initialized) - _runCallbacks("onresize_start", pane); - - $P.css(CSS); // apply the CSS to pane - if (pane !== "center") - sizeHandles(pane); // also update resizer length - if (s.noRoom && !s.isClosed && !s.isHidden) - makePaneFit(pane); // will re-open/show auto-closed/hidden pane - if (s.isVisible) { - $.extend(s, elDims($P)); // update pane dimensions - if (state.initialized) sizeContent(pane); // also resize the contents, if exists - } - } - else if (!s.noRoom && s.isVisible) // no room for pane - makePaneFit(pane); // will hide or close pane - - if (!s.isVisible) - return true; // DONE - next pane - - /* - * Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes - * Normally these panes have only 'left' & 'right' positions so pane auto-sizes - * ALSO required when pane is an IFRAME because will NOT default to 'full width' - * TODO: Can I use width:100% for a north/south iframe? - * TODO: Sounds like a job for $P.outerWidth( sC.innerWidth ) SETTER METHOD - */ - if (pane === "center") { // finished processing midPanes - var fix = browser.isIE6 || !browser.boxModel; - if ($Ps.north && (fix || state.north.tagName=="IFRAME")) - $Ps.north.css("width", cssW($Ps.north, sC.innerWidth)); - if ($Ps.south && (fix || state.south.tagName=="IFRAME")) - $Ps.south.css("width", cssW($Ps.south, sC.innerWidth)); - } - - // resizeAll passes skipCallback because it triggers callbacks after ALL panes are resized - if (!skipCallback && state.initialized) - _runCallbacks("onresize_end", pane); - }); - } - - - /** - * @see window.onresize(), callbacks or custom code - */ -, resizeAll = function (evt) { - // stopPropagation if called by trigger("layoutdestroy") - use evtPane utility - evtPane(evt); - - if (!state.initialized) { - _initLayoutElements(); - return; // no need to resize since we just initialized! - } - var oldW = sC.innerWidth - , oldH = sC.innerHeight - ; - // cannot size layout when 'container' is hidden or collapsed - if (!$N.is(":visible") ) return; - $.extend(state.container, elDims( $N )); // UPDATE container dimensions - if (!sC.outerHeight) return; - - // onresizeall_start will CANCEL resizing if returns false - // state.container has already been set, so user can access this info for calcuations - if (false === _runCallbacks("onresizeall_start")) return false; - - var // see if container is now 'smaller' than before - shrunkH = (sC.innerHeight < oldH) - , shrunkW = (sC.innerWidth < oldW) - , $P, o, s, dir - ; - // NOTE special order for sizing: S-N-E-W - $.each(["south","north","east","west"], function (i, pane) { - if (!$Ps[pane]) return; // no pane - SKIP - s = state[pane]; - o = options[pane]; - dir = _c[pane].dir; - - if (o.autoResize && s.size != o.size) // resize pane to original size set in options - sizePane(pane, o.size, true, true, true); // true=skipCallback/forceResize/noAnimation - else { - setSizeLimits(pane); - makePaneFit(pane, false, true, true); // true=skipCallback/forceResize - } - }); - - sizeMidPanes("", true, true); // true=skipCallback, true=forceResize - sizeHandles(); // reposition the toggler elements - - // trigger all individual pane callbacks AFTER layout has finished resizing - o = options; // reuse alias - $.each(_c.allPanes, function (i, pane) { - $P = $Ps[pane]; - if (!$P) return; // SKIP - if (state[pane].isVisible) // undefined for non-existent panes - _runCallbacks("onresize_end", pane); // callback - if exists - }); - - _runCallbacks("onresizeall_end"); - //_triggerLayoutEvent(pane, 'resizeall'); - } - - /** - * Whenever a pane resizes or opens that has a nested layout, trigger resizeAll - * - * @param {string|Object} evt_or_pane The pane just resized or opened - */ -, resizeChildLayout = function (evt_or_pane) { - var pane = evtPane.call(this, evt_or_pane); - if (!options[pane].resizeChildLayout) return; - var $P = $Ps[pane] - , $C = $Cs[pane] - , d = "layout" - , P = Instance[pane] - , L = children[pane] - ; - // user may have manually set EITHER instance pointer, so handle that - if (P.child && !L) { - // have to reverse the pointers! - var el = P.child.container; - L = children[pane] = (el ? el.data(d) : 0) || null; // set pointer _directly_ to layout instance - } - - // if a layout-pointer exists, see if child has been destroyed - if (L && L.destroyed) - L = children[pane] = null; // clear child pointers - // no child layout pointer is set - see if there is a child layout NOW - if (!L) L = children[pane] = $P.data(d) || ($C ? $C.data(d) : 0) || null; // set/update child pointers - - // ALWAYS refresh the pane.child alias - P.child = children[pane]; - - if (L) L.resizeAll(); - } - - - /** - * IF pane has a content-div, then resize all elements inside pane to fit pane-height - * - * @param {string|Object} evt_or_panes The pane(s) being resized - * @param {boolean=} [remeasure=false] Should the content (header/footer) be remeasured? - */ -, sizeContent = function (evt_or_panes, remeasure) { - if (!isInitialized()) return; - - var panes = evtPane.call(this, evt_or_panes); - panes = panes ? panes.split(",") : _c.allPanes; - - $.each(panes, function (idx, pane) { - var - $P = $Ps[pane] - , $C = $Cs[pane] - , o = options[pane] - , s = state[pane] - , m = s.content // m = measurements - ; - if (!$P || !$C || !$P.is(":visible")) return true; // NOT VISIBLE - skip - - // if content-element was REMOVED, update OR remove the pointer - if (!$C.length) { - initContent(pane, false); // false = do NOT sizeContent() - already there! - if (!$C) return; // no replacement element found - pointer have been removed - } - - // onsizecontent_start will CANCEL resizing if returns false - if (false === _runCallbacks("onsizecontent_start", pane)) return; - - // skip re-measuring offsets if live-resizing - if ((!s.isMoving && !s.isResizing) || o.liveContentResizing || remeasure || m.top == undefined) { - _measure(); - // if any footers are below pane-bottom, they may not measure correctly, - // so allow pane overflow and re-measure - if (m.hiddenFooters > 0 && $P.css("overflow") === "hidden") { - $P.css("overflow", "visible"); - _measure(); // remeasure while overflowing - $P.css("overflow", "hidden"); - } - } - // NOTE: spaceAbove/Below *includes* the pane paddingTop/Bottom, but not pane.borders - var newH = s.innerHeight - (m.spaceAbove - s.css.paddingTop) - (m.spaceBelow - s.css.paddingBottom); - - if (!$C.is(":visible") || m.height != newH) { - // size the Content element to fit new pane-size - will autoHide if not enough room - setOuterHeight($C, newH, true); // true=autoHide - m.height = newH; // save new height - }; - - if (state.initialized) - _runCallbacks("onsizecontent_end", pane); - - function _below ($E) { - return max(s.css.paddingBottom, (parseInt($E.css("marginBottom"), 10) || 0)); - }; - - function _measure () { - var - ignore = options[pane].contentIgnoreSelector - , $Fs = $C.nextAll().not(ignore || ':lt(0)') // not :lt(0) = ALL - , $Fs_vis = $Fs.filter(':visible') - , $F = $Fs_vis.filter(':last') - ; - m = { - top: $C[0].offsetTop - , height: $C.outerHeight() - , numFooters: $Fs.length - , hiddenFooters: $Fs.length - $Fs_vis.length - , spaceBelow: 0 // correct if no content footer ($E) - } - m.spaceAbove = m.top; // just for state - not used in calc - m.bottom = m.top + m.height; - if ($F.length) - //spaceBelow = (LastFooter.top + LastFooter.height) [footerBottom] - Content.bottom + max(LastFooter.marginBottom, pane.paddingBotom) - m.spaceBelow = ($F[0].offsetTop + $F.outerHeight()) - m.bottom + _below($F); - else // no footer - check marginBottom on Content element itself - m.spaceBelow = _below($C); - }; - }); - } - - - /** - * Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary - * - * @see initHandles(), open(), close(), resizeAll() - * @param {string|Object} evt_or_panes The pane(s) being resized - */ -, sizeHandles = function (evt_or_panes) { - var panes = evtPane.call(this, evt_or_panes) - panes = panes ? panes.split(",") : _c.borderPanes; - - $.each(panes, function (i, pane) { - var - o = options[pane] - , s = state[pane] - , $P = $Ps[pane] - , $R = $Rs[pane] - , $T = $Ts[pane] - , $TC - ; - if (!$P || !$R) return; - - var - dir = _c[pane].dir - , _state = (s.isClosed ? "_closed" : "_open") - , spacing = o["spacing"+ _state] - , togAlign = o["togglerAlign"+ _state] - , togLen = o["togglerLength"+ _state] - , paneLen - , left - , offset - , CSS = {} - ; - - if (spacing === 0) { - $R.hide(); - return; - } - else if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason - $R.show(); // in case was previously hidden - - // Resizer Bar is ALWAYS same width/height of pane it is attached to - if (dir === "horz") { // north/south - //paneLen = $P.outerWidth(); // s.outerWidth || - paneLen = sC.innerWidth; // handle offscreen-panes - s.resizerLength = paneLen; - left = $.layout.cssNum($P, "left") - $R.css({ - width: cssW($R, paneLen) // account for borders & padding - , height: cssH($R, spacing) // ditto - , left: left > -9999 ? left : sC.insetLeft // handle offscreen-panes - }); - } - else { // east/west - paneLen = $P.outerHeight(); // s.outerHeight || - s.resizerLength = paneLen; - $R.css({ - height: cssH($R, paneLen) // account for borders & padding - , width: cssW($R, spacing) // ditto - , top: sC.insetTop + getPaneSize("north", true) // TODO: what if no North pane? - //, top: $.layout.cssNum($Ps["center"], "top") - }); - } - - // remove hover classes - removeHover( o, $R ); - - if ($T) { - if (togLen === 0 || (s.isSliding && o.hideTogglerOnSlide)) { - $T.hide(); // always HIDE the toggler when 'sliding' - return; - } - else - $T.show(); // in case was previously hidden - - if (!(togLen > 0) || togLen === "100%" || togLen > paneLen) { - togLen = paneLen; - offset = 0; - } - else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed - if (isStr(togAlign)) { - switch (togAlign) { - case "top": - case "left": offset = 0; - break; - case "bottom": - case "right": offset = paneLen - togLen; - break; - case "middle": - case "center": - default: offset = round((paneLen - togLen) / 2); // 'default' catches typos - } - } - else { // togAlign = number - var x = parseInt(togAlign, 10); // - if (togAlign >= 0) offset = x; - else offset = paneLen - togLen + x; // NOTE: x is negative! - } - } - - if (dir === "horz") { // north/south - var width = cssW($T, togLen); - $T.css({ - width: width // account for borders & padding - , height: cssH($T, spacing) // ditto - , left: offset // TODO: VERIFY that toggler positions correctly for ALL values - , top: 0 - }); - // CENTER the toggler content SPAN - $T.children(".content").each(function(){ - $TC = $(this); - $TC.css("marginLeft", round((width-$TC.outerWidth())/2)); // could be negative - }); - } - else { // east/west - var height = cssH($T, togLen); - $T.css({ - height: height // account for borders & padding - , width: cssW($T, spacing) // ditto - , top: offset // POSITION the toggler - , left: 0 - }); - // CENTER the toggler content SPAN - $T.children(".content").each(function(){ - $TC = $(this); - $TC.css("marginTop", round((height-$TC.outerHeight())/2)); // could be negative - }); - } - - // remove ALL hover classes - removeHover( 0, $T ); - } - - // DONE measuring and sizing this resizer/toggler, so can be 'hidden' now - if (!state.initialized && (o.initHidden || s.noRoom)) { - $R.hide(); - if ($T) $T.hide(); - } - }); - } - - - /** - * @param {string|Object} evt_or_pane - */ -, enableClosable = function (evt_or_pane) { - if (!isInitialized()) return; - var pane = evtPane.call(this, evt_or_pane) - , $T = $Ts[pane] - , o = options[pane] - ; - if (!$T) return; - o.closable = true; - $T .bind("click."+ sID, function(evt){ evt.stopPropagation(); toggle(pane); }) - .css("visibility", "visible") - .css("cursor", "pointer") - .attr("title", state[pane].isClosed ? o.tips.Open : o.tips.Close) // may be blank - .show(); - } - /** - * @param {string|Object} evt_or_pane - * @param {boolean=} [hide=false] - */ -, disableClosable = function (evt_or_pane, hide) { - if (!isInitialized()) return; - var pane = evtPane.call(this, evt_or_pane) - , $T = $Ts[pane] - ; - if (!$T) return; - options[pane].closable = false; - // is closable is disable, then pane MUST be open! - if (state[pane].isClosed) open(pane, false, true); - $T .unbind("."+ sID) - .css("visibility", hide ? "hidden" : "visible") // instead of hide(), which creates logic issues - .css("cursor", "default") - .attr("title", ""); - } - - - /** - * @param {string|Object} evt_or_pane - */ -, enableSlidable = function (evt_or_pane) { - if (!isInitialized()) return; - var pane = evtPane.call(this, evt_or_pane) - , $R = $Rs[pane] - ; - if (!$R || !$R.data('draggable')) return; - options[pane].slidable = true; - if (state[pane].isClosed) - bindStartSlidingEvent(pane, true); - } - /** - * @param {string|Object} evt_or_pane - */ -, disableSlidable = function (evt_or_pane) { - if (!isInitialized()) return; - var pane = evtPane.call(this, evt_or_pane) - , $R = $Rs[pane] - ; - if (!$R) return; - options[pane].slidable = false; - if (state[pane].isSliding) - close(pane, false, true); - else { - bindStartSlidingEvent(pane, false); - $R .css("cursor", "default") - .attr("title", ""); - removeHover(null, $R[0]); // in case currently hovered - } - } - - - /** - * @param {string|Object} evt_or_pane - */ -, enableResizable = function (evt_or_pane) { - if (!isInitialized()) return; - var pane = evtPane.call(this, evt_or_pane) - , $R = $Rs[pane] - , o = options[pane] - ; - if (!$R || !$R.data('draggable')) return; - o.resizable = true; - $R.draggable("enable"); - if (!state[pane].isClosed) - $R .css("cursor", o.resizerCursor) - .attr("title", o.tips.Resize); - } - /** - * @param {string|Object} evt_or_pane - */ -, disableResizable = function (evt_or_pane) { - if (!isInitialized()) return; - var pane = evtPane.call(this, evt_or_pane) - , $R = $Rs[pane] - ; - if (!$R || !$R.data('draggable')) return; - options[pane].resizable = false; - $R .draggable("disable") - .css("cursor", "default") - .attr("title", ""); - removeHover(null, $R[0]); // in case currently hovered - } - - - /** - * Move a pane from source-side (eg, west) to target-side (eg, east) - * If pane exists on target-side, move that to source-side, ie, 'swap' the panes - * - * @param {string|Object} evt_or_pane1 The pane/edge being swapped - * @param {string} pane2 ditto - */ -, swapPanes = function (evt_or_pane1, pane2) { - if (!isInitialized()) return; - var pane1 = evtPane.call(this, evt_or_pane1); - // change state.edge NOW so callbacks can know where pane is headed... - state[pane1].edge = pane2; - state[pane2].edge = pane1; - // run these even if NOT state.initialized - if (false === _runCallbacks("onswap_start", pane1) - || false === _runCallbacks("onswap_start", pane2) - ) { - state[pane1].edge = pane1; // reset - state[pane2].edge = pane2; - return; - } - - var - oPane1 = copy( pane1 ) - , oPane2 = copy( pane2 ) - , sizes = {} - ; - sizes[pane1] = oPane1 ? oPane1.state.size : 0; - sizes[pane2] = oPane2 ? oPane2.state.size : 0; - - // clear pointers & state - $Ps[pane1] = false; - $Ps[pane2] = false; - state[pane1] = {}; - state[pane2] = {}; - - // ALWAYS remove the resizer & toggler elements - if ($Ts[pane1]) $Ts[pane1].remove(); - if ($Ts[pane2]) $Ts[pane2].remove(); - if ($Rs[pane1]) $Rs[pane1].remove(); - if ($Rs[pane2]) $Rs[pane2].remove(); - $Rs[pane1] = $Rs[pane2] = $Ts[pane1] = $Ts[pane2] = false; - - // transfer element pointers and data to NEW Layout keys - move( oPane1, pane2 ); - move( oPane2, pane1 ); - - // cleanup objects - oPane1 = oPane2 = sizes = null; - - // make panes 'visible' again - if ($Ps[pane1]) $Ps[pane1].css(_c.visible); - if ($Ps[pane2]) $Ps[pane2].css(_c.visible); - - // fix any size discrepancies caused by swap - resizeAll(); - - // run these even if NOT state.initialized - _runCallbacks("onswap_end", pane1); - _runCallbacks("onswap_end", pane2); - - return; - - function copy (n) { // n = pane - var - $P = $Ps[n] - , $C = $Cs[n] - ; - return !$P ? false : { - pane: n - , P: $P ? $P[0] : false - , C: $C ? $C[0] : false - , state: $.extend(true, {}, state[n]) - , options: $.extend(true, {}, options[n]) - } - }; - - function move (oPane, pane) { - if (!oPane) return; - var - P = oPane.P - , C = oPane.C - , oldPane = oPane.pane - , c = _c[pane] - , side = c.side.toLowerCase() - , inset = "inset"+ c.side - // save pane-options that should be retained - , s = $.extend(true, {}, state[pane]) - , o = options[pane] - // RETAIN side-specific FX Settings - more below - , fx = { resizerCursor: o.resizerCursor } - , re, size, pos - ; - $.each("fxName,fxSpeed,fxSettings".split(","), function (i, k) { - fx[k +"_open"] = o[k +"_open"]; - fx[k +"_close"] = o[k +"_close"]; - fx[k +"_size"] = o[k +"_size"]; - }); - - // update object pointers and attributes - $Ps[pane] = $(P) - .data({ - layoutPane: Instance[pane] // NEW pointer to pane-alias-object - , layoutEdge: pane - }) - .css(_c.hidden) - .css(c.cssReq) - ; - $Cs[pane] = C ? $(C) : false; - - // set options and state - options[pane] = $.extend(true, {}, oPane.options, fx); - state[pane] = $.extend(true, {}, oPane.state); - - // change classNames on the pane, eg: ui-layout-pane-east ==> ui-layout-pane-west - re = new RegExp(o.paneClass +"-"+ oldPane, "g"); - P.className = P.className.replace(re, o.paneClass +"-"+ pane); - - // ALWAYS regenerate the resizer & toggler elements - initHandles(pane); // create the required resizer & toggler - - // if moving to different orientation, then keep 'target' pane size - if (c.dir != _c[oldPane].dir) { - size = sizes[pane] || 0; - setSizeLimits(pane); // update pane-state - size = max(size, state[pane].minSize); - // use manualSizePane to disable autoResize - not useful after panes are swapped - manualSizePane(pane, size, true, true); // true/true = skipCallback/noAnimation - } - else // move the resizer here - $Rs[pane].css(side, sC[inset] + (state[pane].isVisible ? getPaneSize(pane) : 0)); - - - // ADD CLASSNAMES & SLIDE-BINDINGS - if (oPane.state.isVisible && !s.isVisible) - setAsOpen(pane, true); // true = skipCallback - else { - setAsClosed(pane); - bindStartSlidingEvent(pane, true); // will enable events IF option is set - } - - // DESTROY the object - oPane = null; - }; - } - - - /** - * INTERNAL method to sync pin-buttons when pane is opened or closed - * Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes - * - * @see open(), setAsOpen(), setAsClosed() - * @param {string} pane These are the params returned to callbacks by layout() - * @param {boolean} doPin True means set the pin 'down', False means 'up' - */ -, syncPinBtns = function (pane, doPin) { - if ($.layout.plugins.buttons) - $.each(state[pane].pins, function (i, selector) { - $.layout.buttons.setPinState(Instance, $(selector), pane, doPin); - }); - } - -; // END var DECLARATIONS - - /** - * Capture keys when enableCursorHotkey - toggle pane if hotkey pressed - * - * @see document.keydown() - */ - function keyDown (evt) { - if (!evt) return true; - var code = evt.keyCode; - if (code < 33) return true; // ignore special keys: ENTER, TAB, etc - - var - PANE = { - 38: "north" // Up Cursor - $.ui.keyCode.UP - , 40: "south" // Down Cursor - $.ui.keyCode.DOWN - , 37: "west" // Left Cursor - $.ui.keyCode.LEFT - , 39: "east" // Right Cursor - $.ui.keyCode.RIGHT - } - , ALT = evt.altKey // no worky! - , SHIFT = evt.shiftKey - , CTRL = evt.ctrlKey - , CURSOR = (CTRL && code >= 37 && code <= 40) - , o, k, m, pane - ; - - if (CURSOR && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey - pane = PANE[code]; - else if (CTRL || SHIFT) // check to see if this matches a custom-hotkey - $.each(_c.borderPanes, function (i, p) { // loop each pane to check its hotkey - o = options[p]; - k = o.customHotkey; - m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT" - if ((SHIFT && m=="SHIFT") || (CTRL && m=="CTRL") || (CTRL && SHIFT)) { // Modifier matches - if (k && code === (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches - pane = p; - return false; // BREAK - } - } - }); - - // validate pane - if (!pane || !$Ps[pane] || !options[pane].closable || state[pane].isHidden) - return true; - - toggle(pane); - - evt.stopPropagation(); - evt.returnValue = false; // CANCEL key - return false; - }; - - -/* - * ###################################### - * UTILITY METHODS - * called externally or by initButtons - * ###################################### - */ - - /** - * Change/reset a pane overflow setting & zIndex to allow popups/drop-downs to work - * - * @param {Object=} [el] (optional) Can also be 'bound' to a click, mouseOver, or other event - */ - function allowOverflow (el) { - if (!isInitialized()) return; - if (this && this.tagName) el = this; // BOUND to element - var $P; - if (isStr(el)) - $P = $Ps[el]; - else if ($(el).data("layoutRole")) - $P = $(el); - else - $(el).parents().each(function(){ - if ($(this).data("layoutRole")) { - $P = $(this); - return false; // BREAK - } - }); - if (!$P || !$P.length) return; // INVALID - - var - pane = $P.data("layoutEdge") - , s = state[pane] - ; - - // if pane is already raised, then reset it before doing it again! - // this would happen if allowOverflow is attached to BOTH the pane and an element - if (s.cssSaved) - resetOverflow(pane); // reset previous CSS before continuing - - // if pane is raised by sliding or resizing, or its closed, then abort - if (s.isSliding || s.isResizing || s.isClosed) { - s.cssSaved = false; - return; - } - - var - newCSS = { zIndex: (options.zIndexes.resizer_normal + 1) } - , curCSS = {} - , of = $P.css("overflow") - , ofX = $P.css("overflowX") - , ofY = $P.css("overflowY") - ; - // determine which, if any, overflow settings need to be changed - if (of != "visible") { - curCSS.overflow = of; - newCSS.overflow = "visible"; - } - if (ofX && !ofX.match(/(visible|auto)/)) { - curCSS.overflowX = ofX; - newCSS.overflowX = "visible"; - } - if (ofY && !ofY.match(/(visible|auto)/)) { - curCSS.overflowY = ofX; - newCSS.overflowY = "visible"; - } - - // save the current overflow settings - even if blank! - s.cssSaved = curCSS; - - // apply new CSS to raise zIndex and, if necessary, make overflow 'visible' - $P.css( newCSS ); - - // make sure the zIndex of all other panes is normal - $.each(_c.allPanes, function(i, p) { - if (p != pane) resetOverflow(p); - }); - - }; - /** - * @param {Object=} [el] (optional) Can also be 'bound' to a click, mouseOver, or other event - */ - function resetOverflow (el) { - if (!isInitialized()) return; - if (this && this.tagName) el = this; // BOUND to element - var $P; - if (isStr(el)) - $P = $Ps[el]; - else if ($(el).data("layoutRole")) - $P = $(el); - else - $(el).parents().each(function(){ - if ($(this).data("layoutRole")) { - $P = $(this); - return false; // BREAK - } - }); - if (!$P || !$P.length) return; // INVALID - - var - pane = $P.data("layoutEdge") - , s = state[pane] - , CSS = s.cssSaved || {} - ; - // reset the zIndex - if (!s.isSliding && !s.isResizing) - $P.css("zIndex", options.zIndexes.pane_normal); - - // reset Overflow - if necessary - $P.css( CSS ); - - // clear var - s.cssSaved = false; - }; - -/* - * ##################### - * CREATE/RETURN LAYOUT - * ##################### - */ - - // validate that container exists - var $N = $(this).eq(0); // FIRST matching Container element - if (!$N.length) { - return _log( options.errors.containerMissing ); - }; - - // Users retrieve Instance of a layout with: $N.layout() OR $N.data("layout") - // return the Instance-pointer if layout has already been initialized - if ($N.data("layoutContainer") && $N.data("layout")) - return $N.data("layout"); // cached pointer - - // init global vars - var - $Ps = {} // Panes x5 - set in initPanes() - , $Cs = {} // Content x5 - set in initPanes() - , $Rs = {} // Resizers x4 - set in initHandles() - , $Ts = {} // Togglers x4 - set in initHandles() - , $Ms = $([]) // Masks - up to 2 masks per pane (IFRAME + DIV) - // aliases for code brevity - , sC = state.container // alias for easy access to 'container dimensions' - , sID = state.id // alias for unique layout ID/namespace - eg: "layout435" - ; - - // create Instance object to expose data & option Properties, and primary action Methods - var Instance = { - // layout data - options: options // property - options hash - , state: state // property - dimensions hash - // object pointers - , container: $N // property - object pointers for layout container - , panes: $Ps // property - object pointers for ALL Panes: panes.north, panes.center - , contents: $Cs // property - object pointers for ALL Content: contents.north, contents.center - , resizers: $Rs // property - object pointers for ALL Resizers, eg: resizers.north - , togglers: $Ts // property - object pointers for ALL Togglers, eg: togglers.north - // border-pane open/close - , hide: hide // method - ditto - , show: show // method - ditto - , toggle: toggle // method - pass a 'pane' ("north", "west", etc) - , open: open // method - ditto - , close: close // method - ditto - , slideOpen: slideOpen // method - ditto - , slideClose: slideClose // method - ditto - , slideToggle: slideToggle // method - ditto - // pane actions - , setSizeLimits: setSizeLimits // method - pass a 'pane' - update state min/max data - , _sizePane: sizePane // method -intended for user by plugins only! - , sizePane: manualSizePane // method - pass a 'pane' AND an 'outer-size' in pixels or percent, or 'auto' - , sizeContent: sizeContent // method - pass a 'pane' - , swapPanes: swapPanes // method - pass TWO 'panes' - will swap them - , showMasks: showMasks // method - pass a 'pane' OR list of panes - default = all panes with mask option set - , hideMasks: hideMasks // method - ditto' - // pane element methods - , initContent: initContent // method - ditto - , addPane: addPane // method - pass a 'pane' - , removePane: removePane // method - pass a 'pane' to remove from layout, add 'true' to delete the pane-elem - , createChildLayout: createChildLayout// method - pass a 'pane' and (optional) layout-options (OVERRIDES options[pane].childOptions - // special pane option setting - , enableClosable: enableClosable // method - pass a 'pane' - , disableClosable: disableClosable // method - ditto - , enableSlidable: enableSlidable // method - ditto - , disableSlidable: disableSlidable // method - ditto - , enableResizable: enableResizable // method - ditto - , disableResizable: disableResizable// method - ditto - // utility methods for panes - , allowOverflow: allowOverflow // utility - pass calling element (this) - , resetOverflow: resetOverflow // utility - ditto - // layout control - , destroy: destroy // method - no parameters - , initPanes: isInitialized // method - no parameters - , resizeAll: resizeAll // method - no parameters - // callback triggering - , runCallbacks: _runCallbacks // method - pass evtName & pane (if a pane-event), eg: trigger("onopen", "west") - // alias collections of options, state and children - created in addPane and extended elsewhere - , hasParentLayout: false // set by initContainer() - , children: children // pointers to child-layouts, eg: Instance.children["west"] - , north: false // alias group: { name: pane, pane: $Ps[pane], options: options[pane], state: state[pane], child: children[pane] } - , south: false // ditto - , west: false // ditto - , east: false // ditto - , center: false // ditto - }; - - // create the border layout NOW - if (_create() === 'cancel') // onload_start callback returned false to CANCEL layout creation - return null; - else // true OR false -- if layout-elements did NOT init (hidden or do not exist), can auto-init later - return Instance; // return the Instance object - -} - - -/* OLD versions of jQuery only set $.support.boxModel after page is loaded - * so if this is IE, use support.boxModel to test for quirks-mode (ONLY IE changes boxModel). - */ -$(function(){ - var b = $.layout.browser; - if (b.msie) b.boxModel = $.support.boxModel; -}); - - -/** - * jquery.layout.state 1.0 - * $Date: 2011-07-16 08:00:00 (Sat, 16 July 2011) $ - * - * Copyright (c) 2010 - * Kevin Dalman (http://allpro.net) - * - * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html) - * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses. - * - * @dependancies: UI Layout 1.3.0.rc30.1 or higher - * @dependancies: $.ui.cookie (above) - * - * @support: http://groups.google.com/group/jquery-ui-layout - */ -/* - * State-management options stored in options.stateManagement, which includes a .cookie hash - * Default options saves ALL KEYS for ALL PANES, ie: pane.size, pane.isClosed, pane.isHidden - * - * // STATE/COOKIE OPTIONS - * @example $(el).layout({ - stateManagement: { - enabled: true - , stateKeys: "east.size,west.size,east.isClosed,west.isClosed" - , cookie: { name: "appLayout", path: "/" } - } - }) - * @example $(el).layout({ stateManagement__enabled: true }) // enable auto-state-management using cookies - * @example $(el).layout({ stateManagement__cookie: { name: "appLayout", path: "/" } }) - * @example $(el).layout({ stateManagement__cookie__name: "appLayout", stateManagement__cookie__path: "/" }) - * - * // STATE/COOKIE METHODS - * @example myLayout.saveCookie( "west.isClosed,north.size,south.isHidden", {expires: 7} ); - * @example myLayout.loadCookie(); - * @example myLayout.deleteCookie(); - * @example var JSON = myLayout.readState(); // CURRENT Layout State - * @example var JSON = myLayout.readCookie(); // SAVED Layout State (from cookie) - * @example var JSON = myLayout.state.stateData; // LAST LOADED Layout State (cookie saved in layout.state hash) - * - * CUSTOM STATE-MANAGEMENT (eg, saved in a database) - * @example var JSON = myLayout.readState( "west.isClosed,north.size,south.isHidden" ); - * @example myLayout.loadState( JSON ); - */ - -/** - * UI COOKIE UTILITY - * - * A $.cookie OR $.ui.cookie namespace *should be standard*, but until then... - * This creates $.ui.cookie so Layout does not need the cookie.jquery.js plugin - * NOTE: This utility is REQUIRED by the layout.state plugin - * - * Cookie methods in Layout are created as part of State Management - */ -if (!$.ui) $.ui = {}; -$.ui.cookie = { - - // cookieEnabled is not in DOM specs, but DOES works in all browsers,including IE6 - acceptsCookies: !!navigator.cookieEnabled - -, read: function (name) { - var - c = document.cookie - , cs = c ? c.split(';') : [] - , pair // loop var - ; - for (var i=0, n=cs.length; i < n; i++) { - pair = $.trim(cs[i]).split('='); // name=value pair - if (pair[0] == name) // found the layout cookie - return decodeURIComponent(pair[1]); - - } - return null; - } - -, write: function (name, val, cookieOpts) { - var - params = '' - , date = '' - , clear = false - , o = cookieOpts || {} - , x = o.expires - ; - if (x && x.toUTCString) - date = x; - else if (x === null || typeof x === 'number') { - date = new Date(); - if (x > 0) - date.setDate(date.getDate() + x); - else { - date.setFullYear(1970); - clear = true; - } - } - if (date) params += ';expires='+ date.toUTCString(); - if (o.path) params += ';path='+ o.path; - if (o.domain) params += ';domain='+ o.domain; - if (o.secure) params += ';secure'; - document.cookie = name +'='+ (clear ? "" : encodeURIComponent( val )) + params; // write or clear cookie - } - -, clear: function (name) { - $.ui.cookie.write(name, '', {expires: -1}); - } - -}; -// if cookie.jquery.js is not loaded, create an alias to replicate it -// this may be useful to other plugins or code dependent on that plugin -if (!$.cookie) $.cookie = function (k, v, o) { - var C = $.ui.cookie; - if (v === null) - C.clear(k); - else if (v === undefined) - return C.read(k); - else - C.write(k, v, o); -}; - - -// tell Layout that the state plugin is available -$.layout.plugins.stateManagement = true; - -// Add State-Management options to layout.defaults -$.layout.config.optionRootKeys.push("stateManagement"); -$.layout.defaults.stateManagement = { - enabled: false // true = enable state-management, even if not using cookies -, autoSave: true // Save a state-cookie when page exits? -, autoLoad: true // Load the state-cookie when Layout inits? - // List state-data to save - must be pane-specific -, stateKeys: "north.size,south.size,east.size,west.size,"+ - "north.isClosed,south.isClosed,east.isClosed,west.isClosed,"+ - "north.isHidden,south.isHidden,east.isHidden,west.isHidden" -, cookie: { - name: "" // If not specified, will use Layout.name, else just "Layout" - , domain: "" // blank = current domain - , path: "" // blank = current page, '/' = entire website - , expires: "" // 'days' to keep cookie - leave blank for 'session cookie' - , secure: false - } -}; -// Set stateManagement as a layout-option, NOT a pane-option -$.layout.optionsMap.layout.push("stateManagement"); - -/* - * State Management methods - */ -$.layout.state = { - - /** - * Get the current layout state and save it to a cookie - * - * myLayout.saveCookie( keys, cookieOpts ) - * - * @param {Object} inst - * @param {(string|Array)=} keys - * @param {Object=} cookieOpts - */ - saveCookie: function (inst, keys, cookieOpts) { - var o = inst.options - , oS = o.stateManagement - , oC = $.extend(true, {}, oS.cookie, cookieOpts || null) - , data = inst.state.stateData = inst.readState( keys || oS.stateKeys ) // read current panes-state - ; - $.ui.cookie.write( oC.name || o.name || "Layout", $.layout.state.encodeJSON(data), oC ); - return $.extend(true, {}, data); // return COPY of state.stateData data - } - - /** - * Remove the state cookie - * - * @param {Object} inst - */ -, deleteCookie: function (inst) { - var o = inst.options; - $.ui.cookie.clear( o.stateManagement.cookie.name || o.name || "Layout" ); - } - - /** - * Read & return data from the cookie - as JSON - * - * @param {Object} inst - */ -, readCookie: function (inst) { - var o = inst.options; - var c = $.ui.cookie.read( o.stateManagement.cookie.name || o.name || "Layout" ); - // convert cookie string back to a hash and return it - return c ? $.layout.state.decodeJSON(c) : {}; - } - - /** - * Get data from the cookie and USE IT to loadState - * - * @param {Object} inst - */ -, loadCookie: function (inst) { - var c = $.layout.state.readCookie(inst); // READ the cookie - if (c) { - inst.state.stateData = $.extend(true, {}, c); // SET state.stateData - inst.loadState(c); // LOAD the retrieved state - } - return c; - } - - /** - * Update layout options from the cookie, if one exists - * - * @param {Object} inst - * @param {Object=} stateData - * @param {boolean=} animate - */ -, loadState: function (inst, stateData, animate) { - stateData = $.layout.transformData( stateData ); // panes = default subkey - if ($.isEmptyObject( stateData )) return; - $.extend(true, inst.options, stateData); // update layout options - // if layout has already been initialized, then UPDATE layout state - if (inst.state.initialized) { - var pane, vis, o, s, h, c - , noAnimate = (animate===false) - ; - $.each($.layout.config.borderPanes, function (idx, pane) { - state = inst.state[pane]; - o = stateData[ pane ]; - if (typeof o != 'object') return; // no key, continue - s = o.size; - c = o.initClosed; - h = o.initHidden; - vis = state.isVisible; - // resize BEFORE opening - if (!vis) - inst.sizePane(pane, s, false, false); - if (h === true) inst.hide(pane, noAnimate); - else if (c === false) inst.open (pane, false, noAnimate); - else if (c === true) inst.close(pane, false, noAnimate); - else if (h === false) inst.show (pane, false, noAnimate); - // resize AFTER any other actions - if (vis) - inst.sizePane(pane, s, false, noAnimate); // animate resize if option passed - }); - }; - } - - /** - * Get the *current layout state* and return it as a hash - * - * @param {Object=} inst - * @param {(string|Array)=} keys - */ -, readState: function (inst, keys) { - var - data = {} - , alt = { isClosed: 'initClosed', isHidden: 'initHidden' } - , state = inst.state - , panes = $.layout.config.allPanes - , pair, pane, key, val - ; - if (!keys) keys = inst.options.stateManagement.stateKeys; // if called by user - if ($.isArray(keys)) keys = keys.join(","); - // convert keys to an array and change delimiters from '__' to '.' - keys = keys.replace(/__/g, ".").split(','); - // loop keys and create a data hash - for (var i=0, n=keys.length; i < n; i++) { - pair = keys[i].split("."); - pane = pair[0]; - key = pair[1]; - if ($.inArray(pane, panes) < 0) continue; // bad pane! - val = state[ pane ][ key ]; - if (val == undefined) continue; - if (key=="isClosed" && state[pane]["isSliding"]) - val = true; // if sliding, then *really* isClosed - ( data[pane] || (data[pane]={}) )[ alt[key] ? alt[key] : key ] = val; - } - return data; - } - - /** - * Stringify a JSON hash so can save in a cookie or db-field - */ -, encodeJSON: function (JSON) { - return parse(JSON); - function parse (h) { - var D=[], i=0, k, v, t; // k = key, v = value - for (k in h) { - v = h[k]; - t = typeof v; - if (t == 'string') // STRING - add quotes - v = '"'+ v +'"'; - else if (t == 'object') // SUB-KEY - recurse into it - v = parse(v); - D[i++] = '"'+ k +'":'+ v; - } - return '{'+ D.join(',') +'}'; - }; - } - - /** - * Convert stringified JSON back to a hash object - * @see $.parseJSON(), adding in jQuery 1.4.1 - */ -, decodeJSON: function (str) { - try { return $.parseJSON ? $.parseJSON(str) : window["eval"]("("+ str +")") || {}; } - catch (e) { return {}; } - } - - -, _create: function (inst) { - var _ = $.layout.state; - // ADD State-Management plugin methods to inst - $.extend( inst, { - // readCookie - update options from cookie - returns hash of cookie data - readCookie: function () { return _.readCookie(inst); } - // deleteCookie - , deleteCookie: function () { _.deleteCookie(inst); } - // saveCookie - optionally pass keys-list and cookie-options (hash) - , saveCookie: function (keys, cookieOpts) { return _.saveCookie(inst, keys, cookieOpts); } - // loadCookie - readCookie and use to loadState() - returns hash of cookie data - , loadCookie: function () { return _.loadCookie(inst); } - // loadState - pass a hash of state to use to update options - , loadState: function (stateData, animate) { _.loadState(inst, stateData, animate); } - // readState - returns hash of current layout-state - , readState: function (keys) { return _.readState(inst, keys); } - // add JSON utility methods too... - , encodeJSON: _.encodeJSON - , decodeJSON: _.decodeJSON - }); - - // init state.stateData key, even if plugin is initially disabled - inst.state.stateData = {}; - - // read and load cookie-data per options - var oS = inst.options.stateManagement; - if (oS.enabled) { - if (oS.autoLoad) // update the options from the cookie - inst.loadCookie(); - else // don't modify options - just store cookie data in state.stateData - inst.state.stateData = inst.readCookie(); - } - } - -, _unload: function (inst) { - var oS = inst.options.stateManagement; - if (oS.enabled) { - if (oS.autoSave) // save a state-cookie automatically - inst.saveCookie(); - else // don't save a cookie, but do store state-data in state.stateData key - inst.state.stateData = inst.readState(); - } - } - -}; - -// add state initialization method to Layout's onCreate array of functions -$.layout.onCreate.push( $.layout.state._create ); -$.layout.onUnload.push( $.layout.state._unload ); - - - - -/** - * jquery.layout.buttons 1.0 - * $Date: 2011-07-16 08:00:00 (Sat, 16 July 2011) $ - * - * Copyright (c) 2010 - * Kevin Dalman (http://allpro.net) - * - * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html) - * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses. - * - * @dependancies: UI Layout 1.3.0.rc30.1 or higher - * - * @support: http://groups.google.com/group/jquery-ui-layout - * - * Docs: [ to come ] - * Tips: [ to come ] - */ - -// tell Layout that the state plugin is available -$.layout.plugins.buttons = true; - -// Add buttons options to layout.defaults -$.layout.defaults.autoBindCustomButtons = false; -// Specify autoBindCustomButtons as a layout-option, NOT a pane-option -$.layout.optionsMap.layout.push("autoBindCustomButtons"); - -/* - * Button methods - */ -$.layout.buttons = { - - /** - * Searches for .ui-layout-button-xxx elements and auto-binds them as layout-buttons - * - * @see _create() - * - * @param {Object} inst Layout Instance object - */ - init: function (inst) { - var pre = "ui-layout-button-" - , layout = inst.options.name || "" - , name; - $.each("toggle,open,close,pin,toggle-slide,open-slide".split(","), function (i, action) { - $.each($.layout.config.borderPanes, function (ii, pane) { - $("."+pre+action+"-"+pane).each(function(){ - // if button was previously 'bound', data.layoutName was set, but is blank if layout has no 'name' - name = $(this).data("layoutName") || $(this).attr("layoutName"); - if (name == undefined || name === layout) - inst.bindButton(this, action, pane); - }); - }); - }); - } - - /** - * Helper function to validate params received by addButton utilities - * - * Two classes are added to the element, based on the buttonClass... - * The type of button is appended to create the 2nd className: - * - ui-layout-button-pin // action btnClass - * - ui-layout-button-pin-west // action btnClass + pane - * - ui-layout-button-toggle - * - ui-layout-button-open - * - ui-layout-button-close - * - * @param {Object} inst Layout Instance object - * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" - * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. - * - * @return {Array.} If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise returns null - */ -, get: function (inst, selector, pane, action) { - var $E = $(selector) - , o = inst.options - , err = o.errors.addButtonError - ; - if (!$E.length) { // element not found - $.layout.msg(err +" "+ o.errors.selector +": "+ selector, true); - } - else if ($.inArray(pane, $.layout.config.borderPanes) < 0) { // invalid 'pane' sepecified - $.layout.msg(err +" "+ o.errors.pane +": "+ pane, true); - $E = $(""); // NO BUTTON - } - else { // VALID - var btn = o[pane].buttonClass +"-"+ action; - $E .addClass( btn +" "+ btn +"-"+ pane ) - .data("layoutName", o.name); // add layout identifier - even if blank! - } - return $E; - } - - - /** - * NEW syntax for binding layout-buttons - will eventually replace addToggle, addOpen, etc. - * - * @param {Object} inst Layout Instance object - * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" - * @param {string} action - * @param {string} pane - */ -, bind: function (inst, selector, action, pane) { - var _ = $.layout.buttons; - switch (action.toLowerCase()) { - case "toggle": _.addToggle (inst, selector, pane); break; - case "open": _.addOpen (inst, selector, pane); break; - case "close": _.addClose (inst, selector, pane); break; - case "pin": _.addPin (inst, selector, pane); break; - case "toggle-slide": _.addToggle (inst, selector, pane, true); break; - case "open-slide": _.addOpen (inst, selector, pane, true); break; - } - return inst; - } - - /** - * Add a custom Toggler button for a pane - * - * @param {Object} inst Layout Instance object - * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" - * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. - * @param {boolean=} slide true = slide-open, false = pin-open - */ -, addToggle: function (inst, selector, pane, slide) { - $.layout.buttons.get(inst, selector, pane, "toggle") - .click(function(evt){ - inst.toggle(pane, !!slide); - evt.stopPropagation(); - }); - return inst; - } - - /** - * Add a custom Open button for a pane - * - * @param {Object} inst Layout Instance object - * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" - * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. - * @param {boolean=} slide true = slide-open, false = pin-open - */ -, addOpen: function (inst, selector, pane, slide) { - $.layout.buttons.get(inst, selector, pane, "open") - .attr("title", inst.options[pane].tips.Open) - .click(function (evt) { - inst.open(pane, !!slide); - evt.stopPropagation(); - }); - return inst; - } - - /** - * Add a custom Close button for a pane - * - * @param {Object} inst Layout Instance object - * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" - * @param {string} pane Name of the pane the button is for: 'north', 'south', etc. - */ -, addClose: function (inst, selector, pane) { - $.layout.buttons.get(inst, selector, pane, "close") - .attr("title", inst.options[pane].tips.Close) - .click(function (evt) { - inst.close(pane); - evt.stopPropagation(); - }); - return inst; - } - - /** - * Add a custom Pin button for a pane - * - * Four classes are added to the element, based on the paneClass for the associated pane... - * Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin: - * - ui-layout-pane-pin - * - ui-layout-pane-west-pin - * - ui-layout-pane-pin-up - * - ui-layout-pane-west-pin-up - * - * @param {Object} inst Layout Instance object - * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button" - * @param {string} pane Name of the pane the pin is for: 'north', 'south', etc. - */ -, addPin: function (inst, selector, pane) { - var _ = $.layout.buttons - , $E = _.get(inst, selector, pane, "pin"); - if ($E.length) { - var s = inst.state[pane]; - $E.click(function (evt) { - _.setPinState(inst, $(this), pane, (s.isSliding || s.isClosed)); - if (s.isSliding || s.isClosed) inst.open( pane ); // change from sliding to open - else inst.close( pane ); // slide-closed - evt.stopPropagation(); - }); - // add up/down pin attributes and classes - _.setPinState(inst, $E, pane, (!s.isClosed && !s.isSliding)); - // add this pin to the pane data so we can 'sync it' automatically - // PANE.pins key is an array so we can store multiple pins for each pane - s.pins.push( selector ); // just save the selector string - } - return inst; - } - - /** - * Change the class of the pin button to make it look 'up' or 'down' - * - * @see addPin(), syncPins() - * - * @param {Object} inst Layout Instance object - * @param {Array.} $Pin The pin-span element in a jQuery wrapper - * @param {string} pane These are the params returned to callbacks by layout() - * @param {boolean} doPin true = set the pin 'down', false = set it 'up' - */ -, setPinState: function (inst, $Pin, pane, doPin) { - var updown = $Pin.attr("pin"); - if (updown && doPin === (updown=="down")) return; // already in correct state - var - o = inst.options[pane] - , pin = o.buttonClass +"-pin" - , side = pin +"-"+ pane - , UP = pin +"-up "+ side +"-up" - , DN = pin +"-down "+side +"-down" - ; - $Pin - .attr("pin", doPin ? "down" : "up") // logic - .attr("title", doPin ? o.tips.Unpin : o.tips.Pin) - .removeClass( doPin ? UP : DN ) - .addClass( doPin ? DN : UP ) - ; - } - - /** - * INTERNAL function to sync 'pin buttons' when pane is opened or closed - * Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes - * - * @see open(), close() - * - * @param {Object} inst Layout Instance object - * @param {string} pane These are the params returned to callbacks by layout() - * @param {boolean} doPin True means set the pin 'down', False means 'up' - */ -, syncPinBtns: function (inst, pane, doPin) { - // REAL METHOD IS _INSIDE_ LAYOUT - THIS IS HERE JUST FOR REFERENCE - $.each(inst.state[pane].pins, function (i, selector) { - $.layout.buttons.setPinState(inst, $(selector), pane, doPin); - }); - } - - -, _load: function (inst) { - var _ = $.layout.buttons; - // ADD Button methods to Layout Instance - // Note: sel = jQuery Selector string - $.extend( inst, { - bindButton: function (sel, action, pane) { return _.bind(inst, sel, action, pane); } - // DEPRECATED METHODS - , addToggleBtn: function (sel, pane, slide) { return _.addToggle(inst, sel, pane, slide); } - , addOpenBtn: function (sel, pane, slide) { return _.addOpen(inst, sel, pane, slide); } - , addCloseBtn: function (sel, pane) { return _.addClose(inst, sel, pane); } - , addPinBtn: function (sel, pane) { return _.addPin(inst, sel, pane); } - }); - - // init state array to hold pin-buttons - for (var i=0; i<4; i++) { - var pane = $.layout.config.borderPanes[i]; - inst.state[pane].pins = []; - } - - // auto-init buttons onLoad if option is enabled - if ( inst.options.autoBindCustomButtons ) - _.init(inst); - } - -, _unload: function (inst) { - // TODO: unbind all buttons??? - } - -}; - -// add initialization method to Layout's onLoad array of functions -$.layout.onLoad.push( $.layout.buttons._load ); -//$.layout.onUnload.push( $.layout.buttons._unload ); - - - -/** - * jquery.layout.browserZoom 1.0 - * $Date: 2011-12-29 08:00:00 (Thu, 29 Dec 2011) $ - * - * Copyright (c) 2012 - * Kevin Dalman (http://allpro.net) - * - * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html) - * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses. - * - * @dependancies: UI Layout 1.3.0.rc30.1 or higher - * - * @support: http://groups.google.com/group/jquery-ui-layout - * - * @todo: Extend logic to handle other problematic zooming in browsers - * @todo: Add hotkey/mousewheel bindings to _instantly_ respond to these zoom event - */ - -// tell Layout that the plugin is available -$.layout.plugins.browserZoom = true; - -$.layout.defaults.browserZoomCheckInterval = 1000; -$.layout.optionsMap.layout.push("browserZoomCheckInterval"); - -/* - * browserZoom methods - */ -$.layout.browserZoom = { - - _init: function (inst) { - // abort if browser does not need this check - if ($.layout.browserZoom.ratio() !== false) - $.layout.browserZoom._setTimer(inst); - } - -, _setTimer: function (inst) { - // abort if layout destroyed or browser does not need this check - if (inst.destroyed) return; - var o = inst.options - , s = inst.state - // don't need check if inst has parentLayout, but check occassionally in case parent destroyed! - // MINIMUM 100ms interval, for performance - , ms = inst.hasParentLayout ? 5000 : Math.max( o.browserZoomCheckInterval, 100 ) - ; - // set the timer - setTimeout(function(){ - if (inst.destroyed || !o.resizeWithWindow) return; - var d = $.layout.browserZoom.ratio(); - if (d !== s.browserZoom) { - s.browserZoom = d; - inst.resizeAll(); - } - // set a NEW timeout - $.layout.browserZoom._setTimer(inst); - } - , ms ); - } - -, ratio: function () { - var w = window - , s = screen - , d = document - , dE = d.documentElement || d.body - , b = $.layout.browser - , v = b.version - , r, sW, cW - ; - // we can ignore all browsers that fire window.resize event onZoom - if ((b.msie && v > 8) - || !b.msie - ) return false; // don't need to track zoom - - if (s.deviceXDPI) - return calc(s.deviceXDPI, s.systemXDPI); - // everything below is just for future reference! - if (b.webkit && (r = d.body.getBoundingClientRect)) - return calc((r.left - r.right), d.body.offsetWidth); - if (b.webkit && (sW = w.outerWidth)) - return calc(sW, w.innerWidth); - if ((sW = s.width) && (cW = dE.clientWidth)) - return calc(sW, cW); - return false; // no match, so cannot - or don't need to - track zoom - - function calc (x,y) { return (parseInt(x,10) / parseInt(y,10) * 100).toFixed(); } - } - -}; -// add initialization method to Layout's onLoad array of functions -$.layout.onReady.push( $.layout.browserZoom._init ); - - - -})( jQuery ); diff --git a/nebula-exchange/target/site/scaladocs/lib/modernizr.custom.js b/nebula-exchange/target/site/scaladocs/lib/modernizr.custom.js deleted file mode 100644 index 4688d63..0000000 --- a/nebula-exchange/target/site/scaladocs/lib/modernizr.custom.js +++ /dev/null @@ -1,4 +0,0 @@ -/* Modernizr 2.5.3 (Custom Build) | MIT & BSD - * Build: http://www.modernizr.com/download/#-inlinesvg - */ -;window.Modernizr=function(a,b,c){function u(a){i.cssText=a}function v(a,b){return u(prefixes.join(a+";")+(b||""))}function w(a,b){return typeof a===b}function x(a,b){return!!~(""+a).indexOf(b)}function y(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:w(f,"function")?f.bind(d||b):f}return!1}var d="2.5.3",e={},f=b.documentElement,g="modernizr",h=b.createElement(g),i=h.style,j,k={}.toString,l={svg:"http://www.w3.org/2000/svg"},m={},n={},o={},p=[],q=p.slice,r,s={}.hasOwnProperty,t;!w(s,"undefined")&&!w(s.call,"undefined")?t=function(a,b){return s.call(a,b)}:t=function(a,b){return b in a&&w(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=q.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(q.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(q.call(arguments)))};return e}),m.inlinesvg=function(){var a=b.createElement("div");return a.innerHTML="",(a.firstChild&&a.firstChild.namespaceURI)==l.svg};for(var z in m)t(m,z)&&(r=z.toLowerCase(),e[r]=m[z](),p.push((e[r]?"":"no-")+r));return u(""),h=j=null,e._version=d,e}(this,this.document); \ No newline at end of file diff --git a/nebula-exchange/target/site/scaladocs/lib/navigation-li-a.png b/nebula-exchange/target/site/scaladocs/lib/navigation-li-a.png deleted file mode 100644 index 9b32288e045cd94e6aaa0e35f1382a32b66b64da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1198 zcmV;f1X25mP)0Ed!4I%dZ`*&Mwa}$^y=pHO+G~4PFP7cgqNtZ$C@d7b6ueY6EfuxhrRxTb z)T~ya&4-y}ob2<=X3~k7NxbNd&;u{Yob#Obyyrdd`As60N+sbYO%iU{{(GSei@|cR zGuS!IGHA!t)YSc>qoYVJmkV`tbOa?y%A-GH<cUdUK5PPe5tZ@r@f1t2MrgzaZ_?1v&`X^EOYTd)E}{V5 zBrKVnoSggx-ATO$jP%fpVLd%Pujc0F5{5_@ayADsL3F#_>Dk%Yz5f3G7Z^K)6)Qpn zoJ9)q;cz%LF)?w9y#0>;RLvb1c-_vPEfnk7>VDetXch|w0?yBgaf#`E?QVv5aiCz&KRmDhNAfN^78T-K0o8c>nA1wPy%=( z5O)C7Bna^FIwN@nhG5-_N*fR(<+ zq>qj3TywAajG8nc@EFK`im!TA3)hW85RIX9A?8oY4r+x)7>pTN`NDE(b3=>*Kswq` zNUzwar=gJ9Ku*PmLY@vbr8N{X*`Qgbp%6vFqur}3(J40bgKfgu z08jxxn!Z|ES}Ii0%)Df8Z?DkT*Y{|3b@d57S1nymg#dUKQ9<9L>pLLu-{j-%q}L*f zRsa{DVTI4v*4BQbh?6UYJ3Ku6bNMgH6WG(0l@54P5=M^ M07*qoM6N<$g5>W?*#H0l diff --git a/nebula-exchange/target/site/scaladocs/lib/navigation-li.png b/nebula-exchange/target/site/scaladocs/lib/navigation-li.png deleted file mode 100644 index fd0ad06e819742b15f3a982a9b2e50bbaa886a1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2441 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 TK(qrA00000NkvXXu0mjfp!~2x diff --git a/nebula-exchange/target/site/scaladocs/lib/object_diagram.png b/nebula-exchange/target/site/scaladocs/lib/object_diagram.png deleted file mode 100644 index 6e9f2f743f67c15e04846f14819a913713b216e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3903 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 N002ovPDHLkV1kt{Q<4Ax diff --git a/nebula-exchange/target/site/scaladocs/lib/object_to_class_big.png b/nebula-exchange/target/site/scaladocs/lib/object_to_class_big.png deleted file mode 100644 index 7502942eb68134f5569c5c00e84533f452093c43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9158 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 Qv;Y7A07*qoM6N<$f);0?GXMYp diff --git a/nebula-exchange/target/site/scaladocs/lib/object_to_trait_big.png b/nebula-exchange/target/site/scaladocs/lib/object_to_trait_big.png deleted file mode 100644 index c777bfce8dd0a169f484641a3f439720fd23c427..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9200 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 Qv;Y7A07*qoM6N<$f);0?GXMYp diff --git a/nebula-exchange/target/site/scaladocs/lib/ownderbg2.gif b/nebula-exchange/target/site/scaladocs/lib/ownderbg2.gif deleted file mode 100644 index 848dd5963a133dc18b9f055928150dc5e762dde0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1145 zcmZ?wbhEHbWMq(F*v!D-Kff?yQ@u%!Pt?vPr`9;D%FyV&t)7!JLsnHrA8cd50E+*) zBYXoCToOwXfwYZ%ML}Y6c4~=2Qfhi;o~_dR-TRdkGE;1o!cBb*d<&dYGcrA@ic*8C z{6dnevXd=SlxV%Qmue&kg&dz0$52&wylyQ zNJ0T*r*nQ$s)DJWfo`&anSp|tp`M|!iMhGCj)IYap@F`Ek-njkuA#Y=v5}R5fdUjL z0c|TvNwW%aaf8|g1^l#~=$>Fbx5m+O@q>*W`v>l<2HT7t|lGSUUA&@HaaD@m-- z%_~-hnc$LIoLrPyP?DLSrvNfBF)6>a#8wIDQivCF3*g4)73+b$qnDhYt6z~=pl_&W z0P+${p|3A~rMbCq)x{-2sR;LCHMlsWvLIDID784hv?w_hs9YIjRe_arQEFmIeo;t% zehw@Y12XbU@{2R_3lyA#O%;3-lQZ)`e6V_7Un|eN;*!L?t5X6BYAPL3ueX-RQWVL^UgZccVqW=48iYD#iaVnTdeY)o`iWJGvaXh?8SV1U1$uaCEv zr-!?ntBbRfql3Mjt&O#nrG>efsfn=>FiYv_>S$|eYN)HJswgWdD#**p%1BE|N{EYz ziUvE+||Kg4FF`M Bj3xj8 diff --git a/nebula-exchange/target/site/scaladocs/lib/ownerbg.gif b/nebula-exchange/target/site/scaladocs/lib/ownerbg.gif deleted file mode 100644 index 34a04249ee9edc75662a2539fe7daa04424cbe8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1118 zcmZ?wbhEHbWMq(FSj50^;>3wdmoDwuvuDGG4L5JzWPkz1|J)J20SYdOC5b@V#=fE; zF*!T6L?J0PJu}Z%>HY5gN(z}Nwo2iqz6QPp&Z!xh9#uuD!Bu`C$yM3OmMKd1b_zBX zRu#Dgxv3?I3Kh9IdBs*0wn~X9`AMl(KsHENUr7P1q$Jx`$q^)>0J76LzbI9~RL?*+ z*}%*|!OT$4(AdP>++0V&$iUD*-@r)U&`8(N+{)O<%D_MY3Y37h6{VzE1-ZCE?E>;_ zl`=|73as??%gf94%8m8%i_-NCEiElUW*8ai0#)c1SLT%@R_NvxE5l51Ni9w;$}A|! z%+FH*nV6WAUs__T1av9H3%LbwWAlpjz~0eI&d=4aNG#Ad)H48i38v837r)ZnT)67u zlAu(Cd$Af^98y`3svneEoL^d$oC;K~46>@g%DE^tu_V7JBtJg~7K#BG`6cQEUIa|mjQ{`r z{qy_R&mZ5vef{$J)5j0*-@SeF`qj%9&!0Vg^7zri2lwyYy>t84%^TORUA=Po(!~qs z&z(JU`qar2$B!L7a`@1}1N-;w-Lrew&K=vgZQZhY)5ZeMTG_V zdAT{+S(zE>X{jm6Nr?&Zaj`McQIQehVWAmo_rKzE=rmCW>q^KY-Co3Z@B`F~;CMqH&FX#K^#)_>%=(Oz40}P&vZD%P=Ep@ zplwAdX;wilZcw{`JX@uVl9B=|ef{$Ca=mh6z5JqdeM3u2OOP2xM!G;1y2X`wC5aWf zdBw^w6I@b@lZ!G7N;32F6hI~>Cgqow*eU^C3h_d20o>TUVm+{T^pf*)^(zt!^bPe4 zKwg3=^!3HBG&dKny0|1L72#g21{a4^7NqJ2r55Lx7A2%-qt%$eX-RQWVL^UgZccVqW=48iYD#iaVnTdeY)o`iWJGva zXh?8SV1U1$uaCEvr-!?ntBbRfql3Mjt&KG>(#*|FO^l6zSxQe=M_Wr%LtRZ(MOjHv zL0(Q)Mp{ZzLR?H#L|8~rfS-?-hntI&gPo0)g_((wfkE*n3%I<{0g<5cg@J|3;H2kk MO(h-&o-PJ!02;c9Qvd(} diff --git a/nebula-exchange/target/site/scaladocs/lib/package.png b/nebula-exchange/target/site/scaladocs/lib/package.png deleted file mode 100644 index 6ea17ac320ec13c02680c5549cf496d007ea6acf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3335 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 Y0AfCQM(Z-J8vp 0) { - var fn = scheduler.queues[idx].shift(); - } - return fn; - } - this.add = function(labelName, fn, self, args) { - var doWork = function() { - scheduler.timeout = setTimeout(function() { - var work = scheduler.nextWork(); - if (work != undefined) { - if (work.args == undefined) { work.args = new Array(0); } - work.fn.apply(work.self, work.args); - doWork(); - } - else { - scheduler.timeout = undefined; - } - }, resolution); - } - var idx = 0; - while (idx < scheduler.labels.length && scheduler.labels[idx].name != labelName) { idx = idx + 1; } - if (idx < scheduler.queues.length && scheduler.labels[idx].name == labelName) { - scheduler.queues[idx].push(new scheduler.work(fn, self, args)); - if (scheduler.timeout == undefined) doWork(); - } - else throw("queue for add is non existant"); - } - this.clear = function(labelName) { - var idx = 0; - while (idx < scheduler.labels.length && scheduler.labels[idx].name != labelName) { idx = idx + 1; } - if (idx < scheduler.queues.length && scheduler.labels[idx].name == labelName) { - scheduler.queues[idx] = new Array(); - } - } -}; diff --git a/nebula-exchange/target/site/scaladocs/lib/selected-implicits.png b/nebula-exchange/target/site/scaladocs/lib/selected-implicits.png deleted file mode 100644 index bc29efb3e60134039e702d5449e685a3bc103f06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1150 zcmV-^1cCdBP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyb% z5H~J^JxS;Q00aI>L_t(|+U?vuZxlxy$MNqx?(E$@E}a zfjgk2pr?ZZI(iC9{1RM5N`az8f(nF?5D#);fpbJL7e%q}e0%#alfpQ%40!>*o6k0< z)o$~be)`Ys+>8hzu;10IR{^+p@16iY2d04rkO6`yI{X6A1$Kbce*=Su~m%6x<};NBO|^=w zk&&8I8D)eJLdB9s!^&AlTBkBiQk->uv$J_(rL!`)+`6oQUo`M-?(?sntUozBH8I6_ zIxd}cS_u`9v4GL=Q$k^s5ms8Mgc48JpPpKtTHbQf?P%cW>elMKv(Ak-$BSmt)JB*% z&xl4SAz&~lr34aLhuW=ft3By}IX+c#V!libhr?D})eoI+@M^s{y;vSm62A^F$)OitB>WC^wMc2_eXZ#=?IA zNtVo#TvKb>y}k`n5t#j!>IqWhwOAZQtfS?qODbc_%JAp{Bv5|M;+$+>D$O;$h+90zjvct@cD=76Um1hr9bhBs%or0LWw(j4&M0NBo?c3qpt*ILGd`+j8&ukM^WrzkZ!NckX<_?$*Qo z%j$87JsKwA!0%(gp9dfM)S(Ug1JPplRFf1Ki#3gg$o7X})F#m3e@->|7sOS0SbEhV Q8UO$Q07*qoM6N<$f{R8S_y7O^ diff --git a/nebula-exchange/target/site/scaladocs/lib/selected-right-implicits.png b/nebula-exchange/target/site/scaladocs/lib/selected-right-implicits.png deleted file mode 100644 index 8313f4975b4e7191d18183adcd8de77659622874..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 646 zcmV;10(t$3P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyb% z5H~yS;H?7y00IU{L_t(2&vlbOOIu+S#((eM`{pLzge0aSMr^2qDdNx~brL!h$3j7H z=vW-w3a;+`2(EsF7W@=C3J!%zHAAgkY^&GY>pfj!nreDpp6v(E!+Xx7MC2K81$+m7 zY;JA}!0zrYqoX!HZG4C;@vnu)3ujyHtzOXK7&rxF6g124mS1OCmYnuZ+xuVlXOgMJ zc6`SIH$XZB*WRzaisM*(@Q6t1;PXM}h@;wSWAz%)z$JjLPE>VcqCu%&tubaS2&iC#PW!0_66=%;<0xw^{i3hE^%|)B*O~&n z_No#p0t9Or59T^YDWxZ)$rSL`sPP#KDG(7o7tf`4A3h$uEr?7cOKwR6k+oR=z_!RK zib5?;EM6I9H1O7H{;seXyi77R9j3Fc?F#S)IJZhEKbk8qa%RJ9KCtw_HwGuc_mMD0-%8I-SJwdoORkUZ|94)X^T?I0M7??$cDj1@Kjbd8waHTjq5uE@07*qoM6N<$g8d5^?*IS* diff --git a/nebula-exchange/target/site/scaladocs/lib/selected-right.png b/nebula-exchange/target/site/scaladocs/lib/selected-right.png deleted file mode 100644 index 04eda2f3071a81ada129b906e60709eb5b1c4e29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1380 zcmeAS@N?(olHy`uVBq!ia0vp^AhtLM8;~@ry7vP}NtU=qlmzFem6RtIr7}3C)9WTXpJp<7&;SCUwvn^&w1Gr=XbIJqdZpd>RtPXT0NVp4u- ziLDaQr4TRV7Ql_oD~1LWFu?RH5)1SV^$b8>f+_U%#ji9s7p}UvBq$Z(UaSTehg24% z>IbD3=a&{G10ya?8Dv#~m2**QVo82cNPd0}EEEGW@=NlIGx7@*oP$jjd=ry1^FVyC zdS72F&%EN2#JuEGPZwJypb2`JnJHGz78Y(MCeDVYmgbIzhOP!qZqAm@u103&mL^V) zCPpSOy)OC5rManjB{01y2)#x)^@5T@ZUN9{m(-%nveXo}qWoM1u$Qeeak|CH4X1ff zy(zfeVt`YxKF~4xpom3^XqXT%^?;c0WDDfL6MkwQFtrx}ll6<;A<7I4j5j=8978H@ z)dcU&QVNvVTm1ao`79at5FR1swyg%5$;tYPy#hCG-BSM`+EU9h|6u!#OUJxif~2?K zxN4GUe$wFaojJf9z)p z5$Ey};}0o`4QH}B9yFW z>98SDtSD?}jGxoZxo6X!U$AKQw|sQq!}8b$jjl6i(~7%3uRQeB{zzBi?B~JhyI$eR9CQS uH6MIndtb!u6IcAC@Ew*lAuIQC8Zg|Lxqpi1i6>#8a?jJ%&t;ucLK6TZv;Euv diff --git a/nebula-exchange/target/site/scaladocs/lib/selected.png b/nebula-exchange/target/site/scaladocs/lib/selected.png deleted file mode 100644 index c89765239e074f40ac120c7429b5d65a47dc218d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1864 zcmaJ?c~BEq91ceTBSb(%MUFLype4yBBtTLE0s#pnDTc!!APL!pL`ZhCSs~!4NQ)J% zjYlz75elf(`(i|jO7Osgf;y;Fj)H?0s2weyqg2|B3iglEo!Ncw_vZV)-}ip+_hw7u z#fu%tZe$XP z91$o&BVnZ~rVxV@3dMnm*8Y~u#K+tpr8eFcYX>{J>3IbTC zz*H!%LNtI`QJ#sc#Q9Xh>H96H(Fs|N?n9Y~f-&@Rl)L{K0yfdh!-3YEqj zzr%|}JfTL1%QXsEDBx2G1-eQF@z`8Wa5TsX=5T|!OlA}q5go~mjA8`_aoG{!Y!-W* zD?k)0)vyL1=RzO3+)26SR#2lvW&w<;@?a<$L)5^#E%Q{9dkLIW?*kW_+)L1;Tn1r= zVLsS@9rXAT(LLtrMB5U%^S)m|2QQ!4P`HdBBOI%t8E8By$ z)tP&nmBpWMprzkM_|>^sro&sKcBBkCJasJiG9=P9#hP5QNL2+TkyCcgr_WpFbHr7_ z87m!#YYJH5*b!RP{<^=_J_~2|c=d7fAA8(7t(HqhM@QR7hK6D;&9z@F^LTl&+LYOL zUU{>=KQOIits!(3RqM9J$$Df>Q`4Hfywlrm3@To|dNr2U=+QrVeb>z4pMI4}rAnXe z*Su0wQ(?oEXC7Y0{o&u+%(Fh0o}PZBvZ5lZ@LWaJ!Gk4?)RX?H)qdpTZS_XZsax{y z_MKk#HqH@?F3d85ExWtByE8h5+2NQ~XRSrmZE49;u~@u3JtM<+b!er-?p^yG>?l!7 z)@R5TNdqW$9-&m@9!cz z)|KJ#YjcI$M2lT>D1eiHE7md=9Cb6o??`g%oXydj8XFrc(Rq-nRo~Dc92oPqc4`7jYVX4t*9L^0KwY`(Dn^c;fmUh^Z+y;JQ``m+ENO>F}JvzOG zpA_eOow0f6Rfv^j2{j}iqIq*6)BTacb1Yxm)_q06>xylb&!4}+!4jGxigiTeRX*Cn z<30Wx9WD2E4BzxN*jb#kdlW+%OtH1PfPLmI3$H$qQEoeA@M_zz(dMBx)_57yUHsNs zdvF1nVkziYxo1DV=eKeTc|*$c+^@3gOx8(~UC-Pht#*mPtJ;FH$u9Fm&%)M|KTg|f z5*U9$Nu>g6#DPS~Y)4n$4Wb>UOWwc=wp*D7L1rwgy--9rSyofByyv~cY4K+bR|b+B z((YQ6@^?+kI+3=oS=N8}mgQ8nYNyMpfy*0n{`@+ksvim5?MYSE)$MuW)=GnC(9&ES zE)MxRPw9$#K{-F$s=Aq5o>LYZb)fSRyT%9IcD!es`-6BtsJf2jWPf{YuBrE$LxQ!? zVn<`|QHj6njN1xoI7>WT>~c56r$ss7B6`$yLi+Pwn&+jdS}L$Vm@DT=KyDXF%TVr`iW&f2@9*rcCpU*G%kN@v);?Q2jJaQE~K zoxVPGny*U6lIkvBzs-GdKdhGVrt|YT^Vdn8*CU*fW}Ci*yY2_L3v1RibMA*BoY$Y4 ZNDtm_>Mc9CX5mbjz-9e{{de~$lm|} diff --git a/nebula-exchange/target/site/scaladocs/lib/selected2-right.png b/nebula-exchange/target/site/scaladocs/lib/selected2-right.png deleted file mode 100644 index bf984ef0bac9acacf732a22f6dbb9f648a6dc26a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1434 zcmeAS@N?(olHy`uVBq!ia0vp^JU}eY!3HGlQ`YSVQj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS=07?_nZLn2Bde0{8v^Ko2Tt~skz|cV7z)0WFNY~KZ%Gk)tz(4^Clz_GsrKDK}xwt{?0`hE?GD=Dctn~HE z%ggo3jrH=2()A53EiFN27#ZmTRp=I1=9MH?=;jqG!%T2VElw`VEGWs$&r<-In3$Ab zT4JjNbScCOxdm`z^NOLt1Pn0!io^naLp=kKmtYEgeeo;J&4sHjE(uCSxEHIz#UYgi zsro^w#rdU0$-sz9QwCX8VC7ttnpl!w6q28x0}I7~jQo=P;*9(P1?ON>1>eNv%sdbu ztlrnx$}_LHBrz{J)zigR321^|W@d_&iKVH9n}Ml`sinE4p`ojRlbf@pv#XJrxuuDd zqlu9TOs`9Ra%paAUI|QZ3PP_bPQ9R{kXrz>*(J3ovn(~mttdZN0qkX~Oe}7(Ft;>z zbaFKYnrDICEfBpaSlj~D3-Skcz4}1M=z}5_DWYLQz|;d`!jmnK15fy=dBD_O1WeXN zFSNEXFfj3Xx;TbZ-0BJTJuQ?dve&rp{{2Ne1Xv0M^`dqN6o#(7v-^@5ry`4P^EBOC zzl3jzHSWk1W|3sw);Ue+g;U^>O>?#=UP&uCcCNM}UQqY`_d|&fD$mXQ{c(==)z@ET z6-8WsJ}cX8&(eI*ZD~+t^J3nFi-8`!Zq6JfvCFS!sWLo#9-#4MO^n|D15*n%rrdh_ z?c64vTY1}4B-qwo&yLa&V>QjXcQ{Ddg|Gg%9v?OhmP@U{K>-_Wb*=L_APe@*L{q(Jr$a~Dp z0uLUnIsEVgw zb^Gh3!#nG_`dl;Ss7o9b$omss5Haua%O~3xUd$-@yryCEjht$dO0588|FJa{;N_gy{FZdcQZ9v{BdisYp- zHJ`kr@ZNF#_2kvBmj=Bo*P0sDSkC@KndR}v2pt}MKL2LzQ)!#4?B=IGa(;02XkB+e z+UA+9e^cKCtnU1>r)$si?G5_sWsaKjKm0w#%lN*ryrD|bs&hXR4};S~mM6aHstZA- NrKhW(%Q~loCIFxO8+`x( diff --git a/nebula-exchange/target/site/scaladocs/lib/selected2.png b/nebula-exchange/target/site/scaladocs/lib/selected2.png deleted file mode 100644 index a790bb1169b6b54de1d51f7778ee552979f52183..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1965 zcmeAS@N?(olHy`uVBq!ia0vp^CxBR-gAGXf88D;(DajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_cg49rTIArU1JzCKpT`MG+DAT@dwxdlMo3=B5*6$OdO*{LN8 zNvY|XdA3ULckfqH$V{%1*XSQL?vFu&J;D8jzb> zlBiITo0C^;Rbi_HHrEQs1_|pcDS(xfWZNo192Makpx~Tel&WB=XP}#GU}m6TW~gUq zY+`P1uA^XNU}&IkV5Dzoq-$tyWo%?+V4wg6Nh+i#(Mch>H3D2mX;thjEr=FDs+o0^GXscbn}XpVJ5hw7AF^F7L;V>=P7_pOiaoz zEwNPsx)kDt+yc06!V;*iRM zRQ;gT;{4L0WMIUlDTAykuyQU+O)SYT3dzsUfrVl~Mt(_taYlZDf^)E`f^TASW*&$S zR`2U;<(XGpl9-pA>gi&u1T;Y}Gc(1?!rao>(aF`&)Y9C-(9qSu$<5i)+11F*+|tC! z(Zt9Erq?AuximL5uLPzy1)LqEuE@a9jJa{g3^D*&Fs~}@sPg}hA3HW}*bs2zZP}lLlevA=_U-n$=5&5bna|Ro zr2Kq;ZlP0ibWR_hJ9lpWiz!uc8tF`mg%K|cGE-8Xi0*W2U!-y9WyzzY#H~@SH*>@$ zseF`8+a!0Y?a0N869Ym+-@Jd{U1771b?3>~^XAPvzD32YutZHj$X%{hPhM8G*7Ie^ z?(45b`P!X@+s~$5zT+&;Zp|_IEnicE2OmGbsk)-GK&Ok7i<02OvfcN~%FFGSFVz;w zJpHni>#DT=iM(5&U57r%J7!PHj4vV0>!_hwa)V3FU5<)V5Wtj)rUr z_x@OMhrMuthvj{s_~K>J23#ctD--tXEDh3}dGw%xx?U5Hm;SAjt|^^YCOO8>;4W(W z`B>!wi)4Fbk%f#_R5Z`wIShpf%kMrdS{am?`BMMP;)KgC^MezCb}+X!3X04>KYc=0 zR#uX=we_tFVODdWSs#%Qo55lt(Cc>b)!)p`H+`n$c~0B4YuEdQ0Un!0#W<5w8WS1> zjU#(|d+lGSYu^gc9Ub-|XBRjj>V(vLdtFNI}x@X#@rKBc({rdHG zadB}{adEJA$PLdKG5RM0gA$&|svdjvXi-LPZg17zxGkmW8{DepS^O^EzhB?FuRbCo zqQKAJ|8#0<>Y`n{qHYIXSzdKBa7IiaPpnJ@zlsD;l83n~+r%|1R@_*u>MJ6h&ct{_ z=H=_x!7m;MuX2_MXn9M_J+Cm-hTNpH>=mNsC<9kP)$a(UEUF`RJRVHGw%nH4A_E h2-=FCwErWPz_6w1NS~Nz6ep+x^>p=fS?83{1OQq_0~!DT diff --git a/nebula-exchange/target/site/scaladocs/lib/signaturebg.gif b/nebula-exchange/target/site/scaladocs/lib/signaturebg.gif deleted file mode 100644 index b6ac4415e4a3a3ce7e38401a476beea7b1938585..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1214 zcmZ?wbhEHbWMoihIKsei_wL=3Cr`e6|Ni^;?>BB-U$kh^&6_u0zkc=h?b|o6U*ElR z_x}C+_wL<0ckbN#ckgfCzWw^m>zlW3y?yug<;zz$Zrr$Y=gynAZ*JYXb^ZGFckkZ4 zdiCo6|Njg~K=D6!gl~X?OJYePkhZa}C`e4sPAySLN=?tqvsHS(d%u!GW{Ry+xT&v! zZ-H}aMy5wqQEG6NUr2IQcCuxPlD(aRO@&oOZb5EpNuokUZcbjYRfVlmVoH8esuhq8 z64qBz04piUwpDTjNhpBqbj~kIRWQ{v&`mZlGf*%y)H5_TF*i5YQ7|$vG|)FN(l<2H zH8i&}HnK7>P=Ep@plwAdX;wilZcw{`JX@uVl9B=|ef{$Ca=mh6z5JqdeM3u2OOP2x zM!G;1y2X`wC5aWfdBw^w6I@b@lZ!G7N;32F6hI~>Cgqow*eU^C3h_d20o>TUVm+{T z^pf*)^(zt!^bPe4Kwg3=^!3HBG&dKny0|1L72#g21{a4^7NqJ2r55Lx7A2!(A3h{#L&>yz{$%-qt%$9UanL3(T0L?SR?iPsN6x?nx z!08r!pkwqw5sMVjFd<;-0Wsmp7RZ4o{M0;PYA*sNYsUZo{{H#>>*tT}-@bnN{ORL| z_wRsN?$yf|&!0Vg^7zri2lwyYy>t84%^TORUA=Po(!~qs&z(JU`qar2$B!L7a`@1} z1N-;w-Lrew&K=vgZQZhY)5ZeMTG_VdAT{+S(zE>X{jm6Nr?&Z zaj`McQIQehVWAmo_ zrKzE=rmCW>q^KY-Co3Z@B`F~;CMqH&FX#K^#)_>%=(Qs{t4 sPRwL~E)H9a%WR_Xoj{Yna%DYi=CroINg16w1-Ypui3%0DIeEoa6}C!=DfvmMRzNmLSYJs2tfVB{R>=`0p#ZYe zIlm}X!Bo#cH`&0({$jZP#0Sc6WwiTtM zSp~VcLG1$aY?U%fN(!v>^~=l4^~#O)@{7{-4J|D#L1q{k=>k>g7FXt#Bv$C=6)VF` za7isrF3Kz@$;{7F0GXJWlwVq6s|0i@#0$9vaAWg|^}ycIOU}>LuShJ=H`Fr#c?qV_ z*B8Ii++4Wo;*y|LgnO|XTpUtakg6Y)TAW{6l$;7wt_-rOz{ATTy({MavwGFa70Z_`U9x!5!Ugl^&7CuQ*322xr%jzQdD6rQ{e8VX-Cdm>?QN|s z%}tFB^>wv1)m4=h1nAc$w`R`@o}*+(NU2R;bEa6!9jrm z{(inb-d>&_?ryFw&Q6XF_I9>5)>f7l=4PfQ#zw#_rKhW-t);1EF>tv&&SKd&Be*V&c@2Z%*4pRp!kyoTyW@sNKkpiz$&$%l_m71iJOQf Yv$AL3W|;;C$CD p { - margin-top: 5px; -} - -#types ol li:last-child { - margin-bottom: 5px; -} - -/* -#definition { - padding: 6px 0 6px 6px; - min-height: 59px; - color: white; -} -*/ - -#definition { - display: block-inline; - padding: 5px 0px; - height: 61px; -} - -#definition > img { - float: left; - padding-right: 6px; - padding-left: 5px; -} - -#definition > a > img { - float: left; - padding-right: 6px; - padding-left: 5px; -} - -#definition p + h1 { - margin-top: 3px; -} - -#definition > h1 { -/* padding: 12px 0 12px 6px;*/ - color: white; - text-shadow: 3px black; - text-shadow: black 0px 2px 0px; - font-size: 24pt; - display: inline-block; - overflow: hidden; - margin-top: 10px; -} - -#definition h1 > a { - color: #ffffff; - font-size: 24pt; - text-shadow: black 0px 2px 0px; -/* text-shadow: black 0px 0px 0px;*/ -text-decoration: none; -} - -#definition #owner { - color: #ffffff; - margin-top: 4px; - font-size: 10pt; - overflow: hidden; -} - -#definition #owner > a { - color: #ffffff; -} - -#definition #owner > a:hover { - text-decoration: none; -} - -#signature { - background-image:url('signaturebg2.gif'); - background-color: #d7d7d7; - min-height: 18px; - background-repeat:repeat-x; - font-size: 11.5pt; -/* margin-bottom: 10px;*/ - padding: 8px; -} - -#signature > span.modifier_kind { - display: inline; - float: left; - text-align: left; - width: auto; - position: static; - text-shadow: 2px white; - text-shadow: white 0px 1px 0px; -} - -#signature > span.symbol { - text-align: left; - display: inline; - padding-left: 0.7em; - text-shadow: 2px white; - text-shadow: white 0px 1px 0px; -} - -/* Linear super types and known subclasses */ -.hiddenContent { - display: none; -} - -.toggleContainer .toggle { - cursor: pointer; - padding-left: 15px; - background: url("arrow-right.png") no-repeat 0 3px transparent; -} - -.toggleContainer .toggle.open { - background: url("arrow-down.png") no-repeat 0 3px transparent; -} - -.toggleContainer .hiddenContent { - margin-top: 5px; -} - -.value #definition { - background-color: #2C475C; /* blue */ - background-image:url('defbg-blue.gif'); - background-repeat:repeat-x; -} - -.type #definition { - background-color: #316555; /* green */ - background-image:url('defbg-green.gif'); - background-repeat:repeat-x; -} - -#template { - margin-bottom: 50px; -} - -h3 { - color: white; - padding: 5px 10px; - font-size: 12pt; - font-weight: bold; - text-shadow: black 1px 1px 0px; -} - -dl.attributes > dt { - display: block; - float: left; - font-style: italic; -} - -dl.attributes > dt.implicit { - font-weight: bold; - color: darkgreen; -} - -dl.attributes > dd { - display: block; - padding-left: 10em; - margin-bottom: 5px; - min-height: 15px; -} - -#template .values > h3 { - background: #2C475C url("valuemembersbg.gif") repeat-x bottom left; /* grayish blue */ - height: 18px; -} - -#values ol li:last-child { - margin-bottom: 5px; -} - -#template .types > h3 { - background: #316555 url("typebg.gif") repeat-x bottom left; /* green */ - height: 18px; -} - -#constructors > h3 { - background: #4f504f url("constructorsbg.gif") repeat-x bottom left; /* gray */ - height: 18px; -} - -#inheritedMembers > div.parent > h3 { - background: #dadada url("constructorsbg.gif") repeat-x bottom left; /* gray */ - height: 17px; - font-style: italic; - font-size: 12pt; -} - -#inheritedMembers > div.parent > h3 * { - color: white; -} - -#inheritedMembers > div.conversion > h3 { - background: #dadada url("conversionbg.gif") repeat-x bottom left; /* gray */ - height: 17px; - font-style: italic; - font-size: 12pt; -} - -#inheritedMembers > div.conversion > h3 * { - color: white; -} - -#groupedMembers > div.group > h3 { - background: #dadada url("typebg.gif") repeat-x bottom left; /* green */ - height: 17px; - font-size: 12pt; -} - -#groupedMembers > div.group > h3 * { - color: white; -} - - -/* Member cells */ - -div.members > ol { - background-color: white; - list-style: none -} - -div.members > ol > li { - display: block; - border-bottom: 1px solid gray; - padding: 5px 0 6px; - margin: 0 10px; - position: relative; -} - -div.members > ol > li:last-child { - border: 0; - padding: 5px 0 5px; -} - -/* Member signatures */ - -#tooltip { - background: #EFD5B5; - border: 1px solid gray; - color: black; - display: none; - padding: 5px; - position: absolute; -} - -.signature { - font-family: monospace; - font-size: 10pt; - line-height: 18px; - clear: both; - display: block; - text-shadow: 2px white; - text-shadow: white 0px 1px 0px; -} - -.signature .modifier_kind { - position: absolute; - text-align: right; - width: 14em; -} - -.signature > a > .symbol > .name { - text-decoration: underline; -} - -.signature > a:hover > .symbol > .name { - text-decoration: none; -} - -.signature > a { - text-decoration: none; -} - -.signature > .symbol { - display: block; - padding-left: 14.7em; -} - -.signature .name { - display: inline-block; - font-weight: bold; -} - -.signature .symbol > .implicit { - display: inline-block; - font-weight: bold; - text-decoration: underline; - color: darkgreen; -} - -.signature .symbol .shadowed { - color: darkseagreen; -} - -.signature .symbol .params > .implicit { - font-style: italic; -} - -.signature .symbol .deprecated { - text-decoration: line-through; -} - -.signature .symbol .params .default { - font-style: italic; -} - -#template .signature.closed { - background: url("arrow-right.png") no-repeat 0 5px transparent; - cursor: pointer; -} - -#template .signature.opened { - background: url("arrow-down.png") no-repeat 0 5px transparent; - cursor: pointer; -} - -#template .values .signature .name { - color: darkblue; -} - -#template .types .signature .name { - color: darkgreen; -} - -.full-signature-usecase h4 span { - font-size: 10pt; -} - -.full-signature-usecase > #signature { - padding-top: 0px; -} - -#template .full-signature-usecase > .signature.closed { - background: none; -} - -#template .full-signature-usecase > .signature.opened { - background: none; -} - -.full-signature-block { - padding: 5px 0 0; - border-top: 1px solid #EBEBEB; - margin-top: 5px; - margin-bottom: 5px; -} - -#definition .morelinks { - text-align: right; - position: absolute; - top: 40px; - right: 10px; - width: 450px; -} - -#definition .morelinks a { - color: #EBEBEB; -} - -#template .members li .permalink { - position: absolute; - top: 5px; - right: 5px; -} - -#definition .permalink { - position: absolute; - top: 10px; - right: 15px; -} - -#definition .permalink a { - color: #EBEBEB; -} - -#template .members li .permalink, -#definition .permalink a { - display: none; -} - -#template .members li:hover .permalink, -#definition:hover .permalink a { - display: block; -} - -#template .members li .permalink a, -#definition .permalink a { - text-decoration: none; - font-weight: bold; -} - -/* Comments text formating */ - -.cmt {} - -.cmt p { - margin: 0.7em 0; -} - -.cmt p:first-child { - margin-top: 0; -} - -.cmt p:last-child { - margin-bottom: 0; -} - -.cmt h3, -.cmt h4, -.cmt h5, -.cmt h6 { - margin-bottom: 0.7em; - margin-top: 1.4em; - display: block; - text-align: left; - font-weight: bold; -} - -.cmt h3 { - font-size: 14pt; -} - -.cmt h4 { - font-size: 13pt; -} - -.cmt h5 { - font-size: 12pt; -} - -.cmt h6 { - font-size: 11pt; -} - -.cmt pre { - padding: 5px; - border: 1px solid #ddd; - background-color: #eee; - margin: 5px 0; - display: block; - font-family: monospace; -} - -.cmt pre span.ano { - color: blue; -} - -.cmt pre span.cmt { - color: green; -} - -.cmt pre span.kw { - font-weight: bold; -} - -.cmt pre span.lit { - color: #c71585; -} - -.cmt pre span.num { - color: #1e90ff; /* dodgerblue */ -} - -.cmt pre span.std { - color: #008080; /* teal */ -} - -.cmt ul { - display: block; - list-style: circle; - padding-left: 20px; -} - -.cmt ol { - display: block; - padding-left:20px; -} - -.cmt ol.decimal { - list-style: decimal; -} - -.cmt ol.lowerAlpha { - list-style: lower-alpha; -} - -.cmt ol.upperAlpha { - list-style: upper-alpha; -} - -.cmt ol.lowerRoman { - list-style: lower-roman; -} - -.cmt ol.upperRoman { - list-style: upper-roman; -} - -.cmt li { - display: list-item; -} - -.cmt code { - font-family: monospace; -} - -.cmt a { - font-style: bold; -} - -.cmt em, .cmt i { - font-style: italic; -} - -.cmt strong, .cmt b { - font-weight: bold; -} - -/* Comments structured layout */ - -.group > div.comment { - padding-top: 5px; - padding-bottom: 5px; - padding-right: 5px; - padding-left: 5px; - border: 1px solid #ddd; - background-color: #eeeee; - margin-top:5px; - margin-bottom:5px; - margin-right:5px; - margin-left:5px; - display: block; -} - -p.comment { - display: block; - margin-left: 14.7em; - margin-top: 5px; -} - -.shortcomment { - display: block; - margin: 5px 10px; -} - -div.fullcommenttop { - padding: 10px 10px; - background-image:url('fullcommenttopbg.gif'); - background-repeat:repeat-x; -} - -div.fullcomment { - margin: 5px 10px; -} - -#template div.fullcommenttop, -#template div.fullcomment { - display:none; - margin: 5px 0 0 14.7em; -} - -#template .shortcomment { - margin: 5px 0 0 14.7em; - padding: 0; -} - -div.fullcomment .block { - padding: 5px 0 0; - border-top: 1px solid #EBEBEB; - margin-top: 5px; - overflow: hidden; -} - -div.fullcommenttop .block { - padding: 5px 0 0; - border-top: 1px solid #EBEBEB; - margin-top: 5px; - margin-bottom: 5px -} - -div.fullcomment div.block ol li p, -div.fullcomment div.block ol li { - display:inline -} - -div.fullcomment .block > h5 { - font-style: italic; - font-weight: normal; - display: inline-block; -} - -div.fullcomment .comment { - margin: 5px 0 10px; -} - -div.fullcommenttop .comment:last-child, -div.fullcomment .comment:last-child { - margin-bottom: 0; -} - -div.fullcommenttop dl.paramcmts { - margin-bottom: 0.8em; - padding-bottom: 0.8em; -} - -div.fullcommenttop dl.paramcmts > dt, -div.fullcomment dl.paramcmts > dt { - display: block; - float: left; - font-weight: bold; - min-width: 70px; -} - -div.fullcommenttop dl.paramcmts > dd, -div.fullcomment dl.paramcmts > dd { - display: block; - padding-left: 10px; - margin-bottom: 5px; - margin-left: 70px; - min-height: 15px; -} - -/* Members filter tool */ - -#textfilter { - position: relative; - display: block; - height: 20px; - margin-bottom: 5px; -} - -#textfilter > .pre { - display: block; - position: absolute; - top: 0; - left: 0; - height: 23px; - width: 21px; - background: url("filter_box_left.png"); -} - -#textfilter > .input { - display: block; - position: absolute; - top: 0; - right: 20px; - left: 20px; -} - -#textfilter > .input > input { - height: 20px; - padding: 1px; - font-weight: bold; - color: #000000; - background: #ffffff url("filterboxbarbg.png") repeat-x top left; - width: 100%; -} - -#textfilter > .post { - display: block; - position: absolute; - top: 0; - right: 0; - height: 23px; - width: 21px; - background: url("filter_box_right.png"); -} - -#mbrsel { - padding: 5px 10px; - background-color: #ededee; /* light gray */ - background-image:url('filterboxbg.gif'); - background-repeat:repeat-x; - font-size: 9.5pt; - display: block; - margin-top: 1em; -/* margin-bottom: 1em; */ -} - -#mbrsel > div { - margin-bottom: 5px; -} - -#mbrsel > div:last-child { - margin-bottom: 0; -} - -#mbrsel > div > span.filtertype { - padding: 4px; - margin-right: 5px; - float: left; - display: inline-block; - color: #000000; - font-weight: bold; - text-shadow: white 0px 1px 0px; - width: 4.5em; -} - -#mbrsel > div > ol { - display: inline-block; -} - -#mbrsel > div > a { - position:relative; - top: -8px; - font-size: 11px; - text-shadow: #ffffff 0 1px 0; -} - -#mbrsel > div > ol#linearization { - display: table; - margin-left: 70px; -} - -#mbrsel > div > ol#linearization > li.in { - text-decoration: none; - float: left; - padding-right: 10px; - margin-right: 5px; - background: url(selected-right.png) no-repeat; - background-position: right 0px; -} - -#mbrsel > div > ol#linearization > li.in > span{ - color: #404040; - float: left; - padding: 1px 0 1px 10px; - background: url(selected.png) no-repeat; - background-position: 0px 0px; - text-shadow: #ffffff 0 1px 0; -} - -#mbrsel > div > ol#implicits { - display: table; - margin-left: 70px; -} - -#mbrsel > div > ol#implicits > li.in { - text-decoration: none; - float: left; - padding-right: 10px; - margin-right: 5px; - background: url(selected-right-implicits.png) no-repeat; - background-position: right 0px; -} - -#mbrsel > div > ol#implicits > li.in > span{ - color: #404040; - float: left; - padding: 1px 0 1px 10px; - background: url(selected-implicits.png) no-repeat; - background-position: 0px 0px; - text-shadow: #ffffff 0 1px 0; -} - -#mbrsel > div > ol > li { -/* padding: 3px 10px;*/ - line-height: 16pt; - display: inline-block; - cursor: pointer; -} - -#mbrsel > div > ol > li.in { - text-decoration: none; - float: left; - padding-right: 10px; - margin-right: 5px; - background: url(selected-right.png) no-repeat; - background-position: right 0px; -} - -#mbrsel > div > ol > li.in > span{ - color: #404040; - float: left; - padding: 1px 0 1px 10px; - background: url(selected.png) no-repeat; - background-position: 0px 0px; - text-shadow: #ffffff 0 1px 0; -} - -#mbrsel > div > ol > li.out { - text-decoration: none; - float: left; - padding-right: 10px; - margin-right: 5px; -} - -#mbrsel > div > ol > li.out > span{ - color: #747474; -/* background-color: #999; */ - float: left; - padding: 1px 0 1px 10px; -/* background: url(unselected.png) no-repeat;*/ - background-position: 0px -1px; - text-shadow: #ffffff 0 1px 0; -} -/* -#mbrsel .hideall { - color: #4C4C4C; - line-height: 16px; - font-weight: bold; -} - -#mbrsel .hideall span { - color: #4C4C4C; - font-weight: bold; -} - -#mbrsel .showall { - color: #4C4C4C; - line-height: 16px; - font-weight: bold; -} - -#mbrsel .showall span { - color: #4C4C4C; - font-weight: bold; -}*/ - -.badge { - display: inline-block; - padding: 2px 4px; - font-size: 11.844px; - font-weight: bold; - line-height: 14px; - color: #ffffff; - text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); - white-space: nowrap; - vertical-align: baseline; - background-color: #999999; - padding-right: 9px; - padding-left: 9px; - -webkit-border-radius: 9px; - -moz-border-radius: 9px; - border-radius: 9px; -} - -.badge-red { - background-color: #b94a48; -} diff --git a/nebula-exchange/target/site/scaladocs/lib/template.js b/nebula-exchange/target/site/scaladocs/lib/template.js deleted file mode 100644 index 798a2d4..0000000 --- a/nebula-exchange/target/site/scaladocs/lib/template.js +++ /dev/null @@ -1,500 +0,0 @@ -// © 2009–2010 EPFL/LAMP -// code by Gilles Dubochet with contributions by Pedro Furlanetto and Marcin Kubala - -$(document).ready(function(){ - - var controls = { - visibility: { - publicOnly: $("#visbl").find("> ol > li.public"), - all: $("#visbl").find("> ol > li.all") - } - }; - - // Escapes special characters and returns a valid jQuery selector - function escapeJquery(str){ - return str.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=<>\|])/g, '\\$1'); - } - - function toggleVisibilityFilter(ctrlToEnable, ctrToDisable) { - if (ctrlToEnable.hasClass("out")) { - ctrlToEnable.removeClass("out").addClass("in"); - ctrToDisable.removeClass("in").addClass("out"); - filter(); - } - } - - controls.visibility.publicOnly.click(function () { - toggleVisibilityFilter(controls.visibility.publicOnly, controls.visibility.all); - }); - - controls.visibility.all.click(function () { - toggleVisibilityFilter(controls.visibility.all, controls.visibility.publicOnly); - }); - - function exposeMember(jqElem) { - var jqElemParent = jqElem.parent(), - parentName = jqElemParent.attr("name"), - linearizationName = /^([^#]*)(#.*)?$/gi.exec(parentName)[1]; - - // switch visibility filter if necessary - if (jqElemParent.attr("visbl") == "prt") { - toggleVisibilityFilter(controls.visibility.all, controls.visibility.publicOnly); - } - - // toggle appropriate linearization buttons - if (linearizationName) { - $("#linearization li.out[name='" + linearizationName + "']").removeClass("out").addClass("in"); - } - - filter(); - window.scrollTo(0, 0); - jqElemParent.effect("highlight", {color: "#FFCC85"}, 3000); - $('html,body').animate({scrollTop: jqElemParent.offset().top}, 1000); - } - - var isHiddenClass = function (name) { - return name == 'scala.Any' || - name == 'scala.AnyRef'; - }; - - var isHidden = function (elem) { - return $(elem).attr("data-hidden") == 'true'; - }; - - $("#linearization li:gt(0)").filter(function(){ - return isHiddenClass($(this).attr("name")); - }).removeClass("in").addClass("out"); - - $("#implicits li").filter(function(){ - return isHidden(this); - }).removeClass("in").addClass("out"); - - // Pre-filter members - filter(); - - // Member filter box - var input = $("#textfilter input"); - input.bind("keyup", function(event) { - - switch ( event.keyCode ) { - - case 27: // escape key - input.val(""); - filter(true); - break; - - case 38: // up - input.val(""); - filter(false); - window.scrollTo(0, $("body").offset().top); - input.focus(); - break; - - case 33: //page up - input.val(""); - filter(false); - break; - - case 34: //page down - input.val(""); - filter(false); - break; - - default: - window.scrollTo(0, $("#mbrsel").offset().top); - filter(true); - break; - - } - }); - input.focus(function(event) { - input.select(); - }); - $("#textfilter > .post").click(function() { - $("#textfilter input").attr("value", ""); - filter(); - }); - $(document).keydown(function(event) { - - if (event.keyCode == 9) { // tab - $("#index-input", window.parent.document).focus(); - input.attr("value", ""); - return false; - } - }); - - $("#linearization li").click(function(){ - if ($(this).hasClass("in")) { - $(this).removeClass("in"); - $(this).addClass("out"); - } - else if ($(this).hasClass("out")) { - $(this).removeClass("out"); - $(this).addClass("in"); - } - filter(); - }); - - $("#implicits li").click(function(){ - if ($(this).hasClass("in")) { - $(this).removeClass("in"); - $(this).addClass("out"); - } - else if ($(this).hasClass("out")) { - $(this).removeClass("out"); - $(this).addClass("in"); - } - filter(); - }); - - $("#mbrsel > div[id=ancestors] > ol > li.hideall").click(function() { - $("#linearization li.in").removeClass("in").addClass("out"); - $("#linearization li:first").removeClass("out").addClass("in"); - $("#implicits li.in").removeClass("in").addClass("out"); - - if ($(this).hasClass("out") && $("#mbrsel > div[id=ancestors] > ol > li.showall").hasClass("in")) { - $(this).removeClass("out").addClass("in"); - $("#mbrsel > div[id=ancestors] > ol > li.showall").removeClass("in").addClass("out"); - } - - filter(); - }) - $("#mbrsel > div[id=ancestors] > ol > li.showall").click(function() { - var filteredLinearization = - $("#linearization li.out").filter(function() { - return ! isHiddenClass($(this).attr("name")); - }); - filteredLinearization.removeClass("out").addClass("in"); - - var filteredImplicits = - $("#implicits li.out").filter(function() { - return ! isHidden(this); - }); - filteredImplicits.removeClass("out").addClass("in"); - - if ($(this).hasClass("out") && $("#mbrsel > div[id=ancestors] > ol > li.hideall").hasClass("in")) { - $(this).removeClass("out").addClass("in"); - $("#mbrsel > div[id=ancestors] > ol > li.hideall").removeClass("in").addClass("out"); - } - - filter(); - }); - $("#order > ol > li.alpha").click(function() { - if ($(this).hasClass("out")) { - orderAlpha(); - } - }) - $("#order > ol > li.inherit").click(function() { - if ($(this).hasClass("out")) { - orderInherit(); - } - }); - $("#order > ol > li.group").click(function() { - if ($(this).hasClass("out")) { - orderGroup(); - } - }); - $("#groupedMembers").hide(); - - initInherit(); - - // Create tooltips - $(".extype").add(".defval").tooltip({ - tip: "#tooltip", - position: "top center", - predelay: 500, - onBeforeShow: function(ev) { - $(this.getTip()).text(this.getTrigger().attr("name")); - } - }); - - /* Add toggle arrows */ - //var docAllSigs = $("#template li").has(".fullcomment").find(".signature"); - // trying to speed things up a little bit - var docAllSigs = $("#template li[fullComment=yes] .signature"); - - function commentToggleFct(signature){ - var parent = signature.parent(); - var shortComment = $(".shortcomment", parent); - var fullComment = $(".fullcomment", parent); - var vis = $(":visible", fullComment); - signature.toggleClass("closed").toggleClass("opened"); - if (vis.length > 0) { - shortComment.slideDown(100); - fullComment.slideUp(100); - } - else { - shortComment.slideUp(100); - fullComment.slideDown(100); - } - }; - docAllSigs.addClass("closed"); - docAllSigs.click(function() { - commentToggleFct($(this)); - }); - - /* Linear super types and known subclasses */ - function toggleShowContentFct(e){ - e.toggleClass("open"); - var content = $(".hiddenContent", e.parent().get(0)); - if (content.is(':visible')) { - content.slideUp(100); - } - else { - content.slideDown(100); - } - }; - - $(".toggle:not(.diagram-link)").click(function() { - toggleShowContentFct($(this)); - }); - - // Set parent window title - windowTitle(); - - if ($("#order > ol > li.group").length == 1) { orderGroup(); }; - - function findElementByHash(locationHash) { - var temp = locationHash.replace('#', ''); - var memberSelector = '#' + escapeJquery(temp); - return $(memberSelector); - } - - // highlight and jump to selected member - if (window.location.hash) { - var jqElem = findElementByHash(window.location.hash); - if (jqElem.length > 0) { - exposeMember(jqElem); - } - } -}); - -function orderAlpha() { - $("#order > ol > li.alpha").removeClass("out").addClass("in"); - $("#order > ol > li.inherit").removeClass("in").addClass("out"); - $("#order > ol > li.group").removeClass("in").addClass("out"); - $("#template > div.parent").hide(); - $("#template > div.conversion").hide(); - $("#mbrsel > div[id=ancestors]").show(); - filter(); -}; - -function orderInherit() { - $("#order > ol > li.inherit").removeClass("out").addClass("in"); - $("#order > ol > li.alpha").removeClass("in").addClass("out"); - $("#order > ol > li.group").removeClass("in").addClass("out"); - $("#template > div.parent").show(); - $("#template > div.conversion").show(); - $("#mbrsel > div[id=ancestors]").hide(); - filter(); -}; - -function orderGroup() { - $("#order > ol > li.group").removeClass("out").addClass("in"); - $("#order > ol > li.alpha").removeClass("in").addClass("out"); - $("#order > ol > li.inherit").removeClass("in").addClass("out"); - $("#template > div.parent").hide(); - $("#template > div.conversion").hide(); - $("#mbrsel > div[id=ancestors]").show(); - filter(); -}; - -/** Prepares the DOM for inheritance-based display. To do so it will: - * - hide all statically-generated parents headings; - * - copy all members from the value and type members lists (flat members) to corresponding lists nested below the - * parent headings (inheritance-grouped members); - * - initialises a control variable used by the filter method to control whether filtering happens on flat members - * or on inheritance-grouped members. */ -function initInherit() { - // inheritParents is a map from fully-qualified names to the DOM node of parent headings. - var inheritParents = new Object(); - var groupParents = new Object(); - $("#inheritedMembers > div.parent").each(function(){ - inheritParents[$(this).attr("name")] = $(this); - }); - $("#inheritedMembers > div.conversion").each(function(){ - inheritParents[$(this).attr("name")] = $(this); - }); - $("#groupedMembers > div.group").each(function(){ - groupParents[$(this).attr("name")] = $(this); - }); - - $("#types > ol > li").each(function(){ - var mbr = $(this); - this.mbrText = mbr.find("> .fullcomment .cmt").text(); - var qualName = mbr.attr("name"); - var owner = qualName.slice(0, qualName.indexOf("#")); - var name = qualName.slice(qualName.indexOf("#") + 1); - var inheritParent = inheritParents[owner]; - if (inheritParent != undefined) { - var types = $("> .types > ol", inheritParent); - if (types.length == 0) { - inheritParent.append("

                                  Type Members

                                    "); - types = $("> .types > ol", inheritParent); - } - var clone = mbr.clone(); - clone[0].mbrText = this.mbrText; - types.append(clone); - } - var group = mbr.attr("group") - var groupParent = groupParents[group]; - if (groupParent != undefined) { - var types = $("> .types > ol", groupParent); - if (types.length == 0) { - groupParent.append("
                                      "); - types = $("> .types > ol", groupParent); - } - var clone = mbr.clone(); - clone[0].mbrText = this.mbrText; - types.append(clone); - } - }); - - $("#values > ol > li").each(function(){ - var mbr = $(this); - this.mbrText = mbr.find("> .fullcomment .cmt").text(); - var qualName = mbr.attr("name"); - var owner = qualName.slice(0, qualName.indexOf("#")); - var name = qualName.slice(qualName.indexOf("#") + 1); - var inheritParent = inheritParents[owner]; - if (inheritParent != undefined) { - var values = $("> .values > ol", inheritParent); - if (values.length == 0) { - inheritParent.append("

                                      Value Members

                                        "); - values = $("> .values > ol", inheritParent); - } - var clone = mbr.clone(); - clone[0].mbrText = this.mbrText; - values.append(clone); - } - var group = mbr.attr("group") - var groupParent = groupParents[group]; - if (groupParent != undefined) { - var values = $("> .values > ol", groupParent); - if (values.length == 0) { - groupParent.append("
                                          "); - values = $("> .values > ol", groupParent); - } - var clone = mbr.clone(); - clone[0].mbrText = this.mbrText; - values.append(clone); - } - }); - $("#inheritedMembers > div.parent").each(function() { - if ($("> div.members", this).length == 0) { $(this).remove(); }; - }); - $("#inheritedMembers > div.conversion").each(function() { - if ($("> div.members", this).length == 0) { $(this).remove(); }; - }); - $("#groupedMembers > div.group").each(function() { - if ($("> div.members", this).length == 0) { $(this).remove(); }; - }); -}; - -/* filter used to take boolean scrollToMember */ -function filter() { - var query = $.trim($("#textfilter input").val()).toLowerCase(); - query = query.replace(/[-[\]{}()*+?.,\\^$|#]/g, "\\$&").replace(/\s+/g, "|"); - var queryRegExp = new RegExp(query, "i"); - var privateMembersHidden = $("#visbl > ol > li.public").hasClass("in"); - var orderingAlphabetic = $("#order > ol > li.alpha").hasClass("in"); - var orderingInheritance = $("#order > ol > li.inherit").hasClass("in"); - var orderingGroups = $("#order > ol > li.group").hasClass("in"); - var hiddenSuperclassElementsLinearization = orderingInheritance ? $("#linearization > li:gt(0)") : $("#linearization > li.out"); - var hiddenSuperclassesLinearization = hiddenSuperclassElementsLinearization.map(function() { - return $(this).attr("name"); - }).get(); - var hiddenSuperclassElementsImplicits = orderingInheritance ? $("#implicits > li") : $("#implicits > li.out"); - var hiddenSuperclassesImplicits = hiddenSuperclassElementsImplicits.map(function() { - return $(this).attr("name"); - }).get(); - - var hideInheritedMembers; - - if (orderingAlphabetic) { - $("#allMembers").show(); - $("#inheritedMembers").hide(); - $("#groupedMembers").hide(); - hideInheritedMembers = true; - $("#allMembers > .members").each(filterFunc); - } else if (orderingGroups) { - $("#groupedMembers").show(); - $("#inheritedMembers").hide(); - $("#allMembers").hide(); - hideInheritedMembers = true; - $("#groupedMembers > .group > .members").each(filterFunc); - $("#groupedMembers > div.group").each(function() { - $(this).show(); - if ($("> div.members", this).not(":hidden").length == 0) { - $(this).hide(); - } else { - $(this).show(); - } - }); - } else if (orderingInheritance) { - $("#inheritedMembers").show(); - $("#groupedMembers").hide(); - $("#allMembers").hide(); - hideInheritedMembers = false; - $("#inheritedMembers > .parent > .members").each(filterFunc); - $("#inheritedMembers > .conversion > .members").each(filterFunc); - } - - - function filterFunc() { - var membersVisible = false; - var members = $(this); - members.find("> ol > li").each(function() { - var mbr = $(this); - if (privateMembersHidden && mbr.attr("visbl") == "prt") { - mbr.hide(); - return; - } - var name = mbr.attr("name"); - // Owner filtering must not happen in "inherited from" member lists - if (hideInheritedMembers) { - var ownerIndex = name.indexOf("#"); - if (ownerIndex < 0) { - ownerIndex = name.lastIndexOf("."); - } - var owner = name.slice(0, ownerIndex); - for (var i = 0; i < hiddenSuperclassesLinearization.length; i++) { - if (hiddenSuperclassesLinearization[i] == owner) { - mbr.hide(); - return; - } - }; - for (var i = 0; i < hiddenSuperclassesImplicits.length; i++) { - if (hiddenSuperclassesImplicits[i] == owner) { - mbr.hide(); - return; - } - }; - } - if (query && !(queryRegExp.test(name) || queryRegExp.test(this.mbrText))) { - mbr.hide(); - return; - } - mbr.show(); - membersVisible = true; - }); - - if (membersVisible) - members.show(); - else - members.hide(); - }; - - return false; -}; - -function windowTitle() -{ - try { - parent.document.title=document.title; - } - catch(e) { - // Chrome doesn't allow settings the parent's title when - // used on the local file system. - } -}; diff --git a/nebula-exchange/target/site/scaladocs/lib/tools.tooltip.js b/nebula-exchange/target/site/scaladocs/lib/tools.tooltip.js deleted file mode 100644 index 0af34ec..0000000 --- a/nebula-exchange/target/site/scaladocs/lib/tools.tooltip.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - * tools.tooltip 1.1.3 - Tooltips done right. - * - * Copyright (c) 2009 Tero Piirainen - * http://flowplayer.org/tools/tooltip.html - * - * Dual licensed under MIT and GPL 2+ licenses - * http://www.opensource.org/licenses - * - * Launch : November 2008 - * Date: ${date} - * Revision: ${revision} - */ -(function(c){var d=[];c.tools=c.tools||{};c.tools.tooltip={version:"1.1.3",conf:{effect:"toggle",fadeOutSpeed:"fast",tip:null,predelay:0,delay:30,opacity:1,lazy:undefined,position:["top","center"],offset:[0,0],cancelDefault:true,relative:false,oneInstance:true,events:{def:"mouseover,mouseout",input:"focus,blur",widget:"focus mouseover,blur mouseout",tooltip:"mouseover,mouseout"},api:false},addEffect:function(e,g,f){b[e]=[g,f]}};var b={toggle:[function(e){var f=this.getConf(),g=this.getTip(),h=f.opacity;if(h<1){g.css({opacity:h})}g.show();e.call()},function(e){this.getTip().hide();e.call()}],fade:[function(e){this.getTip().fadeIn(this.getConf().fadeInSpeed,e)},function(e){this.getTip().fadeOut(this.getConf().fadeOutSpeed,e)}]};function a(f,g){var p=this,k=c(this);f.data("tooltip",p);var l=f.next();if(g.tip){l=c(g.tip);if(l.length>1){l=f.nextAll(g.tip).eq(0);if(!l.length){l=f.parent().nextAll(g.tip).eq(0)}}}function o(u){var t=g.relative?f.position().top:f.offset().top,s=g.relative?f.position().left:f.offset().left,v=g.position[0];t-=l.outerHeight()-g.offset[0];s+=f.outerWidth()+g.offset[1];var q=l.outerHeight()+f.outerHeight();if(v=="center"){t+=q/2}if(v=="bottom"){t+=q}v=g.position[1];var r=l.outerWidth()+f.outerWidth();if(v=="center"){s-=r/2}if(v=="left"){s-=r}return{top:t,left:s}}var i=f.is(":input"),e=i&&f.is(":checkbox, :radio, select, :button"),h=f.attr("type"),n=g.events[h]||g.events[i?(e?"widget":"input"):"def"];n=n.split(/,\s*/);if(n.length!=2){throw"Tooltip: bad events configuration for "+h}f.bind(n[0],function(r){if(g.oneInstance){c.each(d,function(){this.hide()})}var q=l.data("trigger");if(q&&q[0]!=this){l.hide().stop(true,true)}r.target=this;p.show(r);n=g.events.tooltip.split(/,\s*/);l.bind(n[0],function(){p.show(r)});if(n[1]){l.bind(n[1],function(){p.hide(r)})}});f.bind(n[1],function(q){p.hide(q)});if(!c.browser.msie&&!i&&!g.predelay){f.mousemove(function(){if(!p.isShown()){f.triggerHandler("mouseover")}})}if(g.opacity<1){l.css("opacity",g.opacity)}var m=0,j=f.attr("title");if(j&&g.cancelDefault){f.removeAttr("title");f.data("title",j)}c.extend(p,{show:function(r){if(r){f=c(r.target)}clearTimeout(l.data("timer"));if(l.is(":animated")||l.is(":visible")){return p}function q(){l.data("trigger",f);var t=o(r);if(g.tip&&j){l.html(f.data("title"))}r=r||c.Event();r.type="onBeforeShow";k.trigger(r,[t]);if(r.isDefaultPrevented()){return p}t=o(r);l.css({position:"absolute",top:t.top,left:t.left});var s=b[g.effect];if(!s){throw'Nonexistent effect "'+g.effect+'"'}s[0].call(p,function(){r.type="onShow";k.trigger(r)})}if(g.predelay){clearTimeout(m);m=setTimeout(q,g.predelay)}else{q()}return p},hide:function(r){clearTimeout(l.data("timer"));clearTimeout(m);if(!l.is(":visible")){return}function q(){r=r||c.Event();r.type="onBeforeHide";k.trigger(r);if(r.isDefaultPrevented()){return}b[g.effect][1].call(p,function(){r.type="onHide";k.trigger(r)})}if(g.delay&&r){l.data("timer",setTimeout(q,g.delay))}else{q()}return p},isShown:function(){return l.is(":visible, :animated")},getConf:function(){return g},getTip:function(){return l},getTrigger:function(){return f},bind:function(q,r){k.bind(q,r);return p},onHide:function(q){return this.bind("onHide",q)},onBeforeShow:function(q){return this.bind("onBeforeShow",q)},onShow:function(q){return this.bind("onShow",q)},onBeforeHide:function(q){return this.bind("onBeforeHide",q)},unbind:function(q){k.unbind(q);return p}});c.each(g,function(q,r){if(c.isFunction(r)){p.bind(q,r)}})}c.prototype.tooltip=function(e){var f=this.eq(typeof e=="number"?e:0).data("tooltip");if(f){return f}var g=c.extend(true,{},c.tools.tooltip.conf);if(c.isFunction(e)){e={onBeforeShow:e}}else{if(typeof e=="string"){e={tip:e}}}e=c.extend(true,g,e);if(typeof e.position=="string"){e.position=e.position.split(/,?\s/)}if(e.lazy!==false&&(e.lazy===true||this.length>20)){this.one("mouseover",function(h){f=new a(c(this),e);f.show(h);d.push(f)})}else{this.each(function(){f=new a(c(this),e);d.push(f)})}return e.api?f:this}})(jQuery); \ No newline at end of file diff --git a/nebula-exchange/target/site/scaladocs/lib/trait.png b/nebula-exchange/target/site/scaladocs/lib/trait.png deleted file mode 100644 index fb961a2eda3f55c9d8272a4793549e23120aec6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3374 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 Ef&ySVw*UYD diff --git a/nebula-exchange/target/site/scaladocs/lib/trait_big.png b/nebula-exchange/target/site/scaladocs/lib/trait_big.png deleted file mode 100644 index 625d9251cba32d350beb988fcd072672d5f3b375..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7410 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 diff --git a/nebula-exchange/target/site/scaladocs/lib/trait_diagram.png b/nebula-exchange/target/site/scaladocs/lib/trait_diagram.png deleted file mode 100644 index 88983254ce3a4295951e4d3af927d50b50a3146d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3882 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 diff --git a/nebula-exchange/target/site/scaladocs/lib/type_diagram.png b/nebula-exchange/target/site/scaladocs/lib/type_diagram.png deleted file mode 100644 index d8152529fdc350853f4b1e7debb0a0c8d632ff7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1841 zcmaJ?c~BE)99T$Lr=we%F*v^CE}IxJ--BM^o`!9R>q2MpO@j3bQT^*1$SrURFCC z2>>oM1k&PKWSh-nWFHq$`FD5iZZP_mU) z32Z{*^D%gSz6vtrXBfhbw5YjYBq1UN%rLG433H~!CL+YN*SaEd?$~D0z}FBwLri;< zlvb$*B`5}i0w$YbV2857P!5yB;|qntIUtwKVYAp=7Kh8=2t_=uh|LDyJ~T2KW=s`n zr1H11$d#C8!f~sJ#mddiW#;mjD3-?JgolSaG`L&_iD20BEVzzfSZqPV3R2i+zz{2r zpcc@fsMDj_xR^#}`lbZ4bwt);d)p?mVJt#tWpS8nM@hp#rSkuwX7dQzhHKz=`TnP{ z4a&2^EDdZ!voQmCaH&C#P*#xygLOEHK`5Fz+(oqs#Zj9HwStoQ0#Kk;ub192qxO9xI4phs&jMDLuu=8ia*d7`^PQtaB8%V%dM-8hnc zWXxx0wa@!*AHI2bF!i_Rsq(Dc+_=BBRdhN%c)_>(jM>>q_pqkTg98IJUyQoI+fvHW+Ky=RaJHK_H8<_+r@L-=`&~A@8@htuCFyo7|Ye*XR%m1bgeEg zFQ4e-O%5~QhcSJ@+e3+4u5h&TQ7=ol(Sy|%)oB~3rR9qStw?S1qbph5q z&KC1Zo}!x;7&ze>Pnnolwm_0_hq|G?I5}umOoG6-og;M~aFwb0gA-m@CB*>;j`-^fFX zREb^}yI;P1`Atbl3E!lcmDl{`I!vRPV6Uv~sjI8I^y}`yW}g)QO8e{-t(G`lzw?&2 vpS!x@6ME$tZpA+Dnp^bdh^L`1X14%ymwB@Ei@#dw_=zcGDrrOPlA?bAm}bg0 diff --git a/nebula-exchange/target/site/scaladocs/lib/type_to_object_big.png b/nebula-exchange/target/site/scaladocs/lib/type_to_object_big.png deleted file mode 100644 index ef2615bacc702f153594af64f60e4443ab91ea99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4969 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 SK}x{k>c&71H4lFd25SHaTcP{_ diff --git a/nebula-exchange/target/site/scaladocs/lib/unselected.png b/nebula-exchange/target/site/scaladocs/lib/unselected.png deleted file mode 100644 index d5ac639405ffe0a45fd51de2904692c7e905c5ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1879 zcmaJ?Yg7|Q6b|^HqG$*RJ1=z=bYV{JM(?ty?5^2v#TP* zXV}>~*-|JJJE=r0C+8;ear$C7`R*|}n8|585uzZXu~b42X<$l_3QK_jDGJSlaJAasf;LDeyc*Eo3}9c9H=gDj{Q* zj|`OIA~+3^WNF~&tne6R)&eD8#Rv=l{0#z90EGz%Frevbt-v5;yw??wYs)r^0lbG0 z3xtdhK`CUBfC$sTfDaS&Qi8r9;LB#Ry}5pVe$xRC$Oc&;hsEZ2vHb+z903Rd9|wc< zrctE|2w4^iul*#@dilU#;T0#zg zj`u%>wK17E%#y=eOs7$jg-dm_xWWY@4Ga;OCI-XO2W~Mk4I?mZ8ioU+XdgfZDG{~B zevg;Q1X8t@fYeG@Di$(G1tx;11R@?Ul*<+Q`0)LL*z6E6I8?+Jg>ZcR_}t(iE{8k7 z6=O;r3ag0$uIe+_cTldS6;Pb?EQU46LRb~5!BF6R$^vBYSiA?-`^Z%d9t(F+E{hC? zWhv~x3O%qzc8_KGsclK)Q{%&GvfDLeTemlSSw(&=%~EktjN#goZ7tzWkmK?P5!pej zcgbngf{{xfoysL(v+nXQ%V%{s8|-goFJRRzm(JR?+Cz5Dqrf!(w;eBS^2Qbbyz`?P z!dmMqkhh4rBr`&DuXwy7?8M666TRIP!-Kxd6IZT;-`w47yRIJLS&eDFPkXt3%K^K0 zxvd>{PEz7$&yN26$`x-%mz9NYMy!!sV%a`j^Hs;A+6_meQ|#(84dYrLzs#D0a-9-> zXp5TI*lAt)^L4$LtW3r!u0(7U$M3WNxbFl#Y6)sfCuM_h0Dj+_NI#oU82h zEYn8MB55VEC76D(^U%6(537s|`qy0xuZxiTBPUkw7FpA|oa|q3x&rEbad)k3?r)?p z@(*3r=L{pJ@|ua7?#u&Zb4jDw}LwD`?cl&LflP?-Dcam`y7@w(rfe&hxxzG!8Rq zd3cU-TVqO9e@jct0m#uM%YI6=c)izt$FXzkCGNCDn?3f0)m2qh)oXI)+J))tQ`J%yf$?jzi#;wb6p+pl6@I6FDcU8S@0 z2yYs0)wkxB8$U4cUAkWXYVtGH@3;Xl6o>{ z`8r;g@W#_6H@AB)wLXucXl($Gw>h+!R+r@OGB4r}H<=k5E!h!hFNAsK@*auZUlX^W z*9BWOitVMP{KWY9K4SyCd2$@CpV8szA3vS`;7CnPa`sOhN%_yZfk4XNe)i15yy{pC4X~ch)SnB{P)qSs-VcSX*DP3r<@Yyzrk~MM=TqvuBRvF tur|z~H^sL5c+!MS88ch*;^?;{KuWlJ)Eh;9cd6x9Ck+V~n}X*q`v(^B>01B* diff --git a/nebula-exchange/target/site/scaladocs/lib/valuemembersbg.gif b/nebula-exchange/target/site/scaladocs/lib/valuemembersbg.gif deleted file mode 100644 index 2a949311d7869cb769ef7fd48a9c03a57937b60d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1206 zcmZ?wbhEHbWMq(GIKsdnZ{h0@Uu7LxEUIN)Ic=RqSb?mWkG6ZfPfmw%K&HM|vRQDB zZ(f&YMvIb7kh)W(qIH0ZeVAK%lWR)7rb~>DTbx&Ro3x3ip?;Zqle1Gx6p~WYGxKbf-tXS8q>!0ns}yePYv5bpoSKp8QB{;0 zT;&&%T$P<{nWAKGr(jcIRgqhen_7~nP?4LHS8P>btCX0MpOk6^WP^nDl@!2AO0sR0 z96=HaAUmD&i&7O#^$c{A4a^J_%nbDmjZMtW&2GK4GRy>*)Z*l#%z~24{5%DaiHS-1r6smXK$k+ikXryZHm_I@>>a)2{9OHt!~%Uo zJp+)JUEg{v+u2}(t{7puX=A(aKG`a!A1`K3k4sX*n*AgcnUy@&(kzb(T9BiuKo0y!L2jYX(`}$gW<`tJD<|U_ky4WfKP0-8COtCUC zHgGd=G%zu>baFB@bTx2tbGCGLH8L}|G;wk?F*1Sab;(aI%}vcKf$2>_=rzTu7nBro z3xGDeq!wkCrKY$Q<>xAZy=;|<+bu>o&4cPq!R;1foO<VgsyL#pFrHdENpF4Zz^r@34jvqUEVojbN~+qz}*ri~lc zuUorj^{SOCmM>enWbvYf3+B(8J7@N+nKPzOn>uCkq=^&y`+9r2yE;4C+ge+in;IMH z>uPJNt12tX%Sua%iwXi?qaq{1!$L!Xg8~Em{d|4A zy*xeK-CSLqog5wP?QCtVtt>6f%}h;V~x zOjJZzNKk;EkC%s=i<5($jg^I&iIIUp@h1zoq|gD8pz?@;RXoAfpyR4Xuvm`MMwJ;w P0sc=M8VWO=IT)+~jV+!7 diff --git a/nebula-exchange/target/site/scaladocs/package.html b/nebula-exchange/target/site/scaladocs/package.html deleted file mode 100644 index 0cf59ee..0000000 --- a/nebula-exchange/target/site/scaladocs/package.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - root - nebula-exchange 2.0.0 API - _root_ - - - - - - - - - - - - - - - - - -

                                          - - - package - - - root - -

                                          - -
                                          - - -
                                          -
                                          - - -
                                          - Visibility -
                                          1. Public
                                          2. All
                                          -
                                          -
                                          - -
                                          -
                                          - - - - - - -
                                          -

                                          Value Members

                                          -
                                          1. - - -

                                            - - - package - - - com - -

                                            - - Permalink - - - -
                                          -
                                          - - - - -
                                          - -
                                          - - -
                                          - -
                                          -
                                          -

                                          Ungrouped

                                          - -
                                          -
                                          - -
                                          - -
                                          - - - - - - diff --git a/nebula-exchange/target/test-classes.timestamp b/nebula-exchange/target/test-classes.timestamp deleted file mode 100644 index 945c9b4..0000000 --- a/nebula-exchange/target/test-classes.timestamp +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file diff --git a/nebula-spark-connector/.gitignore b/nebula-spark-connector/.gitignore new file mode 100644 index 0000000..84e7a6b --- /dev/null +++ b/nebula-spark-connector/.gitignore @@ -0,0 +1,36 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# build target +target/ + +# IDE +.idea/ +.eclipse/ +*.iml + +spark-importer.ipr +spark-importer.iws + +.DS_Store diff --git a/nebula-spark-connector/target/maven-archiver/pom.properties b/nebula-spark-connector/target/maven-archiver/pom.properties deleted file mode 100644 index d111b8b..0000000 --- a/nebula-spark-connector/target/maven-archiver/pom.properties +++ /dev/null @@ -1,5 +0,0 @@ -#Generated by Maven -#Wed Dec 09 18:47:46 CST 2020 -version=2.0.0 -groupId=com.vesoft -artifactId=nebula-spark-connector From 13be96ddb068fb522055408237445c17344f5475 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 10 Dec 2020 09:24:18 +0800 Subject: [PATCH 005/213] remove .DS_Store --- nebula-exchange/src/main/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 nebula-exchange/src/main/.DS_Store diff --git a/nebula-exchange/src/main/.DS_Store b/nebula-exchange/src/main/.DS_Store deleted file mode 100644 index 0e98056ead8b2b4ddd22a5b0719be234dbd12c0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKI|>3p3{BKRv9YwAD|mxJ^aNf&P_YpOMeD6Rmq+vEgD9(wU?VS(yqQeiEc=Sh zMnrUaUQa|uBGQK&%GE;K?A*L%oy;f@jyukBl$C7cbXl~j-zSVa01F&BJoAtH-C@6t zo8MEJr2a0lP&G#k4Lb5A>uO>X7ausK8$-puO2*HpMGtZ*9Gt_1Xeo!mZ{8H^bT~2;Po?-j1=cc0Bf? bs4KR{c};8rosPWIf&3XTU1(I`*9zPLYRVP2 From 181b81c9ee8be7169328d9b743fef1e1dd7bde00 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 10 Dec 2020 13:16:53 +0800 Subject: [PATCH 006/213] add readme --- nebula-exchange/README.md | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index f5a1d46..4a5cb16 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -1,16 +1,37 @@ # 欢迎使用 Nebula Graph Exchange 2.0 -Nebula Graph Exchange(简称为 Exchange),是一款 Apache Spark™ 应用,用于在分布式环境中将集群中的数据批量迁移到 Nebula Graph 中,能支持多种不同格式的批式数据和流式数据的迁移。 +Nebula Exchange(简称为 Exchange),是一款 Apache Spark™ 应用,用于在分布式环境中将集群中的数据批量迁移到 Nebula Graph 中,能支持多种不同格式的批式数据和流式数据的迁移。 + +## 如何编译 +Nebula Exchange 2.0 依赖 Nebula java client。 + +1.编译打包 Nebula Java Client + ``` + $ git clone https://github.com/vesoft-inc/nebula-java.git + $ cd nebula-java + $ mvn clean compile package install -Dtest.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true + ``` +打包结束后在本地 maven repository 中会生成 /com/vesoft/client/2.0.0-beta/client-2.0.0-beta.jar。 + +2.编译打包 Nebula Exchange 2.0 +``` +$ git clone https://github.com/vesoft-inc/nebula-spark-utils.git +$ cd nebula-spark-utils/nebula-exchange +$ mvn clean compile package install -Dtest.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true +``` +编译打包完成后 在 nebula-spark-utils/nebula-exchange/target/ 目录下生成 nebula-exchange-2.0.0.jar。 ## 使用说明 -关于 Nebula Graph Exchange 2.0 的详细使用说明,请参考1.0的使用文档[《Nebula Graph Exchange 用户手册》](https://docs.nebula-graph.com.cn/nebula-exchange/about-exchange/ex-ug-what-is-exchange/ "点击前往 Nebula Graph 网站")。 +关于 Nebula Exchange 2.0 的详细使用说明,请参考1.0的使用文档[《Nebula Graph Exchange 用户手册》](https://docs.nebula-graph.com.cn/nebula-exchange/about-exchange/ex-ug-what-is-exchange/ "点击前往 Nebula Graph 网站")。 注意事项: *1. Nebula Graph 2.0暂时只支持String类型的vid,请勿配置点id或者边的src_id、dst_id的policy* *2. Exchange 2.0 支持Date、DateTime、Time类型数据的导入* + +*3. 配置文件参考 [application.conf](https://github.com/vesoft-inc/nebula-spark-utils/tree/main/nebula-exchange/src/main/resources) ## 贡献 Nebula Graph Exchange 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: From 579f615a6f99b1663dccbc36fc610ce6da7fd872 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 10 Dec 2020 13:37:23 +0800 Subject: [PATCH 007/213] format Nebula Exchange name --- nebula-exchange/README.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index 4a5cb16..a2ce826 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -1,40 +1,40 @@ -# 欢迎使用 Nebula Graph Exchange 2.0 +# 欢迎使用 Nebula Exchange 2.0 Nebula Exchange(简称为 Exchange),是一款 Apache Spark™ 应用,用于在分布式环境中将集群中的数据批量迁移到 Nebula Graph 中,能支持多种不同格式的批式数据和流式数据的迁移。 ## 如何编译 Nebula Exchange 2.0 依赖 Nebula java client。 -1.编译打包 Nebula Java Client - ``` - $ git clone https://github.com/vesoft-inc/nebula-java.git - $ cd nebula-java - $ mvn clean compile package install -Dtest.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true - ``` -打包结束后在本地 maven repository 中会生成 /com/vesoft/client/2.0.0-beta/client-2.0.0-beta.jar。 - -2.编译打包 Nebula Exchange 2.0 -``` -$ git clone https://github.com/vesoft-inc/nebula-spark-utils.git -$ cd nebula-spark-utils/nebula-exchange -$ mvn clean compile package install -Dtest.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true -``` -编译打包完成后 在 nebula-spark-utils/nebula-exchange/target/ 目录下生成 nebula-exchange-2.0.0.jar。 +1. 编译打包 Nebula Java Client + ``` + $ git clone https://github.com/vesoft-inc/nebula-java.git + $ cd nebula-java + $ mvn clean compile package install -Dtest.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true + ``` + 打包结束后在本地 maven repository 中会生成 /com/vesoft/client/2.0.0-beta/client-2.0.0-beta.jar。 + +2. 编译打包 Nebula Exchange 2.0 + ``` + $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git + $ cd nebula-spark-utils/nebula-exchange + $ mvn clean compile package install -Dtest.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true + ``` + 编译打包完成后,在 nebula-spark-utils/nebula-exchange/target/ 目录下生成 nebula-exchange-2.0.0.jar。 ## 使用说明 -关于 Nebula Exchange 2.0 的详细使用说明,请参考1.0的使用文档[《Nebula Graph Exchange 用户手册》](https://docs.nebula-graph.com.cn/nebula-exchange/about-exchange/ex-ug-what-is-exchange/ "点击前往 Nebula Graph 网站")。 +关于 Nebula Exchange 2.0 的详细使用说明,请参考1.0的使用文档[《Nebula Exchange 用户手册》](https://docs.nebula-graph.com.cn/nebula-exchange/about-exchange/ex-ug-what-is-exchange/ "点击前往 Nebula Graph 网站")。 注意事项: *1. Nebula Graph 2.0暂时只支持String类型的vid,请勿配置点id或者边的src_id、dst_id的policy* -*2. Exchange 2.0 支持Date、DateTime、Time类型数据的导入* +*2. Nebula Exchange 2.0 支持Date、DateTime、Time类型数据的导入* *3. 配置文件参考 [application.conf](https://github.com/vesoft-inc/nebula-spark-utils/tree/main/nebula-exchange/src/main/resources) ## 贡献 -Nebula Graph Exchange 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: +Nebula Exchange 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: - 前往 [Nebula Graph 论坛](https://discuss.nebula-graph.com.cn/ "点击前往“Nebula Graph 论坛") 上参与 Issue 讨论,如答疑、提供想法或者报告无法解决的问题 - 撰写或改进文档 From 794dd9ff2a17890c65d72e0729322b9dc3685c10 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 10 Dec 2020 13:44:03 +0800 Subject: [PATCH 008/213] format style --- nebula-exchange/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index a2ce826..6cdda1c 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -31,7 +31,7 @@ Nebula Exchange 2.0 依赖 Nebula java client。 *2. Nebula Exchange 2.0 支持Date、DateTime、Time类型数据的导入* -*3. 配置文件参考 [application.conf](https://github.com/vesoft-inc/nebula-spark-utils/tree/main/nebula-exchange/src/main/resources) +*3. 配置文件参考 [application.conf](https://github.com/vesoft-inc/nebula-spark-utils/tree/main/nebula-exchange/src/main/resources)* ## 贡献 Nebula Exchange 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: From 7d9c3338f276822c477c5dd33ee477db93586dbb Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 11 Dec 2020 18:09:48 +0800 Subject: [PATCH 009/213] Synchronize exchange1.0: fix chinese import --- .../importer/processor/EdgeProcessor.scala | 17 ++---- .../tools/importer/processor/Processor.scala | 9 +-- .../processor/VerticesProcessor.scala | 7 +-- .../tools/importer/utils/NebulaUtils.scala | 55 +++++++++---------- 4 files changed, 35 insertions(+), 53 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.scala index 03aa3db..b12dda9 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.scala @@ -24,7 +24,6 @@ import com.vesoft.nebula.tools.importer.{ } import org.apache.log4j.Logger import com.vesoft.nebula.tools.importer.writer.NebulaGraphClientWriter -import org.apache.commons.lang.StringEscapeUtils import org.apache.spark.sql.streaming.Trigger import org.apache.spark.sql.{DataFrame, Encoders} import org.apache.spark.util.LongAccumulator @@ -102,11 +101,9 @@ class EdgeProcessor(data: DataFrame, if (edgeConfig.sourcePolicy.isEmpty) { // process string type vid if (isVidStringType) { - if (StringEscapeUtils.escapeJava(sourceField).contains('\\')) { - sourceField = StringEscapeUtils.escapeJava(sourceField).mkString("\"", "", "\"") - } else { - sourceField = sourceField.mkString("\"", "", "\"") - } + sourceField = NebulaUtils.escapeUtil(sourceField).mkString("\"", "", "\"") + } else { + assert(NebulaUtils.isNumic(sourceField)) } } @@ -115,11 +112,9 @@ class EdgeProcessor(data: DataFrame, if (edgeConfig.targetPolicy.isEmpty) { // process string type vid if (isVidStringType) { - if (StringEscapeUtils.escapeJava(targetField).contains('\\')) { - targetField = StringEscapeUtils.escapeJava(targetField).mkString("\"", "", "\"") - } else { - targetField = targetField.mkString("\"", "", "\"") - } + targetField = NebulaUtils.escapeUtil(targetField).mkString("\"", "", "\"") + } else { + assert(NebulaUtils.isNumic(targetField)) } } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/Processor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/Processor.scala index c04a909..76a17f3 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/Processor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/Processor.scala @@ -7,8 +7,7 @@ package com.vesoft.nebula.tools.importer.processor import com.vesoft.nebula.meta.PropertyType -import com.vesoft.nebula.tools.importer.utils.HDFSUtils -import org.apache.commons.lang.StringEscapeUtils +import com.vesoft.nebula.tools.importer.utils.{HDFSUtils, NebulaUtils} import org.apache.spark.sql.Row import org.apache.spark.sql.types.{IntegerType, LongType, StringType} @@ -48,11 +47,7 @@ trait Processor extends Serializable { fieldTypeMap(field) match { case PropertyType.STRING => { - val result = if (StringEscapeUtils.escapeJava(row.getString(index)).contains('\\')) { - StringEscapeUtils.escapeJava(row.get(index).toString).mkString("\"", "", "\"") - } else { - row.get(index).toString.mkString("\"", "", "\"") - } + val result = NebulaUtils.escapeUtil(row.getString(index)).mkString("\"", "", "\"") if (toBytes) result.getBytes else result } case PropertyType.DATE => "date(\"" + row.get(index) + "\")" diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.scala index b72e906..a6f67b1 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.scala @@ -23,7 +23,6 @@ import com.vesoft.nebula.tools.importer.{ } import org.apache.log4j.Logger import com.vesoft.nebula.tools.importer.writer.{NebulaGraphClientWriter} -import org.apache.commons.lang.StringEscapeUtils import org.apache.spark.sql.streaming.Trigger import org.apache.spark.sql.{DataFrame, Encoders} import org.apache.spark.util.LongAccumulator @@ -105,11 +104,7 @@ class VerticesProcessor(data: DataFrame, // process string type vid if (isVidStringType) { val value = row.get(index).toString - if (StringEscapeUtils.escapeJava(value).contains('\\')) { - StringEscapeUtils.escapeJava(value).mkString("\"", "", "\"") - } else { - value.mkString("\"", "", "\"") - } + NebulaUtils.escapeUtil(value).mkString("\"", "", "\"") } else { // process int type vid assert(NebulaUtils.isNumic(row.get(index).toString)) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/NebulaUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/NebulaUtils.scala index b1cff5b..4b3aa9a 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/NebulaUtils.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/NebulaUtils.scala @@ -15,15 +15,6 @@ import com.vesoft.nebula.tools.importer.config.{ Type } import org.apache.log4j.Logger -import org.apache.spark.sql.types.DataType -import org.apache.spark.sql.types.DataTypes.{ - BooleanType, - DoubleType, - FloatType, - IntegerType, - LongType, - StringType -} import scala.collection.JavaConversions.seqAsJavaList import scala.collection.mutable @@ -65,30 +56,36 @@ object NebulaUtils { sourceSchemaMap.toMap } - def getDataType(clazz: Class[_]): DataType = { - if (classOf[java.lang.Boolean] == clazz) return BooleanType - else if (classOf[java.lang.Long] == clazz || classOf[java.lang.Integer] == clazz) - return LongType - else if (classOf[java.lang.Double] == clazz || classOf[java.lang.Float] == clazz) - return DoubleType - StringType - } - - def getDataFrameValue(value: String, dataType: DataType): Any = { - dataType match { - case LongType => value.toLong - case IntegerType => value.toInt - case BooleanType => value.toBoolean - case DoubleType => value.toDouble - case FloatType => value.toFloat - case _ => value - } - } - def isNumic(str: String): Boolean = { for (char <- str.toCharArray) { if (!Character.isDigit(char)) return false } true } + + def escapeUtil(str: String): String = { + var s = str + if (s.contains("\\")) { + s = s.replaceAll("\\\\", "\\\\\\\\") + } + if (s.contains("\t")) { + s = s.replaceAll("\t", "\\\\t") + } + if (s.contains("\n")) { + s = s.replaceAll("\n", "\\\\n") + } + if (s.contains("\"")) { + s = s.replaceAll("\"", "\\\\\"") + } + if (s.contains("\'")) { + s = s.replaceAll("\'", "\\\\'") + } + if (s.contains("\r")) { + s = s.replaceAll("\r", "\\\\r") + } + if (s.contains("\b")) { + s = s.replaceAll("\b", "\\\\b") + } + s + } } From c8cfefdc8cb285709fd9b3fea6f019f4e3dbc4a8 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 15 Dec 2020 10:47:33 +0800 Subject: [PATCH 010/213] add new feature description --- nebula-exchange/README.md | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index 6cdda1c..d64a1a4 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -3,35 +3,39 @@ Nebula Exchange(简称为 Exchange),是一款 Apache Spark™ 应用,用于在分布式环境中将集群中的数据批量迁移到 Nebula Graph 中,能支持多种不同格式的批式数据和流式数据的迁移。 ## 如何编译 -Nebula Exchange 2.0 依赖 Nebula java client。 +Nebula Exchange 2.0 依赖 Nebula Java Client 2.0。 -1. 编译打包 Nebula Java Client +1. 编译打包 Nebula Java Client 2.0 ``` $ git clone https://github.com/vesoft-inc/nebula-java.git $ cd nebula-java - $ mvn clean compile package install -Dtest.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true + $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true ``` - 打包结束后在本地 maven repository 中会生成 /com/vesoft/client/2.0.0-beta/client-2.0.0-beta.jar。 + 打包结束后,在本地 Maven Repository 仓库中可以看到生成的 /com/vesoft/client/2.0.0-beta/client-2.0.0-beta.jar。 2. 编译打包 Nebula Exchange 2.0 ``` $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git $ cd nebula-spark-utils/nebula-exchange - $ mvn clean compile package install -Dtest.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true + $ mvn clean package -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true ``` - 编译打包完成后,在 nebula-spark-utils/nebula-exchange/target/ 目录下生成 nebula-exchange-2.0.0.jar。 + 编译打包完成后,可以在 nebula-spark-utils/nebula-exchange/target/ 目录下看到 nebula-exchange-2.0.0.jar 文件。 ## 使用说明 -关于 Nebula Exchange 2.0 的详细使用说明,请参考1.0的使用文档[《Nebula Exchange 用户手册》](https://docs.nebula-graph.com.cn/nebula-exchange/about-exchange/ex-ug-what-is-exchange/ "点击前往 Nebula Graph 网站")。 +关于 Nebula Exchange 2.0 的详细使用说明,请参考 1.0 的使用文档[《Nebula Exchange 用户手册》](https://docs.nebula-graph.com.cn/nebula-exchange/about-exchange/ex-ug-what-is-exchange/ "点击前往 Nebula Graph 网站")。 -注意事项: +特性 & 注意事项: -*1. Nebula Graph 2.0暂时只支持String类型的vid,请勿配置点id或者边的src_id、dst_id的policy* +*1. Nebula Graph 2.0 暂时只支持 String 类型的 VID,请勿配置点 ID 或者边的 src_id、dst_id 的 policy* -*2. Nebula Exchange 2.0 支持Date、DateTime、Time类型数据的导入* +*2. Nebula Exchange 2.0 新增 null、Date、DateTime、Time 类型数据的导入* -*3. 配置文件参考 [application.conf](https://github.com/vesoft-inc/nebula-spark-utils/tree/main/nebula-exchange/src/main/resources)* +*3. Nebula Exchange 2.0 支持 Hive on Spark 以外的 Hive 数据源,需在配置文件中配置 Hive 源,具体配置示例参考 [server_application.conf](https://github.com/vesoft-inc/nebula-spark-utils/blob/main/nebula-exchange/src/main/resources/server_application.conf) 中 Hive 的配置* + +*4. Nebula Exchange 2.0 将导入失败的 INSERT 语句进行落盘,存于配置文件的 error/output 路径中* + +*5. 配置文件参考 [application.conf](https://github.com/vesoft-inc/nebula-spark-utils/tree/main/nebula-exchange/src/main/resources)* ## 贡献 Nebula Exchange 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: From 45489355b79d6fc7ba3a8d4402d87030d612cd8e Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 16 Dec 2020 13:16:45 +0800 Subject: [PATCH 011/213] support CI & format check --- .github/workflows/maven.yml | 34 ++++++++++++++++++++++++++++++++++ .scalafmt.conf | 4 ++++ .travis.yml | 13 +++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 .github/workflows/maven.yml create mode 100644 .scalafmt.conf create mode 100644 .travis.yml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..40ec5be --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,34 @@ +# This workflow will build a Java project with Maven +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: Java CI with Maven + +on: + push: + branches: + - 'main' + pull_request: + branches: + - 'main' + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + + - name: Cache the Maven packages to speed up build + uses: actions/cache@v2 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-maven- + + - name: Build with Maven + run: mvn -B package --file pom.xml diff --git a/.scalafmt.conf b/.scalafmt.conf new file mode 100644 index 0000000..ef61765 --- /dev/null +++ b/.scalafmt.conf @@ -0,0 +1,4 @@ +align = more +maxColumn = 100 +docstrings = ScalaDoc +assumeStandardLibraryStripMargin = true \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..9d0c0d8 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +# Copyright (c) 2020 vesoft inc. All rights reserved. +# +# This source code is licensed under Apache 2.0 License, +# attached with Common Clause Condition 1.0, found in the LICENSES directory. + +language: java + +jdk: + - oraclejdk11 + - openjdk8 + - openjdk11 + +install: mvn clean compile package install -Dgpg.skip -Dmaven.javadoc.skip=true From 6e26d6403a4d1d5057a9a4af29c2be9b3acaa82f Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 16 Dec 2020 19:43:33 +0800 Subject: [PATCH 012/213] unify package name --- .../CheckPointHandler.scala | 7 ++++--- .../importer => exchange}/ErrorHandler.scala | 2 +- .../importer => exchange}/Exchange.scala | 20 +++++++++---------- .../importer => exchange}/GraphProvider.scala | 4 ++-- .../importer => exchange}/MetaProvider.scala | 4 ++-- .../config/Configs.scala | 5 +++-- .../config/SchemaConfigs.scala | 4 ++-- .../config/SinkConfigs.scala | 2 +- .../config/SourceConfigs.scala | 4 ++-- .../importer => exchange}/package.scala | 4 ++-- .../processor/EdgeProcessor.scala | 18 +++++------------ .../processor/Processor.scala | 4 ++-- .../processor/ReloadProcessor.scala | 6 +++--- .../processor/VerticesProcessor.scala | 20 +++++++++---------- .../reader/FileBaseReader.scala | 4 ++-- .../importer => exchange}/reader/Reader.scala | 6 +++--- .../reader/ServerBaseReader.scala | 14 ++++++++++--- .../reader/StreamingBaseReader.scala | 7 ++----- .../utils/HDFSUtils.scala | 2 +- .../utils/KafkaUtils.scala | 4 ++-- .../utils/NebulaUtils.scala | 15 ++++++-------- .../writer/FileBaseWriter.scala | 9 ++------- .../writer/ServerBaseWriter.scala | 10 ++++++---- .../importer => exchange}/writer/Writer.scala | 2 +- .../vesoft/nebula/exchange}/MockConfigs.scala | 16 +++++++++++---- .../nebula/exchange}/MockGraphData.scala | 15 +++----------- .../nebula/exchange}/MockQueryProcessor.scala | 8 +++----- .../nebula/exchange}/MockQueryServer.java | 5 +++-- 28 files changed, 105 insertions(+), 116 deletions(-) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/CheckPointHandler.scala (85%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/ErrorHandler.scala (95%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/Exchange.scala (96%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/GraphProvider.scala (94%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/MetaProvider.scala (96%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/config/Configs.scala (99%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/config/SchemaConfigs.scala (97%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/config/SinkConfigs.scala (96%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/config/SourceConfigs.scala (98%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/package.scala (97%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/processor/EdgeProcessor.scala (94%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/processor/Processor.scala (95%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/processor/ReloadProcessor.scala (89%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/processor/VerticesProcessor.scala (94%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/reader/FileBaseReader.scala (96%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/reader/Reader.scala (93%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/reader/ServerBaseReader.scala (96%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/reader/StreamingBaseReader.scala (90%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/utils/HDFSUtils.scala (97%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/utils/KafkaUtils.scala (76%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/utils/NebulaUtils.scala (90%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/writer/FileBaseWriter.scala (89%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/writer/ServerBaseWriter.scala (97%) rename nebula-exchange/src/main/scala/com/vesoft/nebula/{tools/importer => exchange}/writer/Writer.scala (85%) rename nebula-exchange/src/test/scala/{mock => com/vesoft/nebula/exchange}/MockConfigs.scala (84%) rename nebula-exchange/src/test/scala/{mock => com/vesoft/nebula/exchange}/MockGraphData.scala (95%) rename nebula-exchange/src/test/scala/{mock => com/vesoft/nebula/exchange}/MockQueryProcessor.scala (90%) rename nebula-exchange/src/test/scala/{mock => com/vesoft/nebula/exchange}/MockQueryServer.java (97%) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/CheckPointHandler.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/CheckPointHandler.scala similarity index 85% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/CheckPointHandler.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/CheckPointHandler.scala index e3a4495..6f69291 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/CheckPointHandler.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/CheckPointHandler.scala @@ -4,10 +4,11 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer +package com.vesoft.nebula.exchange -import com.vesoft.nebula.tools.importer.config.{SchemaConfigEntry, SourceCategory} -import com.vesoft.nebula.tools.importer.utils.HDFSUtils +import com.vesoft.nebula.exchange.config.{SourceCategory} +import com.vesoft.nebula.exchange.utils.HDFSUtils +import com.vesoft.nebula.exchange.config.SchemaConfigEntry import org.apache.spark.TaskContext /** diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/ErrorHandler.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala similarity index 95% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/ErrorHandler.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala index 04b337a..39a451d 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/ErrorHandler.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala @@ -4,7 +4,7 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer +package com.vesoft.nebula.exchange import org.apache.hadoop.conf.Configuration import org.apache.hadoop.fs.{FileSystem, Path} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala similarity index 96% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/Exchange.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index 202dddd..08758e6 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -4,15 +4,15 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer +package com.vesoft.nebula.exchange import org.apache.spark.sql.{DataFrame, SparkSession} import java.io.File -import com.vesoft.nebula.tools.importer.config.{ + +import com.vesoft.nebula.exchange.config.{ Configs, DataSourceConfigEntry, FileBaseSourceConfigEntry, - HBaseSourceConfigEntry, HiveSourceConfigEntry, JanusGraphSourceConfigEntry, KafkaSourceConfigEntry, @@ -21,12 +21,8 @@ import com.vesoft.nebula.tools.importer.config.{ PulsarSourceConfigEntry, SourceCategory } -import com.vesoft.nebula.tools.importer.processor.{ - EdgeProcessor, - ReloadProcessor, - VerticesProcessor -} -import com.vesoft.nebula.tools.importer.reader.{ +import com.vesoft.nebula.exchange.processor.{EdgeProcessor, VerticesProcessor} +import com.vesoft.nebula.exchange.reader.{ CSVReader, HBaseReader, HiveReader, @@ -36,9 +32,11 @@ import com.vesoft.nebula.tools.importer.reader.{ MySQLReader, Neo4JReader, ORCReader, - ParquetReader, - PulsarReader + ParquetReader } +import com.vesoft.nebula.exchange.config.HBaseSourceConfigEntry +import com.vesoft.nebula.exchange.processor.ReloadProcessor +import com.vesoft.nebula.exchange.reader.PulsarReader import org.apache.log4j.Logger import org.apache.spark.SparkConf diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/GraphProvider.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala similarity index 94% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/GraphProvider.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala index d99bb05..bbb8355 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/GraphProvider.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala @@ -4,13 +4,13 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer +package com.vesoft.nebula.exchange import com.google.common.net.HostAndPort import com.vesoft.nebula.client.graph.NebulaPoolConfig import com.vesoft.nebula.client.graph.data.{HostAddress, ResultSet} import com.vesoft.nebula.client.graph.net.{NebulaPool, Session} -import com.vesoft.nebula.tools.importer.config.UserConfigEntry +import com.vesoft.nebula.exchange.config.UserConfigEntry import org.apache.log4j.Logger import scala.collection.JavaConverters._ diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/MetaProvider.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala similarity index 96% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/MetaProvider.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala index ea567c2..abf7b8f 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/MetaProvider.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala @@ -4,13 +4,13 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer +package com.vesoft.nebula.exchange import com.google.common.net.HostAndPort import com.vesoft.nebula.client.graph.data.HostAddress import com.vesoft.nebula.client.meta.MetaClient +import com.vesoft.nebula.exchange.config.Type import com.vesoft.nebula.meta.PropertyType -import com.vesoft.nebula.tools.importer.config.Type import org.apache.log4j.Logger import scala.collection.JavaConverters._ diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala similarity index 99% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/Configs.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala index b9f37cf..53b873c 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/Configs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala @@ -4,14 +4,15 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.config +package com.vesoft.nebula.exchange.config import java.io.File import java.nio.file.Files import com.google.common.net.HostAndPort -import com.vesoft.nebula.tools.importer.{Argument, KeyPolicy} +import com.vesoft.nebula.exchange.KeyPolicy import com.typesafe.config.{Config, ConfigFactory} +import com.vesoft.nebula.exchange.Argument import org.apache.log4j.Logger import scala.collection.JavaConverters._ diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SchemaConfigs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SchemaConfigs.scala similarity index 97% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SchemaConfigs.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SchemaConfigs.scala index 33a964d..37ea24b 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SchemaConfigs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SchemaConfigs.scala @@ -4,9 +4,9 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.config +package com.vesoft.nebula.exchange.config -import com.vesoft.nebula.tools.importer.KeyPolicy +import com.vesoft.nebula.exchange.KeyPolicy /** * SchemaConfigEntry is tag/edge super class use to save some basic parameter for importer. diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SinkConfigs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala similarity index 96% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SinkConfigs.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala index 3e8e093..c7839f6 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SinkConfigs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala @@ -4,7 +4,7 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.config +package com.vesoft.nebula.exchange.config /** * SinkCategory is used to expression the writer's type. diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SourceConfigs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala similarity index 98% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SourceConfigs.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala index 6c51b09..542b34a 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/config/SourceConfigs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala @@ -4,9 +4,9 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.config +package com.vesoft.nebula.exchange.config -import com.vesoft.nebula.tools.importer.utils.NebulaUtils +import com.vesoft.nebula.exchange.utils.NebulaUtils /** * Category use to explain the data source which the Spark application could reading. diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/package.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/package.scala similarity index 97% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/package.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/package.scala index 8ffcbd4..7370372 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/package.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/package.scala @@ -4,13 +4,13 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools +package com.vesoft.nebula import com.google.common.base.Optional import com.google.common.util.concurrent.ListenableFuture import scala.collection.mutable.ListBuffer -package object importer { +package object exchange { type GraphSpaceID = Int type PartitionID = Int diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala similarity index 94% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index b12dda9..3a4ceab 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -4,26 +4,19 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.processor +package com.vesoft.nebula.exchange.processor import com.google.common.geometry.{S2CellId, S2LatLng} -import com.vesoft.nebula.tools.importer.config.{ +import com.vesoft.nebula.exchange.config.{ Configs, EdgeConfigEntry, SinkCategory, StreamingDataSourceConfigEntry } -import com.vesoft.nebula.tools.importer.utils.NebulaUtils -import com.vesoft.nebula.tools.importer.{ - Edge, - Edges, - ErrorHandler, - GraphProvider, - MetaProvider, - VidType -} +import com.vesoft.nebula.exchange.utils.NebulaUtils +import com.vesoft.nebula.exchange.{Edge, Edges, ErrorHandler, GraphProvider, MetaProvider, VidType} import org.apache.log4j.Logger -import com.vesoft.nebula.tools.importer.writer.NebulaGraphClientWriter +import com.vesoft.nebula.exchange.writer.NebulaGraphClientWriter import org.apache.spark.sql.streaming.Trigger import org.apache.spark.sql.{DataFrame, Encoders} import org.apache.spark.util.LongAccumulator @@ -47,7 +40,6 @@ class EdgeProcessor(data: DataFrame, private def processEachPartition(iterator: Iterator[Edge]): Unit = { val graphProvider = new GraphProvider(config.databaseConfig.getGraphAddress) - val writer = new NebulaGraphClientWriter(config.databaseConfig, config.userConfig, config.connectionConfig, diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/Processor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala similarity index 95% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/Processor.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala index 76a17f3..380bb06 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/Processor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala @@ -4,10 +4,10 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.processor +package com.vesoft.nebula.exchange.processor import com.vesoft.nebula.meta.PropertyType -import com.vesoft.nebula.tools.importer.utils.{HDFSUtils, NebulaUtils} +import com.vesoft.nebula.exchange.utils.{HDFSUtils, NebulaUtils} import org.apache.spark.sql.Row import org.apache.spark.sql.types.{IntegerType, LongType, StringType} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/ReloadProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala similarity index 89% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/ReloadProcessor.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala index a7f3fc3..df978c8 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/ReloadProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala @@ -4,10 +4,10 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.processor +package com.vesoft.nebula.exchange.processor -import com.vesoft.nebula.tools.importer.{ErrorHandler, GraphProvider} -import com.vesoft.nebula.tools.importer.config.Configs +import com.vesoft.nebula.exchange.{ErrorHandler, GraphProvider} +import com.vesoft.nebula.exchange.config.Configs import org.apache.spark.sql.{DataFrame, Row} import org.apache.spark.util.LongAccumulator diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala similarity index 94% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index a6f67b1..864a3e8 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -4,16 +4,9 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.processor +package com.vesoft.nebula.exchange.processor -import com.vesoft.nebula.tools.importer.config.{ - Configs, - SinkCategory, - StreamingDataSourceConfigEntry, - TagConfigEntry -} -import com.vesoft.nebula.tools.importer.utils.{NebulaUtils} -import com.vesoft.nebula.tools.importer.{ +import com.vesoft.nebula.exchange.{ ErrorHandler, GraphProvider, MetaProvider, @@ -21,8 +14,15 @@ import com.vesoft.nebula.tools.importer.{ Vertices, VidType } +import com.vesoft.nebula.exchange.config.{ + Configs, + SinkCategory, + StreamingDataSourceConfigEntry, + TagConfigEntry +} +import com.vesoft.nebula.exchange.utils.NebulaUtils +import com.vesoft.nebula.exchange.writer.NebulaGraphClientWriter import org.apache.log4j.Logger -import com.vesoft.nebula.tools.importer.writer.{NebulaGraphClientWriter} import org.apache.spark.sql.streaming.Trigger import org.apache.spark.sql.{DataFrame, Encoders} import org.apache.spark.util.LongAccumulator diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/FileBaseReader.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/FileBaseReader.scala similarity index 96% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/FileBaseReader.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/FileBaseReader.scala index 06ac879..2c55f5d 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/FileBaseReader.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/FileBaseReader.scala @@ -4,9 +4,9 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.reader +package com.vesoft.nebula.exchange.reader -import com.vesoft.nebula.tools.importer.config.FileBaseSourceConfigEntry +import com.vesoft.nebula.exchange.config.FileBaseSourceConfigEntry import org.apache.spark.sql.catalyst.encoders.RowEncoder import org.apache.spark.sql.types.StructType import org.apache.spark.sql.{DataFrame, Row, SparkSession} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/Reader.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/Reader.scala similarity index 93% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/Reader.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/Reader.scala index d10f102..f2ecaf3 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/Reader.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/Reader.scala @@ -4,10 +4,10 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.reader +package com.vesoft.nebula.exchange.reader -import com.vesoft.nebula.tools.importer.Offset -import com.vesoft.nebula.tools.importer.utils.HDFSUtils +import com.vesoft.nebula.exchange.Offset +import com.vesoft.nebula.exchange.utils.HDFSUtils import org.apache.spark.sql.{DataFrame, SparkSession} /** diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/ServerBaseReader.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala similarity index 96% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/ServerBaseReader.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala index 71fe14a..0f3b522 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/ServerBaseReader.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala @@ -4,11 +4,18 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.reader +package com.vesoft.nebula.exchange.reader import com.google.common.collect.Maps -import com.vesoft.nebula.tools.importer.config._ -import com.vesoft.nebula.tools.importer.utils.HDFSUtils +import com.vesoft.nebula.exchange.config.{ + HBaseSourceConfigEntry, + HiveSourceConfigEntry, + JanusGraphSourceConfigEntry, + MySQLSourceConfigEntry, + Neo4JSourceConfigEntry, + ServerDataSourceConfigEntry +} +import com.vesoft.nebula.exchange.utils.HDFSUtils import org.apache.hadoop.hbase.HBaseConfiguration import org.apache.hadoop.hbase.client.Result import org.apache.hadoop.hbase.io.ImmutableBytesWritable @@ -31,6 +38,7 @@ import org.neo4j.driver.{AuthTokens, GraphDatabase} import org.neo4j.spark.dataframe.CypherTypes import org.neo4j.spark.utils.Neo4jSessionAwareIterator import org.neo4j.spark.{Executor, Neo4jConfig} + import scala.collection.JavaConverters._ import scala.collection.mutable.ListBuffer diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/StreamingBaseReader.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/StreamingBaseReader.scala similarity index 90% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/StreamingBaseReader.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/StreamingBaseReader.scala index 55177f5..2549317 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/reader/StreamingBaseReader.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/StreamingBaseReader.scala @@ -4,12 +4,9 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.reader +package com.vesoft.nebula.exchange.reader -import com.vesoft.nebula.tools.importer.config.{ - KafkaSourceConfigEntry, - PulsarSourceConfigEntry -} +import com.vesoft.nebula.exchange.config.{KafkaSourceConfigEntry, PulsarSourceConfigEntry} import org.apache.spark.sql.{DataFrame, SparkSession} /** diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/HDFSUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala similarity index 97% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/HDFSUtils.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala index b6a6ae2..77d131f 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/HDFSUtils.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala @@ -4,7 +4,7 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.utils +package com.vesoft.nebula.exchange.utils import java.nio.charset.Charset import org.apache.hadoop.conf.Configuration diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/KafkaUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/KafkaUtils.scala similarity index 76% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/KafkaUtils.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/KafkaUtils.scala index cd019bf..3458d78 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/KafkaUtils.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/KafkaUtils.scala @@ -4,9 +4,9 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.utils +package com.vesoft.nebula.exchange.utils -import com.vesoft.nebula.tools.importer.{Edge, Vertex} +import com.vesoft.nebula.exchange.{Edge, Vertex} object KafkaUtils { diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/NebulaUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala similarity index 90% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/NebulaUtils.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala index 4b3aa9a..009dcf0 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/utils/NebulaUtils.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala @@ -4,17 +4,14 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.utils +package com.vesoft.nebula.exchange.utils -import com.vesoft.nebula.meta.{PropertyType} -import com.vesoft.nebula.tools.importer.MetaProvider -import com.vesoft.nebula.tools.importer.config.{ - EdgeConfigEntry, - SchemaConfigEntry, - TagConfigEntry, - Type -} +import com.vesoft.nebula.exchange.MetaProvider +import com.vesoft.nebula.meta.PropertyType +import com.vesoft.nebula.exchange.MetaProvider +import com.vesoft.nebula.exchange.config.{EdgeConfigEntry, SchemaConfigEntry, TagConfigEntry, Type} import org.apache.log4j.Logger + import scala.collection.JavaConversions.seqAsJavaList import scala.collection.mutable diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/FileBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/FileBaseWriter.scala similarity index 89% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/FileBaseWriter.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/FileBaseWriter.scala index 2fad1d2..6990443 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/FileBaseWriter.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/FileBaseWriter.scala @@ -4,14 +4,9 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.writer +package com.vesoft.nebula.exchange.writer -import org.rocksdb.{ - EnvOptions, - Options, - RocksDB, - SstFileWriter -} +import org.rocksdb.{EnvOptions, Options, RocksDB, SstFileWriter} import org.slf4j.LoggerFactory /** diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala similarity index 97% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala index 6482dd1..48c3c24 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/ServerBaseWriter.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala @@ -4,13 +4,14 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.writer +package com.vesoft.nebula.exchange.writer import java.util.concurrent.{CountDownLatch, TimeUnit} + import com.google.common.base.Optional import com.google.common.util.concurrent.{FutureCallback, RateLimiter} import com.vesoft.nebula.graph.ErrorCode -import com.vesoft.nebula.tools.importer.config.{ +import com.vesoft.nebula.exchange.config.{ ConnectionConfigEntry, DataBaseConfigEntry, RateConfigEntry, @@ -18,8 +19,8 @@ import com.vesoft.nebula.tools.importer.config.{ Type, UserConfigEntry } -import com.vesoft.nebula.tools.importer.utils.{HDFSUtils, NebulaUtils} -import com.vesoft.nebula.tools.importer.{ +import com.vesoft.nebula.exchange.utils.HDFSUtils +import com.vesoft.nebula.exchange.{ Edges, GraphProvider, KeyPolicy, @@ -28,6 +29,7 @@ import com.vesoft.nebula.tools.importer.{ } import org.apache.log4j.Logger import org.apache.spark.util.LongAccumulator + import scala.collection.JavaConverters._ abstract class ServerBaseWriter extends Writer { diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/Writer.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/Writer.scala similarity index 85% rename from nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/Writer.scala rename to nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/Writer.scala index 9ea5783..f750662 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/tools/importer/writer/Writer.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/Writer.scala @@ -4,7 +4,7 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.writer +package com.vesoft.nebula.exchange.writer /** * diff --git a/nebula-exchange/src/test/scala/mock/MockConfigs.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockConfigs.scala similarity index 84% rename from nebula-exchange/src/test/scala/mock/MockConfigs.scala rename to nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockConfigs.scala index 5b7edb5..d5e789d 100644 --- a/nebula-exchange/src/test/scala/mock/MockConfigs.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockConfigs.scala @@ -4,10 +4,18 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package mock - -import com.vesoft.nebula.tools.importer.config._ -import com.vesoft.nebula.tools.importer.test.mock.{MockGraphDataEdge, MockGraphDataVertex} +package com.vesoft.nebula.exchange + +import com.vesoft.nebula.exchange.config.{ + Configs, + ConnectionConfigEntry, + DataBaseConfigEntry, + ErrorConfigEntry, + ExecutionConfigEntry, + RateConfigEntry, + SparkConfigEntry, + UserConfigEntry +} import scala.util.Random diff --git a/nebula-exchange/src/test/scala/mock/MockGraphData.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockGraphData.scala similarity index 95% rename from nebula-exchange/src/test/scala/mock/MockGraphData.scala rename to nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockGraphData.scala index f8a96e4..424986d 100644 --- a/nebula-exchange/src/test/scala/mock/MockGraphData.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockGraphData.scala @@ -4,22 +4,13 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.test.mock +package com.vesoft.nebula.exchange import com.typesafe.config.impl.ConfigImpl.fromAnyRef -import com.vesoft.nebula.tools.importer.KeyPolicy -import com.vesoft.nebula.tools.importer.config.{ - EdgeConfigEntry, - FileBaseSourceConfigEntry, - NebulaSinkConfigEntry, - SinkCategory, - SourceCategory, - TagConfigEntry -} +import com.vesoft.nebula.exchange.KeyPolicy +import com.vesoft.nebula.exchange.config._ import org.apache.spark.sql.{DataFrame, SparkSession} -import scala.collection.immutable - object Spark { private val master = "local[1]" private val appName = "exchange_testing" diff --git a/nebula-exchange/src/test/scala/mock/MockQueryProcessor.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockQueryProcessor.scala similarity index 90% rename from nebula-exchange/src/test/scala/mock/MockQueryProcessor.scala rename to nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockQueryProcessor.scala index 84a819a..50f4b29 100644 --- a/nebula-exchange/src/test/scala/mock/MockQueryProcessor.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockQueryProcessor.scala @@ -4,16 +4,15 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package com.vesoft.nebula.tools.importer.test.mock +package com.vesoft.nebula.exchange import com.vesoft.nebula.graph.{AuthResponse, ErrorCode, ExecutionResponse, GraphService} -import mock.MockConfigs import org.apache.log4j.Logger class MockQueryProcessor extends GraphService.Iface { private[this] val LOG = Logger.getLogger(this.getClass) - var queryStatement: Array[Byte] = null + var queryStatement: Array[Byte] = null var countDownLatchFailOfInsert: Int = -1 var countDownLatchFailOfSentence: Int = -1 @@ -25,8 +24,7 @@ class MockQueryProcessor extends GraphService.Iface { def resetLatchInsert(): Unit = countDownLatchFailOfInsert = -1 def resetLatchSentence(): Unit = countDownLatchFailOfSentence = -1 - override def authenticate(username: Array[Byte], - password: Array[Byte]): AuthResponse = { + override def authenticate(username: Array[Byte], password: Array[Byte]): AuthResponse = { LOG.info(s"Get login user: ${username}, password: ${password}") if (MockConfigs.userConfig.user == username && MockConfigs.userConfig.password == password) new AuthResponse(ErrorCode.SUCCEEDED, "SUCCEEDED".getBytes(), 1) diff --git a/nebula-exchange/src/test/scala/mock/MockQueryServer.java b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockQueryServer.java similarity index 97% rename from nebula-exchange/src/test/scala/mock/MockQueryServer.java rename to nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockQueryServer.java index 52679ac..bc3305b 100644 --- a/nebula-exchange/src/test/scala/mock/MockQueryServer.java +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockQueryServer.java @@ -4,7 +4,7 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package mock; +package com.vesoft.nebula.exchange; import com.facebook.thrift.TProcessor; import com.facebook.thrift.TProcessorFactory; @@ -65,7 +65,8 @@ public void serve() { TRpcConnectionContext serverCtx = new TRpcConnectionContext(client, inputProtocol, outputProtocol); try { - while (processor.process(inputProtocol, outputProtocol, serverCtx)) ; + while (processor.process(inputProtocol, outputProtocol, serverCtx)) + ; } catch (TTransportException e) { } } From c6e686fa961f65b12d4083b6c923badfd520aa1d Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 17 Dec 2020 09:41:01 +0800 Subject: [PATCH 013/213] rm workflow for waiting new client version --- .github/workflows/maven.yml | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 .github/workflows/maven.yml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml deleted file mode 100644 index 40ec5be..0000000 --- a/.github/workflows/maven.yml +++ /dev/null @@ -1,34 +0,0 @@ -# This workflow will build a Java project with Maven -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven - -name: Java CI with Maven - -on: - push: - branches: - - 'main' - pull_request: - branches: - - 'main' - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - - name: Cache the Maven packages to speed up build - uses: actions/cache@v2 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: ${{ runner.os }}-maven- - - - name: Build with Maven - run: mvn -B package --file pom.xml From f4a593fcc02fd63e48bae5fa97932b46c5b3ed67 Mon Sep 17 00:00:00 2001 From: shawdan <61895496+oldLady344@users.noreply.github.com> Date: Thu, 17 Dec 2020 12:52:20 +0800 Subject: [PATCH 014/213] updated readme --- README.md | 7 ++++++- nebula-exchange/README.md | 34 +++++++++++++++++++++------------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 4c5ad19..a1de0a1 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,7 @@ # nebula-spark-utils -Spark related libraries and tools + +The nebula-spark-utils project holds all the Apache Spark™ related libraries and tools for Nebula Graph v2.x. + +For Nebula Graph v2.x, see [nebula-graph](https://github.com/vesoft-inc/nebula-graph). + +If you want to use Spark utitilies for [Nebula Graph v1.x](https://github.com/vesoft-inc/nebula), visit [the v1.0 branch of nebula-java](https://github.com/vesoft-inc/nebula-java/tree/v1.0). diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index d64a1a4..cf09f0b 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -1,44 +1,52 @@ # 欢迎使用 Nebula Exchange 2.0 -Nebula Exchange(简称为 Exchange),是一款 Apache Spark™ 应用,用于在分布式环境中将集群中的数据批量迁移到 Nebula Graph 中,能支持多种不同格式的批式数据和流式数据的迁移。 +Nebula Exchange 2.0(简称为 Exchange 2.0)是一款 Apache Spark™ 应用,用于在分布式环境中将集群中的数据批量迁移到 Nebula Graph 中,能支持多种不同格式的批式数据和流式数据的迁移。 + +Exchange 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Nebula Graph v1.x,请使用 [Nebula Exchange v1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools)。 ## 如何编译 -Nebula Exchange 2.0 依赖 Nebula Java Client 2.0。 -1. 编译打包 Nebula Java Client 2.0 - ``` +Exchange 2.0 依赖 Nebula Java Client 2.0。 + +1. 编译打包 Nebula Java Client 2.0。 + + ```bash $ git clone https://github.com/vesoft-inc/nebula-java.git $ cd nebula-java $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true ``` + 打包结束后,在本地 Maven Repository 仓库中可以看到生成的 /com/vesoft/client/2.0.0-beta/client-2.0.0-beta.jar。 -2. 编译打包 Nebula Exchange 2.0 - ``` +2. 编译打包 Exchange 2.0。 + + ```bash $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git $ cd nebula-spark-utils/nebula-exchange $ mvn clean package -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true ``` + 编译打包完成后,可以在 nebula-spark-utils/nebula-exchange/target/ 目录下看到 nebula-exchange-2.0.0.jar 文件。 ## 使用说明 -关于 Nebula Exchange 2.0 的详细使用说明,请参考 1.0 的使用文档[《Nebula Exchange 用户手册》](https://docs.nebula-graph.com.cn/nebula-exchange/about-exchange/ex-ug-what-is-exchange/ "点击前往 Nebula Graph 网站")。 +关于 Exchange 2.0 的详细使用说明,请参考 Exchange 1.0 的使用文档[《Nebula Exchange 用户手册》](https://docs.nebula-graph.com.cn/nebula-exchange/about-exchange/ex-ug-what-is-exchange/ "点击前往 Nebula Graph 网站")。 特性 & 注意事项: -*1. Nebula Graph 2.0 暂时只支持 String 类型的 VID,请勿配置点 ID 或者边的 src_id、dst_id 的 policy* +*1. Nebula Graph 2.0 暂时只支持 String 类型的 VID,请勿配置点 ID 或者边的 src_id、dst_id 的 policy。* + +*2. Exchange 2.0 新增 null、Date、DateTime、Time 类型数据的导入。* -*2. Nebula Exchange 2.0 新增 null、Date、DateTime、Time 类型数据的导入* +*3. Exchange 2.0 支持 Hive on Spark 以外的 Hive 数据源,需在配置文件中配置 Hive 源,具体配置示例参考 [server_application.conf](https://github.com/vesoft-inc/nebula-spark-utils/blob/main/nebula-exchange/src/main/resources/server_application.conf) 中 Hive 的配置。* -*3. Nebula Exchange 2.0 支持 Hive on Spark 以外的 Hive 数据源,需在配置文件中配置 Hive 源,具体配置示例参考 [server_application.conf](https://github.com/vesoft-inc/nebula-spark-utils/blob/main/nebula-exchange/src/main/resources/server_application.conf) 中 Hive 的配置* +*4. Exchange 2.0 将导入失败的 INSERT 语句进行落盘,存于配置文件的 error/output 路径中。* -*4. Nebula Exchange 2.0 将导入失败的 INSERT 语句进行落盘,存于配置文件的 error/output 路径中* +*5. 配置文件参考 [application.conf](https://github.com/vesoft-inc/nebula-spark-utils/tree/main/nebula-exchange/src/main/resources)。* -*5. 配置文件参考 [application.conf](https://github.com/vesoft-inc/nebula-spark-utils/tree/main/nebula-exchange/src/main/resources)* ## 贡献 -Nebula Exchange 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: +Nebula Exchange 2.0 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: - 前往 [Nebula Graph 论坛](https://discuss.nebula-graph.com.cn/ "点击前往“Nebula Graph 论坛") 上参与 Issue 讨论,如答疑、提供想法或者报告无法解决的问题 - 撰写或改进文档 From 1609890f7ce2f01fb09238d44e41f3d275060d82 Mon Sep 17 00:00:00 2001 From: shawdan <61895496+oldLady344@users.noreply.github.com> Date: Thu, 17 Dec 2020 12:55:24 +0800 Subject: [PATCH 015/213] udpated --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a1de0a1..66d201f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # nebula-spark-utils -The nebula-spark-utils project holds all the Apache Spark™ related libraries and tools for Nebula Graph v2.x. +The nebula-spark-utils repository holds all the Apache Spark™ related libraries and tools for Nebula Graph v2.x. For Nebula Graph v2.x, see [nebula-graph](https://github.com/vesoft-inc/nebula-graph). From d1d32c17fbb259f2ff061a69b337bb9423b59a1e Mon Sep 17 00:00:00 2001 From: shawdan <61895496+oldLady344@users.noreply.github.com> Date: Thu, 17 Dec 2020 14:02:59 +0800 Subject: [PATCH 016/213] removed .github/workflows/maven.yml --- .github/workflows/maven.yml | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 .github/workflows/maven.yml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml deleted file mode 100644 index 40ec5be..0000000 --- a/.github/workflows/maven.yml +++ /dev/null @@ -1,34 +0,0 @@ -# This workflow will build a Java project with Maven -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven - -name: Java CI with Maven - -on: - push: - branches: - - 'main' - pull_request: - branches: - - 'main' - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - - name: Cache the Maven packages to speed up build - uses: actions/cache@v2 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: ${{ runner.os }}-maven- - - - name: Build with Maven - run: mvn -B package --file pom.xml From 94f4102f810eba2a2921f613f7d82fe6ffde4f06 Mon Sep 17 00:00:00 2001 From: shawdan <61895496+oldLady344@users.noreply.github.com> Date: Thu, 17 Dec 2020 14:28:29 +0800 Subject: [PATCH 017/213] fixed typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 66d201f..b78a348 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,4 @@ The nebula-spark-utils repository holds all the Apache Spark™ related libr For Nebula Graph v2.x, see [nebula-graph](https://github.com/vesoft-inc/nebula-graph). -If you want to use Spark utitilies for [Nebula Graph v1.x](https://github.com/vesoft-inc/nebula), visit [the v1.0 branch of nebula-java](https://github.com/vesoft-inc/nebula-java/tree/v1.0). +If you want to use Spark utilities for [Nebula Graph v1.x](https://github.com/vesoft-inc/nebula), visit [the v1.0 branch of nebula-java](https://github.com/vesoft-inc/nebula-java/tree/v1.0). From c4350885e41d1ba246957fc9e8c075e7133ed94a Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 21 Dec 2020 10:24:46 +0800 Subject: [PATCH 018/213] remove specific String type --- .../scala/com/vesoft/nebula/exchange/processor/Processor.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala index 380bb06..947bbd8 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala @@ -47,7 +47,7 @@ trait Processor extends Serializable { fieldTypeMap(field) match { case PropertyType.STRING => { - val result = NebulaUtils.escapeUtil(row.getString(index)).mkString("\"", "", "\"") + val result = NebulaUtils.escapeUtil(row.get(index).toString).mkString("\"", "", "\"") if (toBytes) result.getBytes else result } case PropertyType.DATE => "date(\"" + row.get(index) + "\")" From 52a190831386b51430ffc2448ad19be4c0d8b6ea Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 23 Dec 2020 16:31:03 +0800 Subject: [PATCH 019/213] add README-CH.md --- nebula-exchange/README-CN.md | 54 ++++++++++++++++++++++++++++++++++++ nebula-exchange/README.md | 49 +++++++++++++------------------- 2 files changed, 74 insertions(+), 29 deletions(-) create mode 100644 nebula-exchange/README-CN.md diff --git a/nebula-exchange/README-CN.md b/nebula-exchange/README-CN.md new file mode 100644 index 0000000..aca8e38 --- /dev/null +++ b/nebula-exchange/README-CN.md @@ -0,0 +1,54 @@ +# 欢迎使用 Nebula Exchange 2.0 +[English](https://github.com/vesoft-inc/nebula-spark-utils/blob/main/nebula-exchange/README.md) + +Nebula Exchange 2.0(简称为 Exchange 2.0)是一款 Apache Spark™ 应用,用于在分布式环境中将集群中的数据批量迁移到 Nebula Graph 中,能支持多种不同格式的批式数据和流式数据的迁移。 + +Exchange 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Nebula Graph v1.x,请使用 [Nebula Exchange v1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools/exchange) 。 + +## 如何编译 + +Exchange 2.0 依赖 Nebula Java Client 2.0。 + +1. 编译打包 Nebula Java Client 2.0。 + + ```bash + $ git clone https://github.com/vesoft-inc/nebula-java.git + $ cd nebula-java + $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true + ``` + + 打包结束后,在本地 Maven Repository 仓库中可以看到生成的 /com/vesoft/client/2.0.0-beta/client-2.0.0-beta.jar。 + +2. 编译打包 Exchange 2.0。 + + ```bash + $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git + $ cd nebula-spark-utils/nebula-exchange + $ mvn clean package -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true + ``` + + 编译打包完成后,可以在 nebula-spark-utils/nebula-exchange/target/ 目录下看到 nebula-exchange-2.0.0.jar 文件。 + +## 使用说明 + +关于 Exchange 2.0 的详细使用说明,请参考 Exchange 1.0 的使用文档[《Nebula Exchange 用户手册》](https://docs.nebula-graph.com.cn/nebula-exchange/about-exchange/ex-ug-what-is-exchange/ "点击前往 Nebula Graph 网站")。 + +特性 & 注意事项: + +*1. Nebula Graph 2.0 暂时只支持 String 类型的 VID,请勿配置点 ID 或者边的 src_id、dst_id 的 policy。* + +*2. Exchange 2.0 新增 null、Date、DateTime、Time 类型数据的导入。* + +*3. Exchange 2.0 支持 Hive on Spark 以外的 Hive 数据源,需在配置文件中配置 Hive 源,具体配置示例参考 [server_application.conf](https://github.com/vesoft-inc/nebula-spark-utils/blob/main/nebula-exchange/src/main/resources/server_application.conf) 中 Hive 的配置。* + +*4. Exchange 2.0 将导入失败的 INSERT 语句进行落盘,存于配置文件的 error/output 路径中。* + +*5. 配置文件参考 [application.conf](https://github.com/vesoft-inc/nebula-spark-utils/tree/main/nebula-exchange/src/main/resources)。* + +## 贡献 + +Nebula Exchange 2.0 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: + +- 前往 [Nebula Graph 论坛](https://discuss.nebula-graph.com.cn/ "点击前往“Nebula Graph 论坛") 上参与 Issue 讨论,如答疑、提供想法或者报告无法解决的问题 +- 撰写或改进文档 +- 提交优化代码 diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index cf09f0b..bd3de74 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -1,14 +1,15 @@ -# 欢迎使用 Nebula Exchange 2.0 +# Nebula Exchange 2.0 + [中文版](https://github.com/vesoft-inc/nebula-spark-utils/blob/main/nebula-exchange/README-CN.md) + +Nebula Exchange (Exchange for short) is an Apache Spark application. It is used to migrate cluster data in bulk from Spark to Nebula Graph in a distributed environment. It supports migration of batch data and streaming data in various formats. -Nebula Exchange 2.0(简称为 Exchange 2.0)是一款 Apache Spark™ 应用,用于在分布式环境中将集群中的数据批量迁移到 Nebula Graph 中,能支持多种不同格式的批式数据和流式数据的迁移。 +Exchange 2.0 only supports Nebula Graph 2.x. If you want to import data for Nebula Graph v1.x,please use [Nebula Exchange v1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools/exchange). -Exchange 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Nebula Graph v1.x,请使用 [Nebula Exchange v1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools)。 +## How to Compile -## 如何编译 +Exchange 2.0 depends on the latest Nebula Java Client 2.0。 -Exchange 2.0 依赖 Nebula Java Client 2.0。 - -1. 编译打包 Nebula Java Client 2.0。 +1. Install Nebula Java Client 2.0。 ```bash $ git clone https://github.com/vesoft-inc/nebula-java.git @@ -16,9 +17,9 @@ Exchange 2.0 依赖 Nebula Java Client 2.0。 $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true ``` - 打包结束后,在本地 Maven Repository 仓库中可以看到生成的 /com/vesoft/client/2.0.0-beta/client-2.0.0-beta.jar。 + After the installing, you can see the newly generated /com/vesoft/client/2.0.0-beta/client-2.0.0-beta.jar in your local Maven repository. -2. 编译打包 Exchange 2.0。 +2. Package Exchange 2.0。 ```bash $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git @@ -26,28 +27,18 @@ Exchange 2.0 依赖 Nebula Java Client 2.0。 $ mvn clean package -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true ``` - 编译打包完成后,可以在 nebula-spark-utils/nebula-exchange/target/ 目录下看到 nebula-exchange-2.0.0.jar 文件。 - -## 使用说明 - -关于 Exchange 2.0 的详细使用说明,请参考 Exchange 1.0 的使用文档[《Nebula Exchange 用户手册》](https://docs.nebula-graph.com.cn/nebula-exchange/about-exchange/ex-ug-what-is-exchange/ "点击前往 Nebula Graph 网站")。 - -特性 & 注意事项: - -*1. Nebula Graph 2.0 暂时只支持 String 类型的 VID,请勿配置点 ID 或者边的 src_id、dst_id 的 policy。* - -*2. Exchange 2.0 新增 null、Date、DateTime、Time 类型数据的导入。* - -*3. Exchange 2.0 支持 Hive on Spark 以外的 Hive 数据源,需在配置文件中配置 Hive 源,具体配置示例参考 [server_application.conf](https://github.com/vesoft-inc/nebula-spark-utils/blob/main/nebula-exchange/src/main/resources/server_application.conf) 中 Hive 的配置。* + After the packaging, you can see the newly generated nebula-exchange-2.0.0.jar under this directory nebula-spark-utils/nebula-exchange/target/. + +## How to use -*4. Exchange 2.0 将导入失败的 INSERT 语句进行落盘,存于配置文件的 error/output 路径中。* +For more detail about Exchange, please refer to Exchange 1.0. -*5. 配置文件参考 [application.conf](https://github.com/vesoft-inc/nebula-spark-utils/tree/main/nebula-exchange/src/main/resources)。* -## 贡献 +## New Features -Nebula Exchange 2.0 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: +1. Support to import VID of String type +2. Support to import data of Null, Date, DateTime, and Time types +3. Support to import data from other Hive sources than Hive on Spark +4. Added record and retry of the INSERT statement failure during the import -- 前往 [Nebula Graph 论坛](https://discuss.nebula-graph.com.cn/ "点击前往“Nebula Graph 论坛") 上参与 Issue 讨论,如答疑、提供想法或者报告无法解决的问题 -- 撰写或改进文档 -- 提交优化代码 +Refer to [application.conf](https://github.com/vesoft-inc/nebula-spark-utils/tree/main/nebula-exchange/src/main/resources) to see how to config the configuration file. From ac692ba0bd801442103eb689bc87805e7b1cf66f Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 24 Dec 2020 14:38:22 +0800 Subject: [PATCH 020/213] add link for exchange1.0 --- nebula-exchange/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index bd3de74..5c72bbc 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -31,7 +31,7 @@ Exchange 2.0 depends on the latest Nebula Java Client 2.0。 ## How to use -For more detail about Exchange, please refer to Exchange 1.0. +For more detail about Exchange, please refer to [Exchange 1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools/exchange) . ## New Features From 41464503e6f8f2ee1006b2c9fa7d9710ebdb98e7 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 24 Dec 2020 16:18:02 +0800 Subject: [PATCH 021/213] deal with olLady's comments --- nebula-exchange/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index 5c72bbc..61c0d73 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -27,18 +27,18 @@ Exchange 2.0 depends on the latest Nebula Java Client 2.0。 $ mvn clean package -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true ``` - After the packaging, you can see the newly generated nebula-exchange-2.0.0.jar under this directory nebula-spark-utils/nebula-exchange/target/. + After the packaging, you can see the newly generated nebula-exchange-2.0.0.jar under the nebula-spark-utils/nebula-exchange/target/ directory. ## How to use -For more detail about Exchange, please refer to [Exchange 1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools/exchange) . +For more details about Exchange, please refer to [Exchange 1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools/exchange) . ## New Features -1. Support to import VID of String type -2. Support to import data of Null, Date, DateTime, and Time types -3. Support to import data from other Hive sources than Hive on Spark -4. Added record and retry of the INSERT statement failure during the import +1. Supports to import VID of String type +2. Supports to import data of Null, Date, DateTime, and Time types +3. Supports to import data from other Hive sources than Hive on Spark +4. Adds record and retry of the INSERT statement after failures during data import -Refer to [application.conf](https://github.com/vesoft-inc/nebula-spark-utils/tree/main/nebula-exchange/src/main/resources) to see how to config the configuration file. +Refer to [application.conf](https://github.com/vesoft-inc/nebula-spark-utils/tree/main/nebula-exchange/src/main/resources) as an example to edit the configuration file. From f2ec2f39131b214303cf5a5785c60efec5b270e9 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 24 Dec 2020 16:29:25 +0800 Subject: [PATCH 022/213] deal with olLady's comments --- nebula-exchange/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index 61c0d73..23d9363 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -36,9 +36,9 @@ For more details about Exchange, please refer to [Exchange 1.0](https://github.c ## New Features -1. Supports to import VID of String type -2. Supports to import data of Null, Date, DateTime, and Time types -3. Supports to import data from other Hive sources than Hive on Spark -4. Adds record and retry of the INSERT statement after failures during data import +1. Supports importing vertex data with String type IDs. +2. Supports importing data of the Null, Date, DateTime, and Time types. +3. Supports importing data from other Hive sources besides Hive on Spark. +4. Supports recording and retrying the INSERT statement after failures during data import. Refer to [application.conf](https://github.com/vesoft-inc/nebula-spark-utils/tree/main/nebula-exchange/src/main/resources) as an example to edit the configuration file. From 411dff4d23130437116434fababb5dac64d8bce8 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 18 Dec 2020 13:56:57 +0800 Subject: [PATCH 023/213] add spark partition number for errorBuffer file --- .../scala/com/vesoft/nebula/exchange/Exchange.scala | 2 +- .../nebula/exchange/processor/EdgeProcessor.scala | 13 ++++++++----- .../nebula/exchange/processor/ReloadProcessor.scala | 10 ++++++---- .../exchange/processor/VerticesProcessor.scala | 13 +++++++------ .../nebula/exchange/writer/ServerBaseWriter.scala | 4 ++-- 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index 08758e6..7f8eb55 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -181,7 +181,7 @@ object Exchange { if (ErrorHandler.existError(configs.errorConfig.errorPath)) { val batchSuccess = spark.sparkContext.longAccumulator(s"batchSuccess.reimport") val batchFailure = spark.sparkContext.longAccumulator(s"batchFailure.reimport") - val data = spark.read.text() + val data = spark.read.text(configs.errorConfig.errorPath) val processor = new ReloadProcessor(data, configs, batchSuccess, batchFailure) processor.process() LOG.info(s"batchSuccess.reimport: ${batchSuccess.value}") diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index 3a4ceab..8f109df 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -17,6 +17,7 @@ import com.vesoft.nebula.exchange.utils.NebulaUtils import com.vesoft.nebula.exchange.{Edge, Edges, ErrorHandler, GraphProvider, MetaProvider, VidType} import org.apache.log4j.Logger import com.vesoft.nebula.exchange.writer.NebulaGraphClientWriter +import org.apache.spark.TaskContext import org.apache.spark.sql.streaming.Trigger import org.apache.spark.sql.{DataFrame, Encoders} import org.apache.spark.util.LongAccumulator @@ -60,13 +61,15 @@ class EdgeProcessor(data: DataFrame, errorBuffer.append(failStatement) batchFailure.add(1) } - - if (errorBuffer.nonEmpty) { - ErrorHandler.save(errorBuffer, s"${config.errorConfig.errorPath}/${edgeConfig.name}") - errorBuffer.clear() - } + } + if (errorBuffer.nonEmpty) { + ErrorHandler.save( + errorBuffer, + s"${config.errorConfig.errorPath}/${edgeConfig.name}.${TaskContext.getPartitionId}") + errorBuffer.clear() } writer.close() + graphProvider.close() } override def process(): Unit = { diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala index df978c8..073bf66 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala @@ -8,6 +8,7 @@ package com.vesoft.nebula.exchange.processor import com.vesoft.nebula.exchange.{ErrorHandler, GraphProvider} import com.vesoft.nebula.exchange.config.Configs +import org.apache.spark.TaskContext import org.apache.spark.sql.{DataFrame, Row} import org.apache.spark.util.LongAccumulator @@ -41,10 +42,11 @@ class ReloadProcessor(data: DataFrame, } else { batchSuccess.add(1) } - if (errorBuffer.nonEmpty) { - ErrorHandler.save(errorBuffer, s"${config.errorConfig.errorPath}/reload") - errorBuffer.clear() - } }) + if (errorBuffer.nonEmpty) { + ErrorHandler.save(errorBuffer, + s"${config.errorConfig.errorPath}/reload.${TaskContext.getPartitionId()}") + errorBuffer.clear() + } } } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index 864a3e8..bb5f261 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -23,6 +23,7 @@ import com.vesoft.nebula.exchange.config.{ import com.vesoft.nebula.exchange.utils.NebulaUtils import com.vesoft.nebula.exchange.writer.NebulaGraphClientWriter import org.apache.log4j.Logger +import org.apache.spark.TaskContext import org.apache.spark.sql.streaming.Trigger import org.apache.spark.sql.{DataFrame, Encoders} import org.apache.spark.util.LongAccumulator @@ -75,13 +76,13 @@ class VerticesProcessor(data: DataFrame, errorBuffer.append(failStatement) batchFailure.add(1) } - - if (errorBuffer.nonEmpty) { - ErrorHandler.save(errorBuffer, s"${config.errorConfig.errorPath}/${tagConfig.name}") - errorBuffer.clear() - } } - + if (errorBuffer.nonEmpty) { + ErrorHandler.save( + errorBuffer, + s"${config.errorConfig.errorPath}/${tagConfig.name}.${TaskContext.getPartitionId()}") + errorBuffer.clear() + } writer.close() graphProvider.close() } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala index 48c3c24..d07e26a 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala @@ -148,7 +148,7 @@ class NebulaGraphClientWriter(dataBaseConfigEntry: DataBaseConfigEntry, if (result.isSucceeded) { return null } - LOG.error(s"write vertex failed with statement $sentence. ${result.getErrorMessage}") + LOG.error(s"write vertex failed for ${result.getErrorMessage}") } else { LOG.error(s"write vertex failed because write speed is too fast") } @@ -163,7 +163,7 @@ class NebulaGraphClientWriter(dataBaseConfigEntry: DataBaseConfigEntry, if (result.isSucceeded) { return null } - LOG.error(s"write edge failed with statement $sentence. ${result.getErrorMessage}") + LOG.error(s"write edge failed for ${result.getErrorMessage}") } else { LOG.error(s"write vertex failed because write speed is too fast") } From a5fafc104fb4836a189064a5477d5197ae44b60b Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 18 Dec 2020 09:57:53 +0800 Subject: [PATCH 024/213] add spark-connector 2.0 writer & example --- example/.gitignore | 36 ++ example/pom.xml | 123 +++++ example/src/main/resources/edge | 10 + example/src/main/resources/log4j.properties | 6 + example/src/main/resources/vertex | 10 + .../connector/NebulaSparkWriterExample.scala | 94 ++++ nebula-spark-connector/README.md | 58 +++ nebula-spark-connector/pom.xml | 127 +++++ .../nebula/connector/NebulaConfig.scala | 487 ++++++++++++++++++ .../nebula/connector/NebulaDataSource.scala | 146 ++++++ .../vesoft/nebula/connector/NebulaEnum.scala | 32 ++ .../nebula/connector/NebulaOptions.scala | 230 +++++++++ .../vesoft/nebula/connector/NebulaUtils.scala | 129 +++++ .../nebula/connector/PartitionUtils.scala | 22 + .../vesoft/nebula/connector/Template.scala | 18 + .../connector/exception/Exception.scala | 33 ++ .../connector/nebula/GraphProvider.scala | 62 +++ .../connector/nebula/MetaProvider.scala | 101 ++++ .../com/vesoft/nebula/connector/package.scala | 273 ++++++++++ .../reader/NebulaEdgePartitionReader.scala | 68 +++ .../connector/reader/NebulaPartition.scala | 24 + .../reader/NebulaPartitionReader.scala | 68 +++ .../connector/reader/NebulaSourceReader.scala | 121 +++++ .../reader/NebulaVertexPartitionReader.scala | 67 +++ .../reader/tmp/ScanEdgeResultIterator.scala | 27 + .../reader/tmp/ScanVertexResultIterator.scala | 27 + .../connector/reader/tmp/StorageClient.scala | 17 + .../writer/NebulaCommitMessage.scala | 11 + .../connector/writer/NebulaEdgeWriter.scala | 95 ++++ .../connector/writer/NebulaExecutor.scala | 258 ++++++++++ .../connector/writer/NebulaSourceWriter.scala | 101 ++++ .../connector/writer/NebulaVertexWriter.scala | 73 +++ .../connector/writer/NebulaWriter.scala | 46 ++ .../nebula/connector/NebulaConfigSuit.scala | 95 ++++ .../connector/writer/NebulaExecutorSuit.scala | 122 +++++ pom.xml | 1 + 36 files changed, 3218 insertions(+) create mode 100644 example/.gitignore create mode 100644 example/pom.xml create mode 100644 example/src/main/resources/edge create mode 100644 example/src/main/resources/log4j.properties create mode 100644 example/src/main/resources/vertex create mode 100644 example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala create mode 100644 nebula-spark-connector/README.md create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaDataSource.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaEnum.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaOptions.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/PartitionUtils.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/exception/Exception.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/nebula/GraphProvider.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/nebula/MetaProvider.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaEdgePartitionReader.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartition.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartitionReader.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaSourceReader.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaVertexPartitionReader.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanEdgeResultIterator.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanVertexResultIterator.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/StorageClient.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaCommitMessage.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaSourceWriter.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala create mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaWriter.scala create mode 100644 nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/NebulaConfigSuit.scala create mode 100644 nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuit.scala diff --git a/example/.gitignore b/example/.gitignore new file mode 100644 index 0000000..84e7a6b --- /dev/null +++ b/example/.gitignore @@ -0,0 +1,36 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +# build target +target/ + +# IDE +.idea/ +.eclipse/ +*.iml + +spark-importer.ipr +spark-importer.iws + +.DS_Store diff --git a/example/pom.xml b/example/pom.xml new file mode 100644 index 0000000..091693f --- /dev/null +++ b/example/pom.xml @@ -0,0 +1,123 @@ + + + + nebula-spark + com.vesoft + 2.0.0 + ../pom.xml + + 4.0.0 + + example + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + test-jar + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.1 + + + package + + shade + + + false + + + org.apache.spark:* + org.apache.hadoop:* + org.apache.hive:* + log4j:log4j + org.apache.orc:* + xml-apis:xml-apis + javax.inject:javax.inject + org.spark-project.hive:hive-exec + stax:stax-api + org.glassfish.hk2.external:aopalliance-repackaged + + + + + *:* + + com/vesoft/tools/** + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + + + + + org.slf4j + slf4j-log4j12 + 1.7.25 + + + org.slf4j + slf4j-api + 1.7.25 + + + + org.apache.spark + spark-core_2.11 + 2.4.4 + + + org.apache.spark + spark-sql_2.11 + 2.4.4 + + + + com.vesoft + nebula-spark-connector + 2.0.0 + + + \ No newline at end of file diff --git a/example/src/main/resources/edge b/example/src/main/resources/edge new file mode 100644 index 0000000..0681588 --- /dev/null +++ b/example/src/main/resources/edge @@ -0,0 +1,10 @@ +{"src":12345,"dst":23456,"degree":34, "descr": "aaa","timep": "2020-01-01"} +{"src":11111,"dst":22222,"degree":33, "descr": "aaa","timep": "2020-01-01"} +{"src":11111,"dst":33333,"degree":32, "descr": "a\baa","timep": "2020-01-01"} +{"src":11111,"dst":44444,"degree":31, "descr": "aaa","timep": "2020-01-01"} +{"src":22222,"dst":55555,"degree":30, "descr": "a\naa","timep": "2020-01-01"} +{"src":33333,"dst":44444,"degree":29, "descr": "aaa","timep": "2020-01-01"} +{"src":33333,"dst":55555,"degree":28, "descr": "aa\ta","timep": "2020-01-01"} +{"src":44444,"dst":22222,"degree":27, "descr": "aaa","timep": "2020-01-01"} +{"src":44444,"dst":55555,"degree":26, "descr": "aaa","timep": "2020-01-01"} +{"src":22222,"dst":66666,"degree":25, "descr": "aaa","timep": "2020-01-01"} \ No newline at end of file diff --git a/example/src/main/resources/log4j.properties b/example/src/main/resources/log4j.properties new file mode 100644 index 0000000..913391d --- /dev/null +++ b/example/src/main/resources/log4j.properties @@ -0,0 +1,6 @@ +# Global logging configuration +log4j.rootLogger=INFO, stdout +# Console output... +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n diff --git a/example/src/main/resources/vertex b/example/src/main/resources/vertex new file mode 100644 index 0000000..7694dac --- /dev/null +++ b/example/src/main/resources/vertex @@ -0,0 +1,10 @@ +{"id":"aa","name":"Tom","age":10,"timep": "2020-01-01"} +{"id":"\ns","name":"Bob","age":11,"timep": "2020-01-02"} +{"id":14,"name":"Jane","age":12,"timep": "2020-01-03"} +{"id":15,"name":"Jena","age":13,"timep": "2020-01-04"} +{"id":16,"name":"Ni\tc","age":14,"timep": "2020-01-05"} +{"id":17,"name":"Mei","age":15,"timep": "2020-01-06"} +{"id":18,"name":"HH","age":16,"timep": "2020-01-07"} +{"id":19,"name":"Ty\nler","age":17,"timep": "2020-01-08"} +{"id":20,"name":"Ber","age":18,"timep": "2020-01-09"} +{"id":21,"name":"Mercy","age":19,"timep": "2020-01-10"} \ No newline at end of file diff --git a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala new file mode 100644 index 0000000..152f44e --- /dev/null +++ b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala @@ -0,0 +1,94 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.examples.connector + +import com.facebook.thrift.protocol.TCompactProtocol +import com.vesoft.nebula.connector.{ + NebulaConnectionConfig, + WriteNebulaEdgeConfig, + WriteNebulaVertexConfig +} +import com.vesoft.nebula.connector.connector.NebulaDataFrameWriter +import org.apache.spark.SparkConf +import org.apache.spark.sql.SparkSession +import org.apache.spark.storage.StorageLevel +import org.slf4j.LoggerFactory + +object NebulaSparkWriterExample { + private val LOG = LoggerFactory.getLogger(this.getClass) + + def main(args: Array[String]): Unit = { + + val sparkConf = new SparkConf + sparkConf + .set("spark.serializer", "org.apache.spark.serializer.KryoSerializer") + .registerKryoClasses(Array[Class[_]](classOf[TCompactProtocol])) + val spark = SparkSession + .builder() + .master("local") + .config(sparkConf) + .getOrCreate() + + writeVertex(spark) + // writeEdge(spark) + + spark.close() + sys.exit() + } + + def writeVertex(spark: SparkSession): Unit = { + LOG.info("start to write nebula vertices") + val df = spark.read.json("example/src/main/resources/vertex") + df.show() + + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:45500") + .withGraphAddress("127.0.0.1:3699") + .withConenctionRetry(2) + .build() + val nebulaWriteVertexConfig: WriteNebulaVertexConfig = WriteNebulaVertexConfig + .builder() + .withSpace("test") + .withTag("person") + .withVidField("id") + .withVidAsProp(true) + .withBatch(1000) + .build() + df.write.nebula(config, nebulaWriteVertexConfig).writeVertices() + } + + def writeEdge(spark: SparkSession): Unit = { + LOG.info("start to write nebula edges") + val df = spark.read.json("example/src/main/resources/edge") + df.show() + df.persist(StorageLevel.MEMORY_AND_DISK_SER) + + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress("192.168.8.172:45509") + .withGraphAddress("192.168.8.172:3799") + .withConenctionRetry(2) + .build + val nebulaWriteEdgeConfig: WriteNebulaEdgeConfig = WriteNebulaEdgeConfig + .builder() + .withSpace("exchange") + .withEdge("friend1") + .withSrcIdField("src") + .withDstIdField("dst") + .withRankField("degree") + .withSrcAsProperty(true) + .withDstAsProperty(true) + .withRankAsProperty(true) + .withBatch(1000) + .build() + df.write.nebula(config, nebulaWriteEdgeConfig).writeEdges() + } + +} diff --git a/nebula-spark-connector/README.md b/nebula-spark-connector/README.md new file mode 100644 index 0000000..909f613 --- /dev/null +++ b/nebula-spark-connector/README.md @@ -0,0 +1,58 @@ +# 欢迎使用 Nebula Spark Connector 2.0 + +# 介绍 + +Nebula Spark Connector 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Nebula Graph v1.x,请使用 [Nebula Spark Connector v1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools)。 + +## 如何编译 + +Nebula Spark Connector 2.0 依赖 Nebula Java Client 2.0。 + +1. 编译打包 Nebula Java Client 2.0。 + + ```bash + $ git clone https://github.com/vesoft-inc/nebula-java.git + $ cd nebula-java + $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true + ``` + + 打包结束后,在本地 Maven Repository 仓库中可以看到生成的 /com/vesoft/client/2.0.0-beta/client-2.0.0-beta.jar。 + +2. 编译打包 Nebula Spark Connector 2.0。 + + ```bash + $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git + $ cd nebula-spark-utils/nebula-spark-connector + $ mvn clean package -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true + ``` + + 编译打包完成后,可以在 nebula-spark-utils/nebula-spark-connector/target/ 目录下看到 nebula-spark-connector-2.0.0.jar 文件。 + +## 使用说明 + + 将 DataFrame 作为点写入 Nebula Graph : + ``` + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:45500") + .withGraphAddress("127.0.0.1:3699") + .build() + val nebulaWriteVertexConfig: WriteNebulaVertexConfig = WriteNebulaVertexConfig + .builder() + .withSpace("test") + .withTag("person") + .withVidField("id") + .withVidAsProp(true) + .withBatch(1000) + .build() + df.write.nebula(config, nebulaWriteVertexConfig).writeVertices() + ``` + +## 贡献 + +Nebula Spark Connector 2.0 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: + +- 前往 [Nebula Graph 论坛](https://discuss.nebula-graph.com.cn/ "点击前往“Nebula Graph 论坛") 上参与 Issue 讨论,如答疑、提供想法或者报告无法解决的问题 +- 撰写或改进文档 +- 提交优化代码 diff --git a/nebula-spark-connector/pom.xml b/nebula-spark-connector/pom.xml index 9dbd072..a3d6005 100644 --- a/nebula-spark-connector/pom.xml +++ b/nebula-spark-connector/pom.xml @@ -6,9 +6,136 @@ nebula-spark com.vesoft 2.0.0 + ../pom.xml 4.0.0 nebula-spark-connector + + + 2.4.4 + 2.0.0-beta + 1.8 + 1.8 + 4.13.1 + 3.2.3 + + + + + org.apache.spark + spark-core_2.11 + ${spark.version} + + + org.apache.spark + spark-sql_2.11 + ${spark.version} + + + org.apache.spark + spark-graphx_2.11 + ${spark.version} + + + com.vesoft + client + ${nebula.version} + + + + org.scalatest + scalatest-funsuite_2.11 + ${scalatest.version} + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + test-jar + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${compiler.source.version} + ${compiler.target.version} + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.1 + + + package + + shade + + + false + + + org.apache.spark:* + org.apache.hadoop:* + org.apache.hive:* + log4j:log4j + org.apache.orc:* + xml-apis:xml-apis + javax.inject:javax.inject + org.spark-project.hive:hive-exec + stax:stax-api + org.glassfish.hk2.external:aopalliance-repackaged + + + + + *:* + + com/vesoft/tools/** + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + + net.alchim31.maven + scala-maven-plugin + 3.2.2 + + + + compile + testCompile + + + + + + + + \ No newline at end of file diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala new file mode 100644 index 0000000..1cf623b --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala @@ -0,0 +1,487 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector + +import org.slf4j.{Logger, LoggerFactory} + +import scala.collection.mutable.ListBuffer + +class NebulaConnectionConfig(metaAddress: String, + graphAddress: String, + timeout: Int, + connectionRetry: Int, + executeRetry: Int) + extends Serializable { + def getMetaAddress = metaAddress + def getGraphAddress = graphAddress + def getTimeout = timeout + def getConnectionRetry = connectionRetry + def getExecRetry = executeRetry +} + +object NebulaConnectionConfig { + class ConfigBuilder { + protected var metaAddress: String = _ + protected var graphAddress: String = _ + protected var timeout: Int = 6000 + protected var connectionRetry: Int = 1 + protected var executeRetry: Int = 1 + + def withMetaAddress(metaAddress: String): ConfigBuilder = { + this.metaAddress = metaAddress + this + } + + def withGraphAddress(graphAddress: String): ConfigBuilder = { + this.graphAddress = graphAddress + this + } + + /** + * set timeout, timeout is optional + */ + def withTimeout(timeout: Int): ConfigBuilder = { + this.timeout = timeout + this + } + + /** + * set connectionRetry, connectionRetry is optional + */ + def withConenctionRetry(connectionRetry: Int): ConfigBuilder = { + this.connectionRetry = connectionRetry + this + } + + /** + * set executeRetry, executeRetry is optional + */ + def withExecuteRetry(executeRetry: Int): ConfigBuilder = { + this.executeRetry = executeRetry + this + } + + def check(): Unit = { + assert(!metaAddress.isEmpty, "config address is empty.") + assert(timeout > 0, "timeout must be larger than 0") + assert(connectionRetry > 0 && executeRetry > 0, "retry must be larger than 0.") + } + + /** + * build NebulaConnectionConfig + */ + def build(): NebulaConnectionConfig = { + new NebulaConnectionConfig(metaAddress, graphAddress, timeout, connectionRetry, executeRetry) + } + } + + def builder(): ConfigBuilder = { + new ConfigBuilder + } + +} + +/** + * Base config needed when write dataframe into nebula graph + */ +private[connector] class WriteNebulaConfig(space: String, batch: Int) extends Serializable { + def getSpace = space + def getBatch = batch +} + +/** + * subclass of WriteNebulaConfig to config vertex when write dataframe into nebula graph + * + * @param space: nebula space name + * @param tagName: tag name + * @param vidField: field in dataframe to indicate vertexId + * @param vidPolicy: not required, use hash to map your vertexId + * @param batch: amount of one batch when write into nebula graph + */ +class WriteNebulaVertexConfig(space: String, + tagName: String, + vidField: String, + vidPolicy: String, + batch: Int, + vidAsProp: Boolean) + extends WriteNebulaConfig(space, batch) { + def getTagName = tagName + def getVidField = vidField + def getVidPolicy = if (vidPolicy == null) "" else vidPolicy + def getVidAsProp = vidAsProp +} + +/** + * object WriteNebulaVertexConfig + * */ +object WriteNebulaVertexConfig { + + private val LOG: Logger = LoggerFactory.getLogger(this.getClass) + + class WriteVertexConfigBuilder { + + var space: String = _ + var tagName: String = _ + var vidPolicy: String = _ + var vidField: String = _ + var batch: Int = 1000 + + /** whether set vid as property */ + var vidAsProp: Boolean = false + + def withSpace(space: String): WriteVertexConfigBuilder = { + this.space = space + this + } + + def withTag(tagName: String): WriteVertexConfigBuilder = { + this.tagName = tagName + this + } + + def withVidField(vidField: String): WriteVertexConfigBuilder = { + this.vidField = vidField + this + } + + /** + * set vid policy, its optional + * only "hash" and "uuid" is validate + */ + def withVidPolicy(vidPolicy: String): WriteVertexConfigBuilder = { + this.vidPolicy = vidPolicy + this + } + + /** + * set data amount for one batch, default is 1000 + */ + def withBatch(batch: Int): WriteVertexConfigBuilder = { + this.batch = batch + this + } + + /** + * set whether vid as prop, default is false + */ + def withVidAsProp(vidAsProp: Boolean): WriteVertexConfigBuilder = { + this.vidAsProp = vidAsProp + this + } + + def build(): WriteNebulaVertexConfig = { + check() + new WriteNebulaVertexConfig(space, tagName, vidField, vidPolicy, batch, vidAsProp) + } + + private def check(): Unit = { + assert(space != null && !space.isEmpty, s"config space is empty.") + assert(tagName != null && !tagName.isEmpty, s"config tagName is empty.") + assert(vidField != null && !vidField.isEmpty, "config vidField is empty.") + assert(batch > 0, s"config batch must be positive, your batch is $batch.") + assert( + vidPolicy == null + || vidPolicy.equalsIgnoreCase(KeyPolicy.HASH.toString) + || vidPolicy.equalsIgnoreCase(KeyPolicy.UUID.toString), + "config vidPolicy is illegal, please don't set vidPolicy or set vidPolicy \"HASH\" or \"UUID\"" + ) + LOG.info( + s"NebulaWriteVertexConfig={space=$space,tagName=$tagName,vidField=$vidField,vidPolicy=$vidPolicy,batch=$batch}") + } + } + + def builder(): WriteVertexConfigBuilder = { + new WriteVertexConfigBuilder + } +} + +/** + * subclass of WriteNebulaConfig to config edge when write dataframe into nebula graph + * + * @param space: nebula space name + * @param edgeName: edge name + * @param srcFiled: field in dataframe to indicate src vertex id + * @param srcPolicy: not required, use hash to map your src vertex id + * @param dstField: field in dataframe to indicate dst vertex id + * @param dstPolicy: not required, use hash to map your dst vertex id + * @param rankField: not required, field in dataframe to indicate edge rank + * @param batch: amount of one batch when write into nebula graph + */ +class WriteNebulaEdgeConfig(space: String, + edgeName: String, + srcFiled: String, + srcPolicy: String, + dstField: String, + dstPolicy: String, + rankField: String, + batch: Int, + srcAsProp: Boolean, + dstAsProp: Boolean, + rankAsProp: Boolean) + extends WriteNebulaConfig(space, batch) { + def getEdgeName = edgeName + def getSrcFiled = srcFiled + def getSrcPolicy = if (srcPolicy == null) "" else srcPolicy + def getDstField = dstField + def getDstPolicy = if (dstPolicy == null) "" else dstPolicy + def getRankField = rankField + + def getSrcAsProp = srcAsProp + def getDstAsProp = dstAsProp + def getRankAsProp = rankAsProp + +} + +/** + * object WriteNebulaEdgeConfig + */ +object WriteNebulaEdgeConfig { + + private val LOG: Logger = LoggerFactory.getLogger(WriteNebulaEdgeConfig.getClass) + + class WriteEdgeConfigBuilder { + + var space: String = _ + var edgeName: String = _ + + var srcIdField: String = _ + var srcPolicy: String = _ + var dstIdField: String = _ + var dstPolicy: String = _ + var rankField: String = _ + var batch: Int = 1000 + + /** whether srcId as property */ + var srcAsProp: Boolean = false + + /** whether dstId as property */ + var dstAsProp: Boolean = false + + /** whether set rank as property */ + var rankAsProp: Boolean = false + + def withSpace(space: String): WriteEdgeConfigBuilder = { + this.space = space + this + } + + def withEdge(edgeName: String): WriteEdgeConfigBuilder = { + this.edgeName = edgeName + this + } + + /** + * set rank field in dataframe + * it rankField is not set, then edge has no rank value + * */ + def withRankField(rankField: String): WriteEdgeConfigBuilder = { + this.rankField = rankField + this + } + + def withSrcIdField(srcIdField: String): WriteEdgeConfigBuilder = { + this.srcIdField = srcIdField + this + } + + /** + * set policy for edge src id, its optional + */ + def withSrcPolicy(srcPolicy: String): WriteEdgeConfigBuilder = { + this.srcPolicy = srcPolicy + this + } + + def withDstIdField(dstIdField: String): WriteEdgeConfigBuilder = { + this.dstIdField = dstIdField + this + } + + /** + * set policy for edge dst id, its optional + */ + def withDstPolicy(dstPolicy: String): WriteEdgeConfigBuilder = { + this.dstPolicy = dstPolicy + this + } + + /** + * set data amount for one batch, default is 1000 + */ + def withBatch(batch: Int): WriteEdgeConfigBuilder = { + this.batch = batch + this + } + + /** + * set whether src id as property + */ + def withSrcAsProperty(srcAsProp: Boolean): WriteEdgeConfigBuilder = { + this.srcAsProp = srcAsProp + this + } + + /** + * set whether dst id as property + */ + def withDstAsProperty(dstAsProp: Boolean): WriteEdgeConfigBuilder = { + this.dstAsProp = dstAsProp + this + } + + /** + * set whether rank as property + */ + def withRankAsProperty(rankAsProp: Boolean): WriteEdgeConfigBuilder = { + this.rankAsProp = rankAsProp + this + } + + def build(): WriteNebulaEdgeConfig = { + check() + new WriteNebulaEdgeConfig(space, + edgeName, + srcIdField, + srcPolicy, + dstIdField, + dstPolicy, + rankField, + batch, + srcAsProp, + dstAsProp, + rankAsProp) + } + + private def check(): Unit = { + assert(space != null && !space.isEmpty, s"config space is empty.") + assert(edgeName != null && !edgeName.isEmpty, s"config edgeName is empty.") + assert(srcIdField != null && !srcIdField.isEmpty, "config srcIdField is empty.") + assert(dstIdField != null && !dstIdField.isEmpty, "config dstIdField is empty.") + assert( + srcPolicy == null + || srcPolicy.equalsIgnoreCase(KeyPolicy.HASH.toString) + || srcPolicy.equalsIgnoreCase(KeyPolicy.UUID.toString), + "config srcPolicy is illegal, please don't set srcPolicy or set srcPolicy \"HASH\" or \"UUID\"" + ) + assert( + dstPolicy == null + || dstPolicy.equalsIgnoreCase(KeyPolicy.HASH.toString) + || dstPolicy.equalsIgnoreCase(KeyPolicy.UUID.toString), + "config dstPolicy is illegal, please don't set dstPolicy or set dstPolicy \"HASH\" or \"UUID\"" + ) + assert(batch > 0, s"config batch must be positive, your batch is $batch.") + LOG.info( + s"NebulaWriteEdgeConfig={space=$space,edgeName=$edgeName,srcField=$srcIdField,srcPolicy=$srcPolicy,dstField=$dstIdField,dstPolicy=$dstPolicy,rankField=$rankField}") + } + } + + def builder(): WriteEdgeConfigBuilder = { + new WriteEdgeConfigBuilder + } +} + +/** + * config needed when read from nebula graph + * for read vertex or edge: + * you must need to set these configs: addresses/space/label + * you can set noColumn to true to read no vertex col, and you can set returnCols to read the specific cols, if the returnCols is empty, then read all the columns. + * you can set partitionNum to define spark partition nums to read nebula graph. + */ +class ReadNebulaConfig(space: String, + label: String, + returnCols: List[String], + noColumn: Boolean, + partitionNum: Int, + limit: Int) + extends Serializable { + def getSpace = space + def getLabel = label + def getReturnCols = returnCols + def getNoColumn = noColumn + def getPartitionNum = partitionNum + def getLimit = limit + // todo add filter +} + +/** + * object ReadNebulaConfig + */ +object ReadNebulaConfig { + private val LOG: Logger = LoggerFactory.getLogger(this.getClass) + + class ReadConfigBuilder { + var space: String = _ + var label: String = _ + var returnCols: ListBuffer[String] = new ListBuffer[String] + var noColumn: Boolean = false + var partitionNum: Int = 100 + var limit: Int = 1000 + + def withSpace(space: String): ReadConfigBuilder = { + this.space = space + this + } + def withLabel(label: String): ReadConfigBuilder = { + this.label = label + this + } + + def withReturnCols(returnCols: List[String]): ReadConfigBuilder = { + for (col: String <- returnCols) { + this.returnCols.append(col) + } + this + } + + /** + * if noColumn is set to true, then returnCols is no need and it will be invalidate even if configured + */ + def withNoColumn(noColumn: Boolean): ReadConfigBuilder = { + this.noColumn = noColumn + this + } + + /** + * set partition num for spark, default is 100 + */ + def withPartitionNum(partitionNum: Int): ReadConfigBuilder = { + this.partitionNum = partitionNum + this + } + + /** + * set limit for scan nebula graph, default is 1000 + */ + def withLimit(limit: Int): ReadConfigBuilder = { + this.limit = limit + this + } + + def build(): ReadNebulaConfig = { + check() + new ReadNebulaConfig(space, label, returnCols.toList, noColumn, partitionNum, limit) + } + + private def check(): Unit = { + assert(space != null && !space.isEmpty, s"config space is empty.") + assert(label != null && !label.isEmpty, s"config label is empty.") + assert(limit > 0, s"config limit must be positive, your limit is $limit") + assert(partitionNum > 0, s"config partitionNum must be positive, your partitionNum is $limit") + if (noColumn && returnCols.nonEmpty) { + LOG.warn( + s"noColumn is true, returnCols will be invalidate and your result will not contain cols") + } + LOG.info( + s"NebulaReadConfig={space=$space,label=$label,returnCols=$returnCols,noColumn=$noColumn,partitionNum=$partitionNum}") + } + } + + def builder(): ReadConfigBuilder = { + new ReadConfigBuilder + } + +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaDataSource.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaDataSource.scala new file mode 100644 index 0000000..a343054 --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaDataSource.scala @@ -0,0 +1,146 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector + +import java.util.Map.Entry +import java.util.Optional + +import com.vesoft.nebula.connector.exception.IllegalOptionException +import com.vesoft.nebula.connector.reader.{NebulaDataSourceEdgeReader, NebulaDataSourceVertexReader} +import com.vesoft.nebula.connector.writer.{NebulaDataSourceEdgeWriter, NebulaDataSourceVertexWriter} +import org.apache.spark.sql.SaveMode +import org.apache.spark.sql.catalyst.util.CaseInsensitiveMap +import org.apache.spark.sql.sources.DataSourceRegister +import org.apache.spark.sql.sources.v2.reader.DataSourceReader +import org.apache.spark.sql.sources.v2.writer.DataSourceWriter +import org.apache.spark.sql.sources.v2.{DataSourceOptions, DataSourceV2, ReadSupport, WriteSupport} +import org.apache.spark.sql.types.StructType +import org.slf4j.LoggerFactory + +import scala.collection.JavaConversions.iterableAsScalaIterable + +class NebulaDataSource + extends DataSourceV2 + with ReadSupport + with WriteSupport + with DataSourceRegister { + private val LOG = LoggerFactory.getLogger(this.getClass) + + /** + * The string that represents the format that nebula data source provider uses. + */ + override def shortName(): String = "nebula" + + /** + * Creates a {@link DataSourceReader} to scan the data from Nebula Graph. + */ + override def createReader(options: DataSourceOptions): DataSourceReader = { + val nebulaOptions = getNebulaOptions(options, OperaType.READ) + val dataType = nebulaOptions.dataType + + LOG.info("create reader") + LOG.info(s"options ${options.asMap()}") + + if (DataTypeEnum.VERTEX == DataTypeEnum.withName(dataType)) { + new NebulaDataSourceVertexReader(nebulaOptions) + } else { + new NebulaDataSourceEdgeReader(nebulaOptions) + } + } + + /** + * Creates an optional {@link DataSourceWriter} to save the data to Nebula Graph. + */ + override def createWriter(writeUUID: String, + schema: StructType, + mode: SaveMode, + options: DataSourceOptions): Optional[DataSourceWriter] = { + + val nebulaOptions = getNebulaOptions(options, OperaType.WRITE) + val dataType = nebulaOptions.dataType + if (mode == SaveMode.Ignore || mode == SaveMode.ErrorIfExists) { + LOG.warn(s"Currently do not support mode") + } + + LOG.info("create writer") + LOG.info(s"options ${options.asMap()}") + + if (DataTypeEnum.VERTEX == DataTypeEnum.withName(dataType)) { + val vertexFiled = nebulaOptions.vertexField + val vertexIndex: Int = { + var index: Int = -1 + for (i <- schema.fields.indices) { + if (schema.fields(i).name.equals(vertexFiled)) { + index = i + } + } + if (index < 0) { + throw new IllegalOptionException( + s" vertex field ${vertexFiled} does not exist in dataframe") + } + index + } + Optional.of(new NebulaDataSourceVertexWriter(nebulaOptions, vertexIndex, schema)) + } else { + val srcVertexFiled = nebulaOptions.srcVertexField + val dstVertexField = nebulaOptions.dstVertexField + val rankExist = nebulaOptions.rankField != null + val edgeFieldsIndex = { + var srcIndex: Int = -1 + var dstIndex: Int = -1 + var rankIndex: Int = -1 + for (i <- schema.fields.indices) { + if (schema.fields(i).name.equals(srcVertexFiled)) { + srcIndex = i + } + if (schema.fields(i).name.equals(dstVertexField)) { + dstIndex = i + } + if (rankExist) { + if (schema.fields(i).name.equals(nebulaOptions.rankField)) { + rankIndex = i + } + } + } + // check src filed and dst field + if (srcIndex < 0 || dstIndex < 0) { + throw new IllegalOptionException( + s" srcVertex field ${srcVertexFiled} or dstVertex field ${dstVertexField} do not exist in dataframe") + } + // check rank field + if (rankExist && rankIndex < 0) { + throw new IllegalOptionException(s"rank field does not exist in dataframe") + } + + if (!rankExist) { + (srcIndex, dstIndex, Option.empty) + } else { + (srcIndex, dstIndex, Option(rankIndex)) + } + + } + Optional.of( + new NebulaDataSourceEdgeWriter(nebulaOptions, + edgeFieldsIndex._1, + edgeFieldsIndex._2, + edgeFieldsIndex._3, + schema)) + } + } + + /** + * construct nebula options with DataSourceOptions + */ + def getNebulaOptions(options: DataSourceOptions, operateType: OperaType.Value): NebulaOptions = { + var parameters: Map[String, String] = Map() + for (entry: Entry[String, String] <- options.asMap().entrySet) { + parameters += (entry.getKey -> entry.getValue) + } + val nebulaOptions = new NebulaOptions(CaseInsensitiveMap(parameters))(operateType) + nebulaOptions + } +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaEnum.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaEnum.scala new file mode 100644 index 0000000..d39203f --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaEnum.scala @@ -0,0 +1,32 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector + +object DataTypeEnum extends Enumeration { + + type DataType = Value + val VERTEX = Value("vertex") + val EDGE = Value("edge") + + def validDataType(dataType: String): Boolean = { + dataType.equalsIgnoreCase(VERTEX.toString) || dataType.equalsIgnoreCase(EDGE.toString) + } +} + +object KeyPolicy extends Enumeration { + + type POLICY = Value + val HASH = Value("hash") + val UUID = Value("uuid") +} + +object OperaType extends Enumeration { + + type Operation = Value + val READ = Value("read") + val WRITE = Value("write") +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaOptions.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaOptions.scala new file mode 100644 index 0000000..43acfea --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaOptions.scala @@ -0,0 +1,230 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector + +import java.util.Properties + +import com.google.common.net.HostAndPort +import com.vesoft.nebula.connector.connector.Address +import org.apache.commons.lang.StringUtils +import org.apache.spark.internal.Logging +import org.apache.spark.sql.catalyst.util.CaseInsensitiveMap + +import scala.collection.mutable.ListBuffer + +class NebulaOptions(@transient val parameters: CaseInsensitiveMap[String])( + operaType: OperaType.Value) + extends Serializable + with Logging { + + import NebulaOptions._ + + def this(parameters: Map[String, String], operaType: OperaType.Value) = + this(CaseInsensitiveMap(parameters))(operaType) + + def this(hostAndPorts: String, + spaceName: String, + dataType: String, + label: String, + parameters: Map[String, String], + operaType: OperaType.Value) = { + this( + CaseInsensitiveMap( + parameters ++ Map( + NebulaOptions.META_ADDRESS -> hostAndPorts, + NebulaOptions.SPACE_NAME -> spaceName, + NebulaOptions.TYPE -> dataType, + NebulaOptions.LABEL -> label + )) + )(operaType) + } + + /** + * Return property with all options + */ + val asProperties: Properties = { + val properties = new Properties() + parameters.originalMap.foreach { case (k, v) => properties.setProperty(k, v) } + properties + } + + val timeout: Int = parameters.getOrElse(TIMEOUT, DEFAULT_CONNECTION_TIMEOUT).toString.toInt + val connectionRetry: Int = + parameters.getOrElse(CONNECTION_RETRY, DEFAULT_CONNECTION_RETRY).toString.toInt + val executionRetry: Int = + parameters.getOrElse(EXECUTION_RETRY, DEFAULT_EXECUTION_RETRY).toString.toInt + val user: String = parameters.getOrElse(USER_NAME, DEFAULT_USER_NAME) + val passwd: String = parameters.getOrElse(PASSWD, DEFAULT_PASSWD) + val rateLimit: Long = parameters.getOrElse(RATE_LIMIT, DEFAULT_RATE_LIMIT).toString.toLong + val rateTimeOut: Long = parameters.getOrElse(RATE_TIME_OUT, DEFAULT_RATE_TIME_OUT).toString.toLong + + require(parameters.isDefinedAt(TYPE), s"Option '$TYPE' is required") + val dataType: String = parameters(TYPE) + require( + DataTypeEnum.validDataType(dataType), + s"Option '$TYPE' is illegal, it should be '${DataTypeEnum.VERTEX}' or '${DataTypeEnum.EDGE}'") + + /** nebula common parameters */ + require(parameters.isDefinedAt(META_ADDRESS), s"Option '$META_ADDRESS' is required") + val metaAddress: String = parameters(META_ADDRESS) + + require(parameters.isDefinedAt(SPACE_NAME) && StringUtils.isNotBlank(parameters(SPACE_NAME)), + s"Option '$SPACE_NAME' is required and can not be blank") + val spaceName: String = parameters(SPACE_NAME) + + require(parameters.isDefinedAt(LABEL) && StringUtils.isNotBlank(parameters(LABEL)), + s"Option '$LABEL' is required and can not be blank") + val label: String = parameters(LABEL) + + /** read parameters */ + var returnCols: String = _ + var partitionNums: String = _ + var noColumn: Boolean = _ + var limit: Int = _ + if (operaType == OperaType.READ) { + returnCols = parameters(RETURN_COLS) + noColumn = parameters.getOrElse(NO_COLUMN, false).toString.toBoolean + partitionNums = parameters(PARTITION_NUMBER) + limit = parameters.getOrElse(LIMIT, DEFAULT_LIMIT).toString.toInt + } + + /** write parameters */ + var graphAddress: String = _ + var vidPolicy: String = _ + var srcPolicy: String = _ + var dstPolicy: String = _ + var vertexField: String = _ + var srcVertexField: String = _ + var dstVertexField: String = _ + var rankField: String = _ + var batch: Int = _ + var vidAsProp: Boolean = _ + var srcAsProp: Boolean = _ + var dstAsProp: Boolean = _ + var rankAsProp: Boolean = _ + + if (operaType == OperaType.WRITE) { + require(parameters.isDefinedAt(GRAPH_ADDRESS), + s"option $GRAPH_ADDRESS is required and can not be blank") + graphAddress = parameters(GRAPH_ADDRESS) + + if (parameters.isDefinedAt(VID_POLICY)) { + vidPolicy = parameters(VID_POLICY) + } else { + vidPolicy = null + } + + if (parameters.isDefinedAt(SRC_POLICY)) { + srcPolicy = parameters(SRC_POLICY) + } else { + srcPolicy = null + } + + if (parameters.isDefinedAt(DST_POLICY)) { + dstPolicy = parameters(DST_POLICY) + } else { + dstPolicy = null + } + + vertexField = parameters.getOrElse(VERTEX_FIELD, null) + srcVertexField = parameters.getOrElse(SRC_VERTEX_FIELD, null) + dstVertexField = parameters.getOrElse(DST_VERTEX_FIELD, null) + rankField = parameters.getOrElse(RANK_FIELD, null) + batch = parameters.getOrElse(BATCH, DEFAULT_BATCH).toString.toInt + vidAsProp = parameters.getOrElse(VID_AS_PROP, false).toString.toBoolean + srcAsProp = parameters.getOrElse(SRC_AS_PROP, false).toString.toBoolean + dstAsProp = parameters.getOrElse(DST_AS_PROP, false).toString.toBoolean + rankAsProp = parameters.getOrElse(RANK_AS_PROP, false).toString.toBoolean + } + + def getReturnCols: List[String] = { + returnCols.split(",").toList + } + + def getMetaAddress: List[Address] = { + val hostPorts: ListBuffer[Address] = new ListBuffer[Address] + metaAddress + .split(",") + .foreach(hostPort => { + // check host & port by getting HostAndPort + val addr = HostAndPort.fromString(hostPort) + hostPorts.append((addr.getHostText, addr.getPort)) + }) + hostPorts.toList + } + + def getGraphAddress: List[Address] = { + val hostPorts: ListBuffer[Address] = new ListBuffer[Address] + graphAddress + .split(",") + .foreach(hostPort => { + // check host & port by getting HostAndPort + val addr = HostAndPort.fromString(hostPort) + hostPorts.append((addr.getHostText, addr.getPort)) + }) + hostPorts.toList + } + +} + +class NebulaOptionsInWrite(@transient override val parameters: CaseInsensitiveMap[String]) + extends NebulaOptions(parameters)(OperaType.WRITE) {} + +object NebulaOptions { + + /** nebula common config */ + val SPACE_NAME: String = "spaceName" + val META_ADDRESS: String = "metaAddress" + val GRAPH_ADDRESS: String = "graphAddress" + val TYPE: String = "type" + val LABEL: String = "label" + + /** connection config */ + val TIMEOUT: String = "timeout" + val CONNECTION_RETRY: String = "connectionRetry" + val EXECUTION_RETRY: String = "executionRetry" + val RATE_TIME_OUT: String = "reteTimeOut" + val USER_NAME: String = "user" + val PASSWD: String = "passwd" + + /** read config */ + val RETURN_COLS: String = "returnCols" + val NO_COLUMN: String = "noColumn" + val PARTITION_NUMBER: String = "partitionNumber" + val LIMIT: String = "limit" + + /** write config */ + val RATE_LIMIT: String = "rateLimit" + val VID_POLICY: String = "vidPolicy" + val SRC_POLICY: String = "srcPolicy" + val DST_POLICY: String = "dstPolicy" + val VERTEX_FIELD = "vertexField" + val SRC_VERTEX_FIELD = "srcVertexField" + val DST_VERTEX_FIELD = "dstVertexField" + val RANK_FIELD = "rankFiled" + val BATCH: String = "batch" + val VID_AS_PROP: String = "vidAsProp" + val SRC_AS_PROP: String = "srcAsProp" + val DST_AS_PROP: String = "dstAsProp" + val RANK_AS_PROP: String = "rankAsProp" + + val DEFAULT_TIMEOUT: Int = 3000 + val DEFAULT_CONNECTION_TIMEOUT: Int = 3000 + val DEFAULT_CONNECTION_RETRY: Int = 3 + val DEFAULT_EXECUTION_RETRY: Int = 3 + val DEFAULT_USER_NAME: String = "root" + val DEFAULT_PASSWD: String = "nebula" + + val DEFAULT_LIMIT: Int = 1000 + + val DEFAULT_RATE_LIMIT: Long = 1024L + val DEFAULT_RATE_TIME_OUT: Long = 100 + val DEFAULT_POLICY: String = null + val DEFAULT_BATCH: Int = 1000 + + val EMPTY_STRING: String = "" +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala new file mode 100644 index 0000000..5039406 --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala @@ -0,0 +1,129 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector + +import com.vesoft.nebula.meta.{ColumnDef, ColumnTypeDef, PropertyType} +import org.apache.spark.sql.Row +import org.apache.spark.sql.types.{ + BooleanType, + DataType, + DoubleType, + FloatType, + IntegerType, + LongType, + StringType, + TimestampType +} +import org.slf4j.LoggerFactory + +object NebulaUtils { + private val LOG = LoggerFactory.getLogger(this.getClass) + + var nebulaOptions: NebulaOptions = _ + var parameters: Map[String, String] = Map() + + /** + * convert nebula data type to spark sql data type + */ + def convertDataType(columnTypeDef: ColumnTypeDef): DataType = { + + columnTypeDef.getType match { + case PropertyType.VID | PropertyType.INT8 | PropertyType.INT16 | PropertyType.INT32 | + PropertyType.INT64 => + return LongType + case PropertyType.BOOL => BooleanType + case PropertyType.FLOAT | PropertyType.DOUBLE => DoubleType + case PropertyType.FIXED_STRING | PropertyType.STRING => StringType + case PropertyType.TIMESTAMP => TimestampType + case PropertyType.DATE | PropertyType.TIME | PropertyType.DATETIME => StringType + case PropertyType.UNKNOWN => throw new IllegalArgumentException("unsupported data type") + } + } + + def getColDataType(columnDefs: List[ColumnDef], columnName: String): DataType = { + for (columnDef <- columnDefs) { + if (columnName.equals(new String(columnDef.getName))) { + return convertDataType(columnDef.getType) + } + } + throw new IllegalArgumentException(s"column $columnName does not exist in schema") + } + + //type NebulaValueGetter = (Property, InternalRow, Int) => Unit + +// def makeGetters(schema: StructType): Array[NebulaValueGetter] = +// schema.fields.map(field => makeGetter(field.dataType, field.metadata)) +// +// private def makeGetter(dataType: DataType, metadata: Metadata): NebulaValueGetter = { +// dataType match { +// case BooleanType => +// (prop: Property, row: InternalRow, pos: Int) => +// row.setBoolean(pos, prop.getValueAsBool) +// case LongType => +// (prop: Property, row: InternalRow, pos: Int) => +// row.setLong(pos, prop.getValueAsLong) +// case DoubleType => +// (prop: Property, row: InternalRow, pos: Int) => +// row.setDouble(pos, prop.getValueAsDouble) +// case FloatType => +// (prop: Property, row: InternalRow, pos: Int) => +// row.setFloat(pos, prop.getValueAsFloat) +// case IntegerType => +// (prop: Property, row: InternalRow, pos: Int) => +// row.setInt(pos, prop.getValueAsInt) +// case _ => +// (prop: Property, row: InternalRow, pos: Int) => +// row.update(pos, UTF8String.fromString(prop.getValue.toString)) +// } +// } + + def resolveDataAndType(row: Row, dataType: DataType, i: Int): Any = { + dataType match { + case LongType => row.getLong(i) + case IntegerType => row.getInt(i) + case DoubleType => row.getDouble(i) + case FloatType => row.getFloat(i) + case BooleanType => row.getBoolean(i) + case StringType => row.getString(i) + case _ => row.getString(i) + } + } + + def isNumic(str: String): Boolean = { + for (char <- str.toCharArray) { + if (!Character.isDigit(char)) return false + } + true + } + + def escapeUtil(str: String): String = { + var s = str + if (s.contains("\\")) { + s = s.replaceAll("\\\\", "\\\\\\\\") + } + if (s.contains("\t")) { + s = s.replaceAll("\t", "\\\\t") + } + if (s.contains("\n")) { + s = s.replaceAll("\n", "\\\\n") + } + if (s.contains("\"")) { + s = s.replaceAll("\"", "\\\\\"") + } + if (s.contains("\'")) { + s = s.replaceAll("\'", "\\\\'") + } + if (s.contains("\r")) { + s = s.replaceAll("\r", "\\\\r") + } + if (s.contains("\b")) { + s = s.replaceAll("\b", "\\\\b") + } + s + } + +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/PartitionUtils.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/PartitionUtils.scala new file mode 100644 index 0000000..68cdfe2 --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/PartitionUtils.scala @@ -0,0 +1,22 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector + +import scala.collection.mutable.ListBuffer + +object PartitionUtils { + def getScanParts(index: Int, nebulaTotalPart: Int, sparkPartitionNum: Int): List[Integer] = { + val scanParts = new ListBuffer[Integer] + var currentPart = index + while (currentPart <= nebulaTotalPart) { + scanParts.append(currentPart) + currentPart += sparkPartitionNum + } + scanParts.toList + } + +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala new file mode 100644 index 0000000..1ef7f7d --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala @@ -0,0 +1,18 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector + +object NebulaTemplate { + + private[connector] val BATCH_INSERT_TEMPLATE = "INSERT %s %s(%s) VALUES %s" + private[connector] val VERTEX_VALUE_TEMPLATE = "%s: (%s)" + private[connector] val VERTEX_VALUE_TEMPLATE_WITH_POLICY = "%s(%s): (%s)" + private[connector] val ENDPOINT_TEMPLATE = "%s(\"%s\")" + private[connector] val EDGE_VALUE_WITHOUT_RANKING_TEMPLATE = "%s->%s: (%s)" + private[connector] val EDGE_VALUE_TEMPLATE = "%s->%s@%d: (%s)" + private[connector] val USE_TEMPLATE = "USE %s" +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/exception/Exception.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/exception/Exception.scala new file mode 100644 index 0000000..627ea5d --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/exception/Exception.scala @@ -0,0 +1,33 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.exception + +import com.facebook.thrift.TException + +/*** + * An exception thrown if nebula client connects failed. + */ +class GraphConnectException(message: String, cause: Throwable = null) + extends TException(message, cause) + +/** + * An exception thrown if a required option is missing form [[NebulaOptions]] + */ +class IllegalOptionException(message: String, cause: Throwable = null) + extends IllegalArgumentException(message, cause) + +/** + * An exception thrown if nebula execution failed. + */ +class GraphExecuteException(message: String, cause: Throwable = null) + extends TException(message, cause) + +/** + * An exception thrown if nebula execution occur rpc exception. + */ +class NebulaRPCException(message: String, cause: Throwable = null) + extends RuntimeException(message, cause) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/nebula/GraphProvider.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/nebula/GraphProvider.scala new file mode 100644 index 0000000..42565d8 --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/nebula/GraphProvider.scala @@ -0,0 +1,62 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.nebula + +import com.vesoft.nebula.client.graph.NebulaPoolConfig +import com.vesoft.nebula.client.graph.data.{HostAddress, ResultSet} +import com.vesoft.nebula.client.graph.net.{NebulaPool, Session} +import com.vesoft.nebula.connector.connector.Address +import com.vesoft.nebula.connector.exception.GraphConnectException +import org.apache.log4j.Logger + +import scala.collection.JavaConverters._ +import scala.collection.mutable.ListBuffer + +/** + * GraphProvider for Nebula Graph Service + */ +class GraphProvider(addresses: List[Address]) extends AutoCloseable with Serializable { + private[this] lazy val LOG = Logger.getLogger(this.getClass) + + @transient val nebulaPoolConfig = new NebulaPoolConfig + + @transient val pool: NebulaPool = new NebulaPool + val address = new ListBuffer[HostAddress]() + for (addr <- addresses) { + address.append(new HostAddress(addr._1, addr._2)) + } + nebulaPoolConfig.setMaxConnSize(1) + pool.init(address.asJava, nebulaPoolConfig) + + var session: Session = null + + def releaseGraphClient(session: Session): Unit = { + session.release() + } + + override def close(): Unit = { + pool.close() + } + + def switchSpace(user: String, password: String, space: String): Boolean = { + if (session == null) { + session = pool.getSession(user, password, true) + } + val switchStatment = s"use $space" + LOG.info(s"switch space $space") + val result = submit(switchStatment) + result.isSucceeded + } + + def submit(statement: String): ResultSet = { + if (session == null) { + LOG.error("graph session is null") + throw new GraphConnectException("session is null") + } + session.execute(statement) + } +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/nebula/MetaProvider.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/nebula/MetaProvider.scala new file mode 100644 index 0000000..a0ae79a --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/nebula/MetaProvider.scala @@ -0,0 +1,101 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.nebula + +import com.vesoft.nebula.client.graph.data.HostAddress +import com.vesoft.nebula.client.meta.MetaClient +import com.vesoft.nebula.connector.connector.Address +import com.vesoft.nebula.connector.DataTypeEnum +import com.vesoft.nebula.meta.{PropertyType, Schema} + +import scala.collection.JavaConverters._ +import scala.collection.mutable + +class MetaProvider(addresses: List[Address]) extends AutoCloseable { + + val metaAddress = addresses.map(address => new HostAddress(address._1, address._2)).asJava + val client = new MetaClient(metaAddress) + client.connect() + + def getPartition(space: String): Map[Integer, List[HostAddress]] = { + client + .getPartsAlloc(space) + .asScala + .map(entry => entry._1 -> entry._2.asScala.toList) + .toMap + } + + def getPartitionNumber(space: String): Int = { + client.getPartsAlloc(space).size() + } + + def getVidType(space: String): VidType.Value = { + val vidType = client.getSpace(space).getProperties.getVid_type.getType + if (vidType == PropertyType.FIXED_STRING) { + return VidType.STRING + } + VidType.INT + } + + def getTag(space: String, tag: String): Schema = { + client.getTag(space, tag) + } + + def getEdge(space: String, edge: String): Schema = { + client.getEdge(space, edge) + } + + def getTagSchema(space: String, tag: String): Map[String, Integer] = { + val tagSchema = client.getTag(space, tag) + val schema = new mutable.HashMap[String, Integer] + + val columns = tagSchema.getColumns + for (colDef <- columns.asScala) { + schema.put(new String(colDef.getName), colDef.getType.getType) + } + schema.toMap + } + + def getEdgeSchema(space: String, edge: String): Map[String, Integer] = { + val edgeSchema = client.getEdge(space, edge) + val schema = new mutable.HashMap[String, Integer] + + val columns = edgeSchema.getColumns + for (colDef <- columns.asScala) { + schema.put(new String(colDef.getName), colDef.getType.getType) + } + schema.toMap + } + + def getLabelType(space: String, label: String): DataTypeEnum.Value = { + val tags = client.getTags(space) + for (tag <- tags.asScala) { + if (new String(tag.getTag_name).equals(label)) { + return DataTypeEnum.VERTEX + } + } + val edges = client.getEdges(space) + for (edge <- edges.asScala) { + if (new String(edge.getEdge_name).equals(label)) { + return DataTypeEnum.EDGE + } + } + null + } + + override def close(): Unit = { + client.close() + } + +} + +object VidType extends Enumeration { + type Type = Value + + val STRING = Value("STRING") + val INT = Value("INT") +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala new file mode 100644 index 0000000..1876407 --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala @@ -0,0 +1,273 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector + +import org.apache.spark.rdd.RDD +import org.apache.spark.sql.{ + DataFrame, + DataFrameReader, + DataFrameWriter, + Encoder, + Encoders, + Row, + SaveMode +} +import scala.collection.mutable.ListBuffer + +package object connector { + + type Address = (String, Int) + type NebulaType = Int + type Prop = List[Any] + type PropertyNames = List[String] + type PropertyValues = List[Any] + + type VertexID = Long + type VertexIDSlice = String + type NebulaGraphxVertex = (VertexID, PropertyValues) + type NebulaGraphxEdge = org.apache.spark.graphx.Edge[(EdgeRank, Prop)] + type EdgeRank = Long + + case class NebulaVertex(vertexIDSlice: VertexIDSlice, values: PropertyValues) { + def propertyValues = values.mkString(", ") + + override def toString: String = { + s"Vertex ID: ${vertexIDSlice}, Values: ${values.mkString(", ")}" + } + } + + case class NebulaVertices(propNames: PropertyNames, + values: List[NebulaVertex], + policy: Option[KeyPolicy.Value]) { + + def propertyNames: String = propNames.mkString(",") + + override def toString: String = { + s"Vertices: " + + s"Property Names: ${propNames.mkString(", ")}" + + s"Vertex Values: ${values.mkString(", ")} " + + s"with policy: ${policy}" + } + } + + case class NebulaEdge(source: VertexIDSlice, + target: VertexIDSlice, + rank: Option[EdgeRank], + values: PropertyValues) { + def propertyValues: String = values.mkString(", ") + + override def toString: String = { + s"Edge: ${source}->${target}@${rank} values: ${propertyValues}" + } + } + + case class NebulaEdges(propNames: PropertyNames, + values: List[NebulaEdge], + sourcePolicy: Option[KeyPolicy.Value], + targetPolicy: Option[KeyPolicy.Value]) { + def propertyNames: String = propNames.mkString(",") + def getSourcePolicy = sourcePolicy + def getTargetPolicy = targetPolicy + + override def toString: String = { + "Edges:" + + s" Property Names: ${propNames.mkString(", ")}" + + s" with source policy ${sourcePolicy}" + + s" with target policy ${targetPolicy}" + } + } + + /** + * spark reader for nebula graph + */ + implicit class NebulaDataFrameReader(reader: DataFrameReader) { + var connectionConfig: NebulaConnectionConfig = _ + var readConfig: ReadNebulaConfig = _ + + def nebula(connectionConfig: NebulaConnectionConfig, + readConfig: ReadNebulaConfig): NebulaDataFrameReader = { + this.connectionConfig = connectionConfig + this.readConfig = readConfig + this + } + + /** + * Reading com.vesoft.nebula.tools.connector.vertices from Nebula Graph + * @return DataFrame + */ + def loadVerticesToDF(): DataFrame = { + assert(connectionConfig != null && readConfig != null, + "nebula config is not set, please call nebula() before loadVerticesToDF") + reader + .format(classOf[NebulaDataSource].getName) + .option(NebulaOptions.TYPE, DataTypeEnum.VERTEX.toString) + .option(NebulaOptions.SPACE_NAME, readConfig.getSpace) + .option(NebulaOptions.LABEL, readConfig.getLabel) + .option(NebulaOptions.PARTITION_NUMBER, readConfig.getPartitionNum) + .option(NebulaOptions.RETURN_COLS, readConfig.getReturnCols.mkString(",")) + .option(NebulaOptions.NO_COLUMN, readConfig.getNoColumn) + .option(NebulaOptions.LIMIT, readConfig.getLimit) + .option(NebulaOptions.META_ADDRESS, connectionConfig.getMetaAddress) + .option(NebulaOptions.TIMEOUT, connectionConfig.getTimeout) + .option(NebulaOptions.CONNECTION_RETRY, connectionConfig.getConnectionRetry) + .option(NebulaOptions.EXECUTION_RETRY, connectionConfig.getExecRetry) + .load() + } + + /** + * Reading edges from Nebula Graph + * @return DataFrame + */ + def loadEdgesToDF(): DataFrame = { + assert(connectionConfig != null && readConfig != null, + "nebula config is not set, please call nebula() before loadEdgesToDF") + + reader + .format(classOf[NebulaDataSource].getName) + .option(NebulaOptions.TYPE, DataTypeEnum.EDGE.toString) + .option(NebulaOptions.SPACE_NAME, readConfig.getSpace) + .option(NebulaOptions.LABEL, readConfig.getLabel) + .option(NebulaOptions.RETURN_COLS, readConfig.getReturnCols.mkString(",")) + .option(NebulaOptions.NO_COLUMN, readConfig.getNoColumn) + .option(NebulaOptions.LIMIT, readConfig.getLimit) + .option(NebulaOptions.PARTITION_NUMBER, readConfig.getPartitionNum) + .option(NebulaOptions.META_ADDRESS, connectionConfig.getMetaAddress) + .option(NebulaOptions.TIMEOUT, connectionConfig.getTimeout) + .option(NebulaOptions.CONNECTION_RETRY, connectionConfig.getConnectionRetry) + .option(NebulaOptions.EXECUTION_RETRY, connectionConfig.getExecRetry) + .load() + } + + /** + * read nebula vertex edge to graphx's vertex + */ + def loadVerticesToGraphx(): RDD[NebulaGraphxVertex] = { + val vertexDataset = loadVerticesToDF() + implicit val encoder: Encoder[NebulaGraphxVertex] = + Encoders.bean[NebulaGraphxVertex](classOf[NebulaGraphxVertex]) + vertexDataset + .map(row => { + val fields = row.schema.fields + val vertexId = row.get(0).toString.toLong + val props: ListBuffer[Any] = ListBuffer() + for (i <- row.schema.fields.indices) { + if (i != 0) { + props.append(NebulaUtils.resolveDataAndType(row, fields(i).dataType, i)) + } + } + (vertexId, props.toList) + })(encoder) + .rdd + } + + /** + * read nebula edge edge to graphx's edge + */ + def loadEdgesToGraphx(): RDD[NebulaGraphxEdge] = { + val edgeDataset = loadEdgesToDF() + implicit val encoder: Encoder[NebulaGraphxEdge] = + Encoders.bean[NebulaGraphxEdge](classOf[NebulaGraphxEdge]) + edgeDataset + .map(row => { + val cols = row.schema.fields + val props: ListBuffer[Any] = ListBuffer() + for (i <- row.schema.fields.indices) { + if (i != 0 && i != 1 && i != 2) { + props.append(NebulaUtils.resolveDataAndType(row, cols(i).dataType, i)) + } + } + val edgeProp = (row.get(2).toString.toLong, props.toList) + org.apache.spark.graphx + .Edge(row.get(0).toString.toLong, row.get(1).toString.toLong, edgeProp) + })(encoder) + .rdd + } + + } + + /** + * spark writer for nebula graph + */ + implicit class NebulaDataFrameWriter(writer: DataFrameWriter[Row]) { + + var connectionConfig: NebulaConnectionConfig = _ + var writeNebulaConfig: WriteNebulaConfig = _ + + def test(): NebulaDataFrameWriter = { + this + } + + /** + * config nebula connection + * @param connectionConfig connection parameters + * @param writeNebulaConfig write parameters for vertex or edge + */ + def nebula(connectionConfig: NebulaConnectionConfig, + writeNebulaConfig: WriteNebulaConfig): NebulaDataFrameWriter = { + this.connectionConfig = connectionConfig + this.writeNebulaConfig = writeNebulaConfig + this + } + + /** + * write dataframe into nebula vertex + */ + def writeVertices(): Unit = { + assert(connectionConfig != null && writeNebulaConfig != null, + "nebula config is not set, please call nebula() before writeVertices") + val writeConfig = writeNebulaConfig.asInstanceOf[WriteNebulaVertexConfig] + writer + .format(classOf[NebulaDataSource].getName) + .mode(SaveMode.Overwrite) + .option(NebulaOptions.TYPE, DataTypeEnum.VERTEX.toString) + .option(NebulaOptions.SPACE_NAME, writeConfig.getSpace) + .option(NebulaOptions.LABEL, writeConfig.getTagName) + .option(NebulaOptions.VERTEX_FIELD, writeConfig.getVidField) + .option(NebulaOptions.VID_POLICY, writeConfig.getVidPolicy) + .option(NebulaOptions.BATCH, writeConfig.getBatch) + .option(NebulaOptions.VID_AS_PROP, writeConfig.getVidAsProp) + .option(NebulaOptions.META_ADDRESS, connectionConfig.getMetaAddress) + .option(NebulaOptions.GRAPH_ADDRESS, connectionConfig.getGraphAddress) + .option(NebulaOptions.TIMEOUT, connectionConfig.getTimeout) + .option(NebulaOptions.CONNECTION_RETRY, connectionConfig.getConnectionRetry) + .option(NebulaOptions.EXECUTION_RETRY, connectionConfig.getExecRetry) + .save() + } + + /** + * write dataframe into nebula edge + */ + def writeEdges(): Unit = { + + assert(connectionConfig != null && writeNebulaConfig != null, + "nebula config is not set, please call nebula() before writeEdges") + val writeConfig = writeNebulaConfig.asInstanceOf[WriteNebulaEdgeConfig] + writer + .format(classOf[NebulaDataSource].getName) + .mode(SaveMode.Overwrite) + .option(NebulaOptions.TYPE, DataTypeEnum.EDGE.toString) + .option(NebulaOptions.SPACE_NAME, writeConfig.getSpace) + .option(NebulaOptions.LABEL, writeConfig.getEdgeName) + .option(NebulaOptions.SRC_VERTEX_FIELD, writeConfig.getSrcFiled) + .option(NebulaOptions.DST_VERTEX_FIELD, writeConfig.getDstField) + .option(NebulaOptions.SRC_POLICY, writeConfig.getSrcPolicy) + .option(NebulaOptions.DST_POLICY, writeConfig.getDstPolicy) + .option(NebulaOptions.RANK_FIELD, writeConfig.getRankField) + .option(NebulaOptions.BATCH, writeConfig.getBatch) + .option(NebulaOptions.SRC_AS_PROP, writeConfig.getSrcAsProp) + .option(NebulaOptions.DST_AS_PROP, writeConfig.getDstAsProp) + .option(NebulaOptions.RANK_AS_PROP, writeConfig.getRankAsProp) + .option(NebulaOptions.META_ADDRESS, connectionConfig.getMetaAddress) + .option(NebulaOptions.GRAPH_ADDRESS, connectionConfig.getGraphAddress) + .option(NebulaOptions.TIMEOUT, connectionConfig.getTimeout) + .option(NebulaOptions.CONNECTION_RETRY, connectionConfig.getConnectionRetry) + .option(NebulaOptions.EXECUTION_RETRY, connectionConfig.getExecRetry) + .save() + } + } + +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaEdgePartitionReader.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaEdgePartitionReader.scala new file mode 100644 index 0000000..fe60870 --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaEdgePartitionReader.scala @@ -0,0 +1,68 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.reader + +import java.util + +import com.vesoft.nebula.connector.NebulaOptions +import com.vesoft.nebula.connector.reader.tmp.ScanEdgeResult +import org.apache.spark.sql.types.StructType +import org.slf4j.{Logger, LoggerFactory} + +class NebulaEdgePartitionReader(index: Int, nebulaOptions: NebulaOptions, schema: StructType) + extends NebulaPartitionReader(index, nebulaOptions, schema) { + private val LOG: Logger = LoggerFactory.getLogger(this.getClass) + + private var responseIterator: util.Iterator[ScanEdgeResult] = _ + + override def next(): Boolean = { +// if (dataIterator == null && responseIterator == null && !scanPartIterator.hasNext) return false +// +// var continue: Boolean = false +// var break: Boolean = false +// while ((dataIterator == null || !dataIterator.hasNext) && !break) { +// resultValues.clear() +// continue = false +// if (responseIterator == null || !responseIterator.hasNext) { +// if (scanPartIterator.hasNext) { +// try { +// if (nebulaOptions.noColumn) { +// responseIterator = storageClient.scanEdge(nebulaOptions.spaceName, +// scanPartIterator.next(), +// nebulaOptions.label, +// nebulaOptions.limit) +// } else { +// responseIterator = storageClient.scanEdge(nebulaOptions.spaceName, +// scanPartIterator.next(), +// nebulaOptions.label, +// nebulaOptions.getReturnCols, +// nebulaOptions.limit) +// } +// } catch { +// case e: Exception => +// LOG.error(s"Exception scanning vertex ${nebulaOptions.label}", e) +// throw new Exception(e.getMessage, e) +// } +// // jump to the next loop +// continue = true +// } +// // break while loop +// break = !continue +// } else { +// val next: ScanEdgeResult = responseIterator.next +// // todo dataIterator = next.getVertexTableView +// } +// } +// +// if (dataIterator == null) { +// return false +// } +// dataIterator.hasNext + false + } + +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartition.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartition.scala new file mode 100644 index 0000000..a2c7fbd --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartition.scala @@ -0,0 +1,24 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.reader + +import com.vesoft.nebula.connector.NebulaOptions +import org.apache.spark.sql.catalyst.InternalRow +import org.apache.spark.sql.sources.v2.reader.{InputPartition, InputPartitionReader} +import org.apache.spark.sql.types.StructType + +class NebulaVertexPartition(index: Int, nebulaOptions: NebulaOptions, schema: StructType) + extends InputPartition[InternalRow] { + override def createPartitionReader(): InputPartitionReader[InternalRow] = + new NebulaVertexPartitionReader(index, nebulaOptions, schema) +} + +class NebulaEdgePartition(index: Int, nebulaOptions: NebulaOptions, schema: StructType) + extends InputPartition[InternalRow] { + override def createPartitionReader(): InputPartitionReader[InternalRow] = + new NebulaEdgePartitionReader(index, nebulaOptions, schema) +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartitionReader.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartitionReader.scala new file mode 100644 index 0000000..946d803 --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartitionReader.scala @@ -0,0 +1,68 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.reader + +import com.vesoft.nebula.connector.{NebulaOptions, PartitionUtils} +import com.vesoft.nebula.connector.nebula.MetaProvider +import org.apache.spark.sql.catalyst.InternalRow +import org.apache.spark.sql.sources.v2.reader.InputPartitionReader +import org.apache.spark.sql.types.StructType +import org.slf4j.{Logger, LoggerFactory} + +/** + * Read nebula data for each spark partition + */ +abstract class NebulaPartitionReader extends InputPartitionReader[InternalRow] { + private val LOG: Logger = LoggerFactory.getLogger(this.getClass) + +// protected var dataIterator: Iterator[List[Property]] = _ + protected var scanPartIterator: Iterator[Integer] = _ +// protected var resultValues: mutable.ListBuffer[List[Property]] = +// mutable.ListBuffer[List[Property]]() +// +// todo 对接2.0 +// protected var storageClient: StorageClient = _ + private var schema: StructType = _ + + private var metaProvider: MetaProvider = _ + + /** + * @param index identifier for spark partition + * @param nebulaOptions nebula Options + * @param schema of data need to read + */ + def this(index: Int, nebulaOptions: NebulaOptions, schema: StructType) { + this() + this.schema = schema + + metaProvider = new MetaProvider(nebulaOptions.getMetaAddress) + // todo this.storageClient = new StorageClient + // allocate scanPart to this partition + val totalPart = metaProvider.getPartitionNumber(nebulaOptions.spaceName) + + val scanParts = PartitionUtils.getScanParts(index, totalPart, nebulaOptions.partitionNums.toInt) + LOG.info(s"partition index: ${index}, scanParts: ${scanParts.toString}") + scanPartIterator = scanParts.iterator + } + + override def get(): InternalRow = { +// val getters: Array[NebulaValueGetter] = NebulaUtils.makeGetters(schema) +// val mutableRow = new SpecificInternalRow(schema.fields.map(x => x.dataType)) +// +// val resultSet: Array[Property] = dataIterator.next().toArray +// for (i <- getters.indices) { +// getters(i).apply(resultSet(i), mutableRow, i) +// if (resultSet(i) == null) mutableRow.setNullAt(i) +// } +// mutableRow + null + } + + override def close(): Unit = { + metaProvider.close() + } +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaSourceReader.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaSourceReader.scala new file mode 100644 index 0000000..492c3f1 --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaSourceReader.scala @@ -0,0 +1,121 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.reader + +import java.util + +import com.vesoft.nebula.connector.{DataTypeEnum, NebulaOptions, NebulaUtils} +import com.vesoft.nebula.connector.nebula.MetaProvider +import com.vesoft.nebula.meta.ColumnDef +import org.apache.spark.sql.catalyst.InternalRow +import org.apache.spark.sql.sources.v2.reader.{DataSourceReader, InputPartition} +import org.apache.spark.sql.types.{DataTypes, StructField, StructType} +import org.slf4j.LoggerFactory + +import scala.collection.mutable.ListBuffer +import scala.collection.JavaConverters._ + +/** + * Base class of Nebula Source Reader + */ +abstract class NebulaSourceReader(nebulaOptions: NebulaOptions) extends DataSourceReader { + private val LOG = LoggerFactory.getLogger(this.getClass) + + protected var datasetSchema: StructType = _ + + override def readSchema(): StructType = getSchema(nebulaOptions) + + /** + * return the dataset's schema. Schema includes configured cols in returnCols or includes all properties in nebula. + */ + def getSchema(nebulaOptions: NebulaOptions): StructType = { + val returnCols = nebulaOptions.getReturnCols + val noColumn = nebulaOptions.noColumn + val fields: ListBuffer[StructField] = new ListBuffer[StructField] + val metaProvider = new MetaProvider(nebulaOptions.getMetaAddress) + + import scala.collection.JavaConverters._ + var schemaCols: Seq[ColumnDef] = Seq() + val isVertex = DataTypeEnum.VERTEX.toString.equalsIgnoreCase(nebulaOptions.dataType) + + // construct vertex or edge default prop + if (isVertex) { + fields.append(DataTypes.createStructField("_vertexId", DataTypes.StringType, false)) + } else { + fields.append(DataTypes.createStructField("_srcId", DataTypes.StringType, false)) + fields.append(DataTypes.createStructField("_dstId", DataTypes.StringType, false)) + fields.append(DataTypes.createStructField("_rank", DataTypes.LongType, false)) + } + + // read no column + if (noColumn) { + datasetSchema = new StructType(fields.toArray) + LOG.info(s"dataset's schema: $datasetSchema") + return datasetSchema + } + // get tag schema or edge schema + val schema = if (isVertex) { + metaProvider.getTag(nebulaOptions.spaceName, nebulaOptions.label) + } else { + metaProvider.getEdge(nebulaOptions.spaceName, nebulaOptions.label) + } + + schemaCols = schema.columns.asScala + + // read all columns + if (returnCols.isEmpty) { + schemaCols.foreach(columnDef => { + LOG.info(s"prop name ${new String(columnDef.getName)}, type ${columnDef.getType.getType} ") + fields.append( + DataTypes.createStructField(new String(columnDef.getName), + NebulaUtils.convertDataType(columnDef.getType), + true)) + }) + } else { + for (col: String <- returnCols) { + fields.append( + DataTypes + .createStructField(col, NebulaUtils.getColDataType(schemaCols.toList, col), true)) + } + } + datasetSchema = new StructType(fields.toArray) + LOG.info(s"dataset's schema: $datasetSchema") + datasetSchema + } +} + +/** + * DataSourceReader for Nebula Vertex + */ +class NebulaDataSourceVertexReader(nebulaOptions: NebulaOptions) + extends NebulaSourceReader(nebulaOptions) { + + override def planInputPartitions(): util.List[InputPartition[InternalRow]] = { + + val partitionNum = nebulaOptions.partitionNums.toInt + val partitions = for (index <- 1 to partitionNum) + yield { + new NebulaVertexPartition(index, nebulaOptions, datasetSchema) + } + partitions.map(_.asInstanceOf[InputPartition[InternalRow]]).asJava + } +} + +/** + * DataSourceReader for Nebula Edge + */ +class NebulaDataSourceEdgeReader(nebulaOptions: NebulaOptions) + extends NebulaSourceReader(nebulaOptions) { + + override def planInputPartitions(): util.List[InputPartition[InternalRow]] = { + val partitionNum = nebulaOptions.partitionNums.toInt + val partitions = for (index <- 1 to partitionNum) + yield new NebulaEdgePartition(index, nebulaOptions, datasetSchema) + + partitions.map(_.asInstanceOf[InputPartition[InternalRow]]).asJava + } +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaVertexPartitionReader.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaVertexPartitionReader.scala new file mode 100644 index 0000000..42924aa --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaVertexPartitionReader.scala @@ -0,0 +1,67 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.reader + +import com.vesoft.nebula.connector.NebulaOptions +import org.apache.spark.sql.types.StructType +import org.slf4j.{Logger, LoggerFactory} + +class NebulaVertexPartitionReader(index: Int, nebulaOptions: NebulaOptions, schema: StructType) + extends NebulaPartitionReader(index, nebulaOptions, schema) { + + private val LOG: Logger = LoggerFactory.getLogger(this.getClass) + +// private var responseIterator: util.Iterator[ScanVertexResponse] = _ + + override def next(): Boolean = { +// if (dataIterator == null && responseIterator == null && !scanPartIterator.hasNext) +// return false +// +// var continue: Boolean = false +// var break: Boolean = false +// while ((dataIterator == null || !dataIterator.hasNext) && !break) { +// resultValues.clear() +// continue = false +// if (responseIterator == null || !responseIterator.hasNext) { +// if (scanPartIterator.hasNext) { +// try { +// if (nebulaOptions.noColumn) { +// responseIterator = storageClient.scanVertex(nebulaOptions.spaceName, +// scanPartIterator.next(), +// nebulaOptions.label, +// nebulaOptions.limit) +// } else { +// responseIterator = storageClient.scanVertex(nebulaOptions.spaceName, +// scanPartIterator.next(), +// nebulaOptions.label, +// nebulaOptions.getReturnCols, +// nebulaOptions.limit) +// } +// } catch { +// case e: Exception => +// LOG.error(s"Exception scanning vertex ${nebulaOptions.label}", e) +// throw new Exception(e.getMessage, e) +// } +// // jump to the next loop +// continue = true +// } +// // break while loop +// break = !continue +// } else { +// val next: ScanVertexResponse = responseIterator.next +// // todo dataIterator = next.getVertexTableView +// } +// } +// +// if (dataIterator == null) { +// return false +// } +// dataIterator.hasNext + false + } + +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanEdgeResultIterator.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanEdgeResultIterator.scala new file mode 100644 index 0000000..3d0ac56 --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanEdgeResultIterator.scala @@ -0,0 +1,27 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.reader.tmp + +class ScanEdgeResultIterator { + + def next(): ScanEdgeResult = { + new ScanEdgeResult + } + + def hasNext(): Boolean = { + true + } +} + +class ScanEdgeResult { + val edgeTableViews: List[EdgeTableView] = null + + val propNames: List[String] = null + +} + +class EdgeTableView {} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanVertexResultIterator.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanVertexResultIterator.scala new file mode 100644 index 0000000..d894c7e --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanVertexResultIterator.scala @@ -0,0 +1,27 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.reader.tmp + +class ScanVertexResultIterator { + + def next(): ScanVertexResult = { + new ScanVertexResult + } + + def hasNext(): Boolean = { + true + } +} + +class ScanVertexResult { + val vertexTableViews: List[VertexTableView] = null + + val propNames: List[String] = null + +} + +class VertexTableView {} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/StorageClient.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/StorageClient.scala new file mode 100644 index 0000000..71faec5 --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/StorageClient.scala @@ -0,0 +1,17 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.reader.tmp + +class StorageClient { + def scanVertex(): ScanVertexResultIterator = { + new ScanVertexResultIterator + } + + def scanEdge(): ScanEdgeResultIterator = { + new ScanEdgeResultIterator + } +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaCommitMessage.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaCommitMessage.scala new file mode 100644 index 0000000..ad44044 --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaCommitMessage.scala @@ -0,0 +1,11 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.writer + +import org.apache.spark.sql.sources.v2.writer.WriterCommitMessage + +case class NebulaCommitMessage(executeStatements: List[String]) extends WriterCommitMessage diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala new file mode 100644 index 0000000..1f1be2a --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala @@ -0,0 +1,95 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.writer + +import com.vesoft.nebula.connector.connector.{NebulaEdge, NebulaEdges} +import com.vesoft.nebula.connector.{KeyPolicy, NebulaOptions} +import org.apache.spark.sql.catalyst.InternalRow +import org.apache.spark.sql.sources.v2.writer.{DataWriter, WriterCommitMessage} +import org.apache.spark.sql.types.StructType +import org.slf4j.LoggerFactory + +import scala.collection.mutable.ListBuffer + +class NebulaEdgeWriter(nebulaOptions: NebulaOptions, + srcIndex: Int, + dstIndex: Int, + rankIndex: Option[Int], + schema: StructType) + extends NebulaWriter(nebulaOptions) + with DataWriter[InternalRow] { + + private val LOG = LoggerFactory.getLogger(this.getClass) + + val rankIdx = if (rankIndex.isDefined) rankIndex.get else -1 + val propNames = NebulaExecutor.assignEdgePropNames(schema, + srcIndex, + dstIndex, + rankIdx, + nebulaOptions.srcAsProp, + nebulaOptions.dstAsProp, + nebulaOptions.rankAsProp) + val fieldTypMap = metaProvider.getEdgeSchema(nebulaOptions.spaceName, nebulaOptions.label) + + val srcPolicy = + if (nebulaOptions.srcPolicy.isEmpty) Option.empty + else Option(KeyPolicy.withName(nebulaOptions.srcPolicy)) + val dstPolicy = { + if (nebulaOptions.dstPolicy.isEmpty) Option.empty + else Option(KeyPolicy.withName(nebulaOptions.dstPolicy)) + } + + /** buffer to save batch edges */ + var edges: ListBuffer[NebulaEdge] = new ListBuffer() + + prepareSpace() + + /** + * write one edge record to buffer + */ + override def write(row: InternalRow): Unit = { + val srcId = NebulaExecutor.extraID(schema, row, srcIndex, srcPolicy, isVidStringType) + val dstId = NebulaExecutor.extraID(schema, row, dstIndex, dstPolicy, isVidStringType) + val rank = + if (rankIndex.isEmpty) Option.empty + else Option(NebulaExecutor.extraRank(schema, row, rankIndex.get)) + val values = + NebulaExecutor.assignEdgeValues(schema, + row, + srcIndex, + dstIndex, + rankIdx, + nebulaOptions.srcAsProp, + nebulaOptions.dstAsProp, + nebulaOptions.rankAsProp, + fieldTypMap) + val nebulaEdge = NebulaEdge(srcId, dstId, rank, values) + edges.append(nebulaEdge) + if (edges.size >= nebulaOptions.batch) { + execute() + } + } + + def execute(): Unit = { + val nebulaEdges = NebulaEdges(propNames, edges.toList, srcPolicy, dstPolicy) + val exec = NebulaExecutor.toExecuteSentence(nebulaOptions.label, nebulaEdges) + edges.clear() + submit(exec) + } + + override def commit(): WriterCommitMessage = { + if (edges.nonEmpty) { + execute() + } + NebulaCommitMessage.apply(failedExecs.toList) + } + + override def abort(): Unit = { + LOG.error("insert edge task abort.") + graphProvider.close() + } +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala new file mode 100644 index 0000000..6277cac --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala @@ -0,0 +1,258 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.writer + +import com.vesoft.nebula.connector.NebulaTemplate.{ + BATCH_INSERT_TEMPLATE, + EDGE_VALUE_TEMPLATE, + EDGE_VALUE_WITHOUT_RANKING_TEMPLATE, + ENDPOINT_TEMPLATE, + VERTEX_VALUE_TEMPLATE, + VERTEX_VALUE_TEMPLATE_WITH_POLICY +} +import com.vesoft.nebula.connector.connector.{ + EdgeRank, + NebulaEdges, + NebulaVertices, + PropertyNames, + PropertyValues +} +import com.vesoft.nebula.connector.{DataTypeEnum, KeyPolicy, NebulaUtils} +import com.vesoft.nebula.meta.PropertyType +import org.apache.spark.sql.catalyst.InternalRow +import org.apache.spark.sql.types.StructType + +object NebulaExecutor { + + /** + * deal with vertex ID, used to extra vertex's id and edge's srcId,dstId + * @param schema + * @param record + * @param index + * @param policy + * @param isVidStringType true if vid_type is Fix_String + */ + def extraID(schema: StructType, + record: InternalRow, + index: Int, + policy: Option[KeyPolicy.Value], + isVidStringType: Boolean): String = { + val types = schema.fields.map(field => field.dataType) + val vid = record.get(index, types(index)).toString + if (policy.isEmpty) { + if (isVidStringType) { + NebulaUtils.escapeUtil(vid).mkString("\"", "", "\"") + } else { + assert(NebulaUtils.isNumic(vid)) + vid + } + } else { + vid + } + } + + /** + * extract rank value for edge + * @param schema + * @param record + * @param rankIndex + */ + def extraRank(schema: StructType, record: InternalRow, rankIndex: Int): EdgeRank = { + val types = schema.fields.map(field => field.dataType) + val rank = record.get(rankIndex, types(rankIndex)).toString + assert(NebulaUtils.isNumic(rank), s"rank must be numeric, but your rank is ${rank}") + rank.toLong + } + + /** + * deal with vertex property values + * @param schema + * @param record + * @param vertexIndex + * @param fieldTypeMap + * */ + def assignVertexPropValues(schema: StructType, + record: InternalRow, + vertexIndex: Int, + vidAsProp: Boolean, + fieldTypeMap: Map[String, Integer]): PropertyValues = { + val values = for { + index <- schema.fields.indices + if vidAsProp || index != vertexIndex + } yield { + extraValue(record, schema, index, fieldTypeMap) + } + values.toList + } + + /** + * deal with edge property values + * @param schema + * @param record + * @param srcIndex + * @param dstIndex + * @param rankIndex + * @param fieldTypeMap + */ + def assignEdgeValues(schema: StructType, + record: InternalRow, + srcIndex: Int, + dstIndex: Int, + rankIndex: Int, + srcAsProp: Boolean, + dstAsProp: Boolean, + rankAsProp: Boolean, + fieldTypeMap: Map[String, Integer]): PropertyValues = { + val values = for { + index <- schema.fields.indices + if (srcAsProp || index != srcIndex) && (dstAsProp || index != dstIndex) && (rankAsProp || index != rankIndex) + } yield { + extraValue(record, schema, index, fieldTypeMap) + } + values.toList + } + + /** + * get and convert property value + * + * @param record DataFrame internal row + * @param schema DataFrame schema + * @param index the position of row columns + * @param fieldTypeMap property name -> property datatype in nebula + */ + private[this] def extraValue(record: InternalRow, + schema: StructType, + index: Int, + fieldTypeMap: Map[String, Integer]): Any = { + if (record.isNullAt(index)) return null + + val types = schema.fields.map(field => field.dataType) + val propValue = record.get(index, types(index)) + + val fieldName = schema.fields(index).name + fieldTypeMap(fieldName).toInt match { + case PropertyType.STRING => + NebulaUtils.escapeUtil(propValue.toString).mkString("\"", "", "\"") + case PropertyType.DATE => "date(\"" + propValue + "\")" + case PropertyType.DATETIME => "datatime(\"" + propValue + "\")" + case PropertyType.TIME => "time(\"" + propValue + "\")" + case _ => propValue + } + } + + /** + * deal with vertex property names + * @param schema + * @param vertexIndex + */ + def assignVertexPropNames(schema: StructType, + vertexIndex: Int, + vidAsProp: Boolean): PropertyNames = { + val propNames = for { + index <- schema.indices + if vidAsProp || index != vertexIndex + } yield { + schema.fields(index).name + } + propNames.toList + } + + /** + * deal with edge property names + * srcId,dstId and rank is not in properties. + * + * @param schema DataFrame schema + * @param srcIndex srcId's position in DF + * @param dstIndex dstId's position in DF + * @param rankIndex rankIndex's position in DF + */ + def assignEdgePropNames(schema: StructType, + srcIndex: Int, + dstIndex: Int, + rankIndex: Int, + srcAsProp: Boolean, + dstAsProp: Boolean, + rankAsProp: Boolean): PropertyNames = { + val propNames = for { + index <- schema.indices + if (srcAsProp || index != srcIndex) && (dstAsProp || index != dstIndex) && (rankAsProp || index != rankIndex) + } yield { + schema.fields(index).name + } + propNames.toList + } + + /** + * construct insert statement for vertex + */ + def toExecuteSentence(tagName: String, vertices: NebulaVertices): String = { + BATCH_INSERT_TEMPLATE.format( + DataTypeEnum.VERTEX.toString, + tagName, + vertices.propertyNames, + vertices.values + .map { vertex => + if (vertices.policy.isEmpty) { + VERTEX_VALUE_TEMPLATE.format(vertex.vertexIDSlice, vertex.propertyValues) + } else { + vertices.policy.get match { + case KeyPolicy.HASH => + VERTEX_VALUE_TEMPLATE_WITH_POLICY + .format(KeyPolicy.HASH.toString, vertex.vertexIDSlice, vertex.propertyValues) + case KeyPolicy.UUID => + VERTEX_VALUE_TEMPLATE_WITH_POLICY + .format(KeyPolicy.UUID.toString, vertex.vertexIDSlice, vertex.propertyValues) + case _ => + throw new IllegalArgumentException("Not Support") + } + } + } + .mkString(", ") + ) + } + + /** + * construct insert statement for edge + */ + def toExecuteSentence(edgeName: String, edges: NebulaEdges): String = { + val values = edges.values + .map { edge => + val source = edges.getSourcePolicy match { + case Some(KeyPolicy.HASH) => + ENDPOINT_TEMPLATE.format(KeyPolicy.HASH.toString, edge.source) + case Some(KeyPolicy.UUID) => + ENDPOINT_TEMPLATE.format(KeyPolicy.UUID.toString, edge.source) + case None => + edge.source + case _ => + throw new IllegalArgumentException( + s"source policy ${edges.getSourcePolicy.get} is not supported") + } + + val target = edges.getTargetPolicy match { + case Some(KeyPolicy.HASH) => + ENDPOINT_TEMPLATE.format(KeyPolicy.HASH.toString, edge.target) + case Some(KeyPolicy.UUID) => + ENDPOINT_TEMPLATE.format(KeyPolicy.UUID.toString, edge.target) + case None => + edge.target + case _ => + throw new IllegalArgumentException( + s"target policy ${edges.getTargetPolicy.get} is not supported") + } + + if (edge.rank.isEmpty) + EDGE_VALUE_WITHOUT_RANKING_TEMPLATE + .format(source, target, edge.propertyValues) + else + EDGE_VALUE_TEMPLATE.format(source, target, edge.rank.get, edge.propertyValues) + } + .mkString(", ") + BATCH_INSERT_TEMPLATE.format(DataTypeEnum.EDGE.toString, edgeName, edges.propertyNames, values) + } + +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaSourceWriter.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaSourceWriter.scala new file mode 100644 index 0000000..458126a --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaSourceWriter.scala @@ -0,0 +1,101 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.writer + +import com.vesoft.nebula.connector.NebulaOptions +import org.apache.spark.sql.catalyst.InternalRow +import org.apache.spark.sql.sources.v2.writer.{ + DataSourceWriter, + DataWriter, + DataWriterFactory, + WriterCommitMessage +} +import org.apache.spark.sql.types.StructType +import org.slf4j.LoggerFactory + +/** + * creating and initializing the actual Nebula vertex writer at executor side + */ +class NebulaVertexWriterFactory(nebulaOptions: NebulaOptions, vertexIndex: Int, schema: StructType) + extends DataWriterFactory[InternalRow] { + override def createDataWriter(partitionId: Int, + taskId: Long, + epochId: Long): DataWriter[InternalRow] = { + new NebulaVertexWriter(nebulaOptions, vertexIndex, schema) + } +} + +/** + * creating and initializing the actual Nebula edge writer at executor side + */ +class NebulaEdgeWriterFactory(nebulaOptions: NebulaOptions, + srcIndex: Int, + dstIndex: Int, + rankIndex: Option[Int], + schema: StructType) + extends DataWriterFactory[InternalRow] { + override def createDataWriter(partitionId: Int, + taskId: Long, + epochId: Long): DataWriter[InternalRow] = { + new NebulaEdgeWriter(nebulaOptions, srcIndex, dstIndex, rankIndex, schema) + } +} + +/** + * nebula vertex writer to create factory + */ +class NebulaDataSourceVertexWriter(nebulaOptions: NebulaOptions, + vertexIndex: Int, + schema: StructType) + extends DataSourceWriter { + private val LOG = LoggerFactory.getLogger(this.getClass) + + override def createWriterFactory(): DataWriterFactory[InternalRow] = { + new NebulaVertexWriterFactory(nebulaOptions, vertexIndex, schema) + } + + override def commit(messages: Array[WriterCommitMessage]): Unit = { + LOG.debug(s"${messages.length}") + for (msg <- messages) { + val nebulaMsg = msg.asInstanceOf[NebulaCommitMessage] + LOG.info(s"failed execs:\n ${nebulaMsg.executeStatements.toString()}") + } + } + + override def abort(messages: Array[WriterCommitMessage]): Unit = { + LOG.error("NebulaDataSourceVertexWriter abort") + } +} + +/** + * nebula edge writer to create factory + */ +class NebulaDataSourceEdgeWriter(nebulaOptions: NebulaOptions, + srcIndex: Int, + dstIndex: Int, + rankIndex: Option[Int], + schema: StructType) + extends DataSourceWriter { + private val LOG = LoggerFactory.getLogger(this.getClass) + + override def createWriterFactory(): DataWriterFactory[InternalRow] = { + new NebulaEdgeWriterFactory(nebulaOptions, srcIndex, dstIndex, rankIndex, schema) + } + + override def commit(messages: Array[WriterCommitMessage]): Unit = { + LOG.debug(s"${messages.length}") + for (msg <- messages) { + val nebulaMsg = msg.asInstanceOf[NebulaCommitMessage] + LOG.info(s"failed execs:\n ${nebulaMsg.executeStatements.toString()}") + } + + } + + override def abort(messages: Array[WriterCommitMessage]): Unit = { + LOG.error("NebulaDataSourceEdgeWriter abort") + } +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala new file mode 100644 index 0000000..ce20ded --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala @@ -0,0 +1,73 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.writer + +import com.vesoft.nebula.connector.connector.{NebulaVertex, NebulaVertices} +import com.vesoft.nebula.connector.{KeyPolicy, NebulaOptions} +import org.apache.spark.sql.catalyst.InternalRow +import org.apache.spark.sql.sources.v2.writer.{DataWriter, WriterCommitMessage} +import org.apache.spark.sql.types.StructType +import org.slf4j.LoggerFactory + +import scala.collection.mutable.ListBuffer + +class NebulaVertexWriter(nebulaOptions: NebulaOptions, vertexIndex: Int, schema: StructType) + extends NebulaWriter(nebulaOptions) + with DataWriter[InternalRow] { + + private val LOG = LoggerFactory.getLogger(this.getClass) + + val propNames = NebulaExecutor.assignVertexPropNames(schema, vertexIndex, nebulaOptions.vidAsProp) + val fieldTypMap = metaProvider.getTagSchema(nebulaOptions.spaceName, nebulaOptions.label) + + val policy = { + if (nebulaOptions.vidPolicy.isEmpty) Option.empty + else Option(KeyPolicy.withName(nebulaOptions.vidPolicy)) + } + + /** buffer to save batch vertices */ + var vertices: ListBuffer[NebulaVertex] = new ListBuffer() + + prepareSpace() + + /** + * write one vertex row to buffer + */ + override def write(row: InternalRow): Unit = { + val vertex = + NebulaExecutor.extraID(schema, row, vertexIndex, policy, isVidStringType) + val values = NebulaExecutor.assignVertexPropValues(schema, + row, + vertexIndex, + nebulaOptions.vidAsProp, + fieldTypMap) + val nebulaVertex = NebulaVertex(vertex, values) + vertices.append(nebulaVertex) + if (vertices.size >= nebulaOptions.batch) { + execute() + } + } + + def execute(): Unit = { + val nebulaVertices = NebulaVertices(propNames, vertices.toList, policy) + val exec = NebulaExecutor.toExecuteSentence(nebulaOptions.label, nebulaVertices) + vertices.clear() + submit(exec) + } + + override def commit(): WriterCommitMessage = { + if (vertices.nonEmpty) { + execute() + } + NebulaCommitMessage(failedExecs.toList) + } + + override def abort(): Unit = { + LOG.error("insert vertex task abort.") + graphProvider.close() + } +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaWriter.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaWriter.scala new file mode 100644 index 0000000..e5d80d9 --- /dev/null +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaWriter.scala @@ -0,0 +1,46 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.writer + +import java.util.concurrent.TimeUnit + +import com.google.common.util.concurrent.RateLimiter +import com.vesoft.nebula.connector.NebulaOptions +import com.vesoft.nebula.connector.nebula.{GraphProvider, MetaProvider, VidType} +import org.slf4j.LoggerFactory + +import scala.collection.mutable.ListBuffer + +class NebulaWriter(nebulaOptions: NebulaOptions) extends Serializable { + private val LOG = LoggerFactory.getLogger(this.getClass) + + val failedExecs: ListBuffer[String] = new ListBuffer[String] + + val graphProvider = new GraphProvider(nebulaOptions.getGraphAddress) + val metaProvider = new MetaProvider(nebulaOptions.getMetaAddress) + val isVidStringType = metaProvider.getVidType(nebulaOptions.spaceName) == VidType.STRING + + def prepareSpace(): Unit = { + graphProvider.switchSpace(nebulaOptions.user, nebulaOptions.passwd, nebulaOptions.spaceName) + } + + def submit(exec: String): Unit = { + @transient val rateLimiter = RateLimiter.create(nebulaOptions.rateLimit) + if (rateLimiter.tryAcquire(nebulaOptions.rateTimeOut, TimeUnit.MILLISECONDS)) { + val result = graphProvider.submit(exec) + if (!result.isSucceeded) { + failedExecs.append(exec) + LOG.error(s"failed to write : ${exec}") + } else { + LOG.info(s"succeed to write : ${exec}") + } + } else { + failedExecs.append(exec) + LOG.error(s"failed to acquire reteLimiter for statement {$exec}") + } + } +} diff --git a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/NebulaConfigSuit.scala b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/NebulaConfigSuit.scala new file mode 100644 index 0000000..b54c410 --- /dev/null +++ b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/NebulaConfigSuit.scala @@ -0,0 +1,95 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector + +import org.scalatest.BeforeAndAfterAll +import org.scalatest.funsuite.AnyFunSuite + +class NebulaConfigSuit extends AnyFunSuite with BeforeAndAfterAll { + + test("test NebulaConnectionConfig") { + try { + NebulaConnectionConfig.builder().withTimeout(1).build() + } catch { + case e: java.lang.AssertionError => assert(true) + } + + try { + NebulaConnectionConfig.builder().withTimeout(-1).build() + } catch { + case e: java.lang.AssertionError => assert(true) + } + + try { + NebulaConnectionConfig.builder().withMetaAddress("127.0.0.1:45500").withTimeout(1).build() + assert(true) + } catch { + case _: Throwable => assert(false) + } + } + + test("test WriteNebulaConfig") { + var writeNebulaConfig: WriteNebulaVertexConfig = null + try { + writeNebulaConfig = WriteNebulaVertexConfig + .builder() + .withSpace("test") + .withTag("tag") + .withVidField("vid") + .build() + } catch { + case e: Throwable => assert(false) + } + assert(true) + assert(!writeNebulaConfig.getVidAsProp) + assert(writeNebulaConfig.getSpace.equals("test")) + } + + test("test wrong policy") { + try { + WriteNebulaVertexConfig + .builder() + .withSpace("test") + .withTag("tag") + .withVidField("vId") + .withVidPolicy("wrong_policy") + .build() + } catch { + case e: java.lang.AssertionError => assert(true) + } + } + + test("test wrong batch") { + try { + WriteNebulaVertexConfig + .builder() + .withSpace("test") + .withTag("tag") + .withVidField("vId") + .withVidPolicy("hash") + .withBatch(-1) + .build() + } catch { + case e: java.lang.AssertionError => assert(true) + } + } + + test("test ReadNebulaConfig") { + try { + ReadNebulaConfig + .builder() + .withSpace("test") + .withLabel("tagName") + .withNoColumn(true) + .withReturnCols(List("col")) + .build() + } catch { + case e: java.lang.AssertionError => assert(false) + } + } + +} diff --git a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuit.scala b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuit.scala new file mode 100644 index 0000000..916d43b --- /dev/null +++ b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuit.scala @@ -0,0 +1,122 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.connector.writer + +import com.vesoft.nebula.connector.KeyPolicy +import org.apache.spark.sql.catalyst.InternalRow +import org.apache.spark.sql.catalyst.expressions.GenericInternalRow +import org.apache.spark.sql.types.{ + BooleanType, + DataTypes, + LongType, + StringType, + StructField, + StructType +} +import org.scalatest.BeforeAndAfterAll +import org.scalatest.funsuite.AnyFunSuite + +import scala.collection.mutable.ListBuffer + +class NebulaExecutorSuit extends AnyFunSuite with BeforeAndAfterAll { + var schema: StructType = _ + var row: InternalRow = _ + + override def beforeAll(): Unit = { + val fields = new ListBuffer[StructField] + fields.append(DataTypes.createStructField("col1", StringType, false)) + fields.append(DataTypes.createStructField("col2", BooleanType, false)) + fields.append(DataTypes.createStructField("col3", LongType, false)) + schema = new StructType(fields.toArray) + + val values = new ListBuffer[Any] + values.append("aaa") + values.append(true) + values.append(1L) + row = new GenericInternalRow(values.toArray) + } + + override def afterAll(): Unit = super.afterAll() + + test("test extraID") { + val index: Int = 1 + val policy: Option[KeyPolicy.Value] = None + val isVidStringType: Boolean = true + val stringId = NebulaExecutor.extraID(schema, row, index, policy, isVidStringType) + assert("\"true\"".equals(stringId)) + + // test hash vertexId + val hashId = NebulaExecutor.extraID(schema, row, index, Some(KeyPolicy.HASH), false) + assert("true".equals(hashId)) + } + + test("test extraRank") { + // test correct type for rank + assert(NebulaExecutor.extraRank(schema, row, 2) == 1) + + // test wrong type for rank + try { + NebulaExecutor.extraRank(schema, row, 1) + } catch { + case e: java.lang.AssertionError => assert(true) + } + } + + test("test vid as prop for assignVertexPropValues ") { + val fieldTypeMap: Map[String, Integer] = Map("col1" -> 6, "col2" -> 1, "col3" -> 2) + // test vid as prop + val props = NebulaExecutor.assignVertexPropValues(schema, row, 0, true, fieldTypeMap) + assert(props.size == 3) + assert(props.contains("\"aaa\"")) + } + + test("test vid not as prop for assignVertexPropValues ") { + val fieldTypeMap: Map[String, Integer] = Map("col1" -> 6, "col2" -> 1, "col3" -> 2) + // test vid not as prop + val props = NebulaExecutor.assignVertexPropValues(schema, row, 0, false, fieldTypeMap) + assert(props.size == 2) + assert(!props.contains("\"aaa\"")) + } + + test("test src & dst & rank all as prop for assignEdgeValues") { + val fieldTypeMap: Map[String, Integer] = Map("col1" -> 6, "col2" -> 1, "col3" -> 2) + + val prop = NebulaExecutor.assignEdgeValues(schema, row, 0, 1, 2, true, true, true, fieldTypeMap) + assert(prop.size == 3) + } + + test("test src & dst & rank all not as prop for assignEdgeValues") { + val fieldTypeMap: Map[String, Integer] = Map("col1" -> 6, "col2" -> 1, "col3" -> 2) + + val prop = + NebulaExecutor.assignEdgeValues(schema, row, 0, 1, 2, false, false, false, fieldTypeMap) + assert(prop.isEmpty) + } + + test("test assignVertexPropNames") { + // test vid as prop + val propNames = NebulaExecutor.assignVertexPropNames(schema, 0, true) + assert(propNames.size == 3) + assert(propNames.contains("col1") && propNames.contains("col2") && propNames.contains("col3")) + + // test vid not as prop + val propNames1 = NebulaExecutor.assignVertexPropNames(schema, 0, false) + assert(propNames1.size == 2) + assert(!propNames1.contains("col1") && propNames.contains("col2") && propNames.contains("col3")) + } + + test("test assignEdgePropNames") { + // test src / dst / rank all as prop + val propNames = NebulaExecutor.assignEdgePropNames(schema, 0, 1, 2, true, true, true) + assert(propNames.size == 3) + + // test src / dst / rank all not as prop + val propNames1 = NebulaExecutor.assignEdgePropNames(schema, 0, 1, 2, false, false, false) + assert(propNames1.isEmpty) + } + +} diff --git a/pom.xml b/pom.xml index 111b621..4bb2b55 100644 --- a/pom.xml +++ b/pom.xml @@ -47,6 +47,7 @@ nebula-exchange nebula-spark-connector + example From 6c36bd8bb2d0dddc8317b00fe2b1366f6d005014 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 18 Dec 2020 10:15:28 +0800 Subject: [PATCH 025/213] format parameter in example --- .../examples/connector/NebulaSparkWriterExample.scala | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala index 152f44e..1a43509 100644 --- a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala +++ b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala @@ -72,14 +72,13 @@ object NebulaSparkWriterExample { val config = NebulaConnectionConfig .builder() - .withMetaAddress("192.168.8.172:45509") - .withGraphAddress("192.168.8.172:3799") - .withConenctionRetry(2) + .withMetaAddress("127.0.0.1:45509") + .withGraphAddress("127.0.0.1:3799") .build val nebulaWriteEdgeConfig: WriteNebulaEdgeConfig = WriteNebulaEdgeConfig .builder() - .withSpace("exchange") - .withEdge("friend1") + .withSpace("test") + .withEdge("friend") .withSrcIdField("src") .withDstIdField("dst") .withRankField("degree") From 8763bd48403bad79a6e789e35d17ee9ae2de8c38 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 4 Jan 2021 14:38:21 +0800 Subject: [PATCH 026/213] update link --- nebula-exchange/README-CN.md | 2 +- nebula-exchange/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nebula-exchange/README-CN.md b/nebula-exchange/README-CN.md index aca8e38..f727327 100644 --- a/nebula-exchange/README-CN.md +++ b/nebula-exchange/README-CN.md @@ -1,5 +1,5 @@ # 欢迎使用 Nebula Exchange 2.0 -[English](https://github.com/vesoft-inc/nebula-spark-utils/blob/main/nebula-exchange/README.md) +[English](https://github.com/vesoft-inc/nebula-spark-utils/blob/master/nebula-exchange/README.md) Nebula Exchange 2.0(简称为 Exchange 2.0)是一款 Apache Spark™ 应用,用于在分布式环境中将集群中的数据批量迁移到 Nebula Graph 中,能支持多种不同格式的批式数据和流式数据的迁移。 diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index 23d9363..8ef2872 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -1,5 +1,5 @@ # Nebula Exchange 2.0 - [中文版](https://github.com/vesoft-inc/nebula-spark-utils/blob/main/nebula-exchange/README-CN.md) + [中文版](https://github.com/vesoft-inc/nebula-spark-utils/blob/master/nebula-exchange/README-CN.md) Nebula Exchange (Exchange for short) is an Apache Spark application. It is used to migrate cluster data in bulk from Spark to Nebula Graph in a distributed environment. It supports migration of batch data and streaming data in various formats. From 727854301b1bcf582a3acfe13da1894e99e813b7 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 7 Jan 2021 17:29:34 +0800 Subject: [PATCH 027/213] add import command --- nebula-exchange/README-CN.md | 4 ++++ nebula-exchange/README.md | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/nebula-exchange/README-CN.md b/nebula-exchange/README-CN.md index f727327..5fad55d 100644 --- a/nebula-exchange/README-CN.md +++ b/nebula-exchange/README-CN.md @@ -45,6 +45,10 @@ Exchange 2.0 依赖 Nebula Java Client 2.0。 *5. 配置文件参考 [application.conf](https://github.com/vesoft-inc/nebula-spark-utils/tree/main/nebula-exchange/src/main/resources)。* +*6. Exchange 2.0 的导入命令:* +``` +$SPARK_HOME/bin/submit --class com.vesoft.nebula.exchange.Exchange --master local nebula-exchange-2.0.0.jar -c /path/to/application.conf +``` ## 贡献 Nebula Exchange 2.0 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index 8ef2872..72fe229 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -31,6 +31,11 @@ Exchange 2.0 depends on the latest Nebula Java Client 2.0。 ## How to use +Import command: +``` +$SPARK_HOME/bin/submit --class com.vesoft.nebula.exchange.Exchange --master local nebula-exchange-2.0.0.jar -c /path/to/application.conf +``` + For more details about Exchange, please refer to [Exchange 1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools/exchange) . From defccf37b327b421458329d75b36ed602c6b2be1 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 13 Jan 2021 16:25:41 +0800 Subject: [PATCH 028/213] update client version to rc1 --- nebula-exchange/README-CN.md | 2 +- nebula-exchange/README.md | 2 +- nebula-exchange/pom.xml | 2 +- nebula-spark-connector/README.md | 2 +- nebula-spark-connector/pom.xml | 2 +- .../com/vesoft/nebula/connector/nebula/MetaProvider.scala | 8 -------- 6 files changed, 5 insertions(+), 13 deletions(-) diff --git a/nebula-exchange/README-CN.md b/nebula-exchange/README-CN.md index 5fad55d..4e922a5 100644 --- a/nebula-exchange/README-CN.md +++ b/nebula-exchange/README-CN.md @@ -17,7 +17,7 @@ Exchange 2.0 依赖 Nebula Java Client 2.0。 $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true ``` - 打包结束后,在本地 Maven Repository 仓库中可以看到生成的 /com/vesoft/client/2.0.0-beta/client-2.0.0-beta.jar。 + 打包结束后,在本地 Maven Repository 仓库中可以看到生成的 /com/vesoft/client/2.0.0-rc1/client-2.0.0-rc1.jar。 2. 编译打包 Exchange 2.0。 diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index 72fe229..13ef101 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -17,7 +17,7 @@ Exchange 2.0 depends on the latest Nebula Java Client 2.0。 $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true ``` - After the installing, you can see the newly generated /com/vesoft/client/2.0.0-beta/client-2.0.0-beta.jar in your local Maven repository. + After the installing, you can see the newly generated /com/vesoft/client/2.0.0-rc1/client-2.0.0-rc1.jar in your local Maven repository. 2. Package Exchange 2.0。 diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml index 4ca28fc..d19d53f 100644 --- a/nebula-exchange/pom.xml +++ b/nebula-exchange/pom.xml @@ -28,7 +28,7 @@ 3.9.2 2.11.0-M4 3.7.1 - 2.0.0-beta + 2.0.0-rc1 1.0.0-rc2 1.0.0 2.4.5-M1 diff --git a/nebula-spark-connector/README.md b/nebula-spark-connector/README.md index 909f613..7596143 100644 --- a/nebula-spark-connector/README.md +++ b/nebula-spark-connector/README.md @@ -16,7 +16,7 @@ Nebula Spark Connector 2.0 依赖 Nebula Java Client 2.0。 $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true ``` - 打包结束后,在本地 Maven Repository 仓库中可以看到生成的 /com/vesoft/client/2.0.0-beta/client-2.0.0-beta.jar。 + 打包结束后,在本地 Maven Repository 仓库中可以看到生成的 /com/vesoft/client/2.0.0-rc1/client-2.0.0-rc1.jar。 2. 编译打包 Nebula Spark Connector 2.0。 diff --git a/nebula-spark-connector/pom.xml b/nebula-spark-connector/pom.xml index a3d6005..a7fc6b8 100644 --- a/nebula-spark-connector/pom.xml +++ b/nebula-spark-connector/pom.xml @@ -15,7 +15,7 @@ 2.4.4 - 2.0.0-beta + 2.0.0-rc1 1.8 1.8 4.13.1 diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/nebula/MetaProvider.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/nebula/MetaProvider.scala index a0ae79a..8c062ba 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/nebula/MetaProvider.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/nebula/MetaProvider.scala @@ -21,14 +21,6 @@ class MetaProvider(addresses: List[Address]) extends AutoCloseable { val client = new MetaClient(metaAddress) client.connect() - def getPartition(space: String): Map[Integer, List[HostAddress]] = { - client - .getPartsAlloc(space) - .asScala - .map(entry => entry._1 -> entry._2.asScala.toList) - .toMap - } - def getPartitionNumber(space: String): Int = { client.getPartsAlloc(space).size() } From c620a79d603c3e4c31f7d111fca2dc33b67262a3 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 11 Jan 2021 15:36:46 +0800 Subject: [PATCH 029/213] add spark reader 2.0 --- .../connector/NebulaSparkReaderExample.scala | 136 ++++++++++++++++++ nebula-spark-connector/pom.xml | 8 +- .../nebula/connector/NebulaConfig.scala | 9 +- .../vesoft/nebula/connector/NebulaUtils.scala | 68 ++++----- .../com/vesoft/nebula/connector/package.scala | 44 ++++-- .../reader/NebulaEdgePartitionReader.scala | 105 +++++++------- .../reader/NebulaPartitionReader.scala | 58 +++++--- .../connector/reader/NebulaSourceReader.scala | 26 ++-- .../reader/NebulaVertexPartitionReader.scala | 103 +++++++------ .../reader/tmp/ScanEdgeResultIterator.scala | 27 ---- .../reader/tmp/ScanVertexResultIterator.scala | 27 ---- .../connector/reader/tmp/StorageClient.scala | 17 --- ...nfigSuit.scala => NebulaConfigSuite.scala} | 2 +- ...orSuit.scala => NebulaExecutorSuite.scala} | 2 +- 14 files changed, 388 insertions(+), 244 deletions(-) create mode 100644 example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala delete mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanEdgeResultIterator.scala delete mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanVertexResultIterator.scala delete mode 100644 nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/StorageClient.scala rename nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/{NebulaConfigSuit.scala => NebulaConfigSuite.scala} (97%) rename nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/{NebulaExecutorSuit.scala => NebulaExecutorSuite.scala} (98%) diff --git a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala new file mode 100644 index 0000000..0d1f18e --- /dev/null +++ b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala @@ -0,0 +1,136 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package main.scala.com.vesoft.nebula.examples.connector + +import com.facebook.thrift.protocol.TCompactProtocol +import com.vesoft.nebula.connector.connector.NebulaDataFrameReader +import com.vesoft.nebula.connector.{NebulaConnectionConfig, ReadNebulaConfig} +import org.apache.spark.SparkConf +import org.apache.spark.sql.SparkSession +import org.slf4j.LoggerFactory + +object NebulaSparkReaderExample { + + private val LOG = LoggerFactory.getLogger(this.getClass) + + def main(args: Array[String]): Unit = { + + val sparkConf = new SparkConf + sparkConf + .set("spark.serializer", "org.apache.spark.serializer.KryoSerializer") + .registerKryoClasses(Array[Class[_]](classOf[TCompactProtocol])) + val spark = SparkSession + .builder() + .master("local") + .config(sparkConf) + .getOrCreate() + + // readVertex(spark) + // readEdges(spark) + readVertexGraph(spark) + readEdgeGraph(spark) + + spark.close() + sys.exit() + } + + def readVertex(spark: SparkSession): Unit = { + LOG.info("start to read nebula vertices") + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:45500") + .withConenctionRetry(2) + .build() + val nebulaReadVertexConfig: ReadNebulaConfig = ReadNebulaConfig + .builder() + .withSpace("exchange") + .withLabel("person") + .withNoColumn(false) + .withReturnCols(List("birthday")) + .withLimit(10) + .withPartitionNum(10) + .build() + val vertex = spark.read.nebula(config, nebulaReadVertexConfig).loadVerticesToDF() + vertex.printSchema() + vertex.show(20) + println("vertex count: " + vertex.count()) + } + + def readEdges(spark: SparkSession): Unit = { + LOG.info("start to read nebula edges") + + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:45500") + .withTimeout(6000) + .withConenctionRetry(2) + .build() + val nebulaReadEdgeConfig: ReadNebulaConfig = ReadNebulaConfig + .builder() + .withSpace("exchange") + .withLabel("knows") + .withNoColumn(false) + .withReturnCols(List("degree")) + .withLimit(10) + .withPartitionNum(10) + .build() + val edge = spark.read.nebula(config, nebulaReadEdgeConfig).loadEdgesToDF() + edge.printSchema() + edge.show(20) + println("edge count: " + edge.count()) + } + + def readVertexGraph(spark: SparkSession): Unit = { + LOG.info("start to read graphx vertex") + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress("192.168.8.172:45509") + .withTimeout(6000) + .withConenctionRetry(2) + .build() + val nebulaReadVertexConfig: ReadNebulaConfig = ReadNebulaConfig + .builder() + .withSpace("exchange") + .withLabel("person") + .withNoColumn(false) + .withReturnCols(List("birthday")) + .withLimit(10) + .withPartitionNum(10) + .build() + + val vertexRDD = spark.read.nebula(config, nebulaReadVertexConfig).loadVerticesToGraphx() + LOG.info("vertex rdd first record: " + vertexRDD.first()) + LOG.info("vertex rdd count: {}", vertexRDD.count()) + } + + def readEdgeGraph(spark: SparkSession): Unit = { + LOG.info("start to read graphx edge") + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress("192.168.8.172:45509") + .withTimeout(6000) + .withConenctionRetry(2) + .build() + val nebulaReadEdgeConfig: ReadNebulaConfig = ReadNebulaConfig + .builder() + .withSpace("exchange") + .withLabel("knows1") + .withNoColumn(false) + .withReturnCols(List("timep")) + .withLimit(10) + .withPartitionNum(10) + .build() + val edgeRDD = spark.read.nebula(config, nebulaReadEdgeConfig).loadEdgesToGraphx() + LOG.info("edge rdd first record:" + edgeRDD.first()) + LOG.info("edge rdd count: {}", edgeRDD.count()) + } + +} diff --git a/nebula-spark-connector/pom.xml b/nebula-spark-connector/pom.xml index a7fc6b8..2b90e87 100644 --- a/nebula-spark-connector/pom.xml +++ b/nebula-spark-connector/pom.xml @@ -18,8 +18,9 @@ 2.0.0-rc1 1.8 1.8 - 4.13.1 3.2.3 + 4.13.1 + 1.13 @@ -43,6 +44,11 @@ client ${nebula.version} + + commons-codec + commons-codec + ${codec.version} + org.scalatest diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala index 1cf623b..d5b6827 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala @@ -473,10 +473,15 @@ object ReadNebulaConfig { assert(partitionNum > 0, s"config partitionNum must be positive, your partitionNum is $limit") if (noColumn && returnCols.nonEmpty) { LOG.warn( - s"noColumn is true, returnCols will be invalidate and your result will not contain cols") + s"noColumn is true, returnCols will be invalidate " + + s"and your result will not contain property for $label") + } + if (!noColumn && returnCols.isEmpty) { + LOG.warn(s"returnCols is empty and your result will contain all properties for $label") } LOG.info( - s"NebulaReadConfig={space=$space,label=$label,returnCols=$returnCols,noColumn=$noColumn,partitionNum=$partitionNum}") + s"NebulaReadConfig={space=$space,label=$label,returnCols=${returnCols.toList}," + + s"noColumn=$noColumn,partitionNum=$partitionNum}") } } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala index 5039406..df99658 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala @@ -8,6 +8,7 @@ package com.vesoft.nebula.connector import com.vesoft.nebula.meta.{ColumnDef, ColumnTypeDef, PropertyType} import org.apache.spark.sql.Row +import org.apache.spark.sql.catalyst.InternalRow import org.apache.spark.sql.types.{ BooleanType, DataType, @@ -16,8 +17,10 @@ import org.apache.spark.sql.types.{ IntegerType, LongType, StringType, + StructType, TimestampType } +import org.apache.spark.unsafe.types.UTF8String import org.slf4j.LoggerFactory object NebulaUtils { @@ -34,13 +37,14 @@ object NebulaUtils { columnTypeDef.getType match { case PropertyType.VID | PropertyType.INT8 | PropertyType.INT16 | PropertyType.INT32 | PropertyType.INT64 => - return LongType - case PropertyType.BOOL => BooleanType - case PropertyType.FLOAT | PropertyType.DOUBLE => DoubleType - case PropertyType.FIXED_STRING | PropertyType.STRING => StringType - case PropertyType.TIMESTAMP => TimestampType - case PropertyType.DATE | PropertyType.TIME | PropertyType.DATETIME => StringType - case PropertyType.UNKNOWN => throw new IllegalArgumentException("unsupported data type") + LongType + case PropertyType.BOOL => BooleanType + case PropertyType.FLOAT | PropertyType.DOUBLE => DoubleType + case PropertyType.TIMESTAMP => TimestampType + case PropertyType.FIXED_STRING | PropertyType.STRING | PropertyType.DATE | PropertyType.TIME | + PropertyType.DATETIME => + StringType + case PropertyType.UNKNOWN => throw new IllegalArgumentException("unsupported data type") } } @@ -53,33 +57,31 @@ object NebulaUtils { throw new IllegalArgumentException(s"column $columnName does not exist in schema") } - //type NebulaValueGetter = (Property, InternalRow, Int) => Unit + type NebulaValueGetter = (Object, InternalRow, Int) => Unit -// def makeGetters(schema: StructType): Array[NebulaValueGetter] = -// schema.fields.map(field => makeGetter(field.dataType, field.metadata)) -// -// private def makeGetter(dataType: DataType, metadata: Metadata): NebulaValueGetter = { -// dataType match { -// case BooleanType => -// (prop: Property, row: InternalRow, pos: Int) => -// row.setBoolean(pos, prop.getValueAsBool) -// case LongType => -// (prop: Property, row: InternalRow, pos: Int) => -// row.setLong(pos, prop.getValueAsLong) -// case DoubleType => -// (prop: Property, row: InternalRow, pos: Int) => -// row.setDouble(pos, prop.getValueAsDouble) -// case FloatType => -// (prop: Property, row: InternalRow, pos: Int) => -// row.setFloat(pos, prop.getValueAsFloat) -// case IntegerType => -// (prop: Property, row: InternalRow, pos: Int) => -// row.setInt(pos, prop.getValueAsInt) -// case _ => -// (prop: Property, row: InternalRow, pos: Int) => -// row.update(pos, UTF8String.fromString(prop.getValue.toString)) -// } -// } + def makeGetters(schema: StructType): Array[NebulaValueGetter] = { + schema.fields.map(field => makeGetter(field.dataType)) + } + + private def makeGetter(dataType: DataType): NebulaValueGetter = { + dataType match { + case BooleanType => + (prop: Object, row: InternalRow, pos: Int) => + row.setBoolean(pos, prop.asInstanceOf[Boolean]) + case TimestampType | LongType => + (prop: Object, row: InternalRow, pos: Int) => + row.setLong(pos, prop.asInstanceOf[Long]) + case FloatType | DoubleType => + (prop: Object, row: InternalRow, pos: Int) => + row.setDouble(pos, prop.asInstanceOf[Double]) + case IntegerType => + (prop: Object, row: InternalRow, pos: Int) => + row.setInt(pos, prop.asInstanceOf[Int]) + case _ => + (prop: Object, row: InternalRow, pos: Int) => + row.update(pos, UTF8String.fromString(String.valueOf(prop))) + } + } def resolveDataAndType(row: Row, dataType: DataType, i: Int): Any = { dataType match { diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala index 1876407..9fdbc71 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala @@ -6,7 +6,9 @@ package com.vesoft.nebula.connector +import org.apache.commons.codec.digest.MurmurHash2 import org.apache.spark.rdd.RDD +import org.apache.spark.sql.types.{LongType, StringType} import org.apache.spark.sql.{ DataFrame, DataFrameReader, @@ -16,6 +18,7 @@ import org.apache.spark.sql.{ Row, SaveMode } + import scala.collection.mutable.ListBuffer package object connector { @@ -144,45 +147,70 @@ package object connector { /** * read nebula vertex edge to graphx's vertex + * only support Long vId */ def loadVerticesToGraphx(): RDD[NebulaGraphxVertex] = { val vertexDataset = loadVerticesToDF() implicit val encoder: Encoder[NebulaGraphxVertex] = Encoders.bean[NebulaGraphxVertex](classOf[NebulaGraphxVertex]) + + val fields = vertexDataset.schema.fields vertexDataset .map(row => { - val fields = row.schema.fields - val vertexId = row.get(0).toString.toLong + val vertexId = row.get(0) + val vid: Long = if (row.schema.fields(0).dataType == LongType) { + vertexId.toString.toLong + } else { + MurmurHash2.hash64(vertexId.toString.getBytes(), + vertexId.toString.getBytes().length, + 0xc70f6907) + } + val props: ListBuffer[Any] = ListBuffer() for (i <- row.schema.fields.indices) { if (i != 0) { props.append(NebulaUtils.resolveDataAndType(row, fields(i).dataType, i)) } } - (vertexId, props.toList) + (vid, props.toList) })(encoder) .rdd } /** * read nebula edge edge to graphx's edge + * only support edge with Long srcId and Long dstId */ def loadEdgesToGraphx(): RDD[NebulaGraphxEdge] = { val edgeDataset = loadEdgesToDF() implicit val encoder: Encoder[NebulaGraphxEdge] = Encoders.bean[NebulaGraphxEdge](classOf[NebulaGraphxEdge]) + + val fields = edgeDataset.schema.fields edgeDataset .map(row => { - val cols = row.schema.fields val props: ListBuffer[Any] = ListBuffer() for (i <- row.schema.fields.indices) { if (i != 0 && i != 1 && i != 2) { - props.append(NebulaUtils.resolveDataAndType(row, cols(i).dataType, i)) + props.append(NebulaUtils.resolveDataAndType(row, fields(i).dataType, i)) } } + val srcId = row.get(0).toString.getBytes() + val dstId = row.get(1).toString.getBytes() + val edgeSrc = if (row.schema.fields(0).dataType == LongType) { + srcId.toString.toLong + } else { + MurmurHash2.hash64(srcId, srcId.length, 0xc70f6907) + } + val edgeDst = if (row.schema.fields(0).dataType == LongType) { + dstId.toString.toLong + } else { + MurmurHash2.hash64(dstId, dstId.length, 0xc70f6907) + } + val edgeProp = (row.get(2).toString.toLong, props.toList) org.apache.spark.graphx - .Edge(row.get(0).toString.toLong, row.get(1).toString.toLong, edgeProp) + .Edge(edgeSrc, edgeDst, edgeProp) })(encoder) .rdd } @@ -197,10 +225,6 @@ package object connector { var connectionConfig: NebulaConnectionConfig = _ var writeNebulaConfig: WriteNebulaConfig = _ - def test(): NebulaDataFrameWriter = { - this - } - /** * config nebula connection * @param connectionConfig connection parameters diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaEdgePartitionReader.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaEdgePartitionReader.scala index fe60870..348e677 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaEdgePartitionReader.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaEdgePartitionReader.scala @@ -6,63 +6,72 @@ package com.vesoft.nebula.connector.reader -import java.util - +import com.vesoft.nebula.client.storage.scan.{ScanEdgeResult, ScanEdgeResultIterator} import com.vesoft.nebula.connector.NebulaOptions -import com.vesoft.nebula.connector.reader.tmp.ScanEdgeResult import org.apache.spark.sql.types.StructType import org.slf4j.{Logger, LoggerFactory} +import scala.collection.JavaConverters._ class NebulaEdgePartitionReader(index: Int, nebulaOptions: NebulaOptions, schema: StructType) extends NebulaPartitionReader(index, nebulaOptions, schema) { private val LOG: Logger = LoggerFactory.getLogger(this.getClass) - private var responseIterator: util.Iterator[ScanEdgeResult] = _ + private var responseIterator: ScanEdgeResultIterator = _ override def next(): Boolean = { -// if (dataIterator == null && responseIterator == null && !scanPartIterator.hasNext) return false -// -// var continue: Boolean = false -// var break: Boolean = false -// while ((dataIterator == null || !dataIterator.hasNext) && !break) { -// resultValues.clear() -// continue = false -// if (responseIterator == null || !responseIterator.hasNext) { -// if (scanPartIterator.hasNext) { -// try { -// if (nebulaOptions.noColumn) { -// responseIterator = storageClient.scanEdge(nebulaOptions.spaceName, -// scanPartIterator.next(), -// nebulaOptions.label, -// nebulaOptions.limit) -// } else { -// responseIterator = storageClient.scanEdge(nebulaOptions.spaceName, -// scanPartIterator.next(), -// nebulaOptions.label, -// nebulaOptions.getReturnCols, -// nebulaOptions.limit) -// } -// } catch { -// case e: Exception => -// LOG.error(s"Exception scanning vertex ${nebulaOptions.label}", e) -// throw new Exception(e.getMessage, e) -// } -// // jump to the next loop -// continue = true -// } -// // break while loop -// break = !continue -// } else { -// val next: ScanEdgeResult = responseIterator.next -// // todo dataIterator = next.getVertexTableView -// } -// } -// -// if (dataIterator == null) { -// return false -// } -// dataIterator.hasNext - false - } + if (dataIterator == null && responseIterator == null && !scanPartIterator.hasNext) + return false + var continue: Boolean = false + var break: Boolean = false + while ((dataIterator == null || !dataIterator.hasNext) && !break) { + resultValues.clear() + continue = false + if (responseIterator == null || !responseIterator.hasNext) { + if (scanPartIterator.hasNext) { + try { + if (nebulaOptions.noColumn) { + responseIterator = storageClient.scanEdge(nebulaOptions.spaceName, + scanPartIterator.next(), + nebulaOptions.label, + nebulaOptions.limit, + 0L, + Long.MaxValue, + true, + true) + } else { + responseIterator = storageClient.scanEdge(nebulaOptions.spaceName, + scanPartIterator.next(), + nebulaOptions.label, + nebulaOptions.getReturnCols.asJava, + nebulaOptions.limit, + 0, + Long.MaxValue, + true, + true) + } + } catch { + case e: Exception => + LOG.error(s"Exception scanning vertex ${nebulaOptions.label}", e) + storageClient.close() + throw new Exception(e.getMessage, e) + } + // jump to the next loop + continue = true + } + // break while loop + break = !continue + } else { + val next: ScanEdgeResult = responseIterator.next + if (!next.isEmpty) { + dataIterator = next.getEdgeTableRows.iterator().asScala + } + } + } + + if (dataIterator == null) { + return false + } + dataIterator.hasNext + } } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartitionReader.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartitionReader.scala index 946d803..dcc873f 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartitionReader.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartitionReader.scala @@ -6,29 +6,36 @@ package com.vesoft.nebula.connector.reader -import com.vesoft.nebula.connector.{NebulaOptions, PartitionUtils} +import com.vesoft.nebula.client.graph.data.HostAddress +import com.vesoft.nebula.client.storage.StorageClient +import com.vesoft.nebula.client.storage.data.{BaseTableRow, VertexTableRow} +import com.vesoft.nebula.connector.NebulaUtils.NebulaValueGetter +import com.vesoft.nebula.connector.exception.GraphConnectException +import com.vesoft.nebula.connector.{NebulaOptions, NebulaUtils, PartitionUtils} import com.vesoft.nebula.connector.nebula.MetaProvider import org.apache.spark.sql.catalyst.InternalRow +import org.apache.spark.sql.catalyst.expressions.SpecificInternalRow import org.apache.spark.sql.sources.v2.reader.InputPartitionReader import org.apache.spark.sql.types.StructType import org.slf4j.{Logger, LoggerFactory} +import scala.collection.JavaConverters._ +import scala.collection.mutable +import scala.collection.mutable.ListBuffer + /** * Read nebula data for each spark partition */ abstract class NebulaPartitionReader extends InputPartitionReader[InternalRow] { private val LOG: Logger = LoggerFactory.getLogger(this.getClass) -// protected var dataIterator: Iterator[List[Property]] = _ - protected var scanPartIterator: Iterator[Integer] = _ -// protected var resultValues: mutable.ListBuffer[List[Property]] = -// mutable.ListBuffer[List[Property]]() -// -// todo 对接2.0 -// protected var storageClient: StorageClient = _ - private var schema: StructType = _ - private var metaProvider: MetaProvider = _ + private var schema: StructType = _ + + protected var dataIterator: Iterator[BaseTableRow] = _ + protected var scanPartIterator: Iterator[Integer] = _ + protected var resultValues: mutable.ListBuffer[List[Object]] = mutable.ListBuffer[List[Object]]() + protected var storageClient: StorageClient = _ /** * @param index identifier for spark partition @@ -40,7 +47,16 @@ abstract class NebulaPartitionReader extends InputPartitionReader[InternalRow] { this.schema = schema metaProvider = new MetaProvider(nebulaOptions.getMetaAddress) - // todo this.storageClient = new StorageClient + val address: ListBuffer[HostAddress] = new ListBuffer[HostAddress] + + for (addr <- nebulaOptions.getMetaAddress) { + address.append(new HostAddress(addr._1, addr._2)) + } + + this.storageClient = new StorageClient(address.asJava) + if (!storageClient.connect()) { + throw new GraphConnectException("storage connect failed.") + } // allocate scanPart to this partition val totalPart = metaProvider.getPartitionNumber(nebulaOptions.spaceName) @@ -50,19 +66,19 @@ abstract class NebulaPartitionReader extends InputPartitionReader[InternalRow] { } override def get(): InternalRow = { -// val getters: Array[NebulaValueGetter] = NebulaUtils.makeGetters(schema) -// val mutableRow = new SpecificInternalRow(schema.fields.map(x => x.dataType)) -// -// val resultSet: Array[Property] = dataIterator.next().toArray -// for (i <- getters.indices) { -// getters(i).apply(resultSet(i), mutableRow, i) -// if (resultSet(i) == null) mutableRow.setNullAt(i) -// } -// mutableRow - null + val resultSet: Array[Object] = dataIterator.next().getValues.toArray + val getters: Array[NebulaValueGetter] = NebulaUtils.makeGetters(schema) + val mutableRow = new SpecificInternalRow(schema.fields.map(x => x.dataType)) + + for (i <- getters.indices) { + getters(i).apply(resultSet(i), mutableRow, i) + if (resultSet(i) == null) mutableRow.setNullAt(i) + } + mutableRow } override def close(): Unit = { metaProvider.close() + storageClient.close() } } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaSourceReader.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaSourceReader.scala index 492c3f1..d83aef2 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaSourceReader.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaSourceReader.scala @@ -25,9 +25,15 @@ import scala.collection.JavaConverters._ abstract class NebulaSourceReader(nebulaOptions: NebulaOptions) extends DataSourceReader { private val LOG = LoggerFactory.getLogger(this.getClass) - protected var datasetSchema: StructType = _ + private var datasetSchema: StructType = _ - override def readSchema(): StructType = getSchema(nebulaOptions) + override def readSchema(): StructType = { + datasetSchema = getSchema(nebulaOptions) + LOG.info(s"dataset's schema: $datasetSchema") + datasetSchema + } + + protected def getSchema: StructType = getSchema(nebulaOptions) /** * return the dataset's schema. Schema includes configured cols in returnCols or includes all properties in nebula. @@ -51,11 +57,11 @@ abstract class NebulaSourceReader(nebulaOptions: NebulaOptions) extends DataSour fields.append(DataTypes.createStructField("_rank", DataTypes.LongType, false)) } + var dataSchema: StructType = null // read no column if (noColumn) { - datasetSchema = new StructType(fields.toArray) - LOG.info(s"dataset's schema: $datasetSchema") - return datasetSchema + dataSchema = new StructType(fields.toArray) + return dataSchema } // get tag schema or edge schema val schema = if (isVertex) { @@ -82,9 +88,8 @@ abstract class NebulaSourceReader(nebulaOptions: NebulaOptions) extends DataSour .createStructField(col, NebulaUtils.getColDataType(schemaCols.toList, col), true)) } } - datasetSchema = new StructType(fields.toArray) - LOG.info(s"dataset's schema: $datasetSchema") - datasetSchema + dataSchema = new StructType(fields.toArray) + dataSchema } } @@ -95,11 +100,10 @@ class NebulaDataSourceVertexReader(nebulaOptions: NebulaOptions) extends NebulaSourceReader(nebulaOptions) { override def planInputPartitions(): util.List[InputPartition[InternalRow]] = { - val partitionNum = nebulaOptions.partitionNums.toInt val partitions = for (index <- 1 to partitionNum) yield { - new NebulaVertexPartition(index, nebulaOptions, datasetSchema) + new NebulaVertexPartition(index, nebulaOptions, getSchema) } partitions.map(_.asInstanceOf[InputPartition[InternalRow]]).asJava } @@ -114,7 +118,7 @@ class NebulaDataSourceEdgeReader(nebulaOptions: NebulaOptions) override def planInputPartitions(): util.List[InputPartition[InternalRow]] = { val partitionNum = nebulaOptions.partitionNums.toInt val partitions = for (index <- 1 to partitionNum) - yield new NebulaEdgePartition(index, nebulaOptions, datasetSchema) + yield new NebulaEdgePartition(index, nebulaOptions, getSchema) partitions.map(_.asInstanceOf[InputPartition[InternalRow]]).asJava } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaVertexPartitionReader.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaVertexPartitionReader.scala index 42924aa..e7e4f47 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaVertexPartitionReader.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaVertexPartitionReader.scala @@ -6,62 +6,75 @@ package com.vesoft.nebula.connector.reader +import com.vesoft.nebula.client.storage.scan.{ScanVertexResult, ScanVertexResultIterator} import com.vesoft.nebula.connector.NebulaOptions import org.apache.spark.sql.types.StructType import org.slf4j.{Logger, LoggerFactory} +import scala.collection.JavaConverters._ + class NebulaVertexPartitionReader(index: Int, nebulaOptions: NebulaOptions, schema: StructType) extends NebulaPartitionReader(index, nebulaOptions, schema) { private val LOG: Logger = LoggerFactory.getLogger(this.getClass) -// private var responseIterator: util.Iterator[ScanVertexResponse] = _ + private var responseIterator: ScanVertexResultIterator = _ override def next(): Boolean = { -// if (dataIterator == null && responseIterator == null && !scanPartIterator.hasNext) -// return false -// -// var continue: Boolean = false -// var break: Boolean = false -// while ((dataIterator == null || !dataIterator.hasNext) && !break) { -// resultValues.clear() -// continue = false -// if (responseIterator == null || !responseIterator.hasNext) { -// if (scanPartIterator.hasNext) { -// try { -// if (nebulaOptions.noColumn) { -// responseIterator = storageClient.scanVertex(nebulaOptions.spaceName, -// scanPartIterator.next(), -// nebulaOptions.label, -// nebulaOptions.limit) -// } else { -// responseIterator = storageClient.scanVertex(nebulaOptions.spaceName, -// scanPartIterator.next(), -// nebulaOptions.label, -// nebulaOptions.getReturnCols, -// nebulaOptions.limit) -// } -// } catch { -// case e: Exception => -// LOG.error(s"Exception scanning vertex ${nebulaOptions.label}", e) -// throw new Exception(e.getMessage, e) -// } -// // jump to the next loop -// continue = true -// } -// // break while loop -// break = !continue -// } else { -// val next: ScanVertexResponse = responseIterator.next -// // todo dataIterator = next.getVertexTableView -// } -// } -// -// if (dataIterator == null) { -// return false -// } -// dataIterator.hasNext - false + if (dataIterator == null && responseIterator == null && !scanPartIterator.hasNext) + return false + + var continue: Boolean = false + var break: Boolean = false + while ((dataIterator == null || !dataIterator.hasNext) && !break) { + resultValues.clear() + continue = false + if (responseIterator == null || !responseIterator.hasNext) { + if (scanPartIterator.hasNext) { + try { + if (nebulaOptions.noColumn) { + responseIterator = storageClient.scanVertex(nebulaOptions.spaceName, + scanPartIterator.next(), + nebulaOptions.label, + nebulaOptions.limit, + 0, + Long.MaxValue, + true, + true) + } else { + responseIterator = storageClient.scanVertex(nebulaOptions.spaceName, + scanPartIterator.next(), + nebulaOptions.label, + nebulaOptions.getReturnCols.asJava, + nebulaOptions.limit, + 0, + Long.MaxValue, + true, + true) + } + } catch { + case e: Exception => + LOG.error(s"Exception scanning vertex ${nebulaOptions.label}", e) + storageClient.close() + throw new Exception(e.getMessage, e) + } + // jump to the next loop + continue = true + } + // break while loop + break = !continue + } else { + val next: ScanVertexResult = responseIterator.next + if (!next.isEmpty) { + dataIterator = next.getVertexTableRows.iterator().asScala + } + } + } + + if (dataIterator == null) { + return false + } + dataIterator.hasNext } } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanEdgeResultIterator.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanEdgeResultIterator.scala deleted file mode 100644 index 3d0ac56..0000000 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanEdgeResultIterator.scala +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (c) 2020 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -package com.vesoft.nebula.connector.reader.tmp - -class ScanEdgeResultIterator { - - def next(): ScanEdgeResult = { - new ScanEdgeResult - } - - def hasNext(): Boolean = { - true - } -} - -class ScanEdgeResult { - val edgeTableViews: List[EdgeTableView] = null - - val propNames: List[String] = null - -} - -class EdgeTableView {} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanVertexResultIterator.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanVertexResultIterator.scala deleted file mode 100644 index d894c7e..0000000 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/ScanVertexResultIterator.scala +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (c) 2020 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -package com.vesoft.nebula.connector.reader.tmp - -class ScanVertexResultIterator { - - def next(): ScanVertexResult = { - new ScanVertexResult - } - - def hasNext(): Boolean = { - true - } -} - -class ScanVertexResult { - val vertexTableViews: List[VertexTableView] = null - - val propNames: List[String] = null - -} - -class VertexTableView {} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/StorageClient.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/StorageClient.scala deleted file mode 100644 index 71faec5..0000000 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/tmp/StorageClient.scala +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright (c) 2020 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -package com.vesoft.nebula.connector.reader.tmp - -class StorageClient { - def scanVertex(): ScanVertexResultIterator = { - new ScanVertexResultIterator - } - - def scanEdge(): ScanEdgeResultIterator = { - new ScanEdgeResultIterator - } -} diff --git a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/NebulaConfigSuit.scala b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/NebulaConfigSuite.scala similarity index 97% rename from nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/NebulaConfigSuit.scala rename to nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/NebulaConfigSuite.scala index b54c410..0e6ea06 100644 --- a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/NebulaConfigSuit.scala +++ b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/NebulaConfigSuite.scala @@ -9,7 +9,7 @@ package com.vesoft.nebula.connector import org.scalatest.BeforeAndAfterAll import org.scalatest.funsuite.AnyFunSuite -class NebulaConfigSuit extends AnyFunSuite with BeforeAndAfterAll { +class NebulaConfigSuite extends AnyFunSuite with BeforeAndAfterAll { test("test NebulaConnectionConfig") { try { diff --git a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuit.scala b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala similarity index 98% rename from nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuit.scala rename to nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala index 916d43b..8a941ce 100644 --- a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuit.scala +++ b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala @@ -22,7 +22,7 @@ import org.scalatest.funsuite.AnyFunSuite import scala.collection.mutable.ListBuffer -class NebulaExecutorSuit extends AnyFunSuite with BeforeAndAfterAll { +class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { var schema: StructType = _ var row: InternalRow = _ From c4ab44eac56ebb5b169a3fb1a37ad202e7553150 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 11 Jan 2021 17:53:04 +0800 Subject: [PATCH 030/213] update comment & parameters --- .../examples/connector/NebulaSparkReaderExample.scala | 8 ++++---- .../main/scala/com/vesoft/nebula/connector/package.scala | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala index 0d1f18e..39c2989 100644 --- a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala +++ b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala @@ -29,8 +29,8 @@ object NebulaSparkReaderExample { .config(sparkConf) .getOrCreate() - // readVertex(spark) - // readEdges(spark) + readVertex(spark) + readEdges(spark) readVertexGraph(spark) readEdgeGraph(spark) @@ -91,7 +91,7 @@ object NebulaSparkReaderExample { val config = NebulaConnectionConfig .builder() - .withMetaAddress("192.168.8.172:45509") + .withMetaAddress("127.0.0.1:45500") .withTimeout(6000) .withConenctionRetry(2) .build() @@ -115,7 +115,7 @@ object NebulaSparkReaderExample { val config = NebulaConnectionConfig .builder() - .withMetaAddress("192.168.8.172:45509") + .withMetaAddress("127.0.0.1:45500") .withTimeout(6000) .withConenctionRetry(2) .build() diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala index 9fdbc71..91a86a3 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala @@ -147,7 +147,7 @@ package object connector { /** * read nebula vertex edge to graphx's vertex - * only support Long vId + * use hash() for String type vertex id. */ def loadVerticesToGraphx(): RDD[NebulaGraphxVertex] = { val vertexDataset = loadVerticesToDF() @@ -179,7 +179,7 @@ package object connector { /** * read nebula edge edge to graphx's edge - * only support edge with Long srcId and Long dstId + * use hash() for String type srcId and dstId. */ def loadEdgesToGraphx(): RDD[NebulaGraphxEdge] = { val edgeDataset = loadEdgesToDF() From 952831190692f129a2986127811eef109fdf2a4d Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 11 Jan 2021 18:43:47 +0800 Subject: [PATCH 031/213] add description --- nebula-spark-connector/README.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/nebula-spark-connector/README.md b/nebula-spark-connector/README.md index 7596143..e15dfdb 100644 --- a/nebula-spark-connector/README.md +++ b/nebula-spark-connector/README.md @@ -28,6 +28,13 @@ Nebula Spark Connector 2.0 依赖 Nebula Java Client 2.0。 编译打包完成后,可以在 nebula-spark-utils/nebula-spark-connector/target/ 目录下看到 nebula-spark-connector-2.0.0.jar 文件。 +## 特性 +* 提供了更多连接配置项,如超时时间、连接重试次数、执行重试次数 +* 提供了更多数据配置项,如写入数据时是否将 vertexId 同时作为属性写入、是否将 srcId、dstId、rank 等同时作为属性写入 +* Spark Reader 支持无属性读取,支持全属性读取 +* Spark Reader 支持将 Nebula Graph 数据读取成 Graphx 的 VertexRD 和 EdgeRDD,支持非 Long 型 vertexId +* Nebula Spark Connector 2.0 统一了 SparkSQL 的扩展数据源,统一采用 DataSourceV2 进行 Nebula Graph 数据扩展 + ## 使用说明 将 DataFrame 作为点写入 Nebula Graph : @@ -48,7 +55,26 @@ Nebula Spark Connector 2.0 依赖 Nebula Java Client 2.0。 .build() df.write.nebula(config, nebulaWriteVertexConfig).writeVertices() ``` - + 读取 Nebula Graph 的点数据: + ``` + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:45500") + .withConenctionRetry(2) + .build() + val nebulaReadVertexConfig: ReadNebulaConfig = ReadNebulaConfig + .builder() + .withSpace("exchange") + .withLabel("person") + .withNoColumn(false) + .withReturnCols(List("birthday")) + .withLimit(10) + .withPartitionNum(10) + .build() + val vertex = spark.read.nebula(config, nebulaReadVertexConfig).loadVerticesToDF() + ``` +更多使用示例请参考 [Example](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/example/src/main/scala/com/vesoft/nebula/examples/connector) 。 ## 贡献 Nebula Spark Connector 2.0 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: From c074be7129fb1cb5a4025a56dd9195878db4cf43 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 14 Jan 2021 15:36:48 +0800 Subject: [PATCH 032/213] sync data structure with client --- .../nebula/connector/NebulaOptions.scala | 6 ++- .../vesoft/nebula/connector/NebulaUtils.scala | 25 ++++-------- .../com/vesoft/nebula/connector/package.scala | 4 +- .../reader/NebulaPartitionReader.scala | 38 +++++++++++++++++-- 4 files changed, 48 insertions(+), 25 deletions(-) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaOptions.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaOptions.scala index 43acfea..f1eb17b 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaOptions.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaOptions.scala @@ -142,7 +142,11 @@ class NebulaOptions(@transient val parameters: CaseInsensitiveMap[String])( } def getReturnCols: List[String] = { - returnCols.split(",").toList + if (returnCols.trim.isEmpty) { + List() + } else { + returnCols.split(",").toList + } } def getMetaAddress: List[Address] = { diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala index df99658..8af710c 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala @@ -16,6 +16,7 @@ import org.apache.spark.sql.types.{ FloatType, IntegerType, LongType, + NullType, StringType, StructType, TimestampType @@ -57,7 +58,7 @@ object NebulaUtils { throw new IllegalArgumentException(s"column $columnName does not exist in schema") } - type NebulaValueGetter = (Object, InternalRow, Int) => Unit + type NebulaValueGetter = (Any, InternalRow, Int) => Unit def makeGetters(schema: StructType): Array[NebulaValueGetter] = { schema.fields.map(field => makeGetter(field.dataType)) @@ -66,35 +67,23 @@ object NebulaUtils { private def makeGetter(dataType: DataType): NebulaValueGetter = { dataType match { case BooleanType => - (prop: Object, row: InternalRow, pos: Int) => + (prop: Any, row: InternalRow, pos: Int) => row.setBoolean(pos, prop.asInstanceOf[Boolean]) case TimestampType | LongType => - (prop: Object, row: InternalRow, pos: Int) => + (prop: Any, row: InternalRow, pos: Int) => row.setLong(pos, prop.asInstanceOf[Long]) case FloatType | DoubleType => - (prop: Object, row: InternalRow, pos: Int) => + (prop: Any, row: InternalRow, pos: Int) => row.setDouble(pos, prop.asInstanceOf[Double]) case IntegerType => - (prop: Object, row: InternalRow, pos: Int) => + (prop: Any, row: InternalRow, pos: Int) => row.setInt(pos, prop.asInstanceOf[Int]) case _ => - (prop: Object, row: InternalRow, pos: Int) => + (prop: Any, row: InternalRow, pos: Int) => row.update(pos, UTF8String.fromString(String.valueOf(prop))) } } - def resolveDataAndType(row: Row, dataType: DataType, i: Int): Any = { - dataType match { - case LongType => row.getLong(i) - case IntegerType => row.getInt(i) - case DoubleType => row.getDouble(i) - case FloatType => row.getFloat(i) - case BooleanType => row.getBoolean(i) - case StringType => row.getString(i) - case _ => row.getString(i) - } - } - def isNumic(str: String): Boolean = { for (char <- str.toCharArray) { if (!Character.isDigit(char)) return false diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala index 91a86a3..c6f53c1 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala @@ -169,7 +169,7 @@ package object connector { val props: ListBuffer[Any] = ListBuffer() for (i <- row.schema.fields.indices) { if (i != 0) { - props.append(NebulaUtils.resolveDataAndType(row, fields(i).dataType, i)) + props.append(row.get(i)) } } (vid, props.toList) @@ -192,7 +192,7 @@ package object connector { val props: ListBuffer[Any] = ListBuffer() for (i <- row.schema.fields.indices) { if (i != 0 && i != 1 && i != 2) { - props.append(NebulaUtils.resolveDataAndType(row, fields(i).dataType, i)) + props.append(row.get(i)) } } val srcId = row.get(0).toString.getBytes() diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartitionReader.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartitionReader.scala index dcc873f..aad4a7a 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartitionReader.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/reader/NebulaPartitionReader.scala @@ -6,7 +6,7 @@ package com.vesoft.nebula.connector.reader -import com.vesoft.nebula.client.graph.data.HostAddress +import com.vesoft.nebula.client.graph.data.{HostAddress, ValueWrapper} import com.vesoft.nebula.client.storage.StorageClient import com.vesoft.nebula.client.storage.data.{BaseTableRow, VertexTableRow} import com.vesoft.nebula.connector.NebulaUtils.NebulaValueGetter @@ -66,13 +66,43 @@ abstract class NebulaPartitionReader extends InputPartitionReader[InternalRow] { } override def get(): InternalRow = { - val resultSet: Array[Object] = dataIterator.next().getValues.toArray + val resultSet: Array[ValueWrapper] = + dataIterator.next().getValues.toArray.map(v => v.asInstanceOf[ValueWrapper]) val getters: Array[NebulaValueGetter] = NebulaUtils.makeGetters(schema) val mutableRow = new SpecificInternalRow(schema.fields.map(x => x.dataType)) for (i <- getters.indices) { - getters(i).apply(resultSet(i), mutableRow, i) - if (resultSet(i) == null) mutableRow.setNullAt(i) + val value: ValueWrapper = resultSet(i) + var resolved = false + if (value.isNull) { + mutableRow.setNullAt(i) + resolved = true + } + if (value.isString) { + getters(i).apply(value.asString(), mutableRow, i) + resolved = true + } + if (value.isDate) { + getters(i).apply(value.asDate(), mutableRow, i) + resolved = true + } + if (value.isTime) { + getters(i).apply(value.asTime(), mutableRow, i) + resolved = true + } + if (value.isDateTime) { + getters(i).apply(value.asDateTime(), mutableRow, i) + resolved = true + } + if (value.isLong) { + getters(i).apply(value.asLong(), mutableRow, i) + } + if (value.isBoolean) { + getters(i).apply(value.asBoolean(), mutableRow, i) + } + if (value.isDouble) { + getters(i).apply(value.asDouble(), mutableRow, i) + } } mutableRow } From 5840546e22809e29265f7b05d20f8c23d128d2ab Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 19 Jan 2021 11:24:28 +0800 Subject: [PATCH 033/213] add SST importer --- nebula-exchange/pom.xml | 6 - .../src/main/resources/application.conf | 282 ++++++++++++++++-- .../main/resources/server_application.conf | 183 ------------ .../main/resources/stream_application.conf | 143 --------- .../nebula/exchange/config/Configs.scala | 14 +- .../nebula/exchange/config/SinkConfigs.scala | 5 +- .../exchange/processor/EdgeProcessor.scala | 135 ++++++++- .../nebula/exchange/processor/Processor.scala | 75 ++++- .../processor/VerticesProcessor.scala | 104 ++++++- .../nebula/exchange/utils/HDFSUtils.scala | 13 +- .../exchange/writer/ServerBaseWriter.scala | 4 + .../nebula/exchange/MockGraphData.scala | 1 - 12 files changed, 590 insertions(+), 375 deletions(-) delete mode 100644 nebula-exchange/src/main/resources/server_application.conf delete mode 100644 nebula-exchange/src/main/resources/stream_application.conf diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml index d19d53f..83b5608 100644 --- a/nebula-exchange/pom.xml +++ b/nebula-exchange/pom.xml @@ -29,7 +29,6 @@ 2.11.0-M4 3.7.1 2.0.0-rc1 - 1.0.0-rc2 1.0.0 2.4.5-M1 3.4.6 @@ -504,11 +503,6 @@ - - com.vesoft - nebula-utils - ${nebula-utils.version} - neo4j-contrib neo4j-spark-connector diff --git a/nebula-exchange/src/main/resources/application.conf b/nebula-exchange/src/main/resources/application.conf index 61bfa28..8157cd0 100644 --- a/nebula-exchange/src/main/resources/application.conf +++ b/nebula-exchange/src/main/resources/application.conf @@ -19,6 +19,16 @@ } } + # if the hive is hive-on-spark with derby mode, you can ignore this hive configure + # get the config values from file $HIVE_HOME/conf/hive-site.xml or hive-default.xml + hive: { + waredir: "hdfs://NAMENODE_IP:9000/apps/svr/hive-xxx/warehouse/" + connectionURL: "jdbc:mysql://your_ip:3306/hive_spark?characterEncoding=UTF-8" + connectionDriverName: "com.mysql.jdbc.Driver" + connectionUserName: "user" + connectionPassword: "password" + } + # Nebula Graph relation config nebula: { address:{ @@ -29,6 +39,13 @@ pswd: password space: test + # parameters for SST import, not required + path:{ + local:"/tmp" + remote:"/sst" + hdfs.namenode: "hdfs://name_node:9000" + } + connection { timeout: 3000 retry: 3 @@ -51,9 +68,11 @@ } # Processing tags + # There are tag config examples for different dataSources. tags: [ - # Loading tag from HDFS and data type is parquet + # HDFS parquet + # Import mode is client, just change type.sink to sst if you want to use sst import mode. { name: tag-name-0 type: { @@ -63,49 +82,143 @@ path: hdfs tag path 0 fields: [parquet-field-0, parquet-field-1, parquet-field-2] nebula.fields: [nebula-field-0 nebula-field-1 nebula-field-2] - vertex: hive-field-0 + vertex: { + field:parquet-field-0 + #policy:hash + } batch: 256 partition: 32 } - # Loading tag from HDFS and data type is csv + # HDFS csv + # Import mode is sst, just change type.sink to client if you want to use client import mode. { - name: tag-name-2 + name: tag-name-1 type: { source: csv - sink: client + sink: sst } path: hdfs tag path 2 + # if your csv file has no header, then use _c0,_c1,_c2,.. to indicate fields fields: [csv-field-0, csv-field-1, csv-field-2] nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - vertex: hive-field-0 + vertex: { + filed:csv-field-0 + } separator: "," header: true batch: 256 partition: 32 } - # Loading tag from HDFS and data type is csv + # Hive { name: tag-name-2 type: { - source: csv + source: hive sink: client } - path: hdfs tag path 2 - fields: [csv-field-0, csv-field-1, csv-field-2] + exec: "select hive-field0, hive-field1, hive-field2 from database.table" + fields: [hive-field-0, hive-field-1, hive-field-2] nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - vertex: hive-field-0 - separator: "," - header: true + vertex: { + field: hive-field-0 + # policy: "hash" + } batch: 256 partition: 32 } + + # neo4j + { + name: tag-name-3 + type: { + source: neo4j + sink: client + } + server: "bolt://127.0.0.1:7687" + user: neo4j + password: neo4j + exec: "match (n:label) return n.neo4j-field-0 as neo4j-field-0, n.neo4j-field-1 as neo4j-field-1 order by (n.neo4j-field-0)" + fields: [neo4j-field-0, neo4j-field-1] + nebula.fields: [nebula-field-0, nebula-field-1] + vertex: { + field:neo4j-field-0 + # policy:hash + } + partition: 10 + batch: 1000 + check_point_path: /tmp/test + } + + # HBase + # if fields or vertex contains rowkey, please configure it as "rowkey". + { + name: tag-name-4 + type: { + source: hbase + sink: client + } + host:127.0.0.1 + port:2181 + table:hbase-table + columnFamily:hbase-table-cloumnfamily + fields: [hbase-column-0, hbase-column-1] + nebula.fields: [nebula-field-0, nebula-field-1] + vertex: { + field:rowkey + } + partition: 10 + batch: 1000 + } + + # Pulsar + { + name: tag-name--5 + type: { + source: pulsar + sink: client + } + service: "pulsar://localhost:6650" + admin: "http://localhost:8081" + options: { + # choose one of "topic", "topics", "topicsPattern" + topics: "topic1,topic2" + } + fields: [pulsar-field-0, pulsar-field-1, pulsar-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: { + field:pulsar-field-0 + } + partition: 10 + batch: 1000 + interval.seconds: 10 + } + + # KAFKA + { + name: tag-name-6 + type: { + source: kafka + sink: client + } + service: "kafka.service.address" + topic: "topic-name" + fields: [kafka-field-0, kafka-field-1, kafka-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: { + field: kafka-field-0 + } + partition: 10 + batch: 10 + interval.seconds: 10 + } ] # Processing edges + # There are edge config examples for different dataSources. edges: [ - # Loading tag from HDFS and data type is json + # HDFS json { name: edge-name-0 type: { @@ -116,14 +229,149 @@ fields: [json-field-0, json-field-1, json-field-2] nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] source: { - field: hive-field-0 + field: json-field-0 + #policy: hash } target: { - field: hive-field-1 + field: json-field-1 } - ranking: hive-field-2 + ranking: json-field-2 batch: 256 partition: 32 } + + # HDFS csv + { + name: edge-name-1 + type: { + source: csv + sink: client + } + path: hdfs edge path 0 + fields: [csv-field-0, csv-field-1, csv-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: { + field: csv-field-0 + #policy: hash + } + target: { + field: csv-field-1 + } + ranking: csv-field-2 + separator: "," + header: true + batch: 256 + partition: 32 + } + + # Hive + { + name: edge-name-2 + type: { + source: hive + sink: client + } + exec: "select hive-field0, hive-field1, hive-field2 from database.table" + fields: [ hive-field-0, hive-field-1, hive-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: hive-field-0 + target: hive-field-1 + batch: 256 + partition: 32 + } + + # Neo4j + { + name: edge-name-3 + type: { + source: neo4j + sink: client + } + server: "bolt://127.0.0.1:7687" + user: neo4j + password: neo4j + exec: "match (a:vertex_label)-[r:edge_label]->(b:vertex_label) return a.neo4j-source-field, b.neo4j-target-field, r.neo4j-field-0 as neo4j-field-0, r.neo4j-field-1 as neo4j-field-1 order by id(r)" + fields: [neo4j-field-0, neo4j-field-1] + nebula.fields: [nebula-field-0, nebula-field-1] + source: { + field: a.neo4j-source-field + } + target: { + field: b.neo4j-target-field + } + partition: 10 + batch: 1000 + check_point_path: /tmp/test + } + + # HBase + { + name: edge-name-4 + type: { + source: hbase + sink: client + } + host:127.0.0.1 + port:2181 + table:hbase-table + columnFamily:hbase-table-cloumnfamily + fields: [hbase-column-0, hbase-column-1] + nebula.fields:[nebula-field-0, nebula-field-1] + source: { + field: hbase-column-k + } + target: { + field: hbase-column-h + } + partition: 10 + batch: 1000 + } + + + # Pulsar + { + name: edge-name-5 + type: { + source: pulsar + sink: client + } + service: "pulsar://localhost:6650" + admin: "http://localhost:8081" + options: { + # choose one of "topic", "topics", "topicsPattern" + topic: "topic1" + } + fields: [pulsar-field-0, pulsar-field-1, pulsar-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: { + field: pulsar-field-0 + #policy: hash + } + target: { + field: pulsar-field-1 + } + ranking: pulsar-field-2 + partition: 10 + batch: 10 + interval.seconds: 10 + } + + # KAFKA + { + name: edge-name-6 + type: { + source: kafka + sink: client + } + service: "kafka.service.address" + topic: "topic-name" + fields: [kafka-field-0, kafka-field-1, kafka-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: kafka-field-0 + target: kafka-field-1 + partition: 10 + batch: 1000 + interval.seconds: 10 + } ] } diff --git a/nebula-exchange/src/main/resources/server_application.conf b/nebula-exchange/src/main/resources/server_application.conf deleted file mode 100644 index 64df37b..0000000 --- a/nebula-exchange/src/main/resources/server_application.conf +++ /dev/null @@ -1,183 +0,0 @@ -{ - # Spark relation config - spark: { - driver: { - cores: 1 - maxResultSize: 1G - } - - cores { - max: 16 - } - } - - # if the hive is in the same cluster with spark, you can ignore this hive configure - hive: { - waredir: "hdfs://NAMENODE_IP:9000/apps/svr/hive-xxx/warehouse/" - connectionURL: "jdbc:mysql://your_ip:3306/hive_spark?characterEncoding=UTF-8" - connectionDriverName: "com.mysql.jdbc.Driver" - connectionUserName: "user" - connectionPassword: "password" - } - - # Nebula Graph relation config - nebula: { - address:{ - graph:["127.0.0.1:3699"] - meta:["127.0.0.1:45500"] - } - user: user - pswd: password - space: test - - connection { - timeout: 3000 - retry: 3 - } - - execution { - retry: 3 - } - - error: { - max: 32 - # failed import job will be recorded in output path - output: /tmp/errors - } - - rate: { - limit: 1024 - timeout: 1000 - } - } - - # Processing tags - tags: [ - # Loading from Hive - { - name: tag-name-1 - type: { - source: hive - sink: client - } - exec: "select hive-field0, hive-field1, hive-field2 from database.table" - fields: [hive-field-0, hive-field-1, hive-field-2] - nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - vertex: { - field: hive-field-0 - # nebula 2.0 does not support int vid yet, so do not config policy. - # policy: "hash" - } - vertex: hive-field-0 - batch: 256 - partition: 32 - } - - # Loading tag from neo4j - { - name: tag-name-0 - type: { - source: neo4j - sink: client - } - server: "bolt://127.0.0.1:7687" - user: neo4j - password: neo4j - exec: "match (n:label) return n.neo4j-field-0 as neo4j-field-0, n.neo4j-field-1 as neo4j-field-1 order by (n.neo4j-field-0)" - fields: [neo4j-field-0, neo4j-field-1] - nebula.fields: [nebula-field-0, nebula-field-1] - vertex: { - field:neo4j-field-0 - # nebula 2.0 does not support int vid yet, so do not config policy. - # policy:uuid - } - partition: 10 - batch: 1000 - check_point_path: /tmp/test - } - - # Loading from HBase, if fields or vertex contains rowkey, please configure it as rowkey. - { - name: hbase-table-name - type: { - source: hbase - sink: client - } - host:127.0.0.1 - port:2181 - table:hbase-table - columnFamily:hbase-table-cloumnfamily - fields: [hbase-column-0, hbase-column-1] - nebula.fields: [nebula-field-0, nebula-field-1] - vertex: rowkey - partition: 10 - batch: 1000 - } - ] - - # Processing edges - edges: [ - # Loading from Hive - { - name: edge-name-1 - type: { - source: hive - sink: client - } - exec: "select hive-field0, hive-field1, hive-field2 from database.table" - fields: [ hive-field-0, hive-field-1, hive-field-2] - nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - source: hive-field-0 - target: hive-field-1 - batch: 256 - partition: 32 - } - - # Loading from neo4j - { - name: edge-name-0 - type: { - source: neo4j - sink: client - } - server: "bolt://127.0.0.1:7687" - user: neo4j - password: neo4j - exec: "match (a:vertex_label)-[r:edge_label]->(b:vertex_label) return a.neo4j-source-field, b.neo4j-target-field, r.neo4j-field-0 as neo4j-field-0, r.neo4j-field-1 as neo4j-field-1 order by id(r)" - fields: [neo4j-field-0, neo4j-field-1] - nebula.fields: [nebula-field-0, nebula-field-1] - source: { - field: a.neo4j-source-field - } - target: { - field: b.neo4j-target-field - } - partition: 10 - batch: 1000 - check_point_path: /tmp/test - } - - # Loading from hbase - { - name: hbase-table-name - type: { - source: hbase - sink: client - } - host:127.0.0.1 - port:2181 - table:hbase-table - columnFamily:hbase-table-cloumnfamily - fields: [hbase-column-0, hbase-column-1] - nebula.fields:[nebula-field-0, nebula-field-1] - source: { - field: hbase-column-k - } - target: { - field: hbase-column-h - } - partition: 10 - batch: 1000 - } - ] -} diff --git a/nebula-exchange/src/main/resources/stream_application.conf b/nebula-exchange/src/main/resources/stream_application.conf deleted file mode 100644 index ab0a201..0000000 --- a/nebula-exchange/src/main/resources/stream_application.conf +++ /dev/null @@ -1,143 +0,0 @@ -{ - # Spark relation config - spark: { - app: { - name: Spark Writer - } - - driver: { - cores: 1 - maxResultSize: 1G - } - - cores { - max: 16 - } - } - - # Nebula Graph relation config - nebula: { - address:{ - graph:["127.0.0.1:3699"] - meta:["127.0.0.1:45500"] - } - user: user - pswd: password - space: test - - connection { - timeout: 3000 - retry: 3 - } - - execution { - retry: 3 - } - - error: { - max: 32 - # failed import job will be recorded in output path - output: /tmp/errors - } - - rate: { - limit: 1024 - timeout: 1000 - } - } - - # Processing tags - tags: [ - - # Loading tag from pulsar - { - name: tag-name-0 - type: { - source: pulsar - sink: client - } - service: "pulsar://localhost:6650" - admin: "http://localhost:8081" - options: { - # choose one of "topic", "topics", "topicsPattern" - topics: "topic1,topic2" - } - fields: [pulsar-field-0, pulsar-field-1, pulsar-field-2] - nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - vertex: { - field:pulsar-field-0 - # nebula 2.0 does not support int vid yet, so do not config policy. - # policy:hash - } - partition: 10 - batch: 1000 - interval.seconds: 10 - } - - # Loading from KAFKA - { - name: tag-name-1 - type: { - source: kafka - sink: client - } - service: "kafka.service.address" - topic: "topic-name" - fields: [kafka-field-0, kafka-field-1, kafka-field-2] - nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - vertex: kafka-field-0 - partition: 10 - batch: 10 - interval.seconds: 10 - } - ] - - # Processing edges - edges: [ - - # Loading tag from pulsar - { - name: edge-name-0 - type: { - source: pulsar - sink: client - } - service: "pulsar://localhost:6650" - admin: "http://localhost:8081" - options: { - # choose one of "topic", "topics", "topicsPattern" - topic: "topic1" - } - fields: [pulsar-field-0, pulsar-field-1, pulsar-field-2] - nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - source: { - field: pulsar-field-0 - } - target: { - field: pulsar-field-1 - } - ranking: pulsar-field-2 - partition: 10 - batch: 10 - interval.seconds: 10 - } - - # Loading from KAFKA - { - name: edge-name-1 - type: { - source: kafka - sink: client - } - service: "kafka.service.address" - topic: "topic-name" - fields: [kafka-field-0, kafka-field-1, kafka-field-2] - nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] - source: kafka-field-0 - target: kafka-field-1 - partition: 10 - batch: 1000 - interval.seconds: 10 - } - ] -} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala index 53b873c..ba7b21a 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala @@ -618,10 +618,20 @@ object Configs { case SinkCategory.CLIENT => NebulaSinkConfigEntry(SinkCategory.CLIENT, nebulaConfig.getStringList("address.graph").asScala.toList) - case SinkCategory.SST => + case SinkCategory.SST => { + val fsNameNode = { + if (nebulaConfig.hasPath("path.hdfs.namenode")) + Option(nebulaConfig.getString("path.hdfs.namenode")) + else { + LOG.warn("Import mode is SST, hdfs namenode is not set.") + Option.empty + } + } FileBaseSinkConfigEntry(SinkCategory.SST, nebulaConfig.getString("path.local"), - nebulaConfig.getString("path.remote")) + nebulaConfig.getString("path.remote"), + fsNameNode) + } case _ => throw new IllegalArgumentException("Unsupported data sink") } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala index c7839f6..36f18dc 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala @@ -31,10 +31,11 @@ sealed trait DataSinkConfigEntry { */ case class FileBaseSinkConfigEntry(override val category: SinkCategory.Value, localPath: String, - remotePath: String) + remotePath: String, + fsName: Option[String]) extends DataSinkConfigEntry { override def toString: String = { - s"File sink: from ${localPath} to ${remotePath}" + s"File sink: from ${localPath} to ${fsName.get}${remotePath}" } } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index 8f109df..be87bcf 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -6,23 +6,40 @@ package com.vesoft.nebula.exchange.processor +import java.nio.ByteBuffer +import java.nio.file.{Files, Paths} + import com.google.common.geometry.{S2CellId, S2LatLng} +import com.vesoft.nebula.client.graph.data.HostAddress +import com.vesoft.nebula.client.meta.{MetaCache, MetaManager} +import com.vesoft.nebula.encoder.NebulaCodecImpl import com.vesoft.nebula.exchange.config.{ Configs, EdgeConfigEntry, + FileBaseSinkConfigEntry, SinkCategory, StreamingDataSourceConfigEntry } -import com.vesoft.nebula.exchange.utils.NebulaUtils -import com.vesoft.nebula.exchange.{Edge, Edges, ErrorHandler, GraphProvider, MetaProvider, VidType} +import com.vesoft.nebula.exchange.utils.{HDFSUtils, NebulaUtils} +import com.vesoft.nebula.exchange.{ + Edge, + Edges, + ErrorHandler, + GraphProvider, + KeyPolicy, + MetaProvider, + VidType +} import org.apache.log4j.Logger -import com.vesoft.nebula.exchange.writer.NebulaGraphClientWriter +import com.vesoft.nebula.exchange.writer.{NebulaGraphClientWriter, NebulaSSTWriter} +import org.apache.commons.codec.digest.MurmurHash2 import org.apache.spark.TaskContext import org.apache.spark.sql.streaming.Trigger -import org.apache.spark.sql.{DataFrame, Encoders} +import org.apache.spark.sql.{DataFrame, Encoders, Row} import org.apache.spark.util.LongAccumulator -import scala.collection.mutable.ArrayBuffer +import scala.collection.JavaConverters._ +import scala.collection.mutable.{ArrayBuffer, ListBuffer} class EdgeProcessor(data: DataFrame, edgeConfig: EdgeConfigEntry, @@ -81,7 +98,111 @@ class EdgeProcessor(data: DataFrame, val fieldTypeMap = NebulaUtils.getDataSourceFieldType(edgeConfig, space, metaProvider) val isVidStringType = metaProvider.getVidType(space) == VidType.STRING - if (edgeConfig.dataSinkConfigEntry.category == SinkCategory.SST) {} else { + if (edgeConfig.dataSinkConfigEntry.category == SinkCategory.SST) { + val fileBaseConfig = edgeConfig.dataSinkConfigEntry.asInstanceOf[FileBaseSinkConfigEntry] + val namenode = fileBaseConfig.fsName.orNull + + data + .mapPartitions { iter => + val spaceName = config.databaseConfig.space + val edgeName = edgeConfig.name + iter.map { row => + val srcIndex: Int = row.schema.fieldIndex(edgeConfig.sourceField) + var srcId: String = row.get(srcIndex).toString + val dstIndex: Int = row.schema.fieldIndex(edgeConfig.targetField) + var dstId: String = row.get(dstIndex).toString + + if (edgeConfig.sourcePolicy.isDefined) { + edgeConfig.sourcePolicy.get match { + case KeyPolicy.HASH => + srcId = MurmurHash2 + .hash64(srcId.getBytes(), srcId.getBytes().length, 0xc70f6907) + .toString + case KeyPolicy.UUID => + throw new UnsupportedOperationException("do not support uuid yet") + case _ => + throw new IllegalArgumentException( + s"policy ${edgeConfig.sourcePolicy.get} is invalidate") + } + } + if (edgeConfig.targetPolicy.isDefined) { + edgeConfig.targetPolicy.get match { + case KeyPolicy.HASH => + dstId = MurmurHash2 + .hash64(dstId.getBytes(), dstId.getBytes().length, 0xc70f6907) + .toString + case KeyPolicy.UUID => + throw new UnsupportedOperationException("do not support uuid yet") + case _ => + throw new IllegalArgumentException( + s"policy ${edgeConfig.targetPolicy.get} is invalidate") + } + } + + val ranking: Long = if (edgeConfig.rankingField.isDefined) { + val rankIndex = row.schema.fieldIndex(edgeConfig.rankingField.get) + row.get(rankIndex).toString.toLong + } else { + 0 + } + + val hostAddrs: ListBuffer[HostAddress] = new ListBuffer[HostAddress] + for (addr <- address) { + hostAddrs.append(new HostAddress(addr.getHostText, addr.getPort)) + } + val metaCache: MetaCache = MetaManager.getMetaManager(hostAddrs.asJava) + val codec = new NebulaCodecImpl(metaCache) + val edgeKey = codec.edgeKey(spaceName, srcId, edgeName, ranking, dstId) + val values = for { + property <- fieldKeys if property.trim.length != 0 + } yield + extraValueForSST(row, property, fieldTypeMap) + .asInstanceOf[AnyRef] + + val edgeValue = codec.encode(spaceName, edgeName, nebulaKeys.asJava, values.asJava) + (edgeKey, edgeValue) + } + }(Encoders.tuple(Encoders.BINARY, Encoders.BINARY)) + .toDF("key", "value") + .sortWithinPartitions("key") + .foreachPartition { iterator: Iterator[Row] => + val taskID = TaskContext.get().taskAttemptId() + var writer: NebulaSSTWriter = null + var currentPart = -1 + try { + iterator.foreach { vertex => + val key = vertex.getAs[Array[Byte]](0) + val value = vertex.getAs[Array[Byte]](1) + val part = ByteBuffer.wrap(key, 0, 4).getInt >> 8 + + if (part != currentPart) { + if (writer != null) { + writer.close() + val localFile = s"${fileBaseConfig.localPath}/$currentPart-$taskID.sst" + HDFSUtils.upload(localFile, + s"${fileBaseConfig.remotePath}/$currentPart.sst", + namenode) + Files.delete(Paths.get(localFile)) + } + currentPart = part + val tmp = s"${fileBaseConfig.localPath}/$currentPart-$taskID.sst" + writer = new NebulaSSTWriter(tmp) + writer.prepare() + } + writer.write(key, value) + } + } finally { + if (writer != null) { + writer.close() + val localFile = s"${fileBaseConfig.localPath}/$currentPart-$taskID.sst" + HDFSUtils.upload(localFile, + s"${fileBaseConfig.remotePath}/$currentPart.sst", + namenode) + Files.delete(Paths.get(localFile)) + } + } + } + } else { val edgeFrame = data .map { row => var sourceField = if (!edgeConfig.isGeo) { @@ -115,7 +236,7 @@ class EdgeProcessor(data: DataFrame, val values = for { property <- fieldKeys if property.trim.length != 0 - } yield extraValue(row, property, fieldTypeMap) + } yield extraValueForClient(row, property, fieldTypeMap) if (edgeConfig.rankingField.isDefined) { val index = row.schema.fieldIndex(edgeConfig.rankingField.get) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala index 947bbd8..88ec2fb 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala @@ -6,6 +6,7 @@ package com.vesoft.nebula.exchange.processor +import com.vesoft.nebula.{Date, DateTime, Time} import com.vesoft.nebula.meta.PropertyType import com.vesoft.nebula.exchange.utils.{HDFSUtils, NebulaUtils} import org.apache.spark.sql.Row @@ -37,10 +38,10 @@ trait Processor extends Serializable { * DataTime type: add datetime() function for attribute value. * eg: convert attribute value 2020-01-01T22:30:40 to datetime("2020-01-01T22:30:40") */ - def extraValue(row: Row, - field: String, - fieldTypeMap: Map[String, Int], - toBytes: Boolean = false): Any = { + def extraValueForClient(row: Row, + field: String, + fieldTypeMap: Map[String, Int], + toBytes: Boolean = false): Any = { val index = row.schema.fieldIndex(field) if (row.isNullAt(index)) return null @@ -57,6 +58,72 @@ trait Processor extends Serializable { } } + def extraValueForSST(row: Row, field: String, fieldTypeMap: Map[String, Int]): Any = { + val index = row.schema.fieldIndex(field) + if (row.isNullAt(index)) return null + + fieldTypeMap(field) match { + case PropertyType.UNKNOWN => + throw new IllegalArgumentException("date type in nebula is UNKNOWN.") + case PropertyType.STRING | PropertyType.FIXED_STRING => row.get(index).toString.getBytes + case PropertyType.BOOL => row.get(index).toString.toBoolean + case PropertyType.DOUBLE => row.get(index).toString.toDouble + case PropertyType.FLOAT => row.get(index).toString.toFloat + case PropertyType.INT8 => row.get(index).toString.toByte + case PropertyType.INT16 => row.get(index).toString.toShort + case PropertyType.INT32 => row.get(index).toString.toInt + case PropertyType.INT64 | PropertyType.VID => row.get(index).toString.toLong + case PropertyType.TIME => { + val values = row.get(index).toString.split(":") + if (values.size < 3) { + throw new UnsupportedOperationException( + s"wrong format for time value: ${row.get(index)}, correct format is 12:00:00:0000") + } + new Time(values(0).toByte, + values(1).toByte, + values(2).toByte, + if (values.length > 3) values(3).toInt else 0) + } + case PropertyType.DATE => { + val values = row.get(index).toString.split("-") + if (values.size < 3) { + throw new UnsupportedOperationException( + s"wrong format for date value: ${row.get(index)}, correct format is 2020-01-01") + } + new Date(values(0).toShort, values(1).toByte, values(2).toByte) + } + case PropertyType.DATETIME => { + val rowValue = row.get(index).toString + var dateTimeValue: Array[String] = null + if (rowValue.contains("T")) { + dateTimeValue = rowValue.split("T") + } else if (rowValue.trim.contains(" ")) { + dateTimeValue = rowValue.trim.split(" ") + } else { + throw new UnsupportedOperationException( + s"wrong format for datetime value: $rowValue, correct format is 2020-01-01T12:00:00:0000") + } + + if (dateTimeValue.size < 2) { + throw new UnsupportedOperationException( + s"wrong format for datetime value: $rowValue, correct format is 2020-01-01T12:00:00:0000") + } + + val dateValues = dateTimeValue(0).split("-") + val timeValues = dateTimeValue(1).split(":") + + new DateTime(dateValues(0).toShort, + dateValues(1).toByte, + dateValues(2).toByte, + timeValues(0).toByte, + timeValues(2).toByte, + timeValues(3).toByte, + timeValues(4).toInt) + } + + } + } + def fetchOffset(path: String): Long = { HDFSUtils.getContent(path).toLong } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index bb5f261..20df79f 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -6,9 +6,16 @@ package com.vesoft.nebula.exchange.processor +import java.nio.file.{Files, Paths} +import java.nio.{ByteBuffer, ByteOrder} + +import com.vesoft.nebula.client.graph.data.HostAddress +import com.vesoft.nebula.client.meta.{MetaCache, MetaManager} +import com.vesoft.nebula.encoder.{NebulaCodec, NebulaCodecImpl} import com.vesoft.nebula.exchange.{ ErrorHandler, GraphProvider, + KeyPolicy, MetaProvider, Vertex, Vertices, @@ -16,19 +23,22 @@ import com.vesoft.nebula.exchange.{ } import com.vesoft.nebula.exchange.config.{ Configs, + FileBaseSinkConfigEntry, SinkCategory, StreamingDataSourceConfigEntry, TagConfigEntry } -import com.vesoft.nebula.exchange.utils.NebulaUtils -import com.vesoft.nebula.exchange.writer.NebulaGraphClientWriter +import com.vesoft.nebula.exchange.utils.{HDFSUtils, NebulaUtils} +import com.vesoft.nebula.exchange.writer.{NebulaGraphClientWriter, NebulaSSTWriter} +import org.apache.commons.codec.digest.MurmurHash2 import org.apache.log4j.Logger import org.apache.spark.TaskContext import org.apache.spark.sql.streaming.Trigger -import org.apache.spark.sql.{DataFrame, Encoders} +import org.apache.spark.sql.{DataFrame, Encoders, Row} import org.apache.spark.util.LongAccumulator -import scala.collection.mutable.ArrayBuffer +import scala.collection.JavaConverters._ +import scala.collection.mutable.{ArrayBuffer, ListBuffer} /** * @@ -96,7 +106,89 @@ class VerticesProcessor(data: DataFrame, val fieldTypeMap = NebulaUtils.getDataSourceFieldType(tagConfig, space, metaProvider) val isVidStringType = metaProvider.getVidType(space) == VidType.STRING - if (tagConfig.dataSinkConfigEntry.category == SinkCategory.SST) {} else { + if (tagConfig.dataSinkConfigEntry.category == SinkCategory.SST) { + val fileBaseConfig = tagConfig.dataSinkConfigEntry.asInstanceOf[FileBaseSinkConfigEntry] + val namenode = fileBaseConfig.fsName.orNull + + data + .mapPartitions { iter => + val spaceName = config.databaseConfig.space + val tagName = tagConfig.name + iter.map { row => + val index: Int = row.schema.fieldIndex(tagConfig.vertexField) + var vertexId: String = row.get(index).toString + + if (tagConfig.vertexPolicy.isDefined) { + tagConfig.vertexPolicy.get match { + case KeyPolicy.HASH => + vertexId = MurmurHash2 + .hash64(vertexId.getBytes(), vertexId.getBytes().length, 0xc70f6907) + .toString + case KeyPolicy.UUID => + throw new UnsupportedOperationException("do not support uuid yet") + case _ => + throw new IllegalArgumentException( + s"policy ${tagConfig.vertexPolicy.get} is invalidate") + } + } + + val hostAddrs: ListBuffer[HostAddress] = new ListBuffer[HostAddress] + for (addr <- address) { + hostAddrs.append(new HostAddress(addr.getHostText, addr.getPort)) + } + val metaCache: MetaCache = MetaManager.getMetaManager(hostAddrs.asJava) + val codec = new NebulaCodecImpl(metaCache) + val vertexKey = codec.vertexKey(spaceName, vertexId, tagName) + val values = for { + property <- fieldKeys if property.trim.length != 0 + } yield + extraValueForSST(row, property, fieldTypeMap) + .asInstanceOf[AnyRef] + val vertexValue = codec.encode(spaceName, tagName, nebulaKeys.asJava, values.asJava) + (vertexKey, vertexValue) + } + }(Encoders.tuple(Encoders.BINARY, Encoders.BINARY)) + .toDF("key", "value") + .sortWithinPartitions("key") + .foreachPartition { iterator: Iterator[Row] => + val taskID = TaskContext.get() taskAttemptId () + var writer: NebulaSSTWriter = null + var currentPart = -1 + val localPath = fileBaseConfig.localPath + val remotePath = fileBaseConfig.remotePath + try { + iterator.foreach { vertex => + val key = vertex.getAs[Array[Byte]](0) + val value = vertex.getAs[Array[Byte]](1) + val part = ByteBuffer + .wrap(key, 0, 4) + .order(ByteOrder.LITTLE_ENDIAN) + .getInt >> 8 + + if (part != currentPart) { + if (writer != null) { + writer.close() + val localFile = s"$localPath/$currentPart-$taskID.sst" + HDFSUtils.upload(localFile, s"$remotePath/$currentPart.sst", namenode) + Files.delete(Paths.get(localFile)) + } + currentPart = part + val tmp = s"$localPath/$currentPart-$taskID.sst" + writer = new NebulaSSTWriter(tmp) + writer.prepare() + } + writer.write(key, value) + } + } finally { + if (writer != null) { + writer.close() + val localFile = s"$localPath/$currentPart-$taskID.sst" + HDFSUtils.upload(localFile, s"$remotePath/$currentPart.sst", namenode) + Files.delete(Paths.get(localFile)) + } + } + } + } else { val vertices = data .map { row => val vertexID = { @@ -118,7 +210,7 @@ class VerticesProcessor(data: DataFrame, val values = for { property <- fieldKeys if property.trim.length != 0 - } yield extraValue(row, property, fieldTypeMap) + } yield extraValueForClient(row, property, fieldTypeMap) Vertex(vertexID, values) }(Encoders.kryo[Vertex]) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala index 77d131f..cb2a62d 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala @@ -13,8 +13,13 @@ import scala.io.Source object HDFSUtils { - def getFileSystem(): FileSystem = - FileSystem.get(new Configuration()) + def getFileSystem(namenode: String = null): FileSystem = { + val conf = new Configuration() + if (namenode != null) { + conf.set("fs.default.name", namenode) + } + FileSystem.get(conf) + } def list(path: String): List[String] = { val system = getFileSystem() @@ -56,8 +61,8 @@ object HDFSUtils { } } - def upload(localPath: String, remotePath: String): Unit = { - val system = getFileSystem() + def upload(localPath: String, remotePath: String, namenode: String = null): Unit = { + val system = getFileSystem(namenode) try { system.copyFromLocalFile(new Path(localPath), new Path(remotePath)) } finally { diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala index d07e26a..0e3f642 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala @@ -78,6 +78,8 @@ abstract class ServerBaseWriter extends Writer { ENDPOINT_TEMPLATE.format(KeyPolicy.UUID.toString, element) case None => element + case _ => + throw new IllegalArgumentException(s"policy ${edges.sourcePolicy} is invalidate.") } val target = edges.targetPolicy match { @@ -87,6 +89,8 @@ abstract class ServerBaseWriter extends Writer { ENDPOINT_TEMPLATE.format(KeyPolicy.UUID.toString, edge.destination) case None => edge.destination + case _ => + throw new IllegalArgumentException(s"policy ${edges.sourcePolicy} is invalidate.") } if (edge.ranking.isEmpty) diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockGraphData.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockGraphData.scala index 424986d..2f58bde 100644 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockGraphData.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockGraphData.scala @@ -7,7 +7,6 @@ package com.vesoft.nebula.exchange import com.typesafe.config.impl.ConfigImpl.fromAnyRef -import com.vesoft.nebula.exchange.KeyPolicy import com.vesoft.nebula.exchange.config._ import org.apache.spark.sql.{DataFrame, SparkSession} From 009c538ba3baa4f3816a5928d148629bd5ca97a7 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 19 Jan 2021 19:33:31 +0800 Subject: [PATCH 034/213] modify upload path --- .../nebula/exchange/processor/EdgeProcessor.scala | 14 ++++++++------ .../nebula/exchange/processor/Processor.scala | 2 +- .../exchange/processor/VerticesProcessor.scala | 8 ++++++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index be87bcf..0e2403a 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -179,9 +179,10 @@ class EdgeProcessor(data: DataFrame, if (writer != null) { writer.close() val localFile = s"${fileBaseConfig.localPath}/$currentPart-$taskID.sst" - HDFSUtils.upload(localFile, - s"${fileBaseConfig.remotePath}/$currentPart.sst", - namenode) + HDFSUtils.upload( + localFile, + s"${fileBaseConfig.remotePath}/$currentPart/$currentPart-$taskID.sst", + namenode) Files.delete(Paths.get(localFile)) } currentPart = part @@ -195,9 +196,10 @@ class EdgeProcessor(data: DataFrame, if (writer != null) { writer.close() val localFile = s"${fileBaseConfig.localPath}/$currentPart-$taskID.sst" - HDFSUtils.upload(localFile, - s"${fileBaseConfig.remotePath}/$currentPart.sst", - namenode) + HDFSUtils.upload( + localFile, + s"${fileBaseConfig.remotePath}/$currentPart/$currentPart-$taskID.sst", + namenode) Files.delete(Paths.get(localFile)) } } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala index 88ec2fb..543fbaf 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala @@ -65,7 +65,7 @@ trait Processor extends Serializable { fieldTypeMap(field) match { case PropertyType.UNKNOWN => throw new IllegalArgumentException("date type in nebula is UNKNOWN.") - case PropertyType.STRING | PropertyType.FIXED_STRING => row.get(index).toString.getBytes + case PropertyType.STRING | PropertyType.FIXED_STRING => row.get(index).toString case PropertyType.BOOL => row.get(index).toString.toBoolean case PropertyType.DOUBLE => row.get(index).toString.toDouble case PropertyType.FLOAT => row.get(index).toString.toFloat diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index 20df79f..c80a0e2 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -169,7 +169,9 @@ class VerticesProcessor(data: DataFrame, if (writer != null) { writer.close() val localFile = s"$localPath/$currentPart-$taskID.sst" - HDFSUtils.upload(localFile, s"$remotePath/$currentPart.sst", namenode) + HDFSUtils.upload(localFile, + s"$remotePath/$currentPart/$currentPart-$taskID.sst", + namenode) Files.delete(Paths.get(localFile)) } currentPart = part @@ -183,7 +185,9 @@ class VerticesProcessor(data: DataFrame, if (writer != null) { writer.close() val localFile = s"$localPath/$currentPart-$taskID.sst" - HDFSUtils.upload(localFile, s"$remotePath/$currentPart.sst", namenode) + HDFSUtils.upload(localFile, + s"$remotePath/$currentPart/$currentPart-$taskID.sst", + namenode) Files.delete(Paths.get(localFile)) } } From 57054b36196843ea11332fbb0ac2b2fd48893e88 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 20 Jan 2021 10:04:02 +0800 Subject: [PATCH 035/213] correct config field --- nebula-exchange/src/main/resources/application.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nebula-exchange/src/main/resources/application.conf b/nebula-exchange/src/main/resources/application.conf index 8157cd0..1fdbdd4 100644 --- a/nebula-exchange/src/main/resources/application.conf +++ b/nebula-exchange/src/main/resources/application.conf @@ -103,7 +103,7 @@ fields: [csv-field-0, csv-field-1, csv-field-2] nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] vertex: { - filed:csv-field-0 + field:csv-field-0 } separator: "," header: true From 0c5813eaa9935c8b5487cfea6a3dcd074bfc68d8 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 22 Jan 2021 10:09:53 +0800 Subject: [PATCH 036/213] Synchronize encoder interface & corrent part --- .../vesoft/nebula/exchange/MetaProvider.scala | 2 +- .../exchange/processor/EdgeProcessor.scala | 20 +++++++++---------- .../processor/VerticesProcessor.scala | 18 ++++++++--------- .../nebula/exchange/utils/HDFSUtils.scala | 1 + 4 files changed, 21 insertions(+), 20 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala index abf7b8f..64a510e 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala @@ -31,7 +31,7 @@ class MetaProvider(addresses: List[HostAndPort]) extends AutoCloseable with Seri private val metaClient = new MetaClient(address.asJava) metaClient.connect() - def getPartNumber(space: String): Unit = { + def getPartNumber(space: String): Int = { metaClient.getPartsAlloc(space).size() } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index 0e2403a..5cb999c 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -97,6 +97,7 @@ class EdgeProcessor(data: DataFrame, val metaProvider = new MetaProvider(address) val fieldTypeMap = NebulaUtils.getDataSourceFieldType(edgeConfig, space, metaProvider) val isVidStringType = metaProvider.getVidType(space) == VidType.STRING + val partitionNUm = metaProvider.getPartNumber(space) if (edgeConfig.dataSinkConfigEntry.category == SinkCategory.SST) { val fileBaseConfig = edgeConfig.dataSinkConfigEntry.asInstanceOf[FileBaseSinkConfigEntry] @@ -159,7 +160,7 @@ class EdgeProcessor(data: DataFrame, extraValueForSST(row, property, fieldTypeMap) .asInstanceOf[AnyRef] - val edgeValue = codec.encode(spaceName, edgeName, nebulaKeys.asJava, values.asJava) + val edgeValue = codec.encodeEdge(spaceName, edgeName, nebulaKeys.asJava, values.asJava) (edgeKey, edgeValue) } }(Encoders.tuple(Encoders.BINARY, Encoders.BINARY)) @@ -173,16 +174,18 @@ class EdgeProcessor(data: DataFrame, iterator.foreach { vertex => val key = vertex.getAs[Array[Byte]](0) val value = vertex.getAs[Array[Byte]](1) - val part = ByteBuffer.wrap(key, 0, 4).getInt >> 8 + var part = ByteBuffer.wrap(key, 0, 4).getInt >> 8 + if (part <= 0) { + part = part + partitionNUm + } if (part != currentPart) { if (writer != null) { writer.close() val localFile = s"${fileBaseConfig.localPath}/$currentPart-$taskID.sst" - HDFSUtils.upload( - localFile, - s"${fileBaseConfig.remotePath}/$currentPart/$currentPart-$taskID.sst", - namenode) + HDFSUtils.upload(localFile, + s"${fileBaseConfig.remotePath}/${currentPart}", + namenode) Files.delete(Paths.get(localFile)) } currentPart = part @@ -196,10 +199,7 @@ class EdgeProcessor(data: DataFrame, if (writer != null) { writer.close() val localFile = s"${fileBaseConfig.localPath}/$currentPart-$taskID.sst" - HDFSUtils.upload( - localFile, - s"${fileBaseConfig.remotePath}/$currentPart/$currentPart-$taskID.sst", - namenode) + HDFSUtils.upload(localFile, s"${fileBaseConfig.remotePath}/${currentPart}", namenode) Files.delete(Paths.get(localFile)) } } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index c80a0e2..43e44db 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -105,6 +105,7 @@ class VerticesProcessor(data: DataFrame, val metaProvider = new MetaProvider(address) val fieldTypeMap = NebulaUtils.getDataSourceFieldType(tagConfig, space, metaProvider) val isVidStringType = metaProvider.getVidType(space) == VidType.STRING + val partitionNum = metaProvider.getPartNumber(space) if (tagConfig.dataSinkConfigEntry.category == SinkCategory.SST) { val fileBaseConfig = tagConfig.dataSinkConfigEntry.asInstanceOf[FileBaseSinkConfigEntry] @@ -144,14 +145,14 @@ class VerticesProcessor(data: DataFrame, } yield extraValueForSST(row, property, fieldTypeMap) .asInstanceOf[AnyRef] - val vertexValue = codec.encode(spaceName, tagName, nebulaKeys.asJava, values.asJava) + val vertexValue = codec.encodeTag(spaceName, tagName, nebulaKeys.asJava, values.asJava) (vertexKey, vertexValue) } }(Encoders.tuple(Encoders.BINARY, Encoders.BINARY)) .toDF("key", "value") .sortWithinPartitions("key") .foreachPartition { iterator: Iterator[Row] => - val taskID = TaskContext.get() taskAttemptId () + val taskID = TaskContext.get().taskAttemptId() var writer: NebulaSSTWriter = null var currentPart = -1 val localPath = fileBaseConfig.localPath @@ -160,18 +161,19 @@ class VerticesProcessor(data: DataFrame, iterator.foreach { vertex => val key = vertex.getAs[Array[Byte]](0) val value = vertex.getAs[Array[Byte]](1) - val part = ByteBuffer + var part = ByteBuffer .wrap(key, 0, 4) .order(ByteOrder.LITTLE_ENDIAN) .getInt >> 8 + if (part <= 0) { + part = part + partitionNum + } if (part != currentPart) { if (writer != null) { writer.close() val localFile = s"$localPath/$currentPart-$taskID.sst" - HDFSUtils.upload(localFile, - s"$remotePath/$currentPart/$currentPart-$taskID.sst", - namenode) + HDFSUtils.upload(localFile, s"$remotePath/${currentPart}", namenode) Files.delete(Paths.get(localFile)) } currentPart = part @@ -185,9 +187,7 @@ class VerticesProcessor(data: DataFrame, if (writer != null) { writer.close() val localFile = s"$localPath/$currentPart-$taskID.sst" - HDFSUtils.upload(localFile, - s"$remotePath/$currentPart/$currentPart-$taskID.sst", - namenode) + HDFSUtils.upload(localFile, s"$remotePath/${currentPart}", namenode) Files.delete(Paths.get(localFile)) } } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala index cb2a62d..9e78486 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala @@ -17,6 +17,7 @@ object HDFSUtils { val conf = new Configuration() if (namenode != null) { conf.set("fs.default.name", namenode) + conf.set("fs.defaultFS", namenode) } FileSystem.get(conf) } From 85d726545d6e00c609794075f84323391aae072f Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 15 Jan 2021 16:36:07 +0800 Subject: [PATCH 037/213] support data both as VID and property with different dataType --- .../nebula/exchange/processor/EdgeProcessor.scala | 12 ++++++++++-- .../exchange/processor/VerticesProcessor.scala | 11 +++++++---- .../vesoft/nebula/exchange/utils/NebulaUtils.scala | 10 ---------- .../nebula/exchange/writer/ServerBaseWriter.scala | 11 +++++++---- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index 5cb999c..c643f29 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -221,8 +221,12 @@ class EdgeProcessor(data: DataFrame, if (isVidStringType) { sourceField = NebulaUtils.escapeUtil(sourceField).mkString("\"", "", "\"") } else { - assert(NebulaUtils.isNumic(sourceField)) + assert(NebulaUtils.isNumic(sourceField), + s"space vidType is int, but your srcId $sourceField is not numeric.") } + } else { + assert(!isVidStringType, + "only int vidType can use policy, but your vidType is FIXED_STRING.") } val targetIndex = row.schema.fieldIndex(edgeConfig.targetField) @@ -232,8 +236,12 @@ class EdgeProcessor(data: DataFrame, if (isVidStringType) { targetField = NebulaUtils.escapeUtil(targetField).mkString("\"", "", "\"") } else { - assert(NebulaUtils.isNumic(targetField)) + assert(NebulaUtils.isNumic(targetField), + s"space vidType is int, but your dstId $targetField is not numeric.") } + } else { + assert(!isVidStringType, + "only int vidType can use policy, but your vidType is FIXED_STRING.") } val values = for { diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index 43e44db..c9ccd95 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -197,18 +197,21 @@ class VerticesProcessor(data: DataFrame, .map { row => val vertexID = { val index = row.schema.fieldIndex(tagConfig.vertexField) + val value = row.get(index).toString if (tagConfig.vertexPolicy.isEmpty) { // process string type vid if (isVidStringType) { - val value = row.get(index).toString NebulaUtils.escapeUtil(value).mkString("\"", "", "\"") } else { // process int type vid - assert(NebulaUtils.isNumic(row.get(index).toString)) - row.get(index).toString + assert(NebulaUtils.isNumic(value), + s"space vidType is int, but your vertex id $value is not numeric.") + value } } else { - row.get(index).toString + assert(!isVidStringType, + "only int vidType can use policy, but your vidType is FIXED_STRING.") + value } } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala index 009dcf0..64d35f8 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala @@ -40,16 +40,6 @@ object NebulaUtils { for (i <- nebulaFields.indices) { sourceSchemaMap.put(sourceFields.get(i), nebulaSchemaMap(nebulaFields.get(i))) } - // todo String vid and Int vid - if (dataType == Type.VERTEX) { - sourceSchemaMap.put(sourceConfig.asInstanceOf[TagConfigEntry].vertexField, - PropertyType.STRING) - } else { - sourceSchemaMap.put(sourceConfig.asInstanceOf[EdgeConfigEntry].sourceField, - PropertyType.STRING) - sourceSchemaMap.put(sourceConfig.asInstanceOf[EdgeConfigEntry].targetField, - PropertyType.STRING) - } sourceSchemaMap.toMap } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala index 0e3f642..4e68012 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala @@ -58,7 +58,8 @@ abstract class ServerBaseWriter extends Writer { INSERT_VALUE_TEMPLATE_WITH_POLICY .format(KeyPolicy.UUID.toString, vertex.vertexID, vertex.propertyValues) case _ => - throw new IllegalArgumentException("Not Support") + throw new IllegalArgumentException( + s"invalidate vertex policy ${vertices.policy.get}") } } } @@ -79,7 +80,8 @@ abstract class ServerBaseWriter extends Writer { case None => element case _ => - throw new IllegalArgumentException(s"policy ${edges.sourcePolicy} is invalidate.") + throw new IllegalArgumentException( + s"invalidate source policy ${edges.sourcePolicy.get}") } val target = edges.targetPolicy match { @@ -90,7 +92,8 @@ abstract class ServerBaseWriter extends Writer { case None => edge.destination case _ => - throw new IllegalArgumentException(s"policy ${edges.sourcePolicy} is invalidate.") + throw new IllegalArgumentException( + s"invalidate target policy ${edges.targetPolicy.get}") } if (edge.ranking.isEmpty) @@ -111,7 +114,7 @@ abstract class ServerBaseWriter extends Writer { } /** - * + * write data into Nebula Graph */ class NebulaGraphClientWriter(dataBaseConfigEntry: DataBaseConfigEntry, userConfigEntry: UserConfigEntry, From 87ebcc58588d9e83d014379cffded727bfd507a8 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 22 Jan 2021 16:25:27 +0800 Subject: [PATCH 038/213] revert remote path --- .../nebula/exchange/processor/EdgeProcessor.scala | 12 ++++++++---- .../exchange/processor/VerticesProcessor.scala | 8 ++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index c643f29..cc3aacf 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -183,9 +183,10 @@ class EdgeProcessor(data: DataFrame, if (writer != null) { writer.close() val localFile = s"${fileBaseConfig.localPath}/$currentPart-$taskID.sst" - HDFSUtils.upload(localFile, - s"${fileBaseConfig.remotePath}/${currentPart}", - namenode) + HDFSUtils.upload( + localFile, + s"${fileBaseConfig.remotePath}/${currentPart}/$currentPart-$taskID.sst", + namenode) Files.delete(Paths.get(localFile)) } currentPart = part @@ -199,7 +200,10 @@ class EdgeProcessor(data: DataFrame, if (writer != null) { writer.close() val localFile = s"${fileBaseConfig.localPath}/$currentPart-$taskID.sst" - HDFSUtils.upload(localFile, s"${fileBaseConfig.remotePath}/${currentPart}", namenode) + HDFSUtils.upload( + localFile, + s"${fileBaseConfig.remotePath}/${currentPart}/$currentPart-$taskID.sst", + namenode) Files.delete(Paths.get(localFile)) } } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index c9ccd95..18b0f37 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -173,7 +173,9 @@ class VerticesProcessor(data: DataFrame, if (writer != null) { writer.close() val localFile = s"$localPath/$currentPart-$taskID.sst" - HDFSUtils.upload(localFile, s"$remotePath/${currentPart}", namenode) + HDFSUtils.upload(localFile, + s"$remotePath/${currentPart}/$currentPart-$taskID.sst", + namenode) Files.delete(Paths.get(localFile)) } currentPart = part @@ -187,7 +189,9 @@ class VerticesProcessor(data: DataFrame, if (writer != null) { writer.close() val localFile = s"$localPath/$currentPart-$taskID.sst" - HDFSUtils.upload(localFile, s"$remotePath/${currentPart}", namenode) + HDFSUtils.upload(localFile, + s"$remotePath/${currentPart}/$currentPart-$taskID.sst", + namenode) Files.delete(Paths.get(localFile)) } } From 326cbf87df42162f6b84ce1a6f97d85dd7d064e4 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 26 Jan 2021 11:47:35 +0800 Subject: [PATCH 039/213] fix compute edge part --- .../nebula/exchange/processor/EdgeProcessor.scala | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index cc3aacf..098cac5 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -6,7 +6,7 @@ package com.vesoft.nebula.exchange.processor -import java.nio.ByteBuffer +import java.nio.{ByteBuffer, ByteOrder} import java.nio.file.{Files, Paths} import com.google.common.geometry.{S2CellId, S2LatLng} @@ -97,7 +97,7 @@ class EdgeProcessor(data: DataFrame, val metaProvider = new MetaProvider(address) val fieldTypeMap = NebulaUtils.getDataSourceFieldType(edgeConfig, space, metaProvider) val isVidStringType = metaProvider.getVidType(space) == VidType.STRING - val partitionNUm = metaProvider.getPartNumber(space) + val partitionNum = metaProvider.getPartNumber(space) if (edgeConfig.dataSinkConfigEntry.category == SinkCategory.SST) { val fileBaseConfig = edgeConfig.dataSinkConfigEntry.asInstanceOf[FileBaseSinkConfigEntry] @@ -174,9 +174,12 @@ class EdgeProcessor(data: DataFrame, iterator.foreach { vertex => val key = vertex.getAs[Array[Byte]](0) val value = vertex.getAs[Array[Byte]](1) - var part = ByteBuffer.wrap(key, 0, 4).getInt >> 8 + var part = ByteBuffer + .wrap(key, 0, 4) + .order(ByteOrder.LITTLE_ENDIAN) + .getInt >> 8 if (part <= 0) { - part = part + partitionNUm + part = part + partitionNum } if (part != currentPart) { From 4ed2f0586032e0f6a72ee9c34e3afed988311eb5 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 27 Jan 2021 15:07:10 +0800 Subject: [PATCH 040/213] add readme --- nebula-spark-connector/README.md | 50 +++++++++-------- nebula-spark-connector/README_CN.md | 86 +++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 24 deletions(-) create mode 100644 nebula-spark-connector/README_CN.md diff --git a/nebula-spark-connector/README.md b/nebula-spark-connector/README.md index e15dfdb..f5a257c 100644 --- a/nebula-spark-connector/README.md +++ b/nebula-spark-connector/README.md @@ -1,14 +1,15 @@ -# 欢迎使用 Nebula Spark Connector 2.0 +# Nebula Spark Connector 2.0 +[中文版](https://github.com/vesoft-inc/nebula-spark-utils/blob/master/nebula-spark-connector/README_CN.md) -# 介绍 +## Introduction -Nebula Spark Connector 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Nebula Graph v1.x,请使用 [Nebula Spark Connector v1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools)。 +Nebula Spark Connector 2.0 only supports Nebula Graph 2.x. If you are using Nebula Graph v1.x, please use [Nebula Spark Connector v1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools/nebula-spark) . -## 如何编译 +## How to Compile -Nebula Spark Connector 2.0 依赖 Nebula Java Client 2.0。 +Nebula Spark Connector 2.0 depends on the latest Nebula Java Client 2.0. -1. 编译打包 Nebula Java Client 2.0。 +1. Install Nebula Java Client 2.0. ```bash $ git clone https://github.com/vesoft-inc/nebula-java.git @@ -16,9 +17,9 @@ Nebula Spark Connector 2.0 依赖 Nebula Java Client 2.0。 $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true ``` - 打包结束后,在本地 Maven Repository 仓库中可以看到生成的 /com/vesoft/client/2.0.0-rc1/client-2.0.0-rc1.jar。 + After the installing, you can see the newly generated /com/vesoft/client/2.0.0-rc1/client-2.0.0-rc1.jar in your local Maven repository. -2. 编译打包 Nebula Spark Connector 2.0。 +2. Package Nebula Spark Connector 2.0. ```bash $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git @@ -26,18 +27,18 @@ Nebula Spark Connector 2.0 依赖 Nebula Java Client 2.0。 $ mvn clean package -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true ``` - 编译打包完成后,可以在 nebula-spark-utils/nebula-spark-connector/target/ 目录下看到 nebula-spark-connector-2.0.0.jar 文件。 + After the packaging, you can see the newly generated nebula-spark-connector-2.0.0.jar under the nebula-spark-utils/nebula-spark-connector/target/ directory. -## 特性 -* 提供了更多连接配置项,如超时时间、连接重试次数、执行重试次数 -* 提供了更多数据配置项,如写入数据时是否将 vertexId 同时作为属性写入、是否将 srcId、dstId、rank 等同时作为属性写入 -* Spark Reader 支持无属性读取,支持全属性读取 -* Spark Reader 支持将 Nebula Graph 数据读取成 Graphx 的 VertexRD 和 EdgeRDD,支持非 Long 型 vertexId -* Nebula Spark Connector 2.0 统一了 SparkSQL 的扩展数据源,统一采用 DataSourceV2 进行 Nebula Graph 数据扩展 +## New Features +* Supports more connection configurations, such as timeout, connectionRetry, executionRetry +* Supports more data configurations, such as if vertexId also as property, if srcId, dstId and rank also as properties +* Spark Reader Supports non-property reading, all-property reading, specific-properties reading +* Spark Reader Supports reading Nebula Graph's data to Graphx's VertexRD and EdgeRDD, and supports non-Long type vertexId +* Nebula Spark Connector 2.0 uniformly uses SparkSQL's DataSourceV2 for data source expansion. -## 使用说明 +## How to Use - 将 DataFrame 作为点写入 Nebula Graph : + Write DataFrame into Nebula Graph as Vertex: ``` val config = NebulaConnectionConfig @@ -55,7 +56,7 @@ Nebula Spark Connector 2.0 依赖 Nebula Java Client 2.0。 .build() df.write.nebula(config, nebulaWriteVertexConfig).writeVertices() ``` - 读取 Nebula Graph 的点数据: + Read vertex data from Nebula Graph: ``` val config = NebulaConnectionConfig @@ -74,11 +75,12 @@ Nebula Spark Connector 2.0 依赖 Nebula Java Client 2.0。 .build() val vertex = spark.read.nebula(config, nebulaReadVertexConfig).loadVerticesToDF() ``` -更多使用示例请参考 [Example](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/example/src/main/scala/com/vesoft/nebula/examples/connector) 。 -## 贡献 +For more use details please refer to [Example](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/example/src/main/scala/com/vesoft/nebula/examples/connector) . -Nebula Spark Connector 2.0 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: +## How to Contribute -- 前往 [Nebula Graph 论坛](https://discuss.nebula-graph.com.cn/ "点击前往“Nebula Graph 论坛") 上参与 Issue 讨论,如答疑、提供想法或者报告无法解决的问题 -- 撰写或改进文档 -- 提交优化代码 +Nebula Spark Connector 2.0 is a completely opensource project, opensource enthusiasts are welcome to participate in the following ways: + +- Go to [Nebula Graph Forum](https://discuss.nebula-graph.com.cn/ "go to“Nebula Graph Forum") to participate in issue discussions, such as answering questions, providing ideas, or reporting unsolvable problems; +- write or improve documents; +- submit code to add new features or fix bugs diff --git a/nebula-spark-connector/README_CN.md b/nebula-spark-connector/README_CN.md new file mode 100644 index 0000000..4caa480 --- /dev/null +++ b/nebula-spark-connector/README_CN.md @@ -0,0 +1,86 @@ +# 欢迎使用 Nebula Spark Connector 2.0 +[English](https://github.com/vesoft-inc/nebula-spark-utils/blob/master/nebula-spark-connector/README.md) +## 介绍 + +Nebula Spark Connector 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Nebula Graph v1.x,请使用 [Nebula Spark Connector v1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools)。 + +## 如何编译 + +Nebula Spark Connector 2.0 依赖 Nebula Java Client 2.0。 + +1. 编译打包 Nebula Java Client 2.0。 + + ```bash + $ git clone https://github.com/vesoft-inc/nebula-java.git + $ cd nebula-java + $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true + ``` + + 打包结束后,在本地 Maven Repository 仓库中可以看到生成的 /com/vesoft/client/2.0.0-rc1/client-2.0.0-rc1.jar。 + +2. 编译打包 Nebula Spark Connector 2.0。 + + ```bash + $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git + $ cd nebula-spark-utils/nebula-spark-connector + $ mvn clean package -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true + ``` + + 编译打包完成后,可以在 nebula-spark-utils/nebula-spark-connector/target/ 目录下看到 nebula-spark-connector-2.0.0.jar 文件。 + +## 特性 + +* 提供了更多连接配置项,如超时时间、连接重试次数、执行重试次数 +* 提供了更多数据配置项,如写入数据时是否将 vertexId 同时作为属性写入、是否将 srcId、dstId、rank 等同时作为属性写入 +* Spark Reader 支持无属性读取,支持全属性读取 +* Spark Reader 支持将 Nebula Graph 数据读取成 Graphx 的 VertexRD 和 EdgeRDD,支持非 Long 型 vertexId +* Nebula Spark Connector 2.0 统一了 SparkSQL 的扩展数据源,统一采用 DataSourceV2 进行 Nebula Graph 数据扩展 + +## 使用说明 + + 将 DataFrame 作为点写入 Nebula Graph : + ``` + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:45500") + .withGraphAddress("127.0.0.1:3699") + .build() + val nebulaWriteVertexConfig: WriteNebulaVertexConfig = WriteNebulaVertexConfig + .builder() + .withSpace("test") + .withTag("person") + .withVidField("id") + .withVidAsProp(true) + .withBatch(1000) + .build() + df.write.nebula(config, nebulaWriteVertexConfig).writeVertices() + ``` + 读取 Nebula Graph 的点数据: + ``` + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:45500") + .withConenctionRetry(2) + .build() + val nebulaReadVertexConfig: ReadNebulaConfig = ReadNebulaConfig + .builder() + .withSpace("exchange") + .withLabel("person") + .withNoColumn(false) + .withReturnCols(List("birthday")) + .withLimit(10) + .withPartitionNum(10) + .build() + val vertex = spark.read.nebula(config, nebulaReadVertexConfig).loadVerticesToDF() + ``` +更多使用示例请参考 [Example](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/example/src/main/scala/com/vesoft/nebula/examples/connector) 。 + +## 贡献 + +Nebula Spark Connector 2.0 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: + +- 前往 [Nebula Graph 论坛](https://discuss.nebula-graph.com.cn/ "点击前往“Nebula Graph 论坛") 上参与 Issue 讨论,如答疑、提供想法或者报告无法解决的问题 +- 撰写或改进文档 +- 提交优化代码 From e7487ffc82ba13a6187a6f9761c324ae678d5335 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 27 Jan 2021 18:44:21 +0800 Subject: [PATCH 041/213] add desc about how to connect graphx --- nebula-spark-connector/README.md | 56 ++++++++++++++++++++------- nebula-spark-connector/README_CN.md | 60 ++++++++++++++++++++++------- 2 files changed, 89 insertions(+), 27 deletions(-) diff --git a/nebula-spark-connector/README.md b/nebula-spark-connector/README.md index f5a257c..51a9e14 100644 --- a/nebula-spark-connector/README.md +++ b/nebula-spark-connector/README.md @@ -40,12 +40,11 @@ Nebula Spark Connector 2.0 depends on the latest Nebula Java Client 2.0. Write DataFrame into Nebula Graph as Vertex: ``` - val config = - NebulaConnectionConfig - .builder() - .withMetaAddress("127.0.0.1:45500") - .withGraphAddress("127.0.0.1:3699") - .build() + val config = NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:45500") + .withGraphAddress("127.0.0.1:3699") + .build() val nebulaWriteVertexConfig: WriteNebulaVertexConfig = WriteNebulaVertexConfig .builder() .withSpace("test") @@ -58,12 +57,11 @@ Nebula Spark Connector 2.0 depends on the latest Nebula Java Client 2.0. ``` Read vertex data from Nebula Graph: ``` - val config = - NebulaConnectionConfig - .builder() - .withMetaAddress("127.0.0.1:45500") - .withConenctionRetry(2) - .build() + val config = NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:45500") + .withConenctionRetry(2) + .build() val nebulaReadVertexConfig: ReadNebulaConfig = ReadNebulaConfig .builder() .withSpace("exchange") @@ -75,7 +73,39 @@ Nebula Spark Connector 2.0 depends on the latest Nebula Java Client 2.0. .build() val vertex = spark.read.nebula(config, nebulaReadVertexConfig).loadVerticesToDF() ``` -For more use details please refer to [Example](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/example/src/main/scala/com/vesoft/nebula/examples/connector) . + + 读取 Nebula Graph 的点边数据构造 Graphx 的图: + ``` + val config = NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:45500") + .build() + val nebulaReadVertexConfig = ReadNebulaConfig + .builder() + .withSpace("exchange") + .withLabel("person") + .withNoColumn(false) + .withReturnCols(List("birthday")) + .withLimit(10) + .withPartitionNum(10) + .build() + val nebulaReadEdgeConfig = ReadNebulaConfig + .builder() + .withSpace("exchange") + .withLabel("knows1") + .withNoColumn(false) + .withReturnCols(List("timep")) + .withLimit(10) + .withPartitionNum(10) + .build() + + val vertex = spark.read.nebula(config, nebulaReadVertexConfig).loadVerticesToGraphx() + val edgeRDD = spark.read.nebula(config, nebulaReadEdgeConfig).loadEdgesToGraphx() + val graph = Graph(vertexRDD, edgeRDD) + ``` + After getting Graphx's Graph, you can develop graph algorithms in Graphx like [Nebula-Spark-Algorithm](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools/nebula-algorithm). + +For more use details please refer to [Example](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/example/src/main/scala/com/vesoft/nebula/examples/connector). ## How to Contribute diff --git a/nebula-spark-connector/README_CN.md b/nebula-spark-connector/README_CN.md index 4caa480..a4e7035 100644 --- a/nebula-spark-connector/README_CN.md +++ b/nebula-spark-connector/README_CN.md @@ -40,13 +40,12 @@ Nebula Spark Connector 2.0 依赖 Nebula Java Client 2.0。 将 DataFrame 作为点写入 Nebula Graph : ``` - val config = - NebulaConnectionConfig - .builder() - .withMetaAddress("127.0.0.1:45500") - .withGraphAddress("127.0.0.1:3699") - .build() - val nebulaWriteVertexConfig: WriteNebulaVertexConfig = WriteNebulaVertexConfig + val config = NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:45500") + .withGraphAddress("127.0.0.1:3699") + .build() + val nebulaWriteVertexConfig = WriteNebulaVertexConfig .builder() .withSpace("test") .withTag("person") @@ -58,13 +57,12 @@ Nebula Spark Connector 2.0 依赖 Nebula Java Client 2.0。 ``` 读取 Nebula Graph 的点数据: ``` - val config = - NebulaConnectionConfig - .builder() - .withMetaAddress("127.0.0.1:45500") - .withConenctionRetry(2) - .build() - val nebulaReadVertexConfig: ReadNebulaConfig = ReadNebulaConfig + val config = NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:45500") + .withConenctionRetry(2) + .build() + val nebulaReadVertexConfig = ReadNebulaConfig .builder() .withSpace("exchange") .withLabel("person") @@ -75,6 +73,40 @@ Nebula Spark Connector 2.0 依赖 Nebula Java Client 2.0。 .build() val vertex = spark.read.nebula(config, nebulaReadVertexConfig).loadVerticesToDF() ``` + + 读取 Nebula Graph 的点边数据构造 Graphx 的图: + ``` + val config = NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:45500") + .withConenctionRetry(2) + .build() + val nebulaReadVertexConfig = ReadNebulaConfig + .builder() + .withSpace("exchange") + .withLabel("person") + .withNoColumn(false) + .withReturnCols(List("birthday")) + .withLimit(10) + .withPartitionNum(10) + .build() + + val nebulaReadEdgeConfig = ReadNebulaConfig + .builder() + .withSpace("exchange") + .withLabel("knows1") + .withNoColumn(false) + .withReturnCols(List("timep")) + .withLimit(10) + .withPartitionNum(10) + .build() + + val vertex = spark.read.nebula(config, nebulaReadVertexConfig).loadVerticesToGraphx() + val edgeRDD = spark.read.nebula(config, nebulaReadEdgeConfig).loadEdgesToGraphx() + val graph = Graph(vertexRDD, edgeRDD) + ``` + 得到 Graphx 的 Graph 之后,可以根据 [Nebula-Spark-Algorithm](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools/nebula-algorithm) 的示例在 Graphx 框架中进行算法开发。 + 更多使用示例请参考 [Example](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/example/src/main/scala/com/vesoft/nebula/examples/connector) 。 ## 贡献 From 60c972db1e3aac28112244e0ed7a6e3eed363d62 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 27 Jan 2021 21:00:34 +0800 Subject: [PATCH 042/213] fix grammar --- nebula-spark-connector/README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/nebula-spark-connector/README.md b/nebula-spark-connector/README.md index 51a9e14..1c35185 100644 --- a/nebula-spark-connector/README.md +++ b/nebula-spark-connector/README.md @@ -17,7 +17,7 @@ Nebula Spark Connector 2.0 depends on the latest Nebula Java Client 2.0. $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true ``` - After the installing, you can see the newly generated /com/vesoft/client/2.0.0-rc1/client-2.0.0-rc1.jar in your local Maven repository. + After the installation, you can see the newly generated /com/vesoft/client/2.0.0-rc1/client-2.0.0-rc1.jar in your local Maven repository. 2. Package Nebula Spark Connector 2.0. @@ -30,15 +30,15 @@ Nebula Spark Connector 2.0 depends on the latest Nebula Java Client 2.0. After the packaging, you can see the newly generated nebula-spark-connector-2.0.0.jar under the nebula-spark-utils/nebula-spark-connector/target/ directory. ## New Features -* Supports more connection configurations, such as timeout, connectionRetry, executionRetry -* Supports more data configurations, such as if vertexId also as property, if srcId, dstId and rank also as properties -* Spark Reader Supports non-property reading, all-property reading, specific-properties reading -* Spark Reader Supports reading Nebula Graph's data to Graphx's VertexRD and EdgeRDD, and supports non-Long type vertexId +* Supports more connection configurations, such as timeout, connectionRetry, and executionRetry. +* Supports more data configurations, such as if vertexId also as property, if srcId, dstId and rank also as properties. +* Spark Reader Supports non-property reading, all-property reading, specific-properties reading. +* Spark Reader Supports reading Nebula Graph's data to Graphx's VertexRD and EdgeRDD, and supports non-Long type vertexId. * Nebula Spark Connector 2.0 uniformly uses SparkSQL's DataSourceV2 for data source expansion. ## How to Use - Write DataFrame into Nebula Graph as Vertex: + Write DataFrame into Nebula Graph as Vertices: ``` val config = NebulaConnectionConfig .builder() @@ -55,7 +55,7 @@ Nebula Spark Connector 2.0 depends on the latest Nebula Java Client 2.0. .build() df.write.nebula(config, nebulaWriteVertexConfig).writeVertices() ``` - Read vertex data from Nebula Graph: + Read vertices from Nebula Graph: ``` val config = NebulaConnectionConfig .builder() @@ -74,7 +74,7 @@ Nebula Spark Connector 2.0 depends on the latest Nebula Java Client 2.0. val vertex = spark.read.nebula(config, nebulaReadVertexConfig).loadVerticesToDF() ``` - 读取 Nebula Graph 的点边数据构造 Graphx 的图: + Read vertices and edges from Nebula Graph to construct Graphx's graph: ``` val config = NebulaConnectionConfig .builder() @@ -105,12 +105,12 @@ Nebula Spark Connector 2.0 depends on the latest Nebula Java Client 2.0. ``` After getting Graphx's Graph, you can develop graph algorithms in Graphx like [Nebula-Spark-Algorithm](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools/nebula-algorithm). -For more use details please refer to [Example](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/example/src/main/scala/com/vesoft/nebula/examples/connector). +For more information on usage, please refer to [Example](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/example/src/main/scala/com/vesoft/nebula/examples/connector). ## How to Contribute Nebula Spark Connector 2.0 is a completely opensource project, opensource enthusiasts are welcome to participate in the following ways: -- Go to [Nebula Graph Forum](https://discuss.nebula-graph.com.cn/ "go to“Nebula Graph Forum") to participate in issue discussions, such as answering questions, providing ideas, or reporting unsolvable problems; -- write or improve documents; -- submit code to add new features or fix bugs +- Go to [Nebula Graph Forum](https://discuss.nebula-graph.com.cn/ "go to“Nebula Graph Forum") to participate in issue discussions, such as answering questions, providing ideas, or reporting unsolvable problems. +- Write or improve documents. +- Submit code to add new features or fix bugs. From 71e0c9e06b1aa7f62401c97f28b6d7860735a198 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 28 Jan 2021 15:04:31 +0800 Subject: [PATCH 043/213] update feature description --- nebula-spark-connector/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nebula-spark-connector/README.md b/nebula-spark-connector/README.md index 1c35185..b91f9d2 100644 --- a/nebula-spark-connector/README.md +++ b/nebula-spark-connector/README.md @@ -29,11 +29,11 @@ Nebula Spark Connector 2.0 depends on the latest Nebula Java Client 2.0. After the packaging, you can see the newly generated nebula-spark-connector-2.0.0.jar under the nebula-spark-utils/nebula-spark-connector/target/ directory. -## New Features +## New Features (Compared to Nebula Spark Connector 1.0) * Supports more connection configurations, such as timeout, connectionRetry, and executionRetry. -* Supports more data configurations, such as if vertexId also as property, if srcId, dstId and rank also as properties. -* Spark Reader Supports non-property reading, all-property reading, specific-properties reading. -* Spark Reader Supports reading Nebula Graph's data to Graphx's VertexRD and EdgeRDD, and supports non-Long type vertexId. +* Supports more data configurations, such as whether vertexId can be written as vertex's property, whether srcId, dstId and rank can be written as edge's properties. +* Spark Reader Supports non-property, all-property, and specific-properties read. +* Spark Reader Supports reading data from Nebula Graph to Graphx as VertexRD and EdgeRDD, it also supports String type vertexId. * Nebula Spark Connector 2.0 uniformly uses SparkSQL's DataSourceV2 for data source expansion. ## How to Use From 7a88bb56ad83e349a839b83244aee228cfc2c785 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 28 Jan 2021 16:46:02 +0800 Subject: [PATCH 044/213] update feature description --- nebula-spark-connector/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nebula-spark-connector/README.md b/nebula-spark-connector/README.md index b91f9d2..9f9e7b1 100644 --- a/nebula-spark-connector/README.md +++ b/nebula-spark-connector/README.md @@ -111,6 +111,6 @@ For more information on usage, please refer to [Example](https://github.com/veso Nebula Spark Connector 2.0 is a completely opensource project, opensource enthusiasts are welcome to participate in the following ways: -- Go to [Nebula Graph Forum](https://discuss.nebula-graph.com.cn/ "go to“Nebula Graph Forum") to participate in issue discussions, such as answering questions, providing ideas, or reporting unsolvable problems. +- Go to [Nebula Graph Forum](https://discuss.nebula-graph.com.cn/ "go to“Nebula Graph Forum") to discuss with other users. You can raise your own questions, help others' problems, share your thoughts. - Write or improve documents. - Submit code to add new features or fix bugs. From ff914565725ec24d9f8038f885f3231f61cf0aec Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 29 Jan 2021 15:50:11 +0800 Subject: [PATCH 045/213] support long & string timestamp --- .../vesoft/nebula/exchange/processor/Processor.scala | 10 +++++++++- nebula-spark-connector/pom.xml | 3 +-- .../nebula/connector/writer/NebulaExecutor.scala | 9 ++++++++- .../vesoft/nebula/connector/writer/NebulaWriter.scala | 5 +++-- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala index 543fbaf..eda28d6 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala @@ -54,7 +54,15 @@ trait Processor extends Serializable { case PropertyType.DATE => "date(\"" + row.get(index) + "\")" case PropertyType.DATETIME => "datatime(\"" + row.get(index) + "\")" case PropertyType.TIME => "time(\"" + row.get(index) + "\")" - case _ => row.get(index) + case PropertyType.TIMESTAMP => { + val value = row.get(index).toString + if (NebulaUtils.isNumic(value)) { + value + } else { + "timestamp(\"" + row.get(index) + "\")" + } + } + case _ => row.get(index) } } diff --git a/nebula-spark-connector/pom.xml b/nebula-spark-connector/pom.xml index 2b90e87..0b008e1 100644 --- a/nebula-spark-connector/pom.xml +++ b/nebula-spark-connector/pom.xml @@ -12,10 +12,9 @@ nebula-spark-connector - 2.4.4 - 2.0.0-rc1 + 2.0.0-rc1.20210129 1.8 1.8 3.2.3 diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala index 6277cac..914a457 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala @@ -140,7 +140,14 @@ object NebulaExecutor { case PropertyType.DATE => "date(\"" + propValue + "\")" case PropertyType.DATETIME => "datatime(\"" + propValue + "\")" case PropertyType.TIME => "time(\"" + propValue + "\")" - case _ => propValue + case PropertyType.TIMESTAMP => { + if (NebulaUtils.isNumic(propValue.toString)) { + propValue + } else { + "timestamp(\"" + propValue + "\")" + } + } + case _ => propValue } } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaWriter.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaWriter.scala index e5d80d9..d1d83de 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaWriter.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaWriter.scala @@ -34,9 +34,10 @@ class NebulaWriter(nebulaOptions: NebulaOptions) extends Serializable { val result = graphProvider.submit(exec) if (!result.isSucceeded) { failedExecs.append(exec) - LOG.error(s"failed to write : ${exec}") + LOG.error(s"failed to write ${exec} for " + result.getErrorMessage) } else { - LOG.info(s"succeed to write : ${exec}") + LOG.info(s"batch write succeed") + LOG.debug(s"batch write succeed: ${exec}") } } else { failedExecs.append(exec) From 226f9f0b472ba25c1addde7772219528f8f1a6e4 Mon Sep 17 00:00:00 2001 From: guojun Date: Fri, 29 Jan 2021 16:36:00 +0800 Subject: [PATCH 046/213] Random shuffle address to enable spark to acees random graphd services --- .../main/scala/com/vesoft/nebula/exchange/GraphProvider.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala index bbb8355..7fdc7d9 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala @@ -28,7 +28,8 @@ class GraphProvider(addresses: List[HostAndPort]) extends AutoCloseable with Ser for (addr <- addresses) { address.append(new HostAddress(addr.getHostText, addr.getPort)) } - pool.init(address.asJava, nebulaPoolConfig) + val rand_addr = scala.util.Random.shuffle(address) + pool.init(rand_addr.asJava, nebulaPoolConfig) def getGraphClient(userConfigEntry: UserConfigEntry): Session = { pool.getSession(userConfigEntry.user, userConfigEntry.password, true); From 74bdfe05c76097ae9430f34e95b7f66ae90eb76d Mon Sep 17 00:00:00 2001 From: guojun Date: Tue, 2 Feb 2021 10:54:12 +0800 Subject: [PATCH 047/213] Change to CamelCase --- .../main/scala/com/vesoft/nebula/exchange/GraphProvider.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala index 7fdc7d9..5570f94 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala @@ -28,8 +28,8 @@ class GraphProvider(addresses: List[HostAndPort]) extends AutoCloseable with Ser for (addr <- addresses) { address.append(new HostAddress(addr.getHostText, addr.getPort)) } - val rand_addr = scala.util.Random.shuffle(address) - pool.init(rand_addr.asJava, nebulaPoolConfig) + val randAddr = scala.util.Random.shuffle(address) + pool.init(randAddr.asJava, nebulaPoolConfig) def getGraphClient(userConfigEntry: UserConfigEntry): Session = { pool.getSession(userConfigEntry.user, userConfigEntry.password, true); From 418e557bc5c5786fec8d0c11c18cbe4542afdd51 Mon Sep 17 00:00:00 2001 From: riverzzz <455405955@qq.com> Date: Tue, 2 Feb 2021 16:09:49 +0800 Subject: [PATCH 048/213] 1.suggest spark-submit ... \ --files test-import.conf \ --conf spark.driver.extraClassPath=./ \ --conf spark.executor.extraClassPath=./ \ nebula-exchange-2.0.0.jar -c test-import.conf or spark-submit ... \ --files test-import.conf \ --conf spark.driver.extraJavaOptions=-Dconfig.file=./test-import.conf \ --conf spark.executor.extraJavaOptions=-Dconfig.file=./test-import.conf \ nebula-exchange-2.0.0.jar -c test-import.conf to dynamic load spark config,the old if use with scheduler will can not use. 2.fix bug fileSystem suggest close itself,if not will java.io.IOException: Filesystem closed 3.suggest decrease log print,if data = 1T,then log print will >1T 4.add ver and edge partition cost --- .../scala/com/vesoft/nebula/exchange/ErrorHandler.scala | 2 +- .../main/scala/com/vesoft/nebula/exchange/Exchange.scala | 4 ++-- .../scala/com/vesoft/nebula/exchange/config/Configs.scala | 6 +++--- .../vesoft/nebula/exchange/processor/EdgeProcessor.scala | 2 ++ .../nebula/exchange/processor/VerticesProcessor.scala | 2 ++ .../vesoft/nebula/exchange/writer/ServerBaseWriter.scala | 4 ++-- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala index 39a451d..06ee1e1 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala @@ -22,7 +22,7 @@ object ErrorHandler { } } finally { errors.close() - fileSystem.close() +// fileSystem.close() } } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index 7f8eb55..02595b4 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -40,7 +40,7 @@ import com.vesoft.nebula.exchange.reader.PulsarReader import org.apache.log4j.Logger import org.apache.spark.SparkConf -final case class Argument(config: File = new File("application.conf"), +final case class Argument(config: String = "application.conf", hive: Boolean = false, directly: Boolean = false, dry: Boolean = false, @@ -64,7 +64,7 @@ object Exchange { sys.exit(-1) } - val configs = Configs.parse(c.config) + val configs = Configs.parse(new File(c.config)) LOG.info(s"Config ${configs}") val session = SparkSession diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala index ba7b21a..6861945 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala @@ -721,11 +721,11 @@ object Configs { val parser = new scopt.OptionParser[Argument](programName) { head(programName, "2.0.0") - opt[File]('c', "config") + opt[String]('c', "config") .required() - .valueName("") + .valueName("fileName") .action((x, c) => c.copy(config = x)) - .text("config file") + .text("config fileName") opt[Unit]('h', "hive") .action((_, c) => c.copy(hive = true)) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index 098cac5..dbd3129 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -69,6 +69,7 @@ class EdgeProcessor(data: DataFrame, writer.prepare() // batch write tags + val startTime = System.currentTimeMillis iterator.grouped(edgeConfig.batch).foreach { edge => val edges = Edges(nebulaKeys, edge.toList, edgeConfig.sourcePolicy, edgeConfig.targetPolicy) val failStatement = writer.writeEdges(edges) @@ -85,6 +86,7 @@ class EdgeProcessor(data: DataFrame, s"${config.errorConfig.errorPath}/${edgeConfig.name}.${TaskContext.getPartitionId}") errorBuffer.clear() } + LOG.info(s"edge part-costTime>>>>>>>>>>>>>>>>>${TaskContext.getPartitionId()}-${System.currentTimeMillis() - startTime}") writer.close() graphProvider.close() } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index 18b0f37..b809ee1 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -77,6 +77,7 @@ class VerticesProcessor(data: DataFrame, writer.prepare() // batch write tags + val startTime = System.currentTimeMillis iterator.grouped(tagConfig.batch).foreach { vertex => val vertices = Vertices(nebulaKeys, vertex.toList, tagConfig.vertexPolicy) val failStatement = writer.writeVertices(vertices) @@ -93,6 +94,7 @@ class VerticesProcessor(data: DataFrame, s"${config.errorConfig.errorPath}/${tagConfig.name}.${TaskContext.getPartitionId()}") errorBuffer.clear() } + LOG.info(s"ver part-costTime>>>>>>>>>>>>>>>>>${TaskContext.getPartitionId()}-${System.currentTimeMillis() - startTime}") writer.close() graphProvider.close() } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala index 4e68012..7e98046 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala @@ -149,7 +149,6 @@ class NebulaGraphClientWriter(dataBaseConfigEntry: DataBaseConfigEntry, override def writeVertices(vertices: Vertices): String = { val sentence = toExecuteSentence(config.name, vertices) - LOG.info(sentence) if (rateLimiter.tryAcquire(rateConfig.timeout, TimeUnit.MILLISECONDS)) { val result = graphProvider.submit(session, sentence) if (result.isSucceeded) { @@ -159,12 +158,12 @@ class NebulaGraphClientWriter(dataBaseConfigEntry: DataBaseConfigEntry, } else { LOG.error(s"write vertex failed because write speed is too fast") } + LOG.info(sentence) sentence } override def writeEdges(edges: Edges): String = { val sentence = toExecuteSentence(config.name, edges) - LOG.info(sentence) if (rateLimiter.tryAcquire(rateConfig.timeout, TimeUnit.MILLISECONDS)) { val result = graphProvider.submit(session, sentence) if (result.isSucceeded) { @@ -174,6 +173,7 @@ class NebulaGraphClientWriter(dataBaseConfigEntry: DataBaseConfigEntry, } else { LOG.error(s"write vertex failed because write speed is too fast") } + LOG.info(sentence) sentence } From dc4252d60bcaa5436bcf478e8940181162fd6d57 Mon Sep 17 00:00:00 2001 From: riverzzz <455405955@qq.com> Date: Sun, 7 Feb 2021 15:26:34 +0800 Subject: [PATCH 049/213] delete close code --- .../src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala index 06ee1e1..056d654 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala @@ -22,7 +22,6 @@ object ErrorHandler { } } finally { errors.close() -// fileSystem.close() } } From bcd7db4fec76be6d40c850e11c15d55917ca30e6 Mon Sep 17 00:00:00 2001 From: riverzzz <455405955@qq.com> Date: Sun, 7 Feb 2021 15:37:41 +0800 Subject: [PATCH 050/213] change print log --- .../com/vesoft/nebula/exchange/processor/EdgeProcessor.scala | 2 +- .../vesoft/nebula/exchange/processor/VerticesProcessor.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index dbd3129..c4a10db 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -86,7 +86,7 @@ class EdgeProcessor(data: DataFrame, s"${config.errorConfig.errorPath}/${edgeConfig.name}.${TaskContext.getPartitionId}") errorBuffer.clear() } - LOG.info(s"edge part-costTime>>>>>>>>>>>>>>>>>${TaskContext.getPartitionId()}-${System.currentTimeMillis() - startTime}") + LOG.info(s"spark partition for edge cost time>>>>>>>>>>>>>>>>>${TaskContext.getPartitionId()}-${System.currentTimeMillis() - startTime}") writer.close() graphProvider.close() } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index b809ee1..5909ff7 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -94,7 +94,7 @@ class VerticesProcessor(data: DataFrame, s"${config.errorConfig.errorPath}/${tagConfig.name}.${TaskContext.getPartitionId()}") errorBuffer.clear() } - LOG.info(s"ver part-costTime>>>>>>>>>>>>>>>>>${TaskContext.getPartitionId()}-${System.currentTimeMillis() - startTime}") + LOG.info(s"spark partition for vertex cost time>>>>>>>>>>>>>>>>>${TaskContext.getPartitionId()}-${System.currentTimeMillis() - startTime}") writer.close() graphProvider.close() } From 0da74a947919632016bdc2833bcde871dc6dc050 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 23 Feb 2021 09:59:02 +0800 Subject: [PATCH 051/213] sync java client --- nebula-exchange/README-CN.md | 14 +------------- nebula-exchange/README.md | 14 +------------- nebula-exchange/pom.xml | 10 +++++++++- nebula-spark-connector/README.md | 14 +------------- nebula-spark-connector/README_CN.md | 14 +------------- nebula-spark-connector/pom.xml | 11 +++++++++++ pom.xml | 2 +- 7 files changed, 25 insertions(+), 54 deletions(-) diff --git a/nebula-exchange/README-CN.md b/nebula-exchange/README-CN.md index 4e922a5..2944360 100644 --- a/nebula-exchange/README-CN.md +++ b/nebula-exchange/README-CN.md @@ -7,19 +7,7 @@ Exchange 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Nebula Graph v1. ## 如何编译 -Exchange 2.0 依赖 Nebula Java Client 2.0。 - -1. 编译打包 Nebula Java Client 2.0。 - - ```bash - $ git clone https://github.com/vesoft-inc/nebula-java.git - $ cd nebula-java - $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true - ``` - - 打包结束后,在本地 Maven Repository 仓库中可以看到生成的 /com/vesoft/client/2.0.0-rc1/client-2.0.0-rc1.jar。 - -2. 编译打包 Exchange 2.0。 +1. 编译打包 Exchange 2.0。 ```bash $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index 13ef101..77b59bf 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -7,19 +7,7 @@ Exchange 2.0 only supports Nebula Graph 2.x. If you want to import data for Nebu ## How to Compile -Exchange 2.0 depends on the latest Nebula Java Client 2.0。 - -1. Install Nebula Java Client 2.0。 - - ```bash - $ git clone https://github.com/vesoft-inc/nebula-java.git - $ cd nebula-java - $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true - ``` - - After the installing, you can see the newly generated /com/vesoft/client/2.0.0-rc1/client-2.0.0-rc1.jar in your local Maven repository. - -2. Package Exchange 2.0。 +1. Package Exchange 2.0。 ```bash $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml index 83b5608..ed84eb6 100644 --- a/nebula-exchange/pom.xml +++ b/nebula-exchange/pom.xml @@ -28,7 +28,7 @@ 3.9.2 2.11.0-M4 3.7.1 - 2.0.0-rc1 + 2.0.0-rc1.20210129 1.0.0 2.4.5-M1 3.4.6 @@ -42,6 +42,14 @@ src/test + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + org.scala-tools maven-scala-plugin diff --git a/nebula-spark-connector/README.md b/nebula-spark-connector/README.md index 9f9e7b1..bc65623 100644 --- a/nebula-spark-connector/README.md +++ b/nebula-spark-connector/README.md @@ -7,19 +7,7 @@ Nebula Spark Connector 2.0 only supports Nebula Graph 2.x. If you are using Nebu ## How to Compile -Nebula Spark Connector 2.0 depends on the latest Nebula Java Client 2.0. - -1. Install Nebula Java Client 2.0. - - ```bash - $ git clone https://github.com/vesoft-inc/nebula-java.git - $ cd nebula-java - $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true - ``` - - After the installation, you can see the newly generated /com/vesoft/client/2.0.0-rc1/client-2.0.0-rc1.jar in your local Maven repository. - -2. Package Nebula Spark Connector 2.0. +1. Package Nebula Spark Connector 2.0. ```bash $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git diff --git a/nebula-spark-connector/README_CN.md b/nebula-spark-connector/README_CN.md index a4e7035..00ef4ec 100644 --- a/nebula-spark-connector/README_CN.md +++ b/nebula-spark-connector/README_CN.md @@ -6,19 +6,7 @@ Nebula Spark Connector 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Ne ## 如何编译 -Nebula Spark Connector 2.0 依赖 Nebula Java Client 2.0。 - -1. 编译打包 Nebula Java Client 2.0。 - - ```bash - $ git clone https://github.com/vesoft-inc/nebula-java.git - $ cd nebula-java - $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true - ``` - - 打包结束后,在本地 Maven Repository 仓库中可以看到生成的 /com/vesoft/client/2.0.0-rc1/client-2.0.0-rc1.jar。 - -2. 编译打包 Nebula Spark Connector 2.0。 +1. 编译打包 Nebula Spark Connector 2.0。 ```bash $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git diff --git a/nebula-spark-connector/pom.xml b/nebula-spark-connector/pom.xml index 0b008e1..465129b 100644 --- a/nebula-spark-connector/pom.xml +++ b/nebula-spark-connector/pom.xml @@ -58,6 +58,17 @@ + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + + default-deploy + deploy + + + org.apache.maven.plugins diff --git a/pom.xml b/pom.xml index 4bb2b55..cdd9f83 100644 --- a/pom.xml +++ b/pom.xml @@ -15,7 +15,7 @@ nebula-spark - Nebula Spark Tools + Nebula Spark Utils https://github.com/vesoft-inc/nebula-spark-utils scm:git:https://github.com/vesoft-inc/nebula From c4e60351b7bb994f82bec3b80bbadadfcc586704 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 4 Mar 2021 13:59:47 +0800 Subject: [PATCH 052/213] remove csv's inferSchema & add timestamp case --- nebula-exchange/pom.xml | 2 +- .../com/vesoft/nebula/exchange/Exchange.scala | 15 ++++++++++----- .../nebula/exchange/processor/Processor.scala | 4 +++- .../nebula/exchange/reader/FileBaseReader.scala | 1 - 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml index 83b5608..c1bebc5 100644 --- a/nebula-exchange/pom.xml +++ b/nebula-exchange/pom.xml @@ -28,7 +28,7 @@ 3.9.2 2.11.0-M4 3.7.1 - 2.0.0-rc1 + 2.0.0-rc1.20210129 1.0.0 2.4.5-M1 3.4.6 diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index 02595b4..6d36eff 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -13,12 +13,14 @@ import com.vesoft.nebula.exchange.config.{ Configs, DataSourceConfigEntry, FileBaseSourceConfigEntry, + HBaseSourceConfigEntry, HiveSourceConfigEntry, JanusGraphSourceConfigEntry, KafkaSourceConfigEntry, MySQLSourceConfigEntry, Neo4JSourceConfigEntry, PulsarSourceConfigEntry, + SinkCategory, SourceCategory } import com.vesoft.nebula.exchange.processor.{EdgeProcessor, VerticesProcessor} @@ -34,7 +36,6 @@ import com.vesoft.nebula.exchange.reader.{ ORCReader, ParquetReader } -import com.vesoft.nebula.exchange.config.HBaseSourceConfigEntry import com.vesoft.nebula.exchange.processor.ReloadProcessor import com.vesoft.nebula.exchange.reader.PulsarReader import org.apache.log4j.Logger @@ -137,8 +138,10 @@ object Exchange { batchSuccess, batchFailure) processor.process() - LOG.info(s"batchSuccess.${tagConfig.name}: ${batchSuccess.value}") - LOG.info(s"batchFailure.${tagConfig.name}: ${batchFailure.value}") + if (tagConfig.dataSinkConfigEntry.category == SinkCategory.CLIENT) { + LOG.info(s"batchSuccess.${tagConfig.name}: ${batchSuccess.value}") + LOG.info(s"batchFailure.${tagConfig.name}: ${batchFailure.value}") + } } } } else { @@ -169,8 +172,10 @@ object Exchange { batchFailure ) processor.process() - LOG.info(s"batchSuccess.${edgeConfig.name}: ${batchSuccess.value}") - LOG.info(s"batchFailure.${edgeConfig.name}: ${batchFailure.value}") + if (edgeConfig.dataSinkConfigEntry.category == SinkCategory.CLIENT) { + LOG.info(s"batchSuccess.${edgeConfig.name}: ${batchSuccess.value}") + LOG.info(s"batchFailure.${edgeConfig.name}: ${batchFailure.value}") + } } } } else { diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala index eda28d6..68bf74c 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala @@ -128,7 +128,9 @@ trait Processor extends Serializable { timeValues(3).toByte, timeValues(4).toInt) } - + case PropertyType.TIMESTAMP => { + row.get(index).toString.toLong + } } } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/FileBaseReader.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/FileBaseReader.scala index 2c55f5d..ffe4066 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/FileBaseReader.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/FileBaseReader.scala @@ -82,7 +82,6 @@ class CSVReader(override val session: SparkSession, csvConfig: FileBaseSourceCon session.read .option("delimiter", csvConfig.separator.get) .option("header", csvConfig.header.get) - .option("inferSchema", true) .csv(path) } } From 59a61a7a2b6dcd6fbc649da74b887991d7100dbf Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 8 Mar 2021 14:19:41 +0800 Subject: [PATCH 053/213] deal with null object to NVAL type's Value --- .../vesoft/nebula/exchange/processor/EdgeProcessor.scala | 3 ++- .../com/vesoft/nebula/exchange/processor/Processor.scala | 8 ++++++-- .../nebula/exchange/processor/VerticesProcessor.scala | 3 ++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index c4a10db..acd41eb 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -86,7 +86,8 @@ class EdgeProcessor(data: DataFrame, s"${config.errorConfig.errorPath}/${edgeConfig.name}.${TaskContext.getPartitionId}") errorBuffer.clear() } - LOG.info(s"spark partition for edge cost time>>>>>>>>>>>>>>>>>${TaskContext.getPartitionId()}-${System.currentTimeMillis() - startTime}") + LOG.info(s"spark partition for edge cost time>>>>>>>>>>>>>>>>>${TaskContext + .getPartitionId()}-${System.currentTimeMillis() - startTime}") writer.close() graphProvider.close() } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala index 68bf74c..442c563 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala @@ -6,7 +6,7 @@ package com.vesoft.nebula.exchange.processor -import com.vesoft.nebula.{Date, DateTime, Time} +import com.vesoft.nebula.{Date, DateTime, NullType, Time, Value} import com.vesoft.nebula.meta.PropertyType import com.vesoft.nebula.exchange.utils.{HDFSUtils, NebulaUtils} import org.apache.spark.sql.Row @@ -68,7 +68,11 @@ trait Processor extends Serializable { def extraValueForSST(row: Row, field: String, fieldTypeMap: Map[String, Int]): Any = { val index = row.schema.fieldIndex(field) - if (row.isNullAt(index)) return null + if (row.isNullAt(index)) { + val nullVal = new Value() + nullVal.setNVal(NullType.__NULL__) + return nullVal + } fieldTypeMap(field) match { case PropertyType.UNKNOWN => diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index 5909ff7..e178da6 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -94,7 +94,8 @@ class VerticesProcessor(data: DataFrame, s"${config.errorConfig.errorPath}/${tagConfig.name}.${TaskContext.getPartitionId()}") errorBuffer.clear() } - LOG.info(s"spark partition for vertex cost time>>>>>>>>>>>>>>>>>${TaskContext.getPartitionId()}-${System.currentTimeMillis() - startTime}") + LOG.info(s"spark partition for vertex cost time>>>>>>>>>>>>>>>>>${TaskContext + .getPartitionId()}-${System.currentTimeMillis() - startTime}") writer.close() graphProvider.close() } From eed88c72c1fe7fe407cba58cba9746e11651775e Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 9 Mar 2021 10:11:45 +0800 Subject: [PATCH 054/213] remove >> in log info --- .../com/vesoft/nebula/exchange/processor/EdgeProcessor.scala | 5 +++-- .../vesoft/nebula/exchange/processor/VerticesProcessor.scala | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index acd41eb..009b16a 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -86,8 +86,9 @@ class EdgeProcessor(data: DataFrame, s"${config.errorConfig.errorPath}/${edgeConfig.name}.${TaskContext.getPartitionId}") errorBuffer.clear() } - LOG.info(s"spark partition for edge cost time>>>>>>>>>>>>>>>>>${TaskContext - .getPartitionId()}-${System.currentTimeMillis() - startTime}") + LOG.info( + s"spark partition for edge cost time:" + + s"${TaskContext.getPartitionId()}-${System.currentTimeMillis() - startTime}") writer.close() graphProvider.close() } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index e178da6..94c92ce 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -94,8 +94,9 @@ class VerticesProcessor(data: DataFrame, s"${config.errorConfig.errorPath}/${tagConfig.name}.${TaskContext.getPartitionId()}") errorBuffer.clear() } - LOG.info(s"spark partition for vertex cost time>>>>>>>>>>>>>>>>>${TaskContext - .getPartitionId()}-${System.currentTimeMillis() - startTime}") + LOG.info( + s"spark partition for vertex cost time:" + + s"${TaskContext.getPartitionId()}-${System.currentTimeMillis() - startTime}") writer.close() graphProvider.close() } From 5fdbac555a9b8d56988f0155b9fa3e2e5ad22cc2 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 10 Mar 2021 17:39:58 +0800 Subject: [PATCH 055/213] enable hive config --- .../src/main/scala/com/vesoft/nebula/exchange/Exchange.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index 6d36eff..cb0e48a 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -94,7 +94,10 @@ object Exchange { .set("javax.jdo.option.ConnectionUserName", hiveConfig.connectionUserName) .set("javax.jdo.option.ConnectionPassword", hiveConfig.connectionPassWord) } + session.config(sparkConf) session.enableHiveSupport() + } else { + session.config(sparkConf) } val spark = session.getOrCreate() From 45fabe67b0e38813c522fd7d5283e174ea905b2e Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 18 Mar 2021 18:04:48 +0800 Subject: [PATCH 056/213] sync client encoder & add in and out edge for sst --- .../vesoft/nebula/exchange/MetaProvider.scala | 30 +++++++++++++++- .../exchange/processor/EdgeProcessor.scala | 35 ++++++++++++++----- .../processor/VerticesProcessor.scala | 18 ++++++---- .../nebula/exchange/utils/NebulaUtils.scala | 7 ++++ 4 files changed, 75 insertions(+), 15 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala index 64a510e..5f69fa6 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala @@ -10,7 +10,7 @@ import com.google.common.net.HostAndPort import com.vesoft.nebula.client.graph.data.HostAddress import com.vesoft.nebula.client.meta.MetaClient import com.vesoft.nebula.exchange.config.Type -import com.vesoft.nebula.meta.PropertyType +import com.vesoft.nebula.meta.{EdgeItem, PropertyType, TagItem} import org.apache.log4j.Logger import scala.collection.JavaConverters._ @@ -81,6 +81,34 @@ class MetaProvider(addresses: List[HostAndPort]) extends AutoCloseable with Seri null } + def getSpaceVidLen(space: String): Int = { + val spaceItem = metaClient.getSpace(space); + if (spaceItem == null) { + throw new IllegalArgumentException(s"space $space does not exist.") + } + spaceItem.getProperties.getVid_type.getType_length + } + + def getTagId(space: String, tag: String): TagItem = { + val tagItemList = metaClient.getTags(space).asScala + for (tagItem: TagItem <- tagItemList) { + if (new String(tagItem.tag_name).equals(tag)) { + return tagItem + } + } + throw new IllegalArgumentException(s"tag ${space}.${tag} does not exist.") + } + + def getEdgeType(space: String, edge: String): EdgeItem = { + val edgeItemList = metaClient.getEdges(space).asScala + for (edgeItem: EdgeItem <- edgeItemList) { + if (new String(edgeItem.edge_name).equals(edge)) { + return edgeItem + } + } + throw new IllegalArgumentException(s"edge ${space}.${edge} does not exist.") + } + override def close(): Unit = { metaClient.close() } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index 009b16a..9164032 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -106,11 +106,14 @@ class EdgeProcessor(data: DataFrame, if (edgeConfig.dataSinkConfigEntry.category == SinkCategory.SST) { val fileBaseConfig = edgeConfig.dataSinkConfigEntry.asInstanceOf[FileBaseSinkConfigEntry] val namenode = fileBaseConfig.fsName.orNull + val spaceName = config.databaseConfig.space + val edgeName = edgeConfig.name + + val spaceVidLen = metaProvider.getSpaceVidLen(space) + val edgeItem = metaProvider.getEdgeType(space, edgeName) data .mapPartitions { iter => - val spaceName = config.databaseConfig.space - val edgeName = edgeConfig.name iter.map { row => val srcIndex: Int = row.schema.fieldIndex(edgeConfig.sourceField) var srcId: String = row.get(srcIndex).toString @@ -155,19 +158,35 @@ class EdgeProcessor(data: DataFrame, for (addr <- address) { hostAddrs.append(new HostAddress(addr.getHostText, addr.getPort)) } - val metaCache: MetaCache = MetaManager.getMetaManager(hostAddrs.asJava) - val codec = new NebulaCodecImpl(metaCache) - val edgeKey = codec.edgeKey(spaceName, srcId, edgeName, ranking, dstId) + + val partitionId = NebulaUtils.getPartitionId(spaceName, srcId, partitionNum) + val codec = new NebulaCodecImpl() + val positiceEdgeKey = codec.edgeKeyByDefaultVer(spaceVidLen, + partitionId, + srcId.getBytes, + edgeItem.getEdge_type, + ranking, + dstId.getBytes) + val reverseEdgeKey = codec.edgeKeyByDefaultVer(spaceVidLen, + partitionId, + dstId.getBytes, + -edgeItem.getEdge_type, + ranking, + srcId.getBytes) + val values = for { property <- fieldKeys if property.trim.length != 0 } yield extraValueForSST(row, property, fieldTypeMap) .asInstanceOf[AnyRef] - val edgeValue = codec.encodeEdge(spaceName, edgeName, nebulaKeys.asJava, values.asJava) - (edgeKey, edgeValue) + val edgeValue = codec.encodeEdge(edgeItem, nebulaKeys.asJava, values.asJava) + (positiceEdgeKey, reverseEdgeKey, edgeValue) } - }(Encoders.tuple(Encoders.BINARY, Encoders.BINARY)) + }(Encoders.tuple(Encoders.BINARY, Encoders.BINARY, Encoders.BINARY)) + .flatMap(line => { + List((line._1, line._3), (line._2, line._3)) + })(Encoders.BINARY, Encoders.BINARY) .toDF("key", "value") .sortWithinPartitions("key") .foreachPartition { iterator: Iterator[Row] => diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index 94c92ce..36bc74a 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -114,11 +114,14 @@ class VerticesProcessor(data: DataFrame, if (tagConfig.dataSinkConfigEntry.category == SinkCategory.SST) { val fileBaseConfig = tagConfig.dataSinkConfigEntry.asInstanceOf[FileBaseSinkConfigEntry] val namenode = fileBaseConfig.fsName.orNull + val spaceName = config.databaseConfig.space + val tagName = tagConfig.name + + val spaceVidLen = metaProvider.getSpaceVidLen(space) + val tagItem = metaProvider.getTagId(space, tagName) data .mapPartitions { iter => - val spaceName = config.databaseConfig.space - val tagName = tagConfig.name iter.map { row => val index: Int = row.schema.fieldIndex(tagConfig.vertexField) var vertexId: String = row.get(index).toString @@ -141,15 +144,18 @@ class VerticesProcessor(data: DataFrame, for (addr <- address) { hostAddrs.append(new HostAddress(addr.getHostText, addr.getPort)) } - val metaCache: MetaCache = MetaManager.getMetaManager(hostAddrs.asJava) - val codec = new NebulaCodecImpl(metaCache) - val vertexKey = codec.vertexKey(spaceName, vertexId, tagName) + + val partitionId = NebulaUtils.getPartitionId(spaceName, vertexId, partitionNum) + + val codec = new NebulaCodecImpl() + val vertexKey = + codec.vertexKey(spaceVidLen, partitionId, vertexId.getBytes, tagItem.getTag_id) val values = for { property <- fieldKeys if property.trim.length != 0 } yield extraValueForSST(row, property, fieldTypeMap) .asInstanceOf[AnyRef] - val vertexValue = codec.encodeTag(spaceName, tagName, nebulaKeys.asJava, values.asJava) + val vertexValue = codec.encodeTag(tagItem, nebulaKeys.asJava, values.asJava) (vertexKey, vertexValue) } }(Encoders.tuple(Encoders.BINARY, Encoders.BINARY)) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala index 64d35f8..819bcd8 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala @@ -10,6 +10,7 @@ import com.vesoft.nebula.exchange.MetaProvider import com.vesoft.nebula.meta.PropertyType import com.vesoft.nebula.exchange.MetaProvider import com.vesoft.nebula.exchange.config.{EdgeConfigEntry, SchemaConfigEntry, TagConfigEntry, Type} +import org.apache.commons.codec.digest.MurmurHash2 import org.apache.log4j.Logger import scala.collection.JavaConversions.seqAsJavaList @@ -75,4 +76,10 @@ object NebulaUtils { } s } + + def getPartitionId(spaceName: String, id: String, partitionSize: Int): Int = { + val hash = MurmurHash2.hash64(id.getBytes, id.length, 0xc70f6907) + val hashValue = java.lang.Long.parseUnsignedLong(java.lang.Long.toUnsignedString(hash)) + (Math.floorMod(hashValue, partitionSize) + 1).toInt + } } From 7a85e95bb1b0a3e97656cc4769c20ea9d2909968 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 22 Mar 2021 11:23:48 +0800 Subject: [PATCH 057/213] support datetime separated by space and T --- nebula-exchange/pom.xml | 2 +- .../exchange/processor/EdgeProcessor.scala | 2 +- .../nebula/exchange/processor/Processor.scala | 22 +++++++++++++++---- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml index ed84eb6..93a02d7 100644 --- a/nebula-exchange/pom.xml +++ b/nebula-exchange/pom.xml @@ -28,7 +28,7 @@ 3.9.2 2.11.0-M4 3.7.1 - 2.0.0-rc1.20210129 + 2.0.0-SNAPSHOT 1.0.0 2.4.5-M1 3.4.6 diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index 9164032..a5540e1 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -186,7 +186,7 @@ class EdgeProcessor(data: DataFrame, }(Encoders.tuple(Encoders.BINARY, Encoders.BINARY, Encoders.BINARY)) .flatMap(line => { List((line._1, line._3), (line._2, line._3)) - })(Encoders.BINARY, Encoders.BINARY) + })(Encoders.tuple(Encoders.BINARY, Encoders.BINARY)) .toDF("key", "value") .sortWithinPartitions("key") .foreachPartition { iterator: Iterator[Row] => diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala index 442c563..05ce0ea 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala @@ -113,26 +113,40 @@ trait Processor extends Serializable { dateTimeValue = rowValue.trim.split(" ") } else { throw new UnsupportedOperationException( - s"wrong format for datetime value: $rowValue, correct format is 2020-01-01T12:00:00:0000") + s"wrong format for datetime value: $rowValue, " + + s"correct format is 2020-01-01T12:00:00:0000 or 2020-01-01 12:00:00:0000") } if (dateTimeValue.size < 2) { throw new UnsupportedOperationException( - s"wrong format for datetime value: $rowValue, correct format is 2020-01-01T12:00:00:0000") + s"wrong format for datetime value: $rowValue, " + + s"correct format is 2020-01-01T12:00:00:0000 or 2020-01-01 12:00:00:0000") } val dateValues = dateTimeValue(0).split("-") val timeValues = dateTimeValue(1).split(":") + if (dateValues.size < 3 || timeValues.size < 3) { + throw new UnsupportedOperationException( + s"wrong format for datetime value: $rowValue, " + + s"correct format is 2020-01-01T12:00:00:0000 or 2020-01-01 12:00:00") + } + + val microsec: Int = if (timeValues.size == 4) timeValues(3).toInt else 0 new DateTime(dateValues(0).toShort, dateValues(1).toByte, dateValues(2).toByte, timeValues(0).toByte, + timeValues(1).toByte, timeValues(2).toByte, - timeValues(3).toByte, - timeValues(4).toInt) + microsec) } case PropertyType.TIMESTAMP => { + val value = row.get(index).toString + if (!NebulaUtils.isNumic(value)) { + throw new IllegalArgumentException( + s"timestamp only support long type, your value is ${value}") + } row.get(index).toString.toLong } } From 14fa8a634e457d2d5fb1e8b0cd20cab1ad237c46 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 22 Mar 2021 13:46:49 +0800 Subject: [PATCH 058/213] modify sparkSession's config to enhance the legibility --- .../scala/com/vesoft/nebula/exchange/Exchange.scala | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index cb0e48a..76c221f 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -84,7 +84,7 @@ object Exchange { // config hive for sparkSession if (c.hive) { if (configs.hiveConfigEntry.isEmpty) { - LOG.warn("you don't config hive source, so using hive tied with spark.") + LOG.info("you don't config hive source, so using hive tied with spark.") } else { val hiveConfig = configs.hiveConfigEntry.get sparkConf.set("spark.sql.warehouse.dir", hiveConfig.waredir) @@ -94,10 +94,12 @@ object Exchange { .set("javax.jdo.option.ConnectionUserName", hiveConfig.connectionUserName) .set("javax.jdo.option.ConnectionPassword", hiveConfig.connectionPassWord) } - session.config(sparkConf) + } + + session.config(sparkConf) + + if (c.hive) { session.enableHiveSupport() - } else { - session.config(sparkConf) } val spark = session.getOrCreate() From 31d3f7a1a37aeb963c88fe4c754eb984bb7246ba Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 22 Mar 2021 13:52:37 +0800 Subject: [PATCH 059/213] modify interface name --- .../scala/com/vesoft/nebula/exchange/MetaProvider.scala | 4 ++-- .../vesoft/nebula/exchange/processor/EdgeProcessor.scala | 6 +++--- .../nebula/exchange/processor/VerticesProcessor.scala | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala index 5f69fa6..f483b00 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala @@ -89,7 +89,7 @@ class MetaProvider(addresses: List[HostAndPort]) extends AutoCloseable with Seri spaceItem.getProperties.getVid_type.getType_length } - def getTagId(space: String, tag: String): TagItem = { + def getTagItem(space: String, tag: String): TagItem = { val tagItemList = metaClient.getTags(space).asScala for (tagItem: TagItem <- tagItemList) { if (new String(tagItem.tag_name).equals(tag)) { @@ -99,7 +99,7 @@ class MetaProvider(addresses: List[HostAndPort]) extends AutoCloseable with Seri throw new IllegalArgumentException(s"tag ${space}.${tag} does not exist.") } - def getEdgeType(space: String, edge: String): EdgeItem = { + def getEdgeItem(space: String, edge: String): EdgeItem = { val edgeItemList = metaClient.getEdges(space).asScala for (edgeItem: EdgeItem <- edgeItemList) { if (new String(edgeItem.edge_name).equals(edge)) { diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index a5540e1..565d334 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -110,7 +110,7 @@ class EdgeProcessor(data: DataFrame, val edgeName = edgeConfig.name val spaceVidLen = metaProvider.getSpaceVidLen(space) - val edgeItem = metaProvider.getEdgeType(space, edgeName) + val edgeItem = metaProvider.getEdgeItem(space, edgeName) data .mapPartitions { iter => @@ -161,7 +161,7 @@ class EdgeProcessor(data: DataFrame, val partitionId = NebulaUtils.getPartitionId(spaceName, srcId, partitionNum) val codec = new NebulaCodecImpl() - val positiceEdgeKey = codec.edgeKeyByDefaultVer(spaceVidLen, + val positiveEdgeKey = codec.edgeKeyByDefaultVer(spaceVidLen, partitionId, srcId.getBytes, edgeItem.getEdge_type, @@ -181,7 +181,7 @@ class EdgeProcessor(data: DataFrame, .asInstanceOf[AnyRef] val edgeValue = codec.encodeEdge(edgeItem, nebulaKeys.asJava, values.asJava) - (positiceEdgeKey, reverseEdgeKey, edgeValue) + (positiveEdgeKey, reverseEdgeKey, edgeValue) } }(Encoders.tuple(Encoders.BINARY, Encoders.BINARY, Encoders.BINARY)) .flatMap(line => { diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index 36bc74a..fb56182 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -118,7 +118,7 @@ class VerticesProcessor(data: DataFrame, val tagName = tagConfig.name val spaceVidLen = metaProvider.getSpaceVidLen(space) - val tagItem = metaProvider.getTagId(space, tagName) + val tagItem = metaProvider.getTagItem(space, tagName) data .mapPartitions { iter => From f00d643f262121bcd9214eb4b6f25120473f9cf1 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 22 Mar 2021 16:26:40 +0800 Subject: [PATCH 060/213] add utc note --- nebula-exchange/README-CN.md | 2 +- nebula-exchange/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nebula-exchange/README-CN.md b/nebula-exchange/README-CN.md index 2944360..95939c6 100644 --- a/nebula-exchange/README-CN.md +++ b/nebula-exchange/README-CN.md @@ -25,7 +25,7 @@ Exchange 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Nebula Graph v1. *1. Nebula Graph 2.0 暂时只支持 String 类型的 VID,请勿配置点 ID 或者边的 src_id、dst_id 的 policy。* -*2. Exchange 2.0 新增 null、Date、DateTime、Time 类型数据的导入。* +*2. Exchange 2.0 新增 null、Date、DateTime、Time 类型数据的导入( DateTime 是 UTC 时区,非 Local time)。* *3. Exchange 2.0 支持 Hive on Spark 以外的 Hive 数据源,需在配置文件中配置 Hive 源,具体配置示例参考 [server_application.conf](https://github.com/vesoft-inc/nebula-spark-utils/blob/main/nebula-exchange/src/main/resources/server_application.conf) 中 Hive 的配置。* diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index 77b59bf..c25113d 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -30,7 +30,7 @@ For more details about Exchange, please refer to [Exchange 1.0](https://github.c ## New Features 1. Supports importing vertex data with String type IDs. -2. Supports importing data of the Null, Date, DateTime, and Time types. +2. Supports importing data of the Null, Date, DateTime, and Time types(DateTime uses UTC, not local time). 3. Supports importing data from other Hive sources besides Hive on Spark. 4. Supports recording and retrying the INSERT statement after failures during data import. From 765afa22cfcf36004c1ad5b5f80803b674543544 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 23 Mar 2021 15:14:45 +0800 Subject: [PATCH 061/213] update client version --- nebula-exchange/pom.xml | 2 +- nebula-spark-connector/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml index 93a02d7..99989a6 100644 --- a/nebula-exchange/pom.xml +++ b/nebula-exchange/pom.xml @@ -28,7 +28,7 @@ 3.9.2 2.11.0-M4 3.7.1 - 2.0.0-SNAPSHOT + 2.0.0 1.0.0 2.4.5-M1 3.4.6 diff --git a/nebula-spark-connector/pom.xml b/nebula-spark-connector/pom.xml index 465129b..08644fc 100644 --- a/nebula-spark-connector/pom.xml +++ b/nebula-spark-connector/pom.xml @@ -14,7 +14,7 @@ 2.4.4 - 2.0.0-rc1.20210129 + 2.0.0 1.8 1.8 3.2.3 From 30b3cb79ada14b97eea70457f81d858dc20a18db Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 23 Mar 2021 16:53:05 +0800 Subject: [PATCH 062/213] add javadoc plugin --- nebula-exchange/pom.xml | 35 +++++++++++++++++++++++++++++++--- nebula-spark-connector/pom.xml | 25 ++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml index 99989a6..009f036 100644 --- a/nebula-exchange/pom.xml +++ b/nebula-exchange/pom.xml @@ -46,9 +46,13 @@ org.apache.maven.plugins maven-deploy-plugin - - true - + 2.8.2 + + + default-deploy + deploy + + org.scala-tools @@ -198,6 +202,31 @@ + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + com.facebook.thrift:com.facebook.thrift.* + + + + attach-javadocs + package + + jar + + + UTF-8 + UTF-8 + + -source 8 + -Xdoclint:none + + + + + diff --git a/nebula-spark-connector/pom.xml b/nebula-spark-connector/pom.xml index 08644fc..8859164 100644 --- a/nebula-spark-connector/pom.xml +++ b/nebula-spark-connector/pom.xml @@ -151,6 +151,31 @@ + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + com.facebook.thrift:com.facebook.thrift.* + + + + attach-javadocs + package + + jar + + + UTF-8 + UTF-8 + + -source 8 + -Xdoclint:none + + + + + From 12036e76495730025bf2d3c41ea6fe7cbdf7641d Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 23 Mar 2021 16:53:48 +0800 Subject: [PATCH 063/213] update description for 2.0 --- nebula-exchange/README-CN.md | 4 ++-- nebula-exchange/README.md | 4 ++-- .../scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/nebula-exchange/README-CN.md b/nebula-exchange/README-CN.md index 95939c6..9140ab0 100644 --- a/nebula-exchange/README-CN.md +++ b/nebula-exchange/README-CN.md @@ -23,7 +23,7 @@ Exchange 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Nebula Graph v1. 特性 & 注意事项: -*1. Nebula Graph 2.0 暂时只支持 String 类型的 VID,请勿配置点 ID 或者边的 src_id、dst_id 的 policy。* +*1. Nebula Graph 2.0 支持 String 类型和 Integer 类型的点 id 。* *2. Exchange 2.0 新增 null、Date、DateTime、Time 类型数据的导入( DateTime 是 UTC 时区,非 Local time)。* @@ -35,7 +35,7 @@ Exchange 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Nebula Graph v1. *6. Exchange 2.0 的导入命令:* ``` -$SPARK_HOME/bin/submit --class com.vesoft.nebula.exchange.Exchange --master local nebula-exchange-2.0.0.jar -c /path/to/application.conf +$SPARK_HOME/bin/spark-submit --class com.vesoft.nebula.exchange.Exchange --master local nebula-exchange-2.0.0.jar -c /path/to/application.conf ``` ## 贡献 diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index c25113d..7554a71 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -21,7 +21,7 @@ Exchange 2.0 only supports Nebula Graph 2.x. If you want to import data for Nebu Import command: ``` -$SPARK_HOME/bin/submit --class com.vesoft.nebula.exchange.Exchange --master local nebula-exchange-2.0.0.jar -c /path/to/application.conf +$SPARK_HOME/bin/spark-submit --class com.vesoft.nebula.exchange.Exchange --master local nebula-exchange-2.0.0.jar -c /path/to/application.conf ``` For more details about Exchange, please refer to [Exchange 1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools/exchange) . @@ -29,7 +29,7 @@ For more details about Exchange, please refer to [Exchange 1.0](https://github.c ## New Features -1. Supports importing vertex data with String type IDs. +1. Supports importing vertex data with String and Integer type IDs. 2. Supports importing data of the Null, Date, DateTime, and Time types(DateTime uses UTC, not local time). 3. Supports importing data from other Hive sources besides Hive on Spark. 4. Supports recording and retrying the INSERT statement after failures during data import. diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala index 36f18dc..8470f37 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala @@ -8,7 +8,6 @@ package com.vesoft.nebula.exchange.config /** * SinkCategory is used to expression the writer's type. - * SST is not supported yet. */ object SinkCategory extends Enumeration { type Type = Value From ec5c28a33ef4b67f30dff8fb69fa86ffb28f2136 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 23 Mar 2021 17:23:03 +0800 Subject: [PATCH 064/213] update description for 2.0 --- nebula-exchange/README-CN.md | 4 +-- nebula-exchange/README.md | 4 +-- nebula-exchange/pom.xml | 35 +++++++++++++++++-- .../nebula/exchange/config/SinkConfigs.scala | 1 - nebula-spark-connector/pom.xml | 25 +++++++++++++ 5 files changed, 61 insertions(+), 8 deletions(-) diff --git a/nebula-exchange/README-CN.md b/nebula-exchange/README-CN.md index 95939c6..9140ab0 100644 --- a/nebula-exchange/README-CN.md +++ b/nebula-exchange/README-CN.md @@ -23,7 +23,7 @@ Exchange 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Nebula Graph v1. 特性 & 注意事项: -*1. Nebula Graph 2.0 暂时只支持 String 类型的 VID,请勿配置点 ID 或者边的 src_id、dst_id 的 policy。* +*1. Nebula Graph 2.0 支持 String 类型和 Integer 类型的点 id 。* *2. Exchange 2.0 新增 null、Date、DateTime、Time 类型数据的导入( DateTime 是 UTC 时区,非 Local time)。* @@ -35,7 +35,7 @@ Exchange 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Nebula Graph v1. *6. Exchange 2.0 的导入命令:* ``` -$SPARK_HOME/bin/submit --class com.vesoft.nebula.exchange.Exchange --master local nebula-exchange-2.0.0.jar -c /path/to/application.conf +$SPARK_HOME/bin/spark-submit --class com.vesoft.nebula.exchange.Exchange --master local nebula-exchange-2.0.0.jar -c /path/to/application.conf ``` ## 贡献 diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index c25113d..7554a71 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -21,7 +21,7 @@ Exchange 2.0 only supports Nebula Graph 2.x. If you want to import data for Nebu Import command: ``` -$SPARK_HOME/bin/submit --class com.vesoft.nebula.exchange.Exchange --master local nebula-exchange-2.0.0.jar -c /path/to/application.conf +$SPARK_HOME/bin/spark-submit --class com.vesoft.nebula.exchange.Exchange --master local nebula-exchange-2.0.0.jar -c /path/to/application.conf ``` For more details about Exchange, please refer to [Exchange 1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools/exchange) . @@ -29,7 +29,7 @@ For more details about Exchange, please refer to [Exchange 1.0](https://github.c ## New Features -1. Supports importing vertex data with String type IDs. +1. Supports importing vertex data with String and Integer type IDs. 2. Supports importing data of the Null, Date, DateTime, and Time types(DateTime uses UTC, not local time). 3. Supports importing data from other Hive sources besides Hive on Spark. 4. Supports recording and retrying the INSERT statement after failures during data import. diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml index 93a02d7..e1b258f 100644 --- a/nebula-exchange/pom.xml +++ b/nebula-exchange/pom.xml @@ -46,9 +46,13 @@ org.apache.maven.plugins maven-deploy-plugin - - true - + 2.8.2 + + + default-deploy + deploy + + org.scala-tools @@ -198,6 +202,31 @@ + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + com.facebook.thrift:com.facebook.thrift.* + + + + attach-javadocs + package + + jar + + + UTF-8 + UTF-8 + + -source 8 + -Xdoclint:none + + + + + diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala index 36f18dc..8470f37 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SinkConfigs.scala @@ -8,7 +8,6 @@ package com.vesoft.nebula.exchange.config /** * SinkCategory is used to expression the writer's type. - * SST is not supported yet. */ object SinkCategory extends Enumeration { type Type = Value diff --git a/nebula-spark-connector/pom.xml b/nebula-spark-connector/pom.xml index 465129b..9ff5a87 100644 --- a/nebula-spark-connector/pom.xml +++ b/nebula-spark-connector/pom.xml @@ -151,6 +151,31 @@ + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + com.facebook.thrift:com.facebook.thrift.* + + + + attach-javadocs + package + + jar + + + UTF-8 + UTF-8 + + -source 8 + -Xdoclint:none + + + + + From b95daf187d27cd847620dca15eccbe3cd6a19b8d Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 26 Mar 2021 11:33:45 +0800 Subject: [PATCH 065/213] add more way to get exchange jar --- nebula-exchange/README-CN.md | 8 +++++--- nebula-exchange/README.md | 10 ++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/nebula-exchange/README-CN.md b/nebula-exchange/README-CN.md index 9140ab0..810ebfa 100644 --- a/nebula-exchange/README-CN.md +++ b/nebula-exchange/README-CN.md @@ -5,18 +5,20 @@ Nebula Exchange 2.0(简称为 Exchange 2.0)是一款 Apache Spark™ 应 Exchange 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Nebula Graph v1.x,请使用 [Nebula Exchange v1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools/exchange) 。 -## 如何编译 +## 如何获取 1. 编译打包 Exchange 2.0。 ```bash - $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git + $ git clone -b v2.0.0 https://github.com/vesoft-inc/nebula-spark-utils.git $ cd nebula-spark-utils/nebula-exchange $ mvn clean package -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true ``` 编译打包完成后,可以在 nebula-spark-utils/nebula-exchange/target/ 目录下看到 nebula-exchange-2.0.0.jar 文件。 - +2. 在 Maven 远程仓库下载 + + https://repo1.maven.org/maven2/com/vesoft/nebula-exchange/2.0.0/ ## 使用说明 关于 Exchange 2.0 的详细使用说明,请参考 Exchange 1.0 的使用文档[《Nebula Exchange 用户手册》](https://docs.nebula-graph.com.cn/nebula-exchange/about-exchange/ex-ug-what-is-exchange/ "点击前往 Nebula Graph 网站")。 diff --git a/nebula-exchange/README.md b/nebula-exchange/README.md index 7554a71..9cd9dd0 100644 --- a/nebula-exchange/README.md +++ b/nebula-exchange/README.md @@ -3,20 +3,22 @@ Nebula Exchange (Exchange for short) is an Apache Spark application. It is used to migrate cluster data in bulk from Spark to Nebula Graph in a distributed environment. It supports migration of batch data and streaming data in various formats. -Exchange 2.0 only supports Nebula Graph 2.x. If you want to import data for Nebula Graph v1.x,please use [Nebula Exchange v1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools/exchange). +Exchange 2.0 only supports Nebula Graph 2.0 . If you want to import data for Nebula Graph v1.x,please use [Nebula Exchange v1.0](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools/exchange). -## How to Compile +## How to get 1. Package Exchange 2.0。 ```bash - $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git + $ git clone -b v2.0.0 https://github.com/vesoft-inc/nebula-spark-utils.git $ cd nebula-spark-utils/nebula-exchange $ mvn clean package -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true ``` After the packaging, you can see the newly generated nebula-exchange-2.0.0.jar under the nebula-spark-utils/nebula-exchange/target/ directory. - +2. Download from Maven repository + + https://repo1.maven.org/maven2/com/vesoft/nebula-exchange/2.0.0/ ## How to use Import command: From a2975ca2f7d952f033de2f9b5c0d711e6f444a29 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 30 Mar 2021 12:05:59 +0800 Subject: [PATCH 066/213] exit when finish the import task --- .../src/main/scala/com/vesoft/nebula/exchange/Exchange.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index 76c221f..6ea37bd 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -198,6 +198,7 @@ object Exchange { LOG.info(s"batchFailure.reimport: ${batchFailure.value}") } spark.close() + sys.exit() } /** From 298e9ca887aed0f265452be9f8e573de27aa28e1 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 30 Mar 2021 12:07:17 +0800 Subject: [PATCH 067/213] exit when finish the import task --- .../src/main/scala/com/vesoft/nebula/exchange/Exchange.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index 6ea37bd..f41ca9e 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -198,7 +198,7 @@ object Exchange { LOG.info(s"batchFailure.reimport: ${batchFailure.value}") } spark.close() - sys.exit() + sys.exit(0) } /** From 6351a66a3322b7f2c9baebfa0f95abefb7aae363 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 30 Mar 2021 19:28:08 +0800 Subject: [PATCH 068/213] correct hive's warehouse config & add log for null vid --- nebula-exchange/src/main/resources/application.conf | 2 +- .../main/scala/com/vesoft/nebula/exchange/Exchange.scala | 2 +- .../scala/com/vesoft/nebula/exchange/config/Configs.scala | 8 ++++---- .../vesoft/nebula/exchange/processor/EdgeProcessor.scala | 4 ++++ .../nebula/exchange/processor/VerticesProcessor.scala | 2 ++ 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/nebula-exchange/src/main/resources/application.conf b/nebula-exchange/src/main/resources/application.conf index 1fdbdd4..eaefe22 100644 --- a/nebula-exchange/src/main/resources/application.conf +++ b/nebula-exchange/src/main/resources/application.conf @@ -22,7 +22,7 @@ # if the hive is hive-on-spark with derby mode, you can ignore this hive configure # get the config values from file $HIVE_HOME/conf/hive-site.xml or hive-default.xml hive: { - waredir: "hdfs://NAMENODE_IP:9000/apps/svr/hive-xxx/warehouse/" + warehouse: "hdfs://NAMENODE_IP:9000/apps/svr/hive-xxx/warehouse/" connectionURL: "jdbc:mysql://your_ip:3306/hive_spark?characterEncoding=UTF-8" connectionDriverName: "com.mysql.jdbc.Driver" connectionUserName: "user" diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index f41ca9e..2d4f6cc 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -87,7 +87,7 @@ object Exchange { LOG.info("you don't config hive source, so using hive tied with spark.") } else { val hiveConfig = configs.hiveConfigEntry.get - sparkConf.set("spark.sql.warehouse.dir", hiveConfig.waredir) + sparkConf.set("spark.sql.warehouse.dir", hiveConfig.warehouse) sparkConf .set("javax.jdo.option.ConnectionURL", hiveConfig.connectionURL) .set("javax.jdo.option.ConnectionDriverName", hiveConfig.connectionDriverName) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala index 6861945..355efe8 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala @@ -154,14 +154,14 @@ case class SparkConfigEntry(map: Map[String, String]) { } } -case class HiveConfigEntry(waredir: String, +case class HiveConfigEntry(warehouse: String, connectionURL: String, connectionDriverName: String, connectionUserName: String, connectionPassWord: String) { override def toString: String = s"HiveConfigEntry:{" + - s"waredir=$waredir, " + + s"warehouse=$warehouse, " + s"connectionURL=$connectionURL, " + s"connectionDriverName=$connectionDriverName, " + s"connectionUserName=$connectionUserName, " + @@ -254,12 +254,12 @@ object Configs { var hiveEntryOpt: Option[HiveConfigEntry] = None if (config.hasPath("hive")) { - val waredir = config.getString("hive.waredir") + val warehouse = config.getString("hive.warehouse") val connectionURL = config.getString("hive.connectionURL") val connectionDriverName = config.getString("hive.connectionDriverName") val connectionUserName = config.getString("hive.connectionUserName") val connectionPassword = config.getString("hive.connectionPassword") - val hiveEntry = HiveConfigEntry(waredir, + val hiveEntry = HiveConfigEntry(warehouse, connectionURL, connectionDriverName, connectionUserName, diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index 565d334..dde85c0 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -239,6 +239,8 @@ class EdgeProcessor(data: DataFrame, .map { row => var sourceField = if (!edgeConfig.isGeo) { val sourceIndex = row.schema.fieldIndex(edgeConfig.sourceField) + assert(sourceIndex >= 0 && row.get(sourceIndex) != null, + s"source vertexId must exist and cannot be null, your row data is $row") row.get(sourceIndex).toString } else { val lat = row.getDouble(row.schema.fieldIndex(edgeConfig.latitude.get)) @@ -260,6 +262,8 @@ class EdgeProcessor(data: DataFrame, } val targetIndex = row.schema.fieldIndex(edgeConfig.targetField) + assert(targetIndex >= 0 && row.get(targetIndex) != null, + s"target vertexId must exist and cannot be null, your row data is $row") var targetField = row.get(targetIndex).toString if (edgeConfig.targetPolicy.isEmpty) { // process string type vid diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index fb56182..97ebab8 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -211,6 +211,8 @@ class VerticesProcessor(data: DataFrame, .map { row => val vertexID = { val index = row.schema.fieldIndex(tagConfig.vertexField) + assert(index >= 0 && row.get(index) != null, + s"vertexId must exist and cannot be null, your row data is $row") val value = row.get(index).toString if (tagConfig.vertexPolicy.isEmpty) { // process string type vid From a07dfca9cb05f7b5b46d6026d65049788002fe67 Mon Sep 17 00:00:00 2001 From: cooper-lzy <78672629+cooper-lzy@users.noreply.github.com> Date: Fri, 9 Apr 2021 15:23:35 +0800 Subject: [PATCH 069/213] change repo --- .../about-exchange/ex-ug-limitations.md | 29 + .../doc-2.0/about-exchange/ex-ug-terms.md | 9 + .../about-exchange/ex-ug-what-is-exchange.md | 59 +++ nebula-exchange/doc-2.0/ex-ug-FAQ.md | 95 ++++ nebula-exchange/doc-2.0/ex-ug-compile.md | 85 +++ nebula-exchange/doc-2.0/ex-ug-toc.md | 26 + nebula-exchange/doc-2.0/figs/ex-ug-001.png | Bin 0 -> 151025 bytes nebula-exchange/doc-2.0/figs/ex-ug-002.png | Bin 0 -> 60193 bytes .../ex-ug-para-import-command.md | 19 + .../ex-ug-paras-nebulagraph.md | 16 + .../parameter-reference/ex-ug-paras-neo4j.md | 36 ++ .../parameter-reference/ex-ug-paras-spark.md | 10 + .../use-exchange/ex-ug-import-from-csv.md | 331 ++++++++++++ .../use-exchange/ex-ug-import-from-neo4j.md | 497 ++++++++++++++++++ .../doc-2.0/use-exchange/ex-ug-import-hive.md | 351 +++++++++++++ .../doc-2.0/use-exchange/ex-ug-import-json.md | 288 ++++++++++ .../doc-2.0/use-exchange/ex-ug-import-sst.md | 98 ++++ .../use-exchange/ex-ug-import-steps.md | 42 ++ 18 files changed, 1991 insertions(+) create mode 100644 nebula-exchange/doc-2.0/about-exchange/ex-ug-limitations.md create mode 100644 nebula-exchange/doc-2.0/about-exchange/ex-ug-terms.md create mode 100644 nebula-exchange/doc-2.0/about-exchange/ex-ug-what-is-exchange.md create mode 100644 nebula-exchange/doc-2.0/ex-ug-FAQ.md create mode 100644 nebula-exchange/doc-2.0/ex-ug-compile.md create mode 100644 nebula-exchange/doc-2.0/ex-ug-toc.md create mode 100644 nebula-exchange/doc-2.0/figs/ex-ug-001.png create mode 100644 nebula-exchange/doc-2.0/figs/ex-ug-002.png create mode 100644 nebula-exchange/doc-2.0/parameter-reference/ex-ug-para-import-command.md create mode 100644 nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-nebulagraph.md create mode 100644 nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-neo4j.md create mode 100644 nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-spark.md create mode 100644 nebula-exchange/doc-2.0/use-exchange/ex-ug-import-from-csv.md create mode 100644 nebula-exchange/doc-2.0/use-exchange/ex-ug-import-from-neo4j.md create mode 100644 nebula-exchange/doc-2.0/use-exchange/ex-ug-import-hive.md create mode 100644 nebula-exchange/doc-2.0/use-exchange/ex-ug-import-json.md create mode 100644 nebula-exchange/doc-2.0/use-exchange/ex-ug-import-sst.md create mode 100644 nebula-exchange/doc-2.0/use-exchange/ex-ug-import-steps.md diff --git a/nebula-exchange/doc-2.0/about-exchange/ex-ug-limitations.md b/nebula-exchange/doc-2.0/about-exchange/ex-ug-limitations.md new file mode 100644 index 0000000..c8efd8c --- /dev/null +++ b/nebula-exchange/doc-2.0/about-exchange/ex-ug-limitations.md @@ -0,0 +1,29 @@ +# 使用限制 + +本文描述 Exchange v1.x 的一些使用限制。 + +## Nebula Graph 版本 + +Exchange v1.x 仅支持 Nebula Graph v1.x。如果您正在使用 Nebula Graph v2.x,请使用 [Nebula Exchange v2.x](https://github.com/vesoft-inc/nebula-spark-utils "点击前往 GitHub")。 + +## 使用环境 + +Exchange v1.x 支持以下操作系统: + +- CentOS 7 +- macOS + +> **说明**:仅 Linux 系统支持导入 SST 文件。 + +## 软件依赖 + +为保证 Exchange v1.x 正常工作,确认您的机器上已经安装以下软件: + +- Apache Spark:2.3.0 及以上版本 +- Java:1.8 +- Scala:2.10.7、2.11.12、2.12.10 + +在以下使用场景,还需要部署 Hadoop Distributed File System (HDFS): + +- 以客户端形式迁移 HDFS 上的数据 +- 以 SST 文件格式迁移数据 diff --git a/nebula-exchange/doc-2.0/about-exchange/ex-ug-terms.md b/nebula-exchange/doc-2.0/about-exchange/ex-ug-terms.md new file mode 100644 index 0000000..3a5746b --- /dev/null +++ b/nebula-exchange/doc-2.0/about-exchange/ex-ug-terms.md @@ -0,0 +1,9 @@ +# 名词解释 + +本文描述了您在使用 Exchange 时可能需要了解的名词解释。 + +- Nebula Exchange:在本手册中简称为 Exchange 或 Exchange v1.x,一款基于 Apache Spark™ 的 Spark 应用,用于批量数据迁移。它支持将多种不同来源和格式的数据文件转换为 Nebula Graph 能识别的点和边数据,再并发导入 Nebula Graph。 + +- Aparch Spark™:是专为大规模数据处理而设计的快速通用的计算引擎,是 Apache 软件基金会的一个开源项目。 + +- Driver Program:在本手册中简称为 Driver,是运行应用的 main 函数并且新建 SparkContext 实例的程序。 diff --git a/nebula-exchange/doc-2.0/about-exchange/ex-ug-what-is-exchange.md b/nebula-exchange/doc-2.0/about-exchange/ex-ug-what-is-exchange.md new file mode 100644 index 0000000..5e4366a --- /dev/null +++ b/nebula-exchange/doc-2.0/about-exchange/ex-ug-what-is-exchange.md @@ -0,0 +1,59 @@ +# 什么是 Nebula Exchange + +[Nebula Exchange](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools)(简称为 Exchange)是一款 Apache Spark™ 应用,用于在分布式环境中将集群中的数据批量迁移到 Nebula Graph 中,能支持多种不同格式的批式数据和流式数据的迁移。 + +Exchange 由 Reader、Processor 和 Writer 三部分组成。Reader 读取不同来源的数据返回 DataFrame 后,Processor 遍历 DataFrame 的每一行,根据配置文件中 `fields` 的映射关系,按列名获取对应的值。在遍历指定批处理的行数后,Writer 会将获取的数据一次性写入到 Nebula Graph 中。下图描述了 Exchange 完成数据转换和迁移的过程。 + +![Nebula Graph® Exchange 由 Reader、Pocessor、Writer 组成,可以完成多种不同格式和来源的数据向 Nebula Graph 的迁移](../figs/ex-ug-001.png "Nebula Graph® Exchange 转数据转换和迁移的过程") + +## 适用场景 + +Exchange 可被用于以下场景: + +- 您想将来自 Kafka、Pulsar 平台的流式数据,如日志文件、网购数据、游戏内玩家活动、社交网站信息、金融交易大厅或地理空间服务,以及来自数据中心内所连接设备或仪器的遥测数据等转化为属性图的点或边数据,并导入 Nebula Graph 数据库。 + +- 您想从关系型数据库(如 MySQL)或者分布式文件系统(如 HDFS)中读取批式数据,如某个时间段内的数据,将它们转化为属性图的点或边数据,并导入 Nebula Graph 数据库。 + +- 您想将大批量数据生成 Nebula Graph 能识别的 SST 文件,再导入 Nebula Graph 数据库。 + +## 产品优点 + +Exchange 具有以下优点: + +- 适应性强:支持将多种不同格式或不同来源的数据导入 Nebula Graph 数据库,便于您迁移数据。 + +- 支持导入 SST:支持将不同来源的数据转换为 SST 文件,用于数据导入。 + > **说明**:仅 Linux 系统支持导入 SST 文件。 + +- 支持断点续传:导入数据时支持断点续传,有助于您节省时间,提高数据导入效率。 + > **说明**:目前仅迁移 Neo4j 数据时支持断点续传。 + +- 异步操作:会在源数据中生成一条插入语句,发送给查询服务,最后再执行 Nebula Graph 的插入操作。 + +- 灵活性强:支持同时导入多个标签和边类型,不同标签和边类型可以是不同的数据来源或格式。 + +- 统计功能:使用 Apache Spark™ 中的累加器统计插入操作的成功和失败次数。 + +- 易于使用,对用户友好:采用 HOCON(Human-Optimized Config Object Notation)配置文件格式,具有面向对象风格,便于理解和操作。 + +## 数据格式和来源 + +Exchange v1.x 支持将以下格式或来源的数据转换为 Nebula Graph v1.x 能识别的点和边数据: + +- 存储在 HDFS 的数据,包括: + - Apache Parquet + - Apache ORC + - JSON + - CSV + +- Apache HBase™ + +- 数据仓库:HIVE + +- 图数据库:Neo4j 2.4.5-M1。仅 Neo4j 支持断点续传 + +- 关系型数据库:MySQL + +- 流处理软件平台:Apache Kafka® + +- 发布/订阅消息系统:Apache Pulsar 2.4.5 diff --git a/nebula-exchange/doc-2.0/ex-ug-FAQ.md b/nebula-exchange/doc-2.0/ex-ug-FAQ.md new file mode 100644 index 0000000..c7ef03a --- /dev/null +++ b/nebula-exchange/doc-2.0/ex-ug-FAQ.md @@ -0,0 +1,95 @@ +# 常见问题FAQ + +## 编译问题 + +### 部分非central仓库的包下载失败,报错`Could not resolve dependencies for project xxx` + +请检查Maven安装目录下`libexec/conf/settings.xml`文件的`mirror`部分: + +```text + + alimaven + central + aliyun maven + http://maven.aliyun.com/nexus/content/repositories/central/ + +``` + +检查`mirrorOf`的值是否配置为`*`,如果为`*`,请修改为`central`或`*,!SparkPackagesRepo,!bintray-streamnative-maven`。 + +**原因**:Exchange的`pom.xml`中有两个依赖包不在Maven的central仓库中,`pom.xml`配置了这两个依赖所在的仓库地址。如果您的maven中配置的镜像地址对应的`mirrorOf`值为`*`,那么所有依赖都会在central仓库下载,导致下载失败。 + +## 执行问题 + +### 报错`method name xxx not found` + +一般是端口配置错误,需检查Meta服务、Graph服务、Storage服务的端口配置。 + +### 报NoSuchMethod、MethodNotFound错误(`Exception in thread "main" java.lang.NoSuchMethodError`等) + +绝大多数是因为jar包冲突和版本冲突导致的报错,请检查报错服务的版本,与Exchange中使用的版本进行对比,检查是否一致,尤其是Spark版本、Scala版本、Hive版本。 + +### Exchange导入Hive数据时报错`Exception in thread "main" org.apache.spark.sql.AnalysisException: Table or view not found` + +检查table和database是否正确,在spark-sql中执行用户配置的exec语句,验证exec语句的正确性。 + +### 运行时报错`com.facebook.thrift.protocol.TProtocolException: Expected protocol id xxx` + +请检查Nebula Graph服务端口配置是否正确。 + +- 如果是源码、RPM或DEB安装,请配置各个服务的配置文件中`--port`对应的端口号。 + +- 如果是docker安装,请配置docker映射出来的端口号,查看方式如下: + + 在`nebula-docker-compose`目录下执行`docker-compose ps`,例如: + + ```bash + $ docker-compose ps + Name Command State Ports + --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + nebula-docker-compose_graphd_1 /usr/local/nebula/bin/nebu ... Up (healthy) 0.0.0.0:33205->19669/tcp, 0.0.0.0:33204->19670/tcp, 0.0.0.0:9669->9669/tcp + nebula-docker-compose_metad0_1 ./bin/nebula-metad --flagf ... Up (healthy) 0.0.0.0:33165->19559/tcp, 0.0.0.0:33162->19560/tcp, 0.0.0.0:33167->9559/tcp, 9560/tcp + nebula-docker-compose_metad1_1 ./bin/nebula-metad --flagf ... Up (healthy) 0.0.0.0:33166->19559/tcp, 0.0.0.0:33163->19560/tcp, 0.0.0.0:33168->9559/tcp, 9560/tcp + nebula-docker-compose_metad2_1 ./bin/nebula-metad --flagf ... Up (healthy) 0.0.0.0:33161->19559/tcp, 0.0.0.0:33160->19560/tcp, 0.0.0.0:33164->9559/tcp, 9560/tcp + nebula-docker-compose_storaged0_1 ./bin/nebula-storaged --fl ... Up (healthy) 0.0.0.0:33180->19779/tcp, 0.0.0.0:33178->19780/tcp, 9777/tcp, 9778/tcp, 0.0.0.0:33183->9779/tcp, 9780/tcp + nebula-docker-compose_storaged1_1 ./bin/nebula-storaged --fl ... Up (healthy) 0.0.0.0:33175->19779/tcp, 0.0.0.0:33172->19780/tcp, 9777/tcp, 9778/tcp, 0.0.0.0:33177->9779/tcp, 9780/tcp + nebula-docker-compose_storaged2_1 ./bin/nebula-storaged --fl ... Up (healthy) 0.0.0.0:33184->19779/tcp, 0.0.0.0:33181->19780/tcp, 9777/tcp, 9778/tcp, 0.0.0.0:33185->9779/tcp, 9780/tcp + ``` + + 查看`Ports`列,查找docker映射的端口号,例如: + + - Graph服务可用的端口号是9669。 + + - Meta服务可用的端口号有33167、33168、33164。 + + - Storage服务可用的端口号有33183、33177、33185。 + +## 配置问题 + +### 哪些配置项影响导入性能? + +- batch:每次发送给Nebula Graph服务的nGQL语句中包含的数据条数。 + +- partition:Spark数据的分区数,表示数据导入的并发数。 + +- nebula.rate:向Nebula Graph发送请求前先去令牌桶获取令牌。 + + - limit:表示令牌桶的大小。 + + - timeout:表示获取令牌的超时时间。 + +根据机器性能可适当调整这四项参数的值。如果在导入过程中,Storage服务的leader变更,可以适当调小这四项参数的值,降低导入速度。 + +## 其他问题 + +### Exchange支持哪些版本的Nebula Graph? + +请参见Exchange的[使用限制](ex-ug-limitations.md)。 + +### Exchange与Spark Writer有什么关系? + +Exchange是在Spark Writer基础上开发的Spark应用程序,二者均适用于在分布式环境中将集群的数据批量迁移到Nebula Graph中,但是后期的维护工作将集中在 Exchange上。与Spark Writer相比,Exchange有以下改进: + +- 支持更丰富的数据源,如MySQL、Neo4j、Hive、HBase、Kafka、Pulsar等。 + +- 修复了Spark Writer的部分问题。例如Spark读取HDFS里的数据时,默认读取到的源数据均为String类型,可能与Nebula Graph定义的Schema不同,所以Exchange增加了数据类型的自动匹配和类型转换,当Nebula Graph定义的Schema中数据类型为非String类型(如double)时,Exchange会将String类型的源数据转换为对应的类型(如double)。 \ No newline at end of file diff --git a/nebula-exchange/doc-2.0/ex-ug-compile.md b/nebula-exchange/doc-2.0/ex-ug-compile.md new file mode 100644 index 0000000..05b4872 --- /dev/null +++ b/nebula-exchange/doc-2.0/ex-ug-compile.md @@ -0,0 +1,85 @@ +# 编译Exchange + +本文介绍如何编译Nebula Exchange。您也可以直接[下载](https://repo1.maven.org/maven2/com/vesoft/nebula-exchange/2.0.0/)编译完成的`.jar`文件。 + +## 前提条件 + +安装[Maven](https://maven.apache.org/download.cgi)。 + +## 编译流程 + +1. 克隆仓库`nebula-java`。 + + ```bash + git clone -b v2.0.0-ga https://github.com/vesoft-inc/nebula-java.git + ``` + +2. 切换到目录`nebula-java`。 + + ```bash + cd nebula-java + ``` + +3. 安装Nebula Java Client 2.0.0。 + + ```bash + mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true + ``` + + >**说明**:安装后在本地Maven仓库会生成`.jar`文件,例如`com/vesoft/client/2.0.0/client-2.0.0.jar`。 + +4. 返回根目录克隆仓库`nebula-spark-utils`。 + + ```bash + cd ~ && git clone -b v2.0.0 https://github.com/vesoft-inc/nebula-spark-utils.git + ``` + +5. 切换到目录`nebula-exchange`。 + + ```bash + cd nebula-spark-utils/nebula-exchange + ``` + +6. 打包Nebula Exchange 2.0.0。 + + ```bash + mvn clean package -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true + ``` + + >**说明**:如果报错`Could not resolve dependencies for project xxx`,请修改Maven安装目录下`libexec/conf/settings.xml`文件的`mirror`部分: + > + >```text + > + >alimaven + >central + >aliyun maven + >http://maven.aliyun.com/nexus/content/repositories/central/ + > + >``` + +编译成功后,您可以在当前目录里查看到类似如下目录结构。 + +```text +. +├── README-CN.md +├── README.md +├── pom.xml +├── src +│   ├── main +│   └── test +└── target + ├── classes + ├── classes.timestamp + ├── maven-archiver + ├── nebula-exchange-2.x.y-javadoc.jar + ├── nebula-exchange-2.x.y-sources.jar + ├── nebula-exchange-2.x.y.jar + ├── original-nebula-exchange-2.x.y.jar + └── site +``` + +在`target`目录下,您可以找到`exchange-2.x.y.jar`文件。 + +> **说明**:`.jar`文件版本号会因Nebula Java Client的发布版本而变化。您可以在[Releases页面](https://github.com/vesoft-inc/nebula-java/releases)查看最新版本。 + +迁移数据时,您可以参考配置文件`target/classes/application.conf`、`target/classes/server_application.conf`和`target/classes/stream_application.conf`。 diff --git a/nebula-exchange/doc-2.0/ex-ug-toc.md b/nebula-exchange/doc-2.0/ex-ug-toc.md new file mode 100644 index 0000000..a1260a6 --- /dev/null +++ b/nebula-exchange/doc-2.0/ex-ug-toc.md @@ -0,0 +1,26 @@ +# Nebula Exchange 用户手册 + +- 认识 Nebula Exchange + - [什么是 Nebula Exchange](about-exchange/ex-ug-what-is-exchange.md) + - [使用限制](about-exchange/ex-ug-limitations.md) + - [名词解释](about-exchange/ex-ug-terms.md) + - [常见问题](about-exchange/ex-ug-faq.md) +- [编译 Exchange](ex-ug-compile.md) +- 操作指南 + - [导入数据步骤](use-exchange/ex-ug-import-steps.md) + - 操作示例 + - [导入 Neo4j 数据](use-exchange/ex-ug-import-from-neo4j.md) + - [导入 CSV 文件数据](use-exchange/ex-ug-import-from-csv.md) + - [导入 JSON 文件数据](use-exchange/ex-ug-import-json.md) + - 导入 HBase 数据[DOC_TO_DO] + - 导入 HIVE 数据[DOC_TO_DO] + - 导入 Kafka 数据[DOC_TO_DO] + - 导入 MySQL 数据[DOC_TO_DO] + - [导入 SST 文件](use-exchange/ex-ug-import-sst.md) +- 参数说明 + - [Spark 参数](parameter-reference/ex-ug-paras-spark.md) + - [Nebula Graph 参数](parameter-reference/ex-ug-paras-nebulagraph.md) + - [导入命令参数](parameter-reference/ex-ug-para-import-command.md) +- 错误信息[DOC_TO_DO] + +\* 本页面所列 [DOC_TO_DO] 仅表示文档尚未完成。Exchange 已经具备文档所列所有功能。 diff --git a/nebula-exchange/doc-2.0/figs/ex-ug-001.png b/nebula-exchange/doc-2.0/figs/ex-ug-001.png new file mode 100644 index 0000000000000000000000000000000000000000..0e57d6f37d403a85e59ae6b842c289fbaa8ff791 GIT binary patch literal 151025 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≫nKt| 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

                                          j2=IkPm&a{Wb~$2{BQzg0g! zSYm$t>IxeH8H0aZ~Fpwz&Tt zB7KWt(rXSSZAr|^l4Xwa!HLi&_I?~WXg1HtTqrik%p$qt@geZd1_$FpnNP58gp~N$ z1|Sr{_x}7;Gt&b+m%ffdZRV3kTC+M4H;ir*rma%CmH?cWE%~kMfq|+eywiDeu5 z!xopRNWblY_B`5kCIlH@Mv*`oN{MIJ_T4||YXoKJ2DZCh{-^U3(5zr2svXlZHx#BDGnrtzq1;WDLPdK`27#ZOjv zjXLakBtGWI`1N;t_83_j!uHV;oEZou9a^@?^@o?(CsY#E6J$o3_Im>MXZ-MP59Nv# z4%C109e%2k-6gU#)Cyehcck83CJhuBw=Eve#v=<@Xx)Ku{KUk99+A-j659x_Qc}Us z&D(s(%Jo<1uV&lQD!Wn>VbjyoNx})#r>jO809Jc6EJW^yLL}j)gev(g z!2vXeW)!I0-rhzNN)r%RO{!V^p_s1oc=DC&zLwV8rXTKhxxxBpoDZ>nco^$J%-hZm zCPUtWUqM^JD?U4yR5~yrmSJtl5jRnI<+HIW9q*Eu8T11nlP}^{x`fOFOcDWeP0RJzURtY^h#(JMpe$rpx60 z;k-70V8E26sHCK|lNb?U&#*J{=>LRRtdcLadvKt|fYj{$Zm%NU-i)T&{O#{ZA9rXs z>|%_zqo}lCY2upyJzT=Chn^O}D%heY*sU|6t$2|(3Ehl5W`*bys#aYLw48ZK+mQB^sbm4+*1#ES3}!l#DAA^xSP;*9kLXpXTM& zPR_e4YCa*Z&^sQ1#MIt)0?0DpG3lAU^48j!uwA$A-rW|5)7trD!sBk>RcMNbPV*Wj z%tZ3^>MnL+d@C(L*Dh-%Cs<7VO6^Pha)5ZzyP7kS9c!>>TN6304L*KMWIYTi+H~!p ztGB@VHk@5sIpLSG1C7y0Uml?X`8}m4Lfo(WG(24dT-}fdQE45surF=DdrxA0kl@pH z=#`j-6F*IZ`W%PH1|nF)%by{?Z?R8yDL5YZnqo^K(r@g2f~=(R;#*_7%m#Pp<&kYh z%iY|-?$BCFx_1f)^$|jsl$2QAh>!U?IIuD5)Wfgfxxdx#yEfR8#QE?s2hPl~V02B3 z0%ZY>J3mpj8ks6FI=?jNyP!PTkNd6>7oPL zc`I8+lf*5q(|3vu0z3{G3Yz}f#o3DHl%oy*j550$oc2O>Wx{#WHX1-HOdI6uI88m_ zaoOgm6q!y9#s1N)trPOaAyQiAgvH)orRyo{xq6vM`p+(g5S*TFuu8o0F)R|OK{%x8 zUi$U$@**R0p~Kl8dz>DT5|UDd<2q1k;mH>0!;kqx`oy^aE~Pd}gN zhYfAfv$EOm*QmWN^YmnbEsxZ;G;;B3cAR!M6+GpAQK{ck7fslZ12>Ll%rzWZel?#i zH`;uG4iqc!`dET$!@wDD^9mquVa9-3y(0!NP3Q03lWUq+YS$GVC*Z?S=lOh`xh^+) z6E5pc>FOa-WlXylgU$aU1fKxI3g#em}=U36x#@`*69D zvD(xzc#emSZM7pcU$fOU-z24$#0RHWrbt5d6@rV&@BMn;$Fuh)BqUUI?f$$YR{He; zUrLYN4Ky@Y{gjKu4%>J@p?0{J?5Z)D)I5BCc?K+x*PV7_oeM40Z26_PSU?tstK3Tq zpG*j18MDhXgH;WjOfbLs6=s6ei29f^+IBK&}}SJLE~=)Imnaf&tVym-XE4BhSoe*eQ;2}*r z4GhtGv9!OHvF&7fr~LHdb~gCLhF=4W*vbh-`V=^4rv{G632Owy|NKe# zsm>|oOPY6!tdRUEEqFkd-`M)xh7c=nRaA~Y{0Yn{SJB1v%^jR%bI(<8b3nD;stf3T zIkd!Nv%%g9dd-4A`I(jop%RN);Zq1{psqtDhnfb=2nG91uQ7WXIcKWMs7?rV-N~dd zMc7K3?1ewrFwG-nsE1ntFPiO{@qL}d zzbPuYpM5HlY0QTrpUQp@h7U0YWR*H$n>@WA*EL?R6)~Swxz@s_OuHyc5KHdXYJtTw zXfRmou2^G|7(51jqe~Y)s4z1|!bYhiR@X32$Ejeed2__6((A#En6{+jYsjm^-?N;p zO)ind{a)>nE1f5Do3(&PIfV<#gi;eybgXy!+=h*8UA+U?sc z(_=8bnxD>Aq=>U6k*^}9;oBKPvGblJCP?fJcS#!g ze>+$QDauj@31 zVqaM+WF6k}q94MliOFlWw)=*-81j$T)$4;`=LLXPXWY3zDPanORgdwym9W^XO#8s6 zrl3FsTP}S*P8llg3o2S6BqA~!)7mp=Q;lR#gzAMu2%|Q`$&Edy5Boio=N5#7i6q(O z@uX;k6te&M2(;KK0RGmbxo-+{$euGk*Mz6}p16xjN?>-Bxl<3!1$wIyf&E%_#IOOf zYr#YKFfOmv@gTZh=U*3VdfDPPvmumnosML2b`C4pxIiu@5LrUfKhX4&C!cRuDI2O} z)m1FzY9$QxPFhu(EafUpk=hc#lq`FDsl|U!1p!6Q($R61cU)?=+F@Hmn5FK$0~Dnc z0EblZc(PiPBV)PdO2xBvhQlZ?1M#x|#c=yK{{aa4L6-pI#{v7J2^36BN@?3On@Ne8 z(t2K>c{hQa7%|N1`&tOKRAAU@0O*dIN=e9Zd-=LsQ8nWH4;PgNNdg9GYM1jF|G#JR z1n8<2OzbufG~jN;lK+8HB*DIuW(V`}W_EhtPUXl+OBdE0`iKA>(R1TsVw3}sD|qhW z=Dh$}F2Ci&i1`Ws7X*}sqTd0!Jo9?oO|mUOS0wMr$jY*kkdei8u*n{v&6;G)V>Eza z(T(pLF8yj8;MU^R-6R(N6W> z|Ifni$LV^=&9x?d5+LAez?m2UBB%VI1EO2J^le-&DRj*hRwHK15>daLf>o+f&Po@-CHq?l2~ZlrTVN&A z+Il=+H&wOPSm#(u;!YCO3-l8?UQin<-*DM{2n{t8_r7dLo?VOWrYW0{;QkN#wfr4u z?K;h}kGZg16OT)B;&e*9L3}q^kxQ)m-{{z&$acb)x1d&w6|lEqkFGP+D?ZBhUOX*a z*d3yo1_Jl|D}>v%g>x$nM-*7i#OmH`Y-)1At%pi$f8Ux_2%nu@J*)EHsK8}wZ*Mma z4e_K=!+#_KIJ)dDL(ubJ4#)Nl%7pNCiFcKzS^l|VTjN0}pFxb$)RmgEJs1tY7B8ttD#WhZX z01CtPdrEx2JdYQ())W*SNC(M?6%sORD5)m)d00hzx3=_Pc{6|F20qXKAjq=PCcpIn ze(`ocz}yJ=J~mEJP*ICsmwvfoPqyP7yjYyY=Qi$vS?i#H!{G8?o5Eu zEaBb#ePNibY@r3AQLe!6xvP5^Wsxg^zwaxJC^qj06enN>X2yF!brJ|`5+#HZaDHt- zkS({wAlaslkw%O4zE1;0WL-IdIoiUyo16P5mw&S0t`6Xr#2qwd~)j=0UrX*`Cq+G+qgI6N%XLGwl! z%k~3g35ax>-XG5fm`tXL;BY$0L%L{>yNG5N&ao7vKmv;@Hxgkxs8c*J5pnr8{Y=#F z>^Qkf%WOi*5QrU$4D88fG+T!j*>-iQSBU(3ne2=p(G(~9ry!t?dV)XixC1lS?f$~e zCdl!M5D*YVYooy~yroKQeQiHnP4*5BqoK2l5SqQXiF=~P7^ zhx)!L^Z0aEf*2E%`-az=V=|E{Ko*^Y&(`v%6;*`CxOGg>2eZ6cM*mRFc*S?lvFf}x7G1TcD3FZMnqV6Ti#FWpOO{@(?WSV?!?|a`Og3i z6bkJ3Wc?p-KZ;w(dSt$=KVwvDG-ZJ7m9D>=$b2cGO2RrtJ7}=#?ve=PpkRt~isobc z6eug?@vn~;QdOEQglcAxP~TM`w#TWe!@eQQ!l2U>s!*v>EO5|#lVXR(0p`LyoRT=J zfQkSKOl183H09r>xhkrQnbO+=94P*5K$DTvjsAi5pXPm=@4S{6I&uEE?7-vwy)?Q> zB|a!g4+5Peu3PBvb^w1hbQ@A*xlk_BkL#0av8T0I^QfC1-+k-n*UaDba+pzOz1G}# zvLz#_8MjuKG~P>*|0{xlU27xx-&9K<3(QU7>S9j@NCwFV-YfEXe`|**SgE0S(ulz} zgD|co9bvnj!}t^>ob#8l2)nVd$*g5fk0={Uo5X49Jeol7D1x0lK%%5jYk3))E7@sm zlJC1q{h#=AZP@P$bsd?5GH9F z0Sp4$th_~Q&4~RumYKO54w2N~<<&BKD>qsj!?w;_C?Qjg`HU#FUuEyNJibwCTt#f- zkVeLZb6i)Gxk3sdm4T36US4MFt@iUk8v}yO%=&v0r30LQqV!sJZ;yQ_Nhv9!fCw^9 zG8~m^?Y8+b#RBHWo8oz0BSd?NE~SW&f@W!7gD0AJeP{ER&O-x?9G8D=G+6&Xr#~yE zbqEOZz<**^uv`)RW% zvPj~2X{OOIR4!Uk?y5l{^B%zp`)m0(?CCUaN2jM_f`8%&eq3G2;rZS(Tx|8^XeSjS zi<7Bg-zvaiFP*(t3$L1eiXQ-pM}koF=I0j|GGubug=tKt@n3A8_s_^N5y}$0UXzAs zmt>dEA&gTvMY%3rqdX&}pE+5n!uGy&1k+HK z7Pi&OIlZ(P@2e67{#jkmb92x3OdPgHoa6HNY&)W0A-W3W6s5$+_uI_+qMrjh?az1GlB;*<2ZaL(rsBWAo6n^3HX!2R$P6+0txC?n zQn)J?h+<;Pi{|=Jvbm{po}(&GZhI=qhWzUGRl2H^^z40(=_z=hE`}35ykgRx=kmZi zJl^75FGx{V?+_jOMvX~Mv^zuLE}xIWKDS4k{Y=yJ zj-LbezmmN?ECE^rAs+YV3km8$$-~#T+U^gjcVayYIh4*g(s^AF3Wq^^PKO<3`)KlE zf4DZwh%=Esbp%X%as+f$&J=^tbR>>0MNdqpXHP^DN)?Yn$dw@hqafGo6U^ETYb`OrIMoLrJ^{VbxckZ{cT! zMqo?I6cKl7!v>y9J9ep4?YMnlSUy9U%gYk`9xJI#$B-)~sXjx>?_))2YMo9LsT5kB zzace-L@76 zawS!pTDh$K7i|d)6>t9fJaPHsHd7)hx>(2-o`6BXupuJHOtFy!?R;`QT@DdwnQLu%FH*V%m`Epq!UzC;%{$OX>}$Fa%QxEA%0gK7>E52`raLOTVu zfJKE7IxaCk*CH)`SXQb^j!E9b-NeC6i2TRr$`o>|8TKEScJL>2NE8ppvJN5pf5ZmM zE$VXIFQJNrKg8<3sEbIis;DN-!?Kp3)<~`*=nm)5AwMY{Km-Nvi1!WY$Yu&+cs2KH zn|zZ_l#WRAvt;BMB{chYLkj1FWc~-nk(P}D85$yphjr_u9;EOi_o>R#&L87HN+iu|C zTy@qBv9d7P8}Uf4vp~&57O2#efEE)JoSf;OpKrG9poIyT@br||{F5$4lzr@sSp9o@ zyhMaVr62>sFBrIFvO=!`5*eB2*yXwfoFdFtW{-Qsmn#iwS%-s2$~2nI+gc{WNCaWA zC8&D8=64}knETJwZ4vz=NcliH?k@Q!x|M(GTWVBeUOdzd!i&e_q!2vsdMq^ z>7qaqElINcj;p;UH~xbi#EtDnJ8GsZ+{Vh2tVPtE-11}eAv=zkT{>cdmh+SQg|r`c?m(-JqDz_D_NmFK!bqmsSoKoDoq{a_P_Tn?zGvzS+}ZHopU;|c zvM0k&zw3_$)6nG1x#RV?x>wl2?mO(ZvsP2l~maFD?S@fg% zQ$#^@`772zP0Duvq=2%$wVVmo{s0Nx%JI3yCoZ*6bU8O4i{yZnsLAm;{> zoslI)0m)hh-6EG&9E)3446x~?NHiaQB&>!iWx^&%7Oj{;>KLhx=8{IO_|5s;&v}nL zG-f!AA@DKI?HCD|##S`Uaea6-BYK#rR#${3e!D41{Qf(cr^`|_UTtzU5!DmpDSA8G zpK%H=WMIy~slw_wDA&OeUB&lU!Y~-|@c4~R@zy^o(ZvZ8E#Dw9sQChG1qlZ5AkXDg z(94R0_=#PV!cNk zo)poW3tXoPF6A8ow|)t43|U}p*4XFxa6>WHW)J@yi0XXFQn5^ZE7KOoEW}%p&`{_0 zRIL={ec%`GKVbrp?j-GyL_`qC z=*YhpZ2?L~bs0~X<+eA31CZwhhF;v1yd<{X!HbJN1dMHjxHW?s3+1m?c!1tkEd81C zdTTzFqy2nE9jUBRzFLsGerIj3J#`c(ydtHWfc<0Jl_S{BR|r)mg#22uCE>ZKbQ*_) z!eLIb>Vv8!=-Gc|0vm4Q>Qo?x>kj5kFunI5=|Kb0c4~vW^pJ_qBL`Gg!!HyaROs8? zh=R%Csubls>(#&@L^SsePp6VG70Nj}zAr)ZlaqbWBoH2mXJFMU+yfJ!w+O$((C7ww zy1UQ5;dRzT;(cBB|9IVnId&uJ;?BJ*IlIs~8AR8WzlrpAuLM*rp`BIEy+5$&Rk*ns zOp7Vq)#bH$6hN`#d2)ShxT-uJPHXXx`>MnF*JwX@ZL~X|bYWak2e84wT$2?K|Sr|{N zqZ%)sf*&=2BvDsaXGXM$tXMUr1B>h$8~siJZTiyvZloe`bGQGM{CIIPN|r<2D2t9# zE&h}W)(1jQ#*w_sYLnZWjN{HDA!BMIWT&g19jx3RvA=sFl)^?`V03P$di8{j^Kq_0 z0t~voqI0-|%gxpDP`J+k6+psKtYPu$E1_}`AllLu zdQJSr`Pzpp-&f|xJb;n#^D8&Qroc^_k^{EWqh|T!dpX0kF$+WY^LUE#)8LAFZt&dB z6Kf0 z^;XOdUseC{L6C%nAMUdmF#hHJN)Q!6ZOJaGETx-Y9HofI$Mff5PVRF*n#fs2k3gVf zq19tICCX+!Ppc5uol&1hY`EMc>R`?B5?SkbyN zTYgO1mJnz68s<+AWK>Llt#QHkl9yjZ<*dlaLFKtZ$%Ok6Lj8e7seKpmel)$}^}Nbo zmUl-(!9ok)MaFf>0Y?M}7XeqG_ydqS_P=jl`S3luoH9Wc+>&YbLMLV7I+*I}F?a3e zIMQyVWQgnijx_UhbiSfDlHP)MpPj%?@~}Dz^pY?0oq(=47^|q?nNyp9DdW(w$7t>} zYZW(#);7;(x^&Da>7sFmF_Ef}V!)FaT<0I}Wq1AJoy$6kx0J zmb16sqO{y}Uk)8L@mz1w%5;WYccW$8Rah)cG1^P9-HsPAu-_=>-`F{1h~F&eL8;Uw z8PDm4T9S>s#5jmdd2ESE;DmIJgT0CpSkbFiendOkpo4|XCdlA*7h?6{EzX~+y|?l` z!;0VRf~RiQuD_3C(qC!oOVoNwOJBi3i`gqgu@Uj*^X9m{B69cr`lDs?hnbzVQ-sWT ztnmx%ob?<)B1QZuyx!tX3ykD3ys*}2J!fle>>_uD=hf8IdrY-@-Z#EepunI#Ez^k( zyk-(S?Jw$nK$VkR^!#EKV&rvW#&Ae$6P;Uq7y#yTPZmfG8au~OO^pT5+((#WHL`zw z*YMhcZpEAUqh)RCWwio!Qx2Wo^f2MHlOCkV>>g%x|BJk=^^wi%v)p}%mHScKeCEq( zh1t4u{=^{=@o%{5-rju#+wPu{rMYYWxG4F!$CtTdj+xs!$01Q4TRnkk(6x*LU(;RP7U)oP4o6Zwaj@Q%z?1pRF+W?;$9H#IeC*AGfY^?_4({Jl(M4dQcfioL;^Q3Y2&q@^z=~of%D5Mb zX_pWUX2Cn!f}KrLjwg}vZo)|wdZ|+w_^Bu&4#;~O*y)!}QJ(O(o^ez!`NKUnVkLiv zhDM;kk6yh4P9h>4o66?<>}3O*GI4F2(qXXYJx*rDa2Zt97Lp`lirVe7ou@be1zIf@ z(+8)`YboxsPz+Ha+LTzlJ_^Y^-VB)GllnpPFsk5P*YPg6)FJ7k0~uDQ$~rr!*3W+hmCZ{T#n(8W8>M5VH(x{UAczea-L#UvcwE}se0 zpU@#PJM={Od%Ree>`NhvK#-(Zx$f z1hM~Xw4aGnZo?u@Ofdlsp)orCqQ~odL?O)eEHM^d5d?qiUr>b6DDM`|BO9o(Bf&t* zSlFDdKh5!2PpOCTJ|nZDP5?{Ff+q&Eh)(l?ebu8)BIrp*5{#!zoSx}eoF1>}$6*dq zK2t?ZUTp8k7!`Yj0tPC<7+6|`wq3xuQSZ$u3sPPZy;z{HxF6VK62DQnY-theuXFyP z*V_Bd!>6X#4n4g+T$YftkjLzzWSP~dqn0f%Dm7jAqAd$C8UYA+3~G!A#{JZSm}HG% zY@#i%JJ>PP(PMP64B*ts_lqXS_ofZe#mSpY7gHrx(Y0evmTO_%MULx&nFC^NmDa&x zqp*95$J0Y*LnT%7PmNrVNYE`Jb?N+t_#UPCIT>o{JivT)-dxnFyjt~?bqSX428-1y zc4?@SG;8}XB`wYT(fbvnq(A7yX~hq>-{!aE^%*&AAvK;WHXO$r7F%I+)~wuKAPbK z`qoczU3HqU`*LloyYkzw?Y&?4ZCx-_^_*QQgSU#b(l1lsAxoX(b=&LjwT zg#0~cUXo)ob+Vn!@O|*_%i8`|HNVge(rESrLGTlS(*$dObWTs~RE%7FYw+Z(Mc_DW zx8@LADZDH9fC2wYdX`53GqxAp03sAQf^P2J;>p9fjS=&Qn z*4%v)MJ&L>Hfb!Nm`4|cXXr!5kY$HZsP`sDSSL6=^H$E#UjbflHu>Z#wSMh|UB9mO zBx30z$K*VaOOKPfO1q6D9tNhou-JNsOwC05Wu8TU?xexyzDF(M6RR)Fl$OmT{G}fS4JW>fYBWk-T=oz2JZvbF zAj{9-k$Lc|)&s>BOJC-BI#xoJBEefoXzXv_or7d778QQ%P&V(!F%|X2effb8K-r3Y zA7SI|LR_~~9oHkGrB8-R`@#et2N{^?iz25Ldhm@rn-5W6RhML|V(xK7pZcS+NzG*a zbz*mRX4f)G&o?d=QMf@uC%(Z8iZ4Ey47k7|IP3;v%aHEUF2oS7G_EC8JR7_HgX6}r z>7TO4wWGL%@MZ%wK0-J6*MmfBQQ~`b)uB*Lz;@G=HkmoX=-tj|0%S|h^Zk&WuU4Dm z$}GKPU`9^3nG_xu`~#JU&)WMk!Lq>2J_`wvFkj? zy0TKA33oWWZ!GwZ`T)0Vxk$I)F^hj+-xsZITW=r?52EKpsdEr*^nK!(vlcJx%)u)1 zX_$6ML)e2Ub4llI32-j4BaU1g&7F2p<3D())1n4zH?dZwhTljdI_yGP()IK4B=29B zQe{qux=}%@NlmjncEu%_LGIJ*p73MbMVA$yc;5zy0` znhL>4uS9syiWxhzsq>|6j? z4!Op$ANkd5HtUUuu&Oa$@1w(q2ih&>GqwH{Vi>nAK~!9HI8UbwQn)^D?3K~HNosoT zDxy8~n%UlHU03*%*&hM+aZ-}fjH)s;z)WvF-$6Bi4zY2bvvLau>inkLolM(pIMu`| z@|L?;@w;nynBzjVHy2T*`Ffd|G$_PRaf{h}5g{)bE3m#o#GzM{{5j5=@6mCeHs9i8 z;Va=Rx)KZXvuOUFsDmrxtliaa`jBksV#SzLz6dbS(ph>~6Zc=tS^5_)ikZhp_kD5E zEM!`mbIK0tCl^Ul`t;9(8PBr8c6ECNbi3;VTK&!qC0H&s7VeaKW^iX~axz_MsUw)X zr+E+C=qf6fB>VJwuv}Au?er{}_pR<%U06Y!kN$RkkdEqb!`y_<*ngw`;Uc-63c}=W z9m=_zH;R84s|joU{_cE-RLYPG;Cu@DHIK@mgEls%W+M>LfKZp{fjJI2*ZXs1-rrgV zfCZ+?lRvnMK#Xb;fKo zB7Tk-0R<#mF{ZKe+(5!=1(8Q-iZvPL?CT9>st37n!XI|XKmYSln@q;dcqE;KAeCTK()%y@8wOj}` zAP?|#;?S02dCbsVyMfj6K;N|$6xF%eMxxU#Wys#$KIMX3OhUk{&DP~|h8LM&T36!Y zdCxYB#EeQ(Ejur@J+u6z(dzaY2IH81-PX9TeIN&GVJcd|uuBoyv_C<;fb(W8TdT1e zas*wXtkxWeIjc;u2rQK6<@pQUr@QFLR{-Cv%T%>8bB0)RAvY?bT{LNDsq^r+=i1<{)N`Se1m>^Fz^{V|@v-#T(lAi!6 zAU^XRUtBBt!^GpPs$~K_2be@S&uzqPi<+w}{_3;%1Sqk^Yv8)LRH_P5E}bpBiJAW) zQN=n>DY*V-7xq{lNC7x^zdUM zx<8|tXNuCE&I}=L`=dW(*3?GHRtAj zTSjIudk}lGM>dj)*R@FBF-9kSs5OQq{Xqi@7E=>pxPU7t;Yoew2l2-@l97!K7D8`l zA#y|Z(P`VkGc7zCGJ8I#nh-rpxvxMVzyt6L#4Lf-A}P?G2rABGU3?cgFJ764p`4?K z(qRx~ie))lE&bpNQT^N31dm*)8)itKti`MEaF(m&lZ~!gd$~yC63pRpR7-1APIMpo zBnUF31dYS)X%UtyEiA~nc;ND3Ku|(Hpc=>S3s6XBa4J|J(95+M(-|wq(f)mt_YB#v zD>3LYu?amhAjf}!Xh0i%x7hmmI7rg{!ik%5vb1wc5^LA*EdsSR{ZbCR2B$|Rgk3or zq5@e!?uId=0X$zeD7VOcB}7i7EHc|${s~vH)*_F6ZYSKI(*m^P!x}RHJ#fkTg#lGnCzR2VOLF&RvA6Au=?GXBXQUQ>xaj zmC2>^i3NGT)o71%^y7d^U6nwbld>qFTbe13zZTjo_uAQ(&ro>f(RFWq2u`)@G1f{b zcc&AaPhtnqhO||h)Y!AfGt{ii>Y{a!Z(P_0#zU%qVw z-dKq(8#5C_HQK@FRT?wvJZdKqhKi48%h4>5{C~Uv_A-p}6a3pv+<7kroZo&5 zLP8qf9`&21zu9$Y-Fx^S2B_$Jjv`A^-a~J;M|o+%;hbmJ5+d9WzFXc20Uw#Hz2EKq@R0ccfk$E$?;z`Sgbhl ztQNy!@n2tmM7*b~%;)OAT-gb9EkRY%Ooyy#2B0D6Z4I%-g3U4X)|b#Fkp|Eup`mX< z8Z=c{y*=`|J?;>}t}3RFUE2@HqEUAz+;q}u-jQkF{Xl^Ef%~I1dH2jH6_=VNTS+v= zkP>EUd6~Q9K~#xl2cqDjUva?guD62VBDdd&>ahp(@_KSwU}DJ_#`xj+tw{F@nZO9g zuzAsNNEifI{&CXyx#lPW3%!$U4LZdwy>MV-B0ml47er-$4t3A>5lE+gAdR z&WUxl(MeY(K4ffLP7U2+X>NjYJTHmR2;EMjiW*H0NtvFwUabV8W#HpLdkFow`>;}q zmPfx5{~_Pc7gJZo3CvqCbnWup&$}>fchOwN z2p)4vQu(6^WaA5JdR-YbT@i_MhA}*(OWNL1(iyBWvfL-a60*{)_W7hT=~mK{e9zmU zd+n^gpI#h?>Q|sO7DE=OMJKXQ5KDTlJiGVYl+)23i|P(#z=W@)@ISx~rhD`ZNS924 znd0L!8$L<5{0w^hE~_VOuR=Q1BpZZx$66Hy;SG3$P($>X7rL@KPOJJ>?G_{@Ihc?D zKTCjqDN&@@egAeu+kTwiDn;8?$jizIiV5btz&PnMbGD3ID_dm#(M30kR^X)VEMJH8 zSDE*AEz%$&8pr%$JWB^6^Af_5ia{pbxNyWcOW!%9#!UCD5XEV$V#$9IorXXNLrfEk zg0mF5<%hUIY-6AVLV9C1S+-k#=8qPD(|~t*8NghKfuteAUSREY10_^|BYwFO7Be+t zJN?mr$%Cu`mKt7i<`*^U1?Eb4OoDLgA|&aBwWMeJ>~_w0P8)dC(B|=mNphI={6XIn zK675f_e?!3K8%1=g(&0k$WhW~(@!9&;aSe#U4^TQ3*TgAiptC@+$1z8vEv!?<<5s$ z)$=F)CEI}rI9Hf#(qmZVuHp_H7!?ufbb6*!Q6!>EujQQ%KUkQ^eMMsdx(1C&9WUK$OL>TR%8x|V9K{)E5ndXVHol|4b z=2;GH(9yPfquJ_$6O=$-!mg0g*HX%({U$uoGI@;2*-KOSlQJ*+rYzhAOV(m#y4z&z z&8<0xASQbCkx^o4#dQB`=|^>aE13nIrsdaN>q&i=8;%D+h~Cy2QPO5b`t<25#E2l* zonyd(ia?=x(ru}=377ksa3#F=6SHMV>#?}Io^6m9+wMbPqNHZH|F0cR^*G>CD&2r|x)hG-O)4 zNQAM{0%+3ao;o+M^kkHVcR2zq!EfN3T1J9Frvf}JAqOlu!O>c3_Ez3$JuIkuLsEo_ z4*0J6L*j%bEPYe0UJh}bQg6cU-7dMjB1dD}d18cg_h!({NF~x}CZ5<)!*M8_2f$M{ zBD#Sby zNuUgE(|$#0J{H%G0QM;-n4WMP8yFp*L%@JQ2w}`WAY@EKuP}}qZRk~lG1Po>-F*mL zyebVu@1oJZJU^_x=l1tD)UM?;+-rQ%vb8u(NN3SX5*bXYQJ1p0ElkL<&nkvw-CrMnxbL@x z7!Ce{&AD~mmQzLjLRHt@kPV`9HU-pWHIlW%(01|EA7~-NbQOdp|NQAO z>1n#lCF)c^ZijDJRWS51tG^h!Nlu&S{&C7uKf2_Yv0=G}_7R1<5h+!GSYTIPI#a;) z^w9@tCPQ}e-di{fpfUlU+Bh<&u~-n$t8UR(k2dC{o@2la7-z6u@%_BZxp>y0(7A0m z(*Ko{Nz1GEnKo84wpN{07i+naAA}dJ6P5mpOW%CqX4BOO=g;#Y zbt=K4ptG%$RF|%hKE}6kQM>4hgwSUSwz1?Z(t^HMJ;Uf4G-zB@P8R>JAp!Fszm2n! zNMW`UK0z}{0sU)<_{AplKVeVtJ$O8GUS0Dk3qt{P2_UWK2Sly5JMBH4i`*`{><`R- z&2TP&6iFC8BbKtDSPh#gh0LB*JTvdyMP$y>-qc84C(iZza;tZ%pY6Xt6)<7jp^~xj z^80kmrraS<(gIdTfMnKa+~9Y)rlA0 zjBD-X=G_=E?^|bk?~L!*kY&(kX=vNQqb|5dv+wHmKN$M&;f%(v9MP?uIVwew@Ev^l z2DSg(U_=$(3E`z*=18^J(7!QO2l*d0!v+~5v3~=hL^0KU`?)S;+Y56boavivuW=ID zDsf|OM+3~jK%LeJvqWQcsaV~vNRYK#C~kzNejZ^hpU&9!5gF>kWm&2J-GE}i6O4db+2s=_$B^v;`s z%NCkP!mU@%xc+CDWjEU}GP)K)X$|_tZI@h|56$x@o9J1n@6Z(p>j~#?i7S7636uPW zK9t9cMPadaZVo=s%bZs-9JsE3PIi83aL?t$BHa^WLBgyF2j%iS+sm zj5{q_|HF0{^spoiM(M@U_ zsipUdzdOhSMX=IQ!#?20=`=xSqNPJd+trQDeJe#lMcy||?iDEHSp9;*mY(NEGX^R! z7EM;dfz4|i#k)D_-J3!575@!7mVY0y)?_++qe|c-7>3jJMERwv1LD+S!4@~>gQ4o1 zu2@3!NWYFVT|}N9Zc`E|YP&}5rV@yhJj-;ivFnC+OQruZgE^o>G4hufQhJO-8O)9E(H_17%V@%3od}*h1;IA*?@60(c1(7a z9nz2*$Jafk9qRV_&>bBuPI5K7+{Kwr4Gxd(!|No$QMt{Rf_^3*&Ia*Zui-V=ftD zTQ#>TMBbpuGHc}+GVC}>QX!Hkh01B+7yMCw!fbS1f~NiOKOl5>>ZC#?MuF#0c+#d0YPE%yiJ)4C)4?-ekz zYNZ8Je*7PvX_{aH%JdP+>h&E(O(|y}S*iqMY3KKReDjQBvXAYU^y}G+#_6`(wplF| zTP{8-DQB$dkH+0D*0wb@$to@}W{=#Hwzgx%XW)wx;H;>tAa}FQaKseusL#q^bJYRx z^yahIr&i&|0yuFrxZ$|)6GBGdLl!}e*mIoJN)?5`q)kXNytz*Vs6+Q!zBjhDTm;HL zX3_<%?XVM-l61bQhCSyi2UV}PrC2XPImDg0s_qPP7b3%5jxh zK5HORD`<4BP))mXD&vT)Hk8yc%)@OAS0#h9O_whp3qo+?~vp-K>0BC8Jc0C#(pWUfL5NmFi74CcIy< z{IyWq*h*5Okknx}U@Ir@b9b`}2kXtQ)?0YzXPvh!Ry8UNixM0by1{T@SbauOCJ2$qSDobsVi%C*cf1q z4d^(XE;8(hzZp(mdMe7V3^YdURn%y$!x)2jzB|gg>wUkdS9N8+Fvd>!2JQFnFxNVx zR-+M-J*N!n7lQixHL;hngf!s?1-iDKzZv>9=cKYD*gfyp`(1%i|4`ItR=Ieg-Z@o_ z3cCYQuzY;sQWcT&+#Ct$o(e!d9Ql;6RW4Zl7<{5h|5YX%)|W1Lxe;gWN6q zFH2mj2L`vEZPep39tAvt{=4+aK;kGk^DyD|cn?rLmG8@_*{_tRbEoAaa)4fakUV-O zt*&6*@3&IwN(+claz(19Kx3d-(d*GA-8Ia!UqT5(n_IHT_v=p*(1XI5z z6xqm5)_qr(`>TpPTTH7(Kn$e69XSc^B?G<*>DN~=fgIVV|L6Aqy@)L+Wy4resS(S4|=CfbJ?zwyQ(bKy*w?SQa6Qr~dcL`mfdcf&C5n*8THt&F&c+ zE}2*wTDbT)u%bhx0*(JiU7vq%r+8lLY6_hmEtkuAERfVK$+`PIh_lRz(RGu1bYvtJ z?s)T&|J3LRH8m_~b6vB=CW_V(3u3CeS+o7)%J3##`Wf0(f%0*O% z#w3Cg_>3ZCB>6TwUxb*ViG&KvIQ6Ul97p%TW&AJC1U~p7+xx84$~4 zZtwTbO)q+5wOj`6myUJhnrVYrp{1ovCLn{0z1VYU*2d(H5MklTPV>VY`)3Vbh>=cPrgp8w8}K8>J+qL%KVqyAkP@W^YgO(e1IkP&z$L&1Cs> zPEF5?BP5w1#V8d;zSobQ;FCg6I?M_z^t|5H+KlA}-|T+(l6kzA#nk{b&3@URb9qk% zbTJR{ugY(aeE!%n16>6go3 zP^MEOJ6WN}0`#57d=-0?iZ92~c2XsDjl-bcH>Kyn6e)C8&uKk3-6eCMsW-k5>kMDw zJT0kMJK#H%JaqMEH~&Gpn(h3{<6KTnEddy52v2jKql=|hh)EATivxz{!ukp%VZb~c z`MVudE_Ayz!P_;J?S+=6o3mLP`&-AU)Orc}iaGnAOp8`g0ze+~IJSfDr001=#s3X9$WAnT<(Y89xk)o$tvtrw`eK=Bdm*QZ zAYVS2{Cwek#mpHHYxf0VP;~iE%hG(Z^)1?T{M87x|9NcuEnk8C-FME0qk!io%N_nf zG!uo&t=B)rc8~fxJ3kNinsmhu_f;-OhIU!3<#d`M zCl-(qC72=|ywD27?kIH4#$4pood!D8O?>XIh-y_(>| z;>PirWJ^Jy%^*4!$}f}h(uy89#}u<>dMwwj0&UkZ$@~ee0?_cl>N|IA0>5R;+sU1Z zp3-w0WJC|pWj7lle8s@5;No(5p}qXb+*ERu#Ec&rj$n=$`$|<#&HoRR(2?q0+xcLT z&)}=bC|xr;fgIi=Fg*jBfl_7*gD+J#RkyN+hTnvM|3l-g(# z(_i}HIF2l-*Ki%65_31qsIpx2esjo^X(^0jD9U-!WlH1cC+CF*cDoh6qMO9Q9>DJ=`P>pcS-7cnFL%aik=Z-+rB;%Fzp2D67BZvuLKpso|}*u`!*w+(E}le9Muz7H1sW))O&C zx@;N#T3Oj}?mMXN^Un!8;Onw{cCNI5K zKPG!|ufO)~5O4UY&%JD_`G@ zqQgh3sE`ex&t*0p4tIs_n2dAyN*Wsa&V^~nKGU<{m|ImXeHAVJz>LIoi!7h;S#1C6 zne^d8%lfW`UMjbe`WweQ&9jN|3i>przzh$%Y_`mU`dcR>9EbBa&d(F;xE4Ol zYZqAF72`YXvGqRtD&>~-oLk>}`{4m~{SYwjO%ICC-o--w`in~q{MopTepku%w|qE3 zrJ9y+<|5$Mu&T+w{)sQ>UXT5?YHv~Tmv#itl{taHl|(YHWASokdEox{npipJ*6Fur zCmh50lJsFSbkiLpK^Thd-5AV{<)Rfz8)_ERys?jHPqwY{eQV9}(`ro006vjNd%tW> z{tv_S)xp{8Jg+929+9Qf^6u|sz86HfKvpdTMF&uhz`8ek95Y`liO76><1A2Lf&w8< zT9m*8jtTQ_JL-8(ogR&<_!yTl3JYVk4_Cb!uTjlbz-qp+#{GQW+5Sv(GpP4Csb0o1 z*kPBc4u(YHN!o&b$h7GBvn&`ml}JE}b79mZQP0$=U`08zBU24ZZ)*{CAo4MSOLUk6 z;#f^nKR2g?#Q~s9Z5}fgdujc&Pej@|x|5Lf8?)y$9}(6SE6oEYMm#%`+|9oJmTTnJ z_)R2jZ8cITA?p_xwwlSH{9AfQmT_*y+v{^K$ID)!AyyZ2bWh8p)18tE*oaEt)z8A| zYafN8tud?w^%O?+^t*|Ul*Q4D-d9xlDx8ycHalxU36rn|)r4JeIKpshW|pxeC1etO z5rn+3%yzEexr|Dzv|)@4-gYdTv}l~Dr6XNVWLTo1k?{r>lR+A?RX#n6oJ`Ui}hfetiGv;59oJ?Q!>3!;B`DO?xLUHR-wp<32P)U{nfa5 z@9^|_MaHR>X%S>e!wYa_fcc*ZZ$0x#EsOrGj~RdHukQB!`2L5|@S; zkEQrNIEJmFVDTq4_4lI;iMKo#*1@(1xuUT@3=}3$nWVZ%kjnkK+^^FN$fe7Z-h>dp zQ1HHe2oy)0TLLtJ86-c7V*OfCfK6GgO!t8tIa~u#0EmigAM;h#LoI8t@Voe;lC)kH zd1qTJXZ!a&qZ1Gy%2rh8VEJ*E(^7mYacIkHK4!8LW2$JSyJI@_^rOJ=!d;YD^L3?H z2~`Z5lk($iASjbVfAYGnX6p0itjoip3f?l2uM@oR1<40~v){BN-L!h?ONso*Y||4| zcHJmT)An+IJ|gmJz64^0^|~pZkpe!5Q-N(#rYmW1Dti7(9 z2iL6}#)+oBmn#{@@khc-__u6-El()V(%_wwoc#+$Kha{ctJd#p5>EYerA$nLs)ktk ztBhMtiT&acUe?Y{ahqfJ&c-FjbZ3{(TkRLS9{pD8yJ~5Ar_K`|#CCER&U7CoA#DBUx=gb{I1}igYeU64d7;Y$zmV+$k zZ0L$oBofLIuY$>IdCCvoS+eEI^d3B`cHmhh`2`{3{Os|Lb^L3U{-dGkjQ`%mlClSYlAmU??F(*ypneJwd1N(%k9HB6Iqgh&wC>f0PKh^a~M=%~e__bh|t&MPIcOv@tqt z53KJgtL{9am1d6Y0lJdvRkOcMWM_wbBKLVf4M|RbR$4XhMx-h*7F=}kBKxM1I&w6B ztwT>j<_JOtp}9|v>)y#9y1rUqwI_|@cHh03|7qcv(+uNF`>3_}5`wO^lxN5np5(mJ zNx+At6q;J@2tZXnJGJb|Q=Gi#bebe{l<*wLcNE{Uc#rM_R@FHOrq*X464BlDF+Q`= zBB)h7mHtL4XMfQ=FBCLatOW`*Hg68g_qUjs_~BD~Y>5|`(UP>B)q zTy%`0(Wj7D6gRM&z$fmo_UD^fkieW}S;vQ0Q_GLmoRG;g*?@p&FXBFW)S}3Ml}<9p zza?~5*JciV21-s&E`0oHK=zBI-R~O6crO>$=YG_L1_Yk960?;36z248 zTkwkj>-Uwi@h3@V@`5ba9aP1lB`>HkLZ@UMej zn^g;Y8&;dTlp&p$;*X6}ELzu6K3_b!Xnx8(t1+-YG&HKRt6V?zklNuwY?KayTp*MA z3>06HVyT8atNE;#hWQnv)F&6b&1xb25~_ft|(Nf-H{fKN;e zWthhBJ1{$$0J6NIPg)d@1xwK`<39`W)!{`X1YxWt<+{*Y1}6mTTM!ZZa3 zk8S+$wPPzK6_pGyJoV;wYB5?9Bf&KT#ht^WQ9hktCMGsEPcyd1ek}N7u42Z*E2}%B z_;wgwdB<2k=Z#@=+8d!)Yls^BOnn%a!JttEsZ46Io29CID`&NHj(q+!WyVCDiTu4L zUCy)}fQ6k(oY^A7H>-UizUb(UVRY5tXUi_vq>Slz(+2%~9~P{A-S{%u#3p9HL1rJ29?sDZp76!}Ci&^hPJvMdjzgPJJrb@brvo2KITmHv-P z&#UyBKSZzLVM|-mU-vG|BSxN>JnP(z6!J_2@Gu<4CMNwD9%S4Sc2&*3vGDTj9*5&c zAI5s!-cpyj5Mt+dF7@Py;Wlq4u0*$Ctf&yL!0|PzGgjfkYV4iR-a~30AQFXxS-gQr$_H7l`Ea@9>YDN0k_gz%(?o7buryUdUZE;w` zh|OyC?KV(Smk%$QgiIBkan6;MpQBE+jeaP@UFI>RG4a;MOt<}q6P9a1iU|kvXbD1z zj6TlsVnYIl{C2#f>;@s0AQKZ4b^yfVMTCWknfs=x_Ei}(H|o(ctpx0c4u{O`-iaKh ziiA-75zg9_4;sGUpY3m$nsOX4iO^tBkMj*1O82Nu7|zOSdQwlpB_sIZW1zU)Wz+6ogQa zy`Y~sndZScFVD9=QJ!l16%8aeb^3>f5?oK&b3JBXy4BhFm9GbJl{3~Ej|Pa~)cVg^YtCplfl*bx+L8LuuSft_SXeI;n> zPWbnfI116jdmr$5lyvkapm)C^{u!j3$<}P$dTH9V%E|{rIIYwT$$f*-OfTx)4nn}>F~a^T zmg2Z=*(1M*d6XAiuZi%5T*O!J_%D`Nli7?UyA`qwUqdC35nHl`lR2cy+YYp5T0NTh zPsde`Z^JBt$Vpxl>@Sd@$c?b1ausc<_ULB3CA=?z{FcHChxB!G*|cr>33%F7#cNaW zZ9t_-eNn`FXZhrXp@IewUxw9pgfjjGz>M5}077?@0CjzjOgIp7gM|wQManHH=sf1y zFR7rUq3Mm|AQRM0_qe0FwB9JKq;(F*?O>XHD@QYLqpRtl)A#}w#YgeSs&A>h%Xjz@ zSs3zMu2V7UD14^LAw&m`kYqH$+(7=jK30OufuAe%@B57+`GY8mHb@tiR)&RyWPwAH zNr}*TrGe}%{bq)jPgl1~iJr0+dE3p+m%~2on7BCF7B`XuA*_&)5aWfp2BorQ=j6CJ z<84O`mNp;`RU&O0N)6=R&?O^fVtVaL{QX-SKMUXo4FAG;#0y>9jy^eQw3m(~Hf`9b ze~=A3Y`djKqe;kNCOF-ZIk%p_f!8FyWNKno7b!F7d^84(`u%mx1SC#ZBtqTc^T_4% z;=Il~YkIA~5rLXj4s>US?Pt~$eU5u0qiy^Q3~~uf+NQ8WpLh+pT3PO!+1k5xtI6_s zV00isoy2^rLaMyQx5gT;OW11$llkwC0g=o$i>)7l2MwE- z5(PJN{4NJGX5p1tnlG%!a$~lt1>Bm#2ruI>-Z{9y)tJJ!a=)c;4%1{1k{unPNMc(q zX0>3XIVA6Z?pwPsB8AY{82T9x$L^bV9UAg$tR{g>YoviomEBYRYBNO&UYEp>QjO0Y zZ93hF6j!IQ<>$^dcyK*PoMhOKjYClu>j#m1LqX6p)W>+taRnK~binCpTWf<Wt zg5jD+X?yEJU%TIR_#LhIZLRzMc)tuJGe`S%1>g6`y8tH+ zKOq_Xm10#9j|)kAE3j5lqz4->QVBQDTW|YW-bBhvWM#t)^bhwQ`4n!-?ULG?nAZB3 zYLHvVBs}5u^maeHRBc#pELra&>rHjvb2Kv9JCjx;bf88Tr%{--*j{`1we9c9%l(DY z1Mu-10Gya=sb4qu5JjBdXA2|EJun-w)cd~HfDCQb{}v@US*FQsS(e-H+b_-DMFM{i zs8c5^notji54gYCc!T6Mzf-w;8$LkK!ljH!i9?G(jTFh;tI)TwFd#vkWOLl9Q5Hs@ zkUF!l-Wa~II;%T%bf{K0WsO0a`daH?c5cn4$We8DJ!$z(=UbA37p2uLTF;Z$v?C6d zDs|3FJ}$_6Ab#9iH+5UIFALO+aI7S1d~&jGV-xv#NIjNt9vy}xrs{PELu~H`>8YUZ zanP|XFrMS0lFt>l<-IEjxY%CzIwL6Pr=!UrEn}a3M5ykzKaIaiTftu78wpFm9QZ8E zI?}`SQmHcGPtL4@?P1M_)MpV)T>KdKb-y!d(j9Rc3Wtk_G&Z+is$R;7h>-b_RItWG zL0Hg&p!Kgl#LklB%v?V=41UP)obMqt)kU(J4x?m_f&S7>Uwj5o8*oAMQ@~!<| z8{xGQMvu{BKJaikU43!B`HYm#i(_>>QJiT|EL-B}u~Dn$ zK}leF&bjiJW_&nX+m8L4-tbF()2}$gO><_RIdIMgZz8I+Vg2>sN6b=Z^jkg^2eOxx zlwAamS#GxjWQJj{OV*Qeu6Gq<$J0h~>3b*mI3({HP4e^{K=oyL0lHzT=@XQH*w61& zQ4bU!cs(Y>vJNaQna8v{q=XQFvlShR1KiqjuKEi|6xa=WdcspP`|HC?l3Fa44Pyv} zerO;Q>)Pc)T^n2a!eV1%!$T9r9#ZDI1~vG_4_4pFd~8}+5_v!ceTaKwJuY45K%Y=h zFcnSqF*5c8GIwz&kZGUt0gZ2gA z3=&Ad=fYmMmHb~67zo^Ngeksnp8-84v(s~-+y4?xJZ0&NCS$! z(y*$y{RY>m$!B~q^pnUpO>N`J|5$A%=Cp5QtIwkQvVSFYA)me}B_t1QDCY1z^&=jw zpK6_8qPkR`;eyX`QD3l16RA=Rh0E60@`wtZqHXZkHHLY*Y+iV*1?B(qa2ddDpX))fBP=F|CRX(Y7hB8 zp3FVk4jW5Ju3$eeUN;SXWc40fJ^3|-PbNm8!#bEr-4tjMfVhLKFZ*j9lt(RG$Z!gl z#7rapG%3m6A<$V6AK`fryg{LgzM@+XxIclBxur^kGeqITN~!O%1~e^;#HYSYSgH_2 z{44wY*OyaNQr{|A1=Zu0^^*T-Z5z-;^kfDtnGHo812F{p%7Ilgev4Y4#{`M@0b`|= zrni1T_jBVQV4@=m!0~Y7xZrA089uCC``PWMpOq1 zG7xQlO*>0O7ZbjcYZ+aQ6mD2YB{TGc)mc_v-Y}?$l}BA8Yy?vp3PsyTOXB;B)4~@J z+Yf7XL`OK;D*T_G!q#Jd(2>fCf|eD$vsFHjkR(KaZ@@k1)lNEhu~HHRYP??%s9R@c znflv5R@BCJE=M5+3XmocITY7E?z)W?4nm=%rVjXkK9K&G=RnGcyhL%h;(ingg*J-} zGiGjK^sC@*BLcQ72L?e>;NPU(tyvat53x=!u5!1GN-*U$X z1}XQcd-NQ!T9R zFE%PD0lwT8F~-gXuiob|(a}Zwg1mHorp&UPi-Qa#Gb;;`sZigB2WTQ{68`lPpIh?G zvV*+K2w6oJ{IlWdih+6zlrCCe)7e~?H23?cfWx>|7y~~&Rp*oOE?YUD#at^*_^@3j zGyIbO-C@(FQ^Vl`A2}YS92E4Ga*6(_sr5kU-zX`fN`nCs|g1=ZQJ9Z46(v?2A$GLT3jx7DsQ%Ix#>2>?U zaJStzw!IazZ+IB5;LDiYTC3^TQ^55z^g;MO6Y5MU?UXE?{V4BMj%nmtvz_0m6r*Z} zBc+c%paj^AF#~~M%OLM>WTA7`qq=)LyUbr?8T;wJfF^V4s zBL7Kxm}2y=1_(@s#E-3;D;PE*i9eA}FyB3fHZoMV34Iz{99t0kmqX$sJRJnhM=4Dh zVl^@*_ff*M6}Md-+hAXo2B6TJA6^EFr6lbvNgU5A1hZGNHGVO=M?v|#!Dy#A>mvJ@ zyO|ZZXZdu9#wUp)3OE;Qf!g5Zz`r`3ULsbPZ5|dv>V90PB7Jn;@4k=f_5^$?G1A7A zVnR2@i^hr87t}vm#k4PAD9LaTub8S%gTFT8EohyyQg1dW$XG? z*=c~ya|Rhu@LG)4Tsz-~=Pi^Fnhck@WAG$&f=LaB*H{i%BlVHhzAomP<$sJVL=!wm z%(Hru#lAG1Ls2rv$b{k-!9MVZ)He} zQT*b!uqSdgc`%XLeLe?jGb|a_L71I9PAL?50?sFC;7^HuE>lBrYIQ`Yd-nbl%aC@U zw0CS*raMH2|H$cEK}z+O^DkJ+^S3R5OC~s3X+3@HmBGRVwm}~V1{;P7mxVxO97p$! zfB0`t^ZJ(VBVyQ62VuX(-9$7|4t?Gvw^p1hc`Ri?+>y21&u!L3Rj}SGSAwn1ln~NH z{fBRcOzC}gQm0LC$Yb#o1~;B-wklns*Tx76kf8RtrBZUsj_oxHuZ2Vh+$TlbP{M>J zwQMgH)3@tmBBm->gKb}>RSD`^?{6J@rOg};G?4ve!v7V$ccCISCtK6o!xU$UV$8i_ zYDWgWwHLy0z@;=Oe!jx{60fQlo5?wV+y)^nqH{9;lXKoSi*GCZ1#jufTjZ{VcRTn0 zjP_n4^VczIV!Hdr`m?PR+_7h6yl8p}>+pyXu7)h7T2vFtOj4KvM8d9!vpN%}^A(=W zS_~9pU(CLm3ZIGf#Q_B2Z}i?Y4M@n0rY~VEL<5@8N|y*5@qqa;+zY6nTdRk*Nh2B4TjSGfswIQc2tKbmsfdel~RZC!7UAk2Ai>Y>mDZ>fc0lQN3?Wf!dfR*zC1LbcLE^7ctDYaC#F!_w1G{f2ZoRguL^`2$X4thfA*6FYMtJ<*>N*C- z;e?ogJ_rjc>5>c0T05cCchHn8VAr7kPtfEK4B-O4!*ZE~yi1<_bdE`@}h@B(TV@ z6iRmf4}lB^U_F#V!7$i5YW>XDhN0A#Id~E3YNRmkPQDpw?%(+zWCsd$qU@_KgSKg> zp+d`*lYyhocfa6Eb?(FpE1@VkpwdH4B|$ZcOZyaM{={;UT?HTDm`It3JE^!+GDHaeRIh7psc`ET zgTfytqX8c@wYPG+WAA%h{uVG`&;x~1M8y~MU&+)i>o~8aC{fW3b9A|kGS`cf;BUp_kaec$wsPGN(zsHx4&7`;Sj?0~gDne2XGBjw%a#HsRqT$X0?$KQXczGq{K=n@G2*v9)_&vLRIk9_b&#_>;HSKuZ(5L$29c54@*wvhd+&eeoNHv`-6xXC z^Th~##0h=X4JG8@{;Ag(hL_T$(qQ(-Yvgs>8;`X3%NVPSDSbonIC@l~XgQw$&Q4o0 zRx_*SFs*db?^zLPBco8d74FlN>8Y#v^j<(kg|`5+fJ&sjArCT;(C2RS9;~2{N@z09 zCt8(x_bFk6&-fyPE@pFOpR^PW|FPI_E;pdGpNKEtip4ayHdgtoxEJ>yjN9Fo>YcL~ z0eVbXSpmLCXsGC_7eocirKl~@GW92tA@i}-7~&QHn<{$mcNd~?cwr)QfNV$%adJ)N zyfpYdp3$Ji<=z*h~7%{hyELzhJp;)JkYVjTmxc#yu~k^6;T{GUUvO zPw>6`Uc4J_uzh;30f3u>EuR9ok>q~uTd`#^b{=b-aHb4Rr@GIyZgj-sER2eAid8XP z-3Y4~_MDmkvgt1q4rqRYRKjL&zk*k8KP)@sumE?#$)Kz4MTK}{i(~GoQJ9M1sZ6FC z!0lq3y*WA*KSV_MarKol)Um-NY2UISPu36lbTok5nb?f(Nt0=6>ivFm>AU=RR zWFb&zp!NZZM`$+`mBKPbTYgfji7;2 zLU3^}&c4gOD)zxB`P};PdcB}psv?q>_WtF)^Yoi8R#JE)9W&T5Z!aJ9MF>0d(HuaG zrYQR=C5mF+_>xq+qBa@zg8nHR2oGQYF;%By|1m4Lfa)Py@MH5FtsoLzU2^rBgO5Y+ z?;SzQw00=jtyPOS<9(P~2KlfrZN=lHb9l^?PItlUfZK`|e9?+u#`1Zs)}PK^EtH*L zx>8kn^)u;`m2w$&65rp&f^AYtF9d`q`7+`nssKlVctBno-EhB&;3{IZOBBRK@fSK^ zUYO=8bF5YG`4_=R9@bJ;6hAsdEnfd^AA`@*nYGAa`wW}dc>QdUc-cMntzHV6JNGCY z7H4Mp_@d{d52f4jsN4i1{_qY+w}2u{bxjvtCtd;U3mntreUZ9t)wz*t0YkjZC3M?| zc!!pIMxUG7hm}-Vu7H&r8Q5z-97HgF2JP{!1kfz9O2|&!;`zxKOs(;Y`e zn1(E{Lm&Ub#2;urPNkM|@X-8#8KexVb_f}J0Jj9D+hKmVmbQAIT4awZUeNksY10Co z)G4GlO{|TzrIB97S}%&6q(bqOxk?-1EacCU2oM|Dx*Ai>Z4vvKe8ZB9HBqY-i}CP{ zO^de!*1P;}EO(U~75Wl4LWXn?2qEeA&`=(WgOe^(w{TbQ}}yvF+qrb2!mwr?}Is8FtRpU!x6Z$iI{=wnEeVj_p}bv$#rWE}20 zwr>z%eoag-^+WRKh}81Lu}o7@TI&m_sdZ>9wtE_Hd6qWRLX8paVyVP}6NnH0R!RgE zRq`d3*gKd)RR8WO2H{+cvU}b53>~7{S>sbd_hN>58xw1urcU*$4tK(`I07%=zXBz~ z5a_>4gvcr&qsXdbrRrt8Uuy(UnYIxFsmyq>^5UN-DAEgCJP_$F;7_DFd}j-D(=4)= zZq#<2WQZNWj^tDny(#!m<2{CI_%7rXs_$>#=Ijjbm)K04cluOq4bvz-{fH&h1q1UK zG^wK=3gqI{;kVf(Gcs?s=9r&=;Q59G0_AO|LT&`TfC-2e0W7OAAx%OIxFe)p+oS9q z?MRvW@adeM8l#y;Li18kqU%=nWX6g@r>L=A>jSau?OUi@yVa+q=yXQ`dvnPm$$nQ-te3oPek)oni{a1O!M~e(J5?rs{mn zLXgbM_EN96Sj|hZW#d&}v20k|KMI`5j;Kvq%wM;Xs73o)b{b*7ImTWtgcUoEFLxwN z!d@S-t!$i3oAs?~Xg+xmbRD_ZTjAtEE|wm{zAD>82AcZeqSsiZn_fTS;DJYcYo}a~ zw0Rm2u-zWq+lb#+MC0>WN<$Br9{7&?J7&p7pNzRG|AVQfi2Nf6si4KG=yRf@Ru-+9 z$_N;9XIOK{Y&2V0591s4St`@8ZSf$*(-Bgc-r{Zif+ALb@AaZ-O~X&xF_k(^V+!qo ztb>cQ^+)=9xJc|{0cbiPwzDMn8sxhhM`F)wl{}KxhKa$SHtoM{QlSXwwIk`gV>|y- zkEO}Ur#&O?^0eT0F%1t&!(ePVPoVFv3@Wj`WChT|Btnj;UOmhM$(Izy9op-AXRbZB zXPb2AbU9z0uYs=qg3?V)9n4xFR@oLxsPH_=2wCrDkL3Sct6F9Dq`DI6KISziRXR$* zds<^abZ_bty-i#KD0(PRkBZPX2T!VHWn#XKBJg0gq1$oiarn_5sxxvLf|#-@=Q6@1 zP3koE*b)**AGM>cS#z0($@}$0JL41(T&wr`d3{fOKe2d6WN7FN2TiSV{-delARhq_ zhLXm)n;sIk)`$l{x9>i>({&fZ^OAbw<$aZ26NxIE*cD7Y?PG#ux z2&OTRKnOAg(tp{PTUFMS5N5DG;%SPOja#4%>*Uv5xy=u}jRIp|x8vliWxfl4ung#t zc_7c_jh46Sia+J=uiAX3zk*lrHX7B4L-GAL3x&o3u9t25Lamp5-`a{bjcv>-?tQ<% zY?$~1#CIp)Tv?$9UKja;ed&>(^|;6Q9a;s@V=L8sFB{E=dw7y6(gwCFalUDjQkD6y zU(rXZsEyCi%SmOtT{k4S&zC*9_nkf>rM;&1u_b4{L*BKClR~mN{!qG%9$Hh#kiuvd zO2{u(TFRRgp#5gjsc4p4B&BgRm#wR)$9!O1%BYaIG=Iln)xnRl@Z)6>@^Bm~5goxQ z<%dP8Y>_x`6BKhAi=+Z>KgOU=r)O`3J&rlk^RBkY$g#hx@s=sjzf-jcK8Z|j@8g=B z`B&oX-;G#Gso)#jm8(|@&)M)tUXHCv<~(Aezd0d2!4&1qLdh{m9q>NYG5;1vmL4lP z!PtF+S*qvD3f8?@q0_dzY?MRy@YlbX3OIQy761hhU2wBq)=hXkeM@}duQs&bC=&+NNH6u$ zUzd-WmQ=+F0Rmze?~M|PSrTv7^1HME%JKJ4R17fB=Jo9A{}|T4{m*;9#sUx+!>b=( zj(_*&{<(%c1MZ7<#y8wI+5g`^VRAe`)-p`z zf1xfP2<}6+JBML^AVvP>vatDmnDtbBL-xN@$95mn$dh=g{aqCJZQlXr{{OB2f7*I| zaT<7)Xe{6VB0PZZ(1B`)ume#_NZW)Hm@nZUu~i@%n*UuC?&~K?Uu7JrCsJ2rWm9gM zs!my_YKc@o`SvF9{1f8*z4yR{uso)%h^?%&w8pd8c(c6!E+^9NI=EQMfH9E4?|fyB>(^b literal 0 HcmV?d00001 diff --git a/nebula-exchange/doc-2.0/figs/ex-ug-002.png b/nebula-exchange/doc-2.0/figs/ex-ug-002.png new file mode 100644 index 0000000000000000000000000000000000000000..a4abbef115da17e612b6f6d43ee9728aaa3232d7 GIT binary patch literal 60193 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�wMox-jhh9Z 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 literal 0 HcmV?d00001 diff --git a/nebula-exchange/doc-2.0/parameter-reference/ex-ug-para-import-command.md b/nebula-exchange/doc-2.0/parameter-reference/ex-ug-para-import-command.md new file mode 100644 index 0000000..a322933 --- /dev/null +++ b/nebula-exchange/doc-2.0/parameter-reference/ex-ug-para-import-command.md @@ -0,0 +1,19 @@ +# 导入命令参数 + +完成配置文件修改后,运行以下命令将指定来源的数据导入 Nebula Graph 数据库。 + +```bash +$SPARK_HOME/bin/spark-submit --class com.vesoft.nebula.tools.importer.Exchange --master "local[10]" target/exchange-1.x.y.jar -c /path/to/conf/application.conf +``` + +> **说明**:JAR 文件版本号以您实际编译得到的 JAR 文件名称为准。 + +下表列出了命令的相关参数。 + +| 参数 | 是否必需 | 默认值 | 说明 | +| :--- | :--- | :--- | :--- | +| `--class`  | 是 | 无 | 指定 Driver 主类。 | +| `--master`  | 是 | 无 | 指定 Spark 集群中 Master 进程的 URL。详细信息参考 [master-urls](https://spark.apache.org/docs/latest/submitting-applications.html#master-urls "点击前往 Apache Spark 文档")。 | +| `-c`  / `--config`  | 是 | 无 | 指定配置文件的路径。 | +| `-h`  / `--hive`  | 否 | `false` | 添加这个参数表示支持从 HIVE 中导入数据。 | +| `-D`  / `--dry`  | 否 | `false` | 添加这个参数表示检查配置文件的格式是否符合要求,但不会校验 `tags` 和 `edges` 的配置项是否正确。正式导入数据时不能添加这个参数。 | diff --git a/nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-nebulagraph.md b/nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-nebulagraph.md new file mode 100644 index 0000000..e43298a --- /dev/null +++ b/nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-nebulagraph.md @@ -0,0 +1,16 @@ +# Nebula Graph 相关参数 + +下表列出在使用 Exchange 导入数据时您需要设置的 Nebula Graph 相关参数。实际应用时的参数设置,参考不同来源数据的 [操作示例](../use-exchange/ex-ug-import-from-neo4j.md)。 + +| 参数 | 默认值 | 数据类型 | 是否必需 | 说明 | +| :--- | :--- | :--- | :--- | :--- | +| `nebula.address.graph` | 无 | `list[string]` | 是 | Nebula Graph 图数据库 Graph 服务的地址列表。如果有多个地址,以英文逗号(,)分隔。格式为 `"ip1:port","ip2:port","ip3:port"`。 | +| `nebula.address.meta` | 无 | `list[string]` | 是 | Nebula Graph 图数据库 Meta 服务的地址列表。如果有多个地址,以英文逗号(,)分隔。格式为 `"ip1:port","ip2:port","ip3:port"`。 | +| `nebula.user` | `user` | `string` | 是 | 数据库用户名,默认为 `user` 。如果 Nebula Graph 启用了身份认证:
                                          - 如果未创建不同用户,使用 `root` 。
                                          - 如果已经创建了不同的用户并且分配了指定空间的角色,则使用对该空间拥有写操作权限的用户。 | +| `nebula.pswd` | `password` | `string` | 是 | 数据库用户名对应的密码,默认 `user` 的密码为 `password` 。如果 Nebula Graph 启用了身份认证:
                                          - 使用 `root` 时,密码为 `nebula` 。
                                          - 使用其他用户账号时,设置账号对应的密码。 | +| `nebula.space` | 无 | `string` | 是 | 导入数据对应的图空间(Space)名称。 | +| `nebula.connection.timeout` | 3000 | `int` | 否 | Thrift 连接的超时时间,单位为 ms。 | +| `nebula.connection.retry` | 3 | `int` | 否 | Thrift 连接重试次数。 | +| `nebula.execution.retry` | 3 | `int` | 否 | nGQL 语句执行重试次数。 | +| `nebula.error.max` | 32 | `int` | 否 | 指定导入过程中的最大失败次数。当失败次数达到最大值时,提交的 Spark 作业将自动停止。 | +| `nebula.error.output` | 无 | `string` | 是 | 在 Nebula Graph 服务器上指定输出错误信息的日志路径。您可以在这个文件里查看发生的所有错误信息。 | diff --git a/nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-neo4j.md b/nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-neo4j.md new file mode 100644 index 0000000..fef818a --- /dev/null +++ b/nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-neo4j.md @@ -0,0 +1,36 @@ +# Neo4j 数据源相关参数 + +如果要导入的数据来源为 Neo4j,您可能需要配置以下参数。 + +| 参数 | 默认值 | 数据类型 | 是否必需 | 说明 | +| :--- | :--- | :--- | :--- | :--- | +| `tags.name` | 无 | `string` | 是 | 设置为 Nebula Graph 中的标签名称。 | +| `tags.type.source` | 无 | `string` | 是 | 指定标签源数据的格式。设置为 `neo4j`。 | +| `tags.type.sink` | 无 | `string` | 是 | 指定标签源数据导入 Nebula Graph 的方式。可以设置为:
                                          - `client`:以客户端形式导入
                                          - `sst`:以 SST 文件格式导入 | +| `tags.server` | 无 | `string` | 是 | 设置 Neo4j 数据库服务器地址,格式必须为 `bolt://:7687` 。 | +| `tags.user` | 无 | `string` | 是 | Neo4j 数据库登录账号。 | +| `tags.password` | 无 | `string` | 是 | Neo4j 数据库账号登录密码。 | +| `tags.encription` | `false` | `string` | 否 | 传输是否加密,默认值为 `false`,表示不加密。设置为 `true` 时,表示加密。 | +| `tags.database` | 无 | `string` | 否 | 设置源数据所在 Neo4j 数据库的名称。如果您使用 Community Edition Neo4j,不支持这个参数。 | +| `tags.exec` | 无 | `string` | 是 | 写入 Cypher 语句,从 Neo4j 数据库中检索打了某种标签的点的属性,并指定别名。Cypher 语句不能以英文分号(`;`)结尾。
                                          例如,写入 Cypher 语句 `match (n:label) return n.neo4j-field-0 as neo4j-field-0, n.neo4j-field-1 as neo4j-field-1 order by (n.neo4j-field-0)`。| +| `tags.fields` | 无 | `list[string]` | 是 | 指定源数据中与 Nebula Graph 标签对应的属性名称。以列表形式列出,多个属性名称之间以英文逗号(`,`)隔开。列出的属性名称必须与 `tags.exec` 中列出的属性名称保持一致。 | +| `tags.nebula.fields` | 无 | `list[string]` | 是 | 指定 Nebula Graph Schema 中标签对应的属性名称。以列表形式列出。与 `tags.fields` 列表中的属性名称一一对应,形成映射关系。多个属性名称之间以英文逗号(`,`)隔开。 | +| `tags.vertex`
                                          或者
                                          tags {
                                              vertex {
                                                   field: [name]
                                                   policy: "hash"
                                              }
                                          }
                                          | 无 | `string` | 是 | 将源数据中某个属性的值作为 Nebula Graph 点 VID 的来源。
                                          如果属性为 `int` 或者 `long` 类型,使用 `tags.vertex: [field name]` 设置 VID 列。
                                          如果不是上述类型的属性,您可以通过 `tags.vertex.field` 和 `tags.vertex.policy`  对 VID 进行预处理。其中,`tags.vertex.policy` 可以设置为 `"hash"`。 | +| `tags.batch` | 256 | `int` | 是 | 单次写入 Nebula Graph 的点数据量。 | +| `tags.partition` | 32 | `int` | 是 | Spark 的分区数量。 | +| `tags.check_point_path` | 无 | `string` | 否 | 设置保存导入进度信息的目录,用于断点续传。如果未设置,表示不启用断点续传。 | +| `edges.name` | 无 | `string` | 是 | 指定 Nebula Graph 中的边类型名称。 | +| `edges.type.source` | 无 | `string` | 是 | 指定源数据格式,设置为 neo4j。 | +| `edges.type.sink` | 无 | `string` | 是 | 指定边数据导入 Nebula Graph 的方式。可以设置为:
                                          - `client`:以客户端形式导入
                                          - `sst`:以 SST 文件格式导入
                                          | +| `edges.server` | 无 | `string` | 是 | 指定 Neo4j 数据库服务器地址,格式必须为 `bolt://:7687` 。 | +| `edges.user` | 无 | `string` | 是 | 指定 Neo4j 数据库登录账号。 | +| `edges.password` | 无 | `string` | 是 | 指定 Neo4j 数据库账号登录密码。 | +| `edges.exec` | 无 | `string` | 是 | 写入 Cypher 语句,表示从 Neo4j 数据库中查询关系属性。Cypher 语句不能以英文分号(`;`)结尾。
                                          例如,写入 Cypher 语句 `match (a:vertex_label)-[r:edge_label]->(b:vertex_label) return a.neo4j-source-field, b.neo4j-target-field, r.neo4j-field-0 as neo4j-field-0, r.neo4j-field-1 as neo4j-field-1 order by id(r)`。 | +| `edges.fields` | 无 | `list[string]` | 是 | 指定源数据中与 Nebula Graph 边类型对应的属性名称。以列表形式列出,多个属性名称之间以英文逗号(`,`)隔开。列出的属性名称必须与 `edges.exec` 中列出的属性名称保持一致。 | +| `edges.nebula.fields` | 无 | `list[string]` | 是 | Nebula Graph Schema 中边类型对应的属性名称。以列表形式列出,与 `edges.fields` 列表中的属性名称一一对应,形成映射关系。多个属性名称之间以英文逗号(`,`)隔开。 | +| `edges.source`
                                          或者 
                                          edges: {
                                              source: {
                                                  field: [name]
                                                  policy:   "hash" 
                                              }
                                          }
                                          | 无 | `string` | 否 | 指定源数据中某个属性,将它的值用作 Nebula Graph 边的起始点 VID。
                                          如果是上述类型的属性,使用 `edges.source = field` 设置起始点 VID 列。
                                          如果不是上述类型的属性,您可以通过 `edges.source.field` 和 `edges.source.policy`  对 VID 进行预处理,即使用 `hash()`函数处理属性名称,生成的数值用作 VID。其中,`edges.source.policy` 可以设置为 `"hash"`。 | +| `edges.target`
                                          或者
                                          edges: {
                                              target: {
                                                  field: [name]
                                                  policy: "hash"   
                                              }
                                          }
                                          | 无 | `string` | 否 | 指定源数据中某个属性,将它的值用作 Nebula Graph 边的目标点 VID。必须为 `int` 或 `long` 类型的属性。
                                          如果属性为 `int` 或者 `long` 类型,使用 `edges.target: [field name]` 设置目标点 VID 列。
                                          如果不是上述类型的属性,您可以通过 `edges.target.field` 和 `edges.target.policy`  对 VID 进行预处理。其中,`edges.target.policy` 设置为 `"hash"`。 | +| `edges.ranking` | 无 | `string` | 否 | 将源数据中某一列数据作为 Nebula Graph 中边的 Rank 值。 | +| `edges.batch` | 256 | `int` | 是 | 单次写入 Nebula Graph 的边数据量。 | +| `edges.partition` | 32 | `int` | 是 | Spark 的分区数量。 | +| `edges.check_point_path` | 无 | `string` | 否 | 设置保存导入进度信息的目录,用于断点续传。如果未设置,表示不启用断点续传。 | diff --git a/nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-spark.md b/nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-spark.md new file mode 100644 index 0000000..a5e26e9 --- /dev/null +++ b/nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-spark.md @@ -0,0 +1,10 @@ +# Spark 参数 + +在使用 Exchange 导入数据时,您可以根据需要设置 Spark 参数,详细信息的 Spark 参数信息,参考[《Apache Spark 文档》](https://spark.apache.org/docs/latest/configuration.html#application-properties "点击前往 Apache Spark 文档")。下表仅提供部分参数的配置说明。实际应用时的参数设置,参考不同来源数据的 [操作示例](../use-exchange/ex-ug-import-from-neo4j.md)。 + +| 参数 | 默认值 | 数据类型 | 是否必需 | 说明 | +| :--- | :--- | :--- | :--- | :--- | +| `spark.app.name` | Spark Writer | `string` | 否 | Spark Driver Program 名称。 | +| `spark.driver.cores` | 1 | `int` | 否 | Driver 进程的核数,仅适用于集群模式。 | +| `spark.driver.maxResultSize` | 1G | `string` | 否 | 每个 Spark 操作(例如收集)中所有分区的序列化结果的上限(以字节为单位)。最小值为 1M,设为 0 则表示无限制上限。 | +| `spark.cores.max` | 无 | `int` | 否 | 当以“粗粒度”共享模式在独立部署集群或 Mesos 集群上运行时,跨集群(而非从每台计算机)请求应用程序的最大 CPU 核数。如果未设置,则默认值为 Spark 的独立集群管理器上的 `spark.deploy.defaultCores` 或 Mesos 上的 infinite(所有可用的内核)。 | diff --git a/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-from-csv.md b/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-from-csv.md new file mode 100644 index 0000000..b47c66b --- /dev/null +++ b/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-from-csv.md @@ -0,0 +1,331 @@ +# 导入 CSV 文件数据 + +本文以一个示例说明如何使用 Exchange 将存储在 HDFS 上的 CSV 文件数据导入 Nebula Graph。 + +如果您要向 Nebula Graph 导入本地 CSV 文件,参考 [CSV 文件导入示例](../../manual-CN/1.overview/2.quick-start/4.import-csv-file.md)。 + +## 数据集 + +本文以美国 Stanford Network Analysis Platform (SNAP) 提供的 [Social Network: MOOC User Action Dataset](https://snap.stanford.edu/data/act-mooc.html "点击前往 Stanford Network Analysis Platform (SNAP) 网站") 以及由公开网络上获取的不重复的 97 个课程名称作为示例数据集,包括: + +- 两类点(`user` 和 `course`),共计 7,144 个点。 +- 一种关系(`action`),共计 411,749 条边。 + +详细的数据集,您可以从 [nebula-web-docker](https://github.com/vesoft-inc/nebula-web-docker/tree/master/example/mooc-actions "点击前往 GitHub") 仓库中下载。 + +## 环境配置 + +本文示例在 MacOS 下完成,以下是相关的环境配置信息: + +- 硬件规格: + - CPU:1.7 GHz Quad-Core Intel Core i7 + - 内存:16 GB + +- Spark:2.3.0,单机版 + +- Hadoop:2.9.2,伪分布式部署 + +- Nebula Graph:V1.1.0,使用 Docker Compose 部署。详细信息,参考 [使用 Docker Compose 部署 Nebula Graph](https://github.com/vesoft-inc/nebula-docker-compose/blob/master/README_zh-CN.md) + +## 前提条件 + +开始导入数据之前,您需要确认以下信息: + +- 已经完成 Exchange 编译。详细信息,参考 [编译 Exchange](../ex-ug-compile.md)。本示例中使用 Exchange v1.1.0。 + +- 已经安装 Spark。 + +- 已经安装并开启 Hadoop 服务。 + +- 已经部署并启动 Nebula Graph,并获取: + - Graph 服务、Meta 服务所在机器的 IP 地址和端口信息。 + - Nebula Graph 数据库的拥有写权限的用户名及其密码。 + +- 在 Nebula Graph 中创建图数据模式(Schema)所需的所有信息,包括标签和边类型的名称、属性等。 + +## 操作步骤 + +### 步骤 1. 在 Nebula Graph 中创建 Schema + +分析 CSV 文件中的数据,按以下步骤在 Nebula Graph 中创建 Schema: + +1. 确认 Schema 要素:Nebula Graph 中的 Schema 要素如下表所示。 + + | 要素 | 名称 | 属性 | + | :--- | :--- | :--- | + | 标签(Tag) | `user` | `userId int` | + | 标签(Tag) | `course` | `courseId int, courseName string` | + | 边类型(Edge Type) | `action` | `actionId int, duration double, label bool, feature0 double, feature1 double, feature2 double, feature3 double` | + +2. 在 Nebula Graph 里创建一个图空间 **csv**,并创建一个 Schema,如下所示。 + + ```ngql + -- 创建图空间 + CREATE SPACE csv(partition_num=10, replica_factor=1); + + -- 选择图空间 csv + USE csv; + + -- 创建标签 user + CREATE TAG user(userId int); + + -- 创建标签 course + CREATE TAG course(courseId int, courseName string); + + -- 创建边类型 action + CREATE EDGE action (actionId int, duration double, label bool, feature0 double, feature1 double, feature2 double, feature3 double); + ``` + +关于 Nebula Graph 构图的更多信息,参考《Nebula Graph Database 手册》的 [快速开始](../../manual-CN/1.overview/2.quick-start/1.get-started/ "点击前往 Nebula Graph 网站")。 + +### 步骤 2. 处理 CSV 文件 + +确认以下信息: + +1. CSV 文件已经根据 Schema 作了处理。详细操作请参考 [Nebula Graph Studio 快速开始](../../nebula-studio/quick-start/st-ug-prepare-csv.md)。 + > **说明**:Exchange 支持上传有表头或者无表头的 CSV 文件。 + +2. CSV 文件必须存储在 HDFS 中,并已获取文件存储路径。 + +### 步骤 3. 修改配置文件 + +完成 Exchange 编译后,进入 `nebula-java/tools/exchange` 目录,根据 `target/classes/application.conf` 文件修改 CSV 数据源相关的配置文件。在本示例中,文件被重命名为 `csv_application.conf`。以下仅详细说明点和边数据的配置信息,本次示例中未使用的配置项已被注释,但是提供了配置说明。Spark 和 Nebula Graph 相关配置,参考 [Spark 参数](../parameter-reference/ex-ug-paras-spark.md)和 [Nebula Graph 参数](../parameter-reference/ex-ug-paras-nebulagraph.md)。 + +```conf +{ + # Spark 相关配置 + spark: { + app: { + name: Spark Writer + } + driver: { + cores: 1 + maxResultSize: 1G + } + cores { + max: 16 + } + } + # Nebula Graph 相关配置 + nebula: { + address:{ + # 以下为 Nebula Graph 的 Graph 服务和 Meta 服务所在机器的 IP 地址及端口 + # 如果有多个地址,格式为 "ip1:port","ip2:port","ip3:port" + # 不同地址之间以英文逗号 (,) 隔开 + graph:["127.0.0.1:3699"] + meta:["127.0.0.1:45500"] + } + # 填写的账号必须拥有 Nebula Graph 相应图空间的写数据权限 + user: user + pswd: password + # 填写 Nebula Graph 中需要写入数据的图空间名称 + space: csv + connection { + timeout: 3000 + retry: 3 + } + execution { + retry: 3 + } + error: { + max: 32 + output: /tmp/errors + } + rate: { + limit: 1024 + timeout: 1000 + } + } + # 处理标签 + tags: [ + # 设置标签 course 相关信息 + { + # Nebula Graph 中对应的标签名称。 + name: course + type: { + # 指定数据源文件格式,设置为 csv。 + source: csv + # 指定点数据导入 Nebula Graph 的方式, + # 可以设置为:client(以客户端形式导入)和 sst(以 SST 文件格式导入)。 + # 关于 SST 文件导入配置,参考文档:导入 SST 文件(https:// + # docs.nebula-graph.com.cn/nebula-exchange/ + # use-exchange/ex-ug-import-sst/)。 + sink: client + } + # CSV 文件所在的 HDFS 路径,String 类型,必须以 hdfs:// 开头。 + path: "hdfs://namenode_ip:port/path/to/course.csv" + + # 如果 CSV 文件里不带表头,则写入 [_c0, _c1, _c2, ... _cn], + # 表示 CSV 文件中的数据列名,作为 course 各属性值来源。 + # 如果 CSV 文件里有表头,则写入各列名。 + # fields 与 nebula.fields 的顺序必须一一对应。 + fields: [_c0, _c1] + + # 设置 Nebula Graph 中与 CSV 文件各列对应的属性名称, + # fields 与 nebula.fields 的顺序必须一一对应。 + nebula.fields: [courseId, courseName] + + # Exchange 1.1.0 添加了 csv.fields 参数: + # 如果配置了 csv.fields,无论 CSV 文件是否有表头, + # fields 的配置必须与 csv.fields 的配置保持一致。 + # csv.fields: [courseId, courseName] + + # 指定 CSV 中的某一列数据为 Nebula Graph 中点 VID 的来源。 + # vertex.field 的值必须与上述 fields 或者 csv.fields 中的列名保持一致。 + # 如果数据不是 int 类型,则添加 vertex.policy 指定 VID 映射策略,建议设置为 "hash"。 + vertex: { + field: _c1, + policy: "hash" + } + + # 标明数据源中数据分隔方式,默认为英文逗号(,)。 + separator: "," + + # 如果 CSV 文件中有表头,header 设置为 true。 + # 如果 CSV 文件中没有表头,header 设置为 false(默认值)。 + header: false + + # 单次写入 Nebula Graph 的最大点数据量。 + batch: 256 + + # Spark 分区数量 + partition: 32 + + # isImplicit 的设置说明参考:https://github.com/vesoft-inc/nebula-java/ + # blob/v1.0/tools/exchange/src/main/resources/application.conf + isImplicit: true + } + + # 设置标签 user 相关信息 + { + name: user + type: { + source: csv + sink: client + } + path: "hdfs://namenode_ip:port/path/to/user.csv" + + # Exchange 1.1.0 添加了 csv.fields 参数 + # 如果 CSV 文件里不带表头,但是配置了 csv.fields, + # 则 fields 的配置必须与 csv.fields 保持一致, + # Exchange 会将 csv.fields 里的设置作为表头。 + # fields 与 nebula.fields 的顺序必须一一对应。 + fields: [userId] + + # 设置 Nebula Graph 中与 CSV 文件各列对应的属性名称, + # 必须与 fields 或者 csv.fields 的顺序一一对应。 + nebula.fields: [userId] + + # 如果配置了 csv.fields,无论 CSV 文件是否有表头, + # 均以这个参数指定的名称作为表头, + # fields 的配置必须与 csv.fields 的配置保持一致, + # 同时,vertex 的设置必须与 csv.fields 的设置相同。 + csv.fields: [userId] + + # vertex 的值必须与 fields 或者 csv.fields 中相应的列名保持一致。 + vertex: userId + separator: "," + header: false + batch: 256 + partition: 32 + + # isImplicit 设置说明,详见 https://github.com/vesoft-inc/nebula-java/blob + # /v1.0/tools/exchange/src/main/resources/application.conf + isImplicit: true + } + ] + # 处理边数据 + edges: [ + # 设置边类型 action 相关信息 + { + # Nebula Graph 中对应的边类型名称。 + name: action + type: { + # 指定数据源文件格式,设置为 csv。 + source: csv + + # 指定边数据导入 Nebula Graph 的方式, + # 可以设置为:client(以客户端形式导入)和 sst(以 SST 文件格式导入)。 + # 关于 SST 文件导入配置,参考文档:导入 SST 文件(https:// + # docs.nebula-graph.com.cn/nebula-exchange/ + # use-exchange/ex-ug-import-sst/)。 + sink: client + } + + # 指定 CSV 文件所在的 HDFS 路径,String 类型,必须以 hdfs:// 开头。 + path: "hdfs://namenode_ip:port/path/to/actions.csv" + + # 如果 CSV 文件里不带表头, + # 则写入 [_c0, _c1, _c2, ... _cn], + # 依次表示 CSV 文件中各数据列,作为 action 各属性值来源。 + # 如果 CSV 文件里有表头,则写入各列名。 + # fields 与 nebula.fields 的顺序必须一一对应。 + fields: [_c0, _c3, _c4, _c5, _c6, _c7, _c8] + + # Nebula Graph 中 action 的属性名称,必须与 fields 里的列顺序一一对应。 + nebula.fields: [actionId, duration, feature0, feature1, feature2, feature3, label] + + # Exchange 1.1.0 添加了 csv.fields 参数: + # 如果配置了 csv.fields,无论 CSV 文件是否有表头, + # 均以这个参数指定的名称作为表头, + # fields 的配置必须与 csv.fields 的配置保持一致。 + # csv.fields: [actionId, duration, feature0, feature1, feature2, feature3, label] + + # 边起点和边终点 VID 数据来源, + # 如果不是 int 类型数据,则添加 policy 指定 VID 映射策略,建议设置为 "hash"。 + source: _c1 + target: { + field: _c2 + policy: "hash" + } + + # 标明数据源中数据分隔方式,默认为英文逗号(,)。 + separator: "," + + # 如果 CSV 文件中有表头,header 设置为 true。 + # 如果 CSV 文件中没有表头,header 设置为 false(默认)。 + header: false + + # 单次向 Nebula Graph 写入的最大边数据量。 + batch: 256 + + # 设置 Spark 分区数量。 + partition: 32 + isImplicit: true + } + ] + # 如果还有其他边,再添加其他边类型相关的设置。 +} +``` + +### 步骤 4. (可选)检查配置文件是否正确 + +完成配置后,运行以下命令检查配置文件格式是否正确。关于参数的说明,参考 [导入命令参数](../parameter-reference/ex-ug-para-import-command.md)。 + +```bash +$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.tools.importer.Exchange /path/to/exchange-1.1.0.jar -c /path/to/conf/csv_application.conf -D +``` + +### 步骤 5. 向 Nebula Graph 导入数据 + +运行以下命令将 CSV 文件数据导入到 Nebula Graph 中。关于参数的说明,参考 [导入命令参数](../parameter-reference/ex-ug-para-import-command.md)。 + +```bash +$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.tools.importer.Exchange /path/to/exchange-1.1.0.jar -c /path/to/conf/csv_application.conf +``` + +### 步骤 6. (可选)验证数据 + +您可以在 Nebula Graph 客户端(例如 Nebula Graph Studio)里执行语句,确认数据是否已导入,例如: + +```ngql +GO FROM 1 OVER action; +``` + +如果返回边终点(`action._dst`)即表明数据已导入。 + +您也可以使用 db_dump 工具统计数据是否已经全部导入。详细的使用信息参考 [Dump Tool](https://docs.nebula-graph.com.cn/manual-CN/3.build-develop-and-administration/5.storage-service-administration/data-export/dump-tool/)。 + +### 步骤 7. (可选)在 Nebula Graph 中重构索引 + +导入数据后,您可以在 Nebula Graph 中重新创建并重构索引。详细信息,参考[《Nebula Graph Database 手册》](https://docs.nebula-graph.com.cn/manual-CN/2.query-language/4.statement-syntax/1.data-definition-statements/ "点击前往 Nebula Graph 网站")。 diff --git a/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-from-neo4j.md b/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-from-neo4j.md new file mode 100644 index 0000000..c346b8b --- /dev/null +++ b/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-from-neo4j.md @@ -0,0 +1,497 @@ + +# 导入 Neo4j 数据 + +您可以使用 Exchange 将 Neo4j 数据离线批量导入 Nebula Graph 数据库。 + +## 实现方法 + +Exchange 使用 **Neo4j Driver 4.0.1** 实现对 Neo4j 数据的读取。执行批量导出之前,您需要在配置文件中写入针对标签(label)和关系类型(Relationship Type)自动执行的 Cypher 语句,以及 Spark 分区数,提高数据导出性能。 + +Exchange 读取 Neo4j 数据时需要完成以下工作: + +1. Exchange 中的 Reader 会将配置文件中 `exec` 部分的 Cypher `RETURN` 语句后面的语句替换为 `COUNT(*)`,并执行这个语句,从而获取数据总量,再根据 Spark 分区数量计算每个分区的起始偏移量和大小。 +2. (可选)如果用户配置了 `check_point_path` 目录,Reader 会读取目录中的文件。如果当前处于续传的状态,Reader 会计算每个 Spark 分区应该有的偏移量和大小。 +3. 在每个 Spark 分区里,Exchange 中的 Reader 会在 Cypher 语句后面添加不同的 `SKIP` 和 `LIMIT` 语句,调用 Neo4j Driver 并行执行,将数据分布到不同的 Spark 分区中。 +4. Reader 最后将返回的数据处理成 DataFrame。 + +至此,Exchange 即完成了对 Neo4j 数据的导出。之后,数据被并行写入 Nebula Graph 数据库中。 + +整个过程如下图所示。 + +![Nebula Graph® Exchange 从 Neo4j 数据库中导出数据再并行导入 Nebula Graph 数据库中](../figs/ex-ug-002.png "Nebula Graph® Exchange 迁移 Neo4j 数据") + +本文以一个示例说明如何使用 Exchange 将 Neo4j 的数据批量导入 Nebula Graph 数据库。 + +> **说明**:本文仅说明如何以客户端形式迁移数据。您也能通过 SST 文件将 Neo4j 的数据批量转入 Nebula Graph 数据库,具体操作基本相同,仅配置文件修改有差异,详细信息参考 [导入 SST 文件](ex-ug-import-sst.md)。 + +## 示例场景 + +假设您在 Neo4j 数据库里有一个图数据集,需要使用 Exchange 将数据迁移到 Nebula Graph 数据库中。 + +### 环境配置 + +以下为本示例中的环境配置信息: + +- 服务器规格: + - CPU:Intel(R) Xeon(R) CPU E5-2697 v3 @ 2.60GHz + - CPU 内核数:14 + - 内存:251 GB +- Spark:单机版,2.4.6 pre-build for Hadoop 2.7 +- Neo4j:3.5.20 Community Edition +- Nebula Graph:V1.0.1,使用 Docker Compose 部署。详细信息,参考 [使用 Docker Compose 部署 Nebula Graph](https://github.com/vesoft-inc/nebula-docker-compose/blob/master/README_zh-CN.md) + +### 数据集信息 + +Neo4j 的数据集信息如下: + +- 两种标签(此处命名为 tagA 和 tagB),共计 100 万个节点(node)。 +- 一种连接上述两类点的关系类型(Relationship Type,此处命名为 edgeAB),共计 1000 万条关系边(Relationship)。 + +上述三者分别拥有如下表所示的属性。 + +| 要素名称 | 属性 **idInt** | 属性 **idString** | 属性 **tboolean** | 属性 **tdouble** | +| :--- | :--- | :--- | :--- | --- | +| tagA | `int` | `string` | `bool` | `double` | +| tagB | `int` | `string` | `bool` | `double` | +| edgeAB | `int` | `string` | `bool` | `double` | + +### 数据库信息 + +在本示例中 Neo4j 数据库和 Nebula Graph 数据库的信息如下: + +- Neo4j 数据库: + - 服务器地址及端口为:`bolt://127.0.0.1:7687` + - 用户名:_neo4j_ + - 密码:_neo4j_ + +- Nebula Graph 数据库: + - 服务器地址及端口为:`127.0.0.1:3699` + - 用户名:本示例中 Nebula Graph 数据库没有启用身份认证,所以,用户名为 _user_ + - 密码:_password_ + +## 前提条件 + +开始迁移数据之前,您需要确保以下信息: + +- 已经完成 Exchange 编译。详细信息,参考 [编译 Exchange](../ex-ug-compile.md)。 + +- 已经安装了 Spark。 + +- 在 Nebula Graph 中创建图数据模式所需的所有信息,包括标签和边类型的名称、属性等。 + +## 操作步骤 + +### 步骤 1. 在 Nebula Graph 中构建图数据模式(Schema) + +根据示例场景,按以下步骤完成 Nebula Graph 构建图数据模式: + +1. 确认图数据模式要素:Neo4j 中的标签和关系类型及其属性与 Nebula Graph 中的数据模式要素对应关系如下表所示。 + + | Neo4j 要素 | Nebula Graph 要素 | 要素名称 | + | :--- | :--- | :--- | + | Node | Tag | tagA 和 tagB | + | Relationship Type | Edge Type | edgAB | + +2. 确认 Nebula Graph 需要的分区数量:全集群硬盘数量 * (2 至 10)。本示例中假设为 10。 + +3. 确认 Nebula Graph 需要的副本数量。本示例中假设为 1。 + +4. 在 Nebula Graph 里创建一个图空间 **test**,并创建一个图数据模式,如下所示。 + + ```ngql + -- 创建图空间,本示例中假设只需要一个副本 + nebula> CREATE SPACE test(partition_num=10, replica_factor=1); + + -- 选择图空间 test + nebula> USE test; + + -- 创建标签 tagA + nebula> CREATE TAG tagA(idInt int, idString string, tboolean bool, tdouble double); + + -- 创建标签 tagB + nebula> CREATE TAG tagB(idInt int, idString string, tboolean bool, tdouble double); + + -- 创建边类型 edgeAB + nebula> CREATE EDGE edgeAB(idInt int, idString string, tboolean bool, tdouble double); + ``` + +关于 Nebula Graph 构图的更多信息,参考《Nebula Graph Database 手册》的 [快速开始](https://docs.nebula-graph.com.cn/manual-CN/1.overview/2.quick-start/1.get-started/ "点击前往 Nebula Graph 网站")。 + +### 步骤 2. 配置源数据 + +为了提高 Neo4j 数据的导出速度,在 Neo4j 数据库中为 tagA 和 tagB 的 `idInt` 属性创建索引。详细信息,参考 Neo4j 用户手册。 + +### 步骤 3. 修改配置文件 + +完成 Exchange 编译后,进入 `nebula-java/tools/exchange` 目录,您可以参考 `target/classes/server_application.conf` 修改配置文件。在本示例中,文件被重命名为 `neo4j_application.conf`。以下仅详细说明点和边数据的配置信息,本次示例中未使用的配置项已被注释,但是提供了配置说明。Spark 和 Nebula Graph 相关配置,参考 [Spark 参数](../parameter-reference/ex-ug-paras-spark.md)、[Nebula Graph 参数](../parameter-reference/ex-ug-paras-nebulagraph.md)。 + +```conf +{ + # Spark 相关配置 + spark: { + app: { + name: Spark Writer + } + + driver: { + cores: 1 + maxResultSize: 1G + } + + cores { + max: 16 + } + } + + # Nebula Graph 相关配置 + nebula: { + address:{ + # 以下为 Nebula Graph 的 Graph 服务和 Meta 服务所在机器的 IP 地址及端口。 + # 如果有多个地址,格式为 "ip1:port","ip2:port","ip3:port"。 + # 不同地址之间以英文逗号 (,) 隔开。 + graph:["127.0.0.1:3699"] + meta:["127.0.0.1:45500"] + } + # 填写的账号必须拥有 Nebula Graph 相应图空间的写数据权限。 + user: user + pswd: password + # 填写 Nebula Graph 中需要写入数据的图空间名称。 + space: test + connection { + timeout: 3000 + retry: 3 + } + execution { + retry: 3 + } + error: { + max: 32 + output: /tmp/errors + } + rate: { + limit: 64M + timeout: 1000 + } + } + + # 处理点数据 + tags: [ + # 设置标签相关信息 + { + name: tagA + # 设置 Neo4j 数据库服务器地址,String 类型,格式必须为 "bolt://ip:port"。 + server: "bolt://127.0.0.1:7687" + + # Neo4j 数据库登录账号和密码。 + user: neo4j + password: neo4j + + # 传输是否加密,默认值为 false,表示不加密;设置为 true 时,表示加密。 + encryption: false + + # 设置源数据所在 Neo4j 数据库的名称。如果您使用 Community Edition Neo4j,不支持这个参数。 + # database: graph.db + + type: { + # 指定数据来源,设置为 neo4j。 + source: neo4j + # 指定点数据导入 Nebula Graph 的方式, + # 可以设置为:client(以客户端形式导入)和 sst(以 SST 文件格式导入)。 + # 关于 SST 文件导入配置,参考文档:导入 SST 文件(https:// + # docs.nebula-graph.com.cn/nebula-exchange/ + # use-exchange/ex-ug-import-sst/)。 + sink: client + } + + # 指定 Nebula Graph Schema 中标签对应的属性名称,以列表形式列出, + # 与 tags.fields 列表中的属性名称一一对应,形成映射关系, + # 多个属性名称之间以英文逗号(,)隔开。 + nebula.fields: [idInt, idString, tdouble, tboolean] + + # 指定源数据中与 Nebula Graph 标签对应的属性名称, + # 以列表形式列出,多个属性名称之间以英文逗号(,)隔开, + # 列出的属性名称必须与 exec 中列出的属性名称保持一致。 + fields : [idInt, idString, tdouble, tboolean] + + # 将源数据中某个属性的值作为 Nebula Graph 点 VID 的来源, + # 如果属性为 int 或者 long 类型,使用 vertex 设置 VID 列。 + vertex: idInt + # 如果数据不是 int 类型,则添加 vertex.policy 指定 VID 映射策略,建议设置为 "hash"。 + # vertex { + # field: name + # policy: "hash" + #} + + # Spark 的分区数量,默认值为 32。 + partition: 10 + + # 单次写入 Nebula Graph 的点数据量,默认值为 256。 + batch: 2000 + + # 设置保存导入进度信息的目录,用于断点续传, + # 如果未设置,表示不启用断点续传。 + check_point_path: "file:///tmp/test" + + # 写入 Cypher 语句,从 Neo4j 数据库中检索打了某种标签的点的属性,并指定别名 + # Cypher 语句不能以英文分号(`;`)结尾。 + exec: "match (n:tagA) return n.idInt as idInt, n.idString as idString, n.tdouble as tdouble, n.tboolean as tboolean order by n.idInt" + } + # 如果有多个标签,则参考以上说明添加更多的标签相关信息。 + ] + + # 处理边数据 + edges: [ + { + # 指定 Nebula Graph 中的边类型名称。 + name: edgeAB + type: { + # 指定数据来源,设置为 neo4j。 + source: neo4j + + # 指定边数据导入 Nebula Graph 的方式, + # 可以设置为:client(以客户端形式导入)和 sst(以 SST 文件格式导入)。 + # 关于 SST 文件导入配置,参考文档:导入 SST 文件(https:// + # docs.nebula-graph.com.cn/nebula-exchange/ + # use-exchange/ex-ug-import-sst/)。 + sink: client + } + + # 设置 Neo4j 数据库的信息,包括 IP 地址、端口、用户名和密码。 + server: "bolt://127.0.0.1:7687" + user: neo4j + password: neo4j + + # 写入 Cypher 语句,表示从 Neo4j 数据库中查询关系属性。 + # Cypher 语句不能以英文分号(`;`)结尾。 + exec: "match (a:tagA)-[r:edgeAB]->(b:tagB) return a.idInt, b.idInt, r.idInt as idInt, r.idString as idString, r.tdouble as tdouble, r.tboolean as tboolean order by id(r)" + + # 在 fields 里指定 Neo4j 中关系的属性名称,其对应的 value + # 会作为 Nebula Graph 中 edgeAB 的属性(nebula.fields)值来源 + # fields 和 nebula.fields 里的配置必须一一对应 + # 如果需要指定多个列名称,用英文逗号(,)隔开 + fields: [r.idInt, r.idString, r.tdouble, r.tboolean] + nebula.fields: [idInt, idString, tdboule, tboolean] + + # 指定源数据中某个属性的值作为 Nebula Graph 边的起始点 VID。 + # 如果属性为 `int` 或者 `long` 类型,使用 source.field 设置起始点 VID 列 + # source.field: field_name + # 如果不是上述类型的属性,则添加 source.policy 指定 VID 映射策略,建议设置为 "hash"。 + source: { + field: a.idInt + policy: "hash" + } + + # 指定源数据中某个属性的值作为 Nebula Graph 边的终点 VID。 + # 如果属性为 `int` 或者 `long` 类型,使用 target.field 设置终点 VID 列 + # target.field: field_name + # 如果不是上述类型的属性,则添加 target.policy 指定 VID 映射策略,建议设置为 "hash"。 + target: { + field: b.idInt + policy: "hash" + } + + # 将源数据中某一列数据作为 Nebula Graph 中边的 Rank 值来源。 + ranking: idInt + + # Spark 的分区数量,默认值为 32。 + # 为减轻 Neo4j 的排序压力,将 partition 设置为 1 + partition: 1 + + + + # 单次写入 Nebula Graph 的点数据量,默认值为 256 + batch: 1000 + + # 设置保存导入进度信息的目录,用于断点续传。如果未设置,表示不启用断点续传。 + check_point_path: /tmp/test + } + ] +} +``` + +#### exec 配置说明 + +在配置源数据的 `tags.exec` 或者 `edges.exec` 参数时,需要写入 Cypher 查询语句。为了保证每次查询结果排序一致,并且为了防止在导入时丢失数据,强烈建议您在 Cypher 查询语句中加入 `ORDER BY` 子句,同时,为了提高数据导入效率,最好选取有索引的属性作为排序的属性。如果没有索引,您也可以观察默认的排序,选择合适的属性用于排序,以提高效率。如果默认的排序找不到规律,您可以根据点或关系的 ID 进行排序,并且将 `partition` 设置为一个尽量小的值,减轻 Neo4j 的排序压力。 + +> **说明**:使用 `ORDER BY` 子句会延长数据导入的时间。 + +另外,Exchange 需要在不同 Spark 分区执行不同 `SKIP` 和 `LIMIT` 的 Cypher 语句,所以,在 `tags.exec` 和 `edges.exec` 对应的 Cypher 语句中不能含有 `SKIP` 和 `LIMIT` 子句。 + +#### tags.vertex 或 edges.vertex 配置说明 + +Nebula Graph 在创建点和边时会将 ID 作为唯一主键,如果主键已存在则会覆盖该主键中的数据。所以,假如将某个 Neo4j 属性值作为 Nebula Graph 的 ID,而这个属性值在 Neo4j 中是有重复的,就会导致“重复 ID”,它们对应的数据有且只有一条会存入 Nebula Graph 中,其它的则会被覆盖掉。由于数据导入过程是并发地往 Nebula Graph 中写数据,最终保存的数据并不能保证是 Neo4j 中最新的数据。 + +#### check_point_path 配置说明 + +如果启用了断点续传功能,为避免数据丢失,在断点和续传之间,数据库不应该改变状态,例如不能添加数据或删除数据,同时,不能更改 `partition` 数量配置。 + +### 步骤 4. (可选)检查配置文件是否正确 + +完成配置后,运行以下命令检查配置文件格式是否正确。关于参数的说明,参考 [导入命令参数](../parameter-reference/ex-ug-para-import-command.md)。 + +```bash +$SPARK_HOME/bin/spark-submit --master "local[10]" --class com.vesoft.nebula.tools.importer.Exchange target/exchange-1.x.y.jar -c /path/to/conf/neo4j_application.conf -D +``` + +### 步骤 5. 向 Nebula Graph 导入数据 + +运行以下命令使用 Exchange 将 Neo4j 的数据迁移到 Nebula Graph 中。关于参数的说明,参考 [导入命令参数](../parameter-reference/ex-ug-para-import-command.md)。 + +```bash +$SPARK_HOME/bin/spark-submit --master "local[10]" --class com.vesoft.nebula.tools.importer.Exchange target/exchange-1.x.y.jar -c /path/to/conf/neo4j_application.conf +``` + +> **说明**:JAR 文件版本号以您实际编译得到的 JAR 文件名称为准。 + +### 步骤 6. (可选)验证数据 + +您可以在 Nebula Graph 客户端(例如 Nebula Graph Studio)里执行语句,确认数据是否已导入,例如: + +```ngql +GO FROM OVER edgeAB; +``` + +如果返回边终点(`edgeAB._dst`)即表明数据已导入。 + +您也可以使用 db_dump 工具统计数据是否已经全部导入。详细的使用信息参考 [Dump Tool](https://docs.nebula-graph.com.cn/manual-CN/3.build-develop-and-administration/5.storage-service-administration/data-export/dump-tool/)。 + +### 步骤 7. (可选)在 Nebula Graph 中重构索引 + +Exchange 导入数据时,并不会导入 Neo4j 数据库中的索引,所以,导入数据后,您可以在 Nebula Graph 中重新创建并重构索引。详细信息,参考[《Nebula Graph Database 手册》](https://docs.nebula-graph.com.cn/manual-CN/2.query-language/4.statement-syntax/1.data-definition-statements/ "点击前往 Nebula Graph 网站")。 + +## 性能说明 + +以下为单次测试数据,仅供参考。测试性能如下: + +- 导入 100 万个点,耗时 9 s +- 导入 1,000 万条边,耗时 43 s +- 总耗时:52 s + +## 附录:Neo4j 3.5 Community 和 Nebula Graph 1.0.1 对比 + +Neo4j 和 Nebula Graph 在系统架构、数据模型和访问方式上都有一些差异,部分差异可能会对您使用 Exchange 迁移数据产生影响。下表列出了常见的异同。 + +

                                          + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                          对比项Neo4j 3.5 ConmunityNebula Graph 1.0.1对使用 Exchange 的影响
                                          系统架构分布式仅 Enterprise 支持支持
                                          数据分片不支持支持
                                          开源协议AGPLApache 2.0
                                          开发语言JavaC++
                                          高可用不支持支持
                                          数据模型属性图
                                          SchemaSchema optional 或者 Schema free强 Schema +
                                            +
                                          • 必须在 Nebula Graph 中事先创建Schema
                                          • +
                                          • Neo4j 中的 Schema 必须与 Nebula Graph 的保持一致
                                          • +
                                          +
                                          点类型/边类型Label(可以没有 Label,Label 不决定属性 Schema)Tag/EdgeType(必须至少有一个 Tag,并且与 Schema 对应)
                                          点 ID/唯一主键点允许无主键(会有多条重复记录)。由内置 id() 标识,或者由约束来保证主键唯一。点必须有唯一标识符,称为 VID。VID 由应用程序生成。主键相同的重复记录只保留最新的一份。
                                          属性索引支持支持无法导入索引,必须在导入后再重新创建。
                                          约束(Constrains)支持不支持不会导入约束。
                                          事务支持不支持
                                          查询语句示例列出所有 labels 或 tagsMATCH (n) RETURN distinct labels(n);
                                          call db.labels();
                                          +
                                          SHOW TAGS;
                                          插入指定类型的点CREATE (:Person {age: 16})INSERT VERTEX <tag_name> (prop_name_list) VALUES <vid>:(prop_value_list)
                                          更新点属性SET n.name = VUPDATE VERTEX <vid> SET <update_columns>
                                          查询指定点的属性MATCH (n)
                                          WHERE ID(n) = vid
                                          RETURN properties(n)
                                          FETCH PROP ON <tag_name> <vid>
                                          查询指定点的某一类关系MATCH (n)-[r:edge_type]->() WHERE ID(n) = vidGO FROM <vid> OVER <edge_type>
                                          两点路径MATCH p =(a)-[]->(b)
                                          WHERE ID(a) = a_vid AND ID(b) = b_vid
                                          RETURN p
                                          FIND ALL PATH FROM <a_vid> TO <b_vid> OVER *
                                          diff --git a/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-hive.md b/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-hive.md new file mode 100644 index 0000000..862f89c --- /dev/null +++ b/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-hive.md @@ -0,0 +1,351 @@ +# 导入 HIVE 数据 + +本文以一个示例说明如何使用 Exchange 将存储在 HIVE 的数据导入 Nebula Graph。 + +## 数据集 + +本文以美国 Stanford Network Analysis Platform (SNAP) 提供的 [Social Network: MOOC User Action Dataset](https://snap.stanford.edu/data/act-mooc.html "点击前往 Stanford Network Analysis Platform (SNAP) 网站") 以及由公开网络上获取的不重复的 97 个课程名称作为示例数据集,包括: + +- 两类点(`user` 和 `course`),共计 7,144 个点。 +- 一种关系(`action`),共计 411,749 条边。 + +详细的数据集,您可以从 [nebula-web-docker](https://github.com/vesoft-inc/nebula-web-docker/tree/master/example/mooc-actions "点击前往 GitHub") 仓库中下载。 + +在本示例中,该数据集已经存入 HIVE 中名为 `mooc` 的数据库中,以 `users`、`courses` 和 `actions` 三个表存储了所有点和边的信息。以下为各个表的结构。 + +```sql +scala> sql("describe mooc.users").show ++--------+---------+-------+ +|col_name|data_type|comment| ++--------+---------+-------+ +| userid| bigint| null| ++--------+---------+-------+ + +scala> sql("describe mooc.courses").show ++----------+---------+-------+ +| col_name|data_type|comment| ++----------+---------+-------+ +| courseid| bigint| null| +|coursename| string| null| ++----------+---------+-------+ + +scala> sql("describe mooc.actions").show ++--------+---------+-------+ +|col_name|data_type|comment| ++--------+---------+-------+ +|actionid| bigint| null| +| srcid| bigint| null| +| dstid| string| null| +|duration| double| null| +|feature0| double| null| +|feature1| double| null| +|feature2| double| null| +|feature3| double| null| +| label| boolean| null| ++--------+---------+-------+ +``` + +> **说明**:Hive 的 `bigint` 与 Nebula Graph 的 `int` 对应。 + +## 环境配置 + +本文示例在 MacOS 下完成,以下是相关的环境配置信息: + +- 硬件规格: + - CPU:1.7 GHz Quad-Core Intel Core i7 + - 内存:16 GB + +- Spark:2.4.7,单机版 + +- Hadoop:2.9.2,伪分布式部署 + +- HIVE:2.3.7,Hive Metastore 数据库为 MySQL 8.0.22 + +- Nebula Graph:V1.2.0,使用 Docker Compose 部署。详细信息,参考 [使用 Docker Compose 部署 Nebula Graph](https://github.com/vesoft-inc/nebula-docker-compose/blob/master/README_zh-CN.md) + +## 前提条件 + +开始导入数据之前,您需要确认以下信息: + +- 已经完成 Exchange 编译。详细信息,参考 [编译 Exchange](../ex-ug-compile.md)。本示例中使用 Exchange v1.1.0。 + +- 已经安装 Spark。 + +- 已经安装并开启 Hadoop 服务,并已启动 Hive Metastore 数据库(本示例中为 MySQL)。 + +- 已经部署并启动 Nebula Graph,并获取: + - Graph 服务、Meta 服务所在机器的 IP 地址和端口信息。 + - Nebula Graph 数据库的拥有写权限的用户名及其密码。 + +- 在 Nebula Graph 中创建图数据模式(Schema)所需的所有信息,包括标签和边类型的名称、属性等。 + +## 操作步骤 + +### 步骤 1. 在 Nebula Graph 中创建 Schema + +按以下步骤在 Nebula Graph 中创建 Schema: + +1. 确认 Schema 要素:Nebula Graph 中的 Schema 要素如下表所示。 + + | 要素 | 名称 | 属性 | + | :--- | :--- | :--- | + | 标签(Tag) | `user` | `userId int` | + | 标签(Tag) | `course` | `courseId int, courseName string` | + | 边类型(Edge Type) | `action` | `actionId int, duration double, label bool, feature0 double, feature1 double, feature2 double, feature3 double` | + +2. 在 Nebula Graph 里创建一个图空间 **hive**,并创建一个 Schema,如下所示。 + + ```ngql + -- 创建图空间 + CREATE SPACE hive(partition_num=10, replica_factor=1); + + -- 选择图空间 hive + USE hive; + + -- 创建标签 user + CREATE TAG user(userId int); + + -- 创建标签 course + CREATE TAG course(courseId int, courseName string); + + -- 创建边类型 action + CREATE EDGE action (actionId int, duration double, label bool, feature0 double, feature1 double, feature2 double, feature3 double); + ``` + +关于 Nebula Graph 构图的更多信息,参考《Nebula Graph Database 手册》的 [快速开始](../../manual-CN/1.overview/2.quick-start/1.get-started/ "点击前往 Nebula Graph 网站")。 + +### 步骤 2. 使用 Spark SQL 确认 HIVE SQL 语句 + +启动 spark-shell 环境后,依次运行以下语句,确认 Spark 能读取 HIVE 中的数据。 + +```sql +scala> sql("select userid from mooc.users").show +scala> sql("select courseid, coursename from mooc.courses").show +scala> sql("select actionid, srcid, dstid, duration, feature0, feature1, feature2, feature3, label from mooc.actions").show +``` + +以下为 `mooc.actions` 表中读出的结果。 + +```mysql ++--------+-----+--------------------+--------+------------+------------+-----------+-----------+-----+ +|actionid|srcid| dstid|duration| feature0| feature1| feature2| feature3|label| ++--------+-----+--------------------+--------+------------+------------+-----------+-----------+-----+ +| 0| 0|Environmental Dis...| 0.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 1| 0| History of Ecology| 6.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 2| 0| Women in Islam| 41.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 3| 0| History of Ecology| 49.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 4| 0| Women in Islam| 51.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 5| 0|Legacies of the A...| 55.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 6| 0| ITP Core 2| 59.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 7| 0|The Research Pape...| 62.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 8| 0| Neurobiology| 65.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 9| 0| Wikipedia| 113.0|-0.319991479|-0.435701433|1.108826104|12.77723482|false| +| 10| 0|Media History and...| 226.0|-0.319991479|-0.435701433|0.607804941|149.4512115|false| +| 11| 0| WIKISOO| 974.0|-0.319991479|-0.435701433|1.108826104|3.344522776|false| +| 12| 0|Environmental Dis...| 1000.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 13| 0| WIKISOO| 1172.0|-0.319991479|-0.435701433|1.108826104|1.136866766|false| +| 14| 0| Women in Islam| 1182.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 15| 0| History of Ecology| 1185.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 16| 0|Human Development...| 1687.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 17| 1|Human Development...| 7262.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 18| 1| History of Ecology| 7266.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 19| 1| Women in Islam| 7273.0|-0.319991479|-0.435701433|0.607804941|0.936170765|false| ++--------+-----+--------------------+--------+------------+------------+-----------+-----------+-----+ +only showing top 20 rows +``` + +### 步骤 3. 修改配置文件 + +完成 Exchange 编译后,进入 `nebula-java/tools/exchange` 目录,根据 `target/classes/application.conf` 文件修改 HIVE 数据源相关的配置文件。在本示例中,文件被重命名为 `hive_application.conf`。以下仅详细说明点和边数据的配置信息,本次示例中未使用的配置项已被注释,但是提供了配置说明。Spark 和 Nebula Graph 相关配置,参考 [Spark 参数](../parameter-reference/ex-ug-paras-spark.md)和 [Nebula Graph 参数](../parameter-reference/ex-ug-paras-nebulagraph.md)。 + +```conf +{ + # Spark 相关配置 + spark: { + app: { + name: Spark Writer + } + driver: { + cores: 1 + maxResultSize: 1G + } + cores { + max: 16 + } + } + # Nebula Graph 相关配置 + nebula: { + address:{ + # 以下为 Nebula Graph 的 Graph 服务和 Meta 服务所在机器的 IP 地址及端口 + # 如果有多个地址,格式为 "ip1:port","ip2:port","ip3:port" + # 不同地址之间以英文逗号 (,) 隔开 + graph:["127.0.0.1:3699"] + meta:["127.0.0.1:45500"] + } + # 填写的账号必须拥有 Nebula Graph 相应图空间的写数据权限 + user: user + pswd: password + # 填写 Nebula Graph 中需要写入数据的图空间名称 + space: hive + connection { + timeout: 3000 + retry: 3 + } + execution { + retry: 3 + } + error: { + max: 32 + output: /tmp/errors + } + rate: { + limit: 1024 + timeout: 1000 + } + } + # 处理标签 + tags: [ + # 设置标签相关信息 + { + # Nebula Graph 中对应的标签名称。 + name: user + type: { + # 指定数据源文件格式,设置为 hive。 + source: hive + # 指定点数据导入 Nebula Graph 的方式, + # 可以设置为:client(以客户端形式导入)和 sst(以 SST 文件格式导入)。 + # 关于 SST 文件导入配置,参考文档:导入 SST 文件(https:// + # docs.nebula-graph.com.cn/nebula-exchange/ + # use-exchange/ex-ug-import-sst/)。 + sink: client + } + + # 设置读取数据库 mooc 中 users 表数据的 SQL 语句 + exec: "select userid from mooc.users" + + # 在 fields 里指定 users 表中的列名称,其对应的 value + # 会作为 Nebula Graph 中指定属性 userId (nebula.fields) 的数据源 + # fields 和 nebula.fields 里的配置必须一一对应 + # 如果需要指定多个列名称,用英文逗号(,)隔开 + fields: [userid] + nebula.fields: [userId] + + # 指定表中某一列数据为 Nebula Graph 中点 VID 的来源。 + # vertex.field 的值必须与上述 fields 中的列名保持一致。 + # 如果数据不是 int 类型,则添加 vertex.policy 指定 VID 映射策略,建议设置为 "hash",参考以下 course 标签的设置。 + vertex: userid + + # 单次写入 Nebula Graph 的最大点数据量。 + batch: 256 + + # Spark 分区数量 + partition: 32 + + # isImplicit 的设置说明参考:https://github.com/vesoft-inc/nebula-java/ + # blob/v1.0/tools/exchange/src/main/resources/application.conf + isImplicit: true + } + { + name: course + type: { + source: hive + sink: client + } + exec: "select courseid, coursename from mooc.courses" + fields: [courseid, coursename] + nebula.fields: [courseId, courseName] + + # 指定表中某一列数据为 Nebula Graph 中点 VID 的来源。 + # vertex.field 的值必须与上述 fields 中的列名保持一致。 + # 如果数据不是 int 类型,则添加 vertex.policy 指定 VID 映射策略,建议设置为 "hash"。 + vertex: { + field: coursename + policy: "hash" + } + batch: 256 + partition: 32 + isImplicit: true + } + + ] + + # 处理边数据 + edges: [ + # 设置边类型 action 相关信息 + { + # Nebula Graph 中对应的边类型名称。 + name: action + + type: { + # 指定数据源文件格式,设置为 hive。 + source: hive + + # 指定边数据导入 Nebula Graph 的方式, + # 可以设置为:client(以客户端形式导入)和 sst(以 SST 文件格式导入)。 + # 关于 SST 文件导入配置,参考文档:导入 SST 文件(https:// + # docs.nebula-graph.com.cn/nebula-exchange/ + # use-exchange/ex-ug-import-sst/)。 + sink: client + } + + # 设置读取数据库 mooc 中 actions 表数据的 SQL 语句 + exec: "select actionid, srcid, dstid, duration, feature0, feature1, feature2, feature3, label from mooc.actions" + + # 在 fields 里指定 actions 表中的列名称,其对应的 value + # 会作为 Nebula Graph 中 action 的属性(nebula.fields)值来源 + # fields 和 nebula.fields 里的配置必须一一对应 + # 如果需要指定多个列名称,用英文逗号(,)隔开 + fields: [actionid, duration, feature0, feature1, feature2, feature3, label] + nebula.fields: [actionId, duration, feature0, feature1, feature2, feature3, label] + + # 在 source 里,将 actions 表中某一列作为边起点数据源 + # 在 target 里,将 actions 表中某一列作为边终点数据源 + # 如果数据源是 int 或 long 类型,直接指定列名 + # 如果数据源不是 int 类型,则添加 vertex.policy 指定 VID 映射策略,建议设置为 "hash" + source: srcid + target: { + field: dstid + policy: "hash" + } + + # 单次写入 Nebula Graph 的最大点数据量。 + batch: 256 + + # Spark 分区数量 + partition: 32 + } + ] +} +``` + +### 步骤 4. (可选)检查配置文件是否正确 + +完成配置后,运行以下命令检查配置文件格式是否正确。关于参数的说明,参考 [导入命令参数](../parameter-reference/ex-ug-para-import-command.md)。 + +```bash +$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.tools.importer.Exchange /path/to/exchange-1.1.0.jar -c /path/to/conf/hive_application.conf -h -D +``` + +### 步骤 5. 向 Nebula Graph 导入数据 + +运行以下命令将 HIVE 中的数据导入到 Nebula Graph 中。关于参数的说明,参考 [导入命令参数](../parameter-reference/ex-ug-para-import-command.md)。 + +```bash +$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.tools.importer.Exchange /path/to/exchange-1.1.0.jar -c /path/to/conf/hive_application.conf -h +``` + +### 步骤 6. (可选)验证数据 + +您可以在 Nebula Graph 客户端(例如 Nebula Graph Studio)里执行语句,确认数据是否已导入,例如: + +```ngql +GO FROM 1 OVER action; +``` + +如果返回边终点(`action._dst`)即表明数据已导入。 + +您也可以使用 db_dump 工具统计数据是否已经全部导入。详细的使用信息参考 [Dump Tool](https://docs.nebula-graph.com.cn/manual-CN/3.build-develop-and-administration/5.storage-service-administration/data-export/dump-tool/)。 + +### 步骤 7. (可选)在 Nebula Graph 中重构索引 + +导入数据后,您可以在 Nebula Graph 中重新创建并重构索引。详细信息,参考[《Nebula Graph Database 手册》](https://docs.nebula-graph.com.cn/manual-CN/2.query-language/4.statement-syntax/1.data-definition-statements/ "点击前往 Nebula Graph 网站")。 diff --git a/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-json.md b/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-json.md new file mode 100644 index 0000000..2befa8c --- /dev/null +++ b/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-json.md @@ -0,0 +1,288 @@ +# 导入 JSON 文件数据 + +本文以一个示例说明如何使用 Exchange 将存储在 HDFS 上的 JSON 文件数据导入 Nebula Graph。 + +## 数据集 + +本示例所用 JSON 文件(test.json)结构为:`{"source":int, "target":int, "likeness":double}`,表示 `source` 与 `target` 之间一种 `like` 关系。共计 21,645 条数据。 + +以下为部分示例数据: + +```json +{"source":53802643,"target":87847387,"likeness":0.34} +{"source":29509860,"target":57501950,"likeness":0.40} +{"source":97319348,"target":50240344,"likeness":0.77} +{"source":94295709,"target":8189720,"likeness":0.82} +{"source":78707720,"target":53874070,"likeness":0.98} +{"source":23399562,"target":20136097,"likeness":0.47} +``` + +## 环境配置 + +本文示例在 MacOS 下完成,以下是相关的环境配置信息: + +- 硬件规格: + - CPU:1.7 GHz Quad-Core Intel Core i7 + - 内存:16 GB + +- Spark:2.3.0,单机版 + +- Hadoop:2.9.2,伪分布式部署 + +- Nebula Graph:V1.1.0,使用 Docker Compose 部署。详细信息,参考 [使用 Docker Compose 部署 Nebula Graph](https://github.com/vesoft-inc/nebula-docker-compose/blob/master/README_zh-CN.md) + +## 前提条件 + +开始迁移数据之前,您需要确认以下信息: + +- 已经完成 Exchange 编译。详细信息,参考 [编译 Exchange](../ex-ug-compile.md)。本示例中使用 Exchange v1.0.1。 + +- 已经安装 Spark。 + +- 已经安装并开启 Hadoop 服务。 + +- 已经部署并启动 Nebula Graph,并获取: + - Graph 服务、Meta 服务所在机器的 IP 地址和端口信息。 + - Nebula Graph 数据库的拥有写权限的用户名及其密码。 + +- 在 Nebula Graph 中创建图数据模式(Schema)所需的所有信息,包括标签和边类型的名称、属性等。 + +## 操作步骤 + +### 步骤 1. 在 Nebula Graph 中创建 Schema + +分析 JSON 文件中的数据,按以下步骤在 Nebula Graph 中创建 Schema: + +1. 确认 Schema 要素:Nebula Graph 中的 Schema 要素如下表所示。 + + | 要素 | 名称 | 属性 | + | :--- | :--- | :--- | + | 标签(Tag) | `source` | `srcId int` | + | 标签(Tag) | `target` | `dstId int` | + | 边类型(Edge Type) | `like` | `likeness double` | + +2. 在 Nebula Graph 里创建一个图空间 **json**,并创建一个 Schema,如下所示。 + + ```ngql + -- 创建图空间 + CREATE SPACE json (partition_num=10, replica_factor=1); + + -- 选择图空间 json + USE json; + + -- 创建标签 source + CREATE TAG source (srcId int); + + -- 创建标签 target + CREATE TAG target (dstId int); + + -- 创建边类型 like + CREATE EDGE like (likeness double); + ``` + +关于 Nebula Graph 构图的更多信息,参考《Nebula Graph Database 手册》的 [快速开始](https://docs.nebula-graph.com.cn/manual-CN/1.overview/2.quick-start/1.get-started/ "点击前往 Nebula Graph 网站")。 + +### 步骤 2. 处理 JSON 文件 + +分别创建点和边数据 JSON 文件。同时,JSON 文件必须存储在 HDFS 里,并获取文件存储路径。 + +> **说明**:本示例中仅使用一个 JSON 文件同时写入点和边数据,其中,表示 source 和 target 的部分点数据是重复的,所以,在写入数据时,这些点会被重复写入。向 Nebula Graph 插入点或边时,允许重复插入,但是最后读取时以最后一次写入的数据为准,所以,并不影响使用。在实际使用时,最好分别创建点和边数据文件,提高数据写入速度。 + +### 步骤 3. 修改配置文件 + +完成 Exchange 编译后,进入 `nebula-java/tools/exchange` 目录,根据 `target/classes/application.conf` 文件修改 果断 数据源相关的配置文件。在本示例中,文件被重命名为 `json_application.conf`。以下配置文件中提供了 JSON 源数据所有配置项。本次示例中未使用的配置项已被注释,但是提供了配置说明。Spark 和 Nebula Graph 相关配置,参考 [Spark 参数](../parameter-reference/ex-ug-paras-spark.md)和 [Nebula Graph 参数](../parameter-reference/ex-ug-paras-nebulagraph.md)。 + +```conf +{ + # Spark 相关配置 + spark: { + app: { + name: Spark Writer + } + + driver: { + cores: 1 + maxResultSize: 1G + } + + cores { + max: 16 + } + } + + # Nebula Graph 相关配置 + nebula: { + address:{ + # 以下为 Nebula Graph 的 Graph 服务和 Meta 服务所在机器的 IP 地址及端口 + # 如果有多个地址,格式为 "ip1:port","ip2:port","ip3:port" + # 不同地址之间以英文逗号 (,) 隔开 + graph:["127.0.0.1:3699"] + meta:["127.0.0.1:45500"] + } + # 填写的账号必须拥有 Nebula Graph 相应图空间的写数据权限 + user: user + pswd: password + + # 填写 Nebula Graph 中需要写入数据的图空间名称 + space: json + + connection { + timeout: 3000 + retry: 3 + } + + execution { + retry: 3 + } + + error: { + max: 32 + output: /tmp/errors + } + + rate: { + limit: 1024 + timeout: 1000 + } + } + + # 处理标签 + tags: [ + # 设置标签 source 相关信息 + { + # 设置为 Nebula Graph 中对应的标签名称 + name: source + type: { + # 指定数据源文件格式,设置为 json。 + source: json + + # 指定标签数据导入 Nebula Graph 的方式, + # 可以设置为:client(以客户端形式导入)和 sst(以 SST 文件格式导入)。 + # 关于 SST 文件导入配置,参考文档:导入 SST 文件。 + sink: client + } + + # JSON 文件所在的 HDFS 路径,String 类型,必须以 hdfs:// 开头。 + path: "hdfs://namenode_ip:port/path/to/test.json" + + # 在 fields 里指定 JSON 文件中 key 名称,其对应的 value + # 会作为 Nebula Graph 中指定属性 srcId 的数据源 + # 如果需要指定多个值,用英文逗号(,)隔开 + fields: ["source"] + nebula.fields: ["srcId"] + + # 将 JSON 文件中某个 key 对应的值作为 Nebula Graph 中点 VID 的来源 + # 如果 VID 源数据不是 int 类型,则使用以下内容来代替 vertex 的设置,在其中指定 VID 映射策略,建议设置为 "hash"。 + # vertex: { + # field: key_name_in_json + # policy: "hash" + # } + vertex: source + + batch: 256 + partition: 32 + + # isImplicit 设置说明,详见 https://github.com/vesoft-inc/ + # nebula-java/blob/v1.0/tools/exchange/src/main/resources/ + # application.conf + isImplicit: true + } + # 设置标签 target 相关信息 + { + name: target + type: { + source: json + sink: client + } + path: "hdfs://namenode_ip:port/path/to/test.json" + fields: ["target"] + nebula.fields: ["dstId"] + vertex: "target" + batch: 256 + partition: 32 + isImplicit: true + } + # 如果还有其他标签,参考以上配置添加 + ] + + # 处理边数据 + edges: [ + # 设置边类型 like 相关信息 + { + # Nebula Graph 中对应的边类型名称。 + name: like + type: { + # 指定数据源文件格式,设置为 json。 + source: json + + # 指定边数据导入 Nebula Graph 的方式, + # 可以设置为:client(以客户端形式导入)和 sst(以 SST 文件格式导入)。 + # 关于 SST 文件导入配置,参考文档:导入 SST 文件(https:// + # docs.nebula-graph.com.cn/nebula-exchange/ + # use-exchange/ex-ug-import-sst/)。 + sink: client + } + + # 指定 JSON 文件所在的 HDFS 路径,String 类型,必须以 hdfs:// 开头。 + path: "hdfs://namenode_ip:port/path/to/test.json" + + # 在 fields 里指定 JSON 文件中 key 名称,其对应的 value + # 会作为 Nebula Graph 中指定属性 likeness 的数据源 + # 如果需要指定多个值,用英文逗号(,)隔开 + fields: ["likeness"] + nebula.fields: ["likeness"] + + # 将 JSON 文件中某两个 key 对应的值作为 Nebula Graph 中边起点和边终点 VID 的来源 + # 如果 VID 源数据不是 int 类型,则使用以下内容来代替 source + # 和/或 target 的设置,在其中指定 VID 映射策略,建议设置为 "hash"。 + # source: { + # field: key_name_in_json + # policy: "hash" + # } + # target: { + # field: key_name_in_json + # policy: "hash" + # } + source: "source" + target: "target" + + batch: 256 + partition: 32 + isImplicit: true + } + # 如果还有其他边类型,参考以上配置添加 + ] +} +``` + +### 步骤 4. (可选)检查配置文件是否正确 + +完成配置后,运行以下命令检查配置文件格式是否正确。关于参数的说明,参考 [导入命令参数](../parameter-reference/ex-ug-para-import-command.md)。 + +```bash +$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.tools.importer.Exchange /path/to/exchange-1.0.1.jar -c /path/to/conf/json_application.conf -D +``` + +### 步骤 5. 向 Nebula Graph 导入数据 + +运行以下命令将 JSON 文件数据导入 Nebula Graph 中。关于参数的说明,参考 [导入命令参数](../parameter-reference/ex-ug-para-import-command.md)。 + +```bash +$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.tools.importer.Exchange /path/to/exchange-1.0.1.jar -c /path/to/conf/json_application.conf +``` + +### 步骤 6. (可选)验证数据 + +您可以在 Nebula Graph 客户端(例如 Nebula Graph Studio)里执行语句,确认数据是否已导入,例如: + +```ngql +GO FROM 53802643 OVER like; +``` + +如果返回边终点(`like._dst`)即表明数据已导入。 + +您也可以使用 db_dump 工具统计数据是否已经全部导入。详细的使用信息参考 [Dump Tool](https://docs.nebula-graph.com.cn/manual-CN/3.build-develop-and-administration/5.storage-service-administration/data-export/dump-tool/)。 + +### 步骤 7. (可选)在 Nebula Graph 中重构索引 + +导入数据后,您可以在 Nebula Graph 中重新创建并重构索引。详细信息,参考[《Nebula Graph Database 手册》](https://docs.nebula-graph.com.cn/manual-CN/2.query-language/4.statement-syntax/1.data-definition-statements/ "点击前往 Nebula Graph 网站")。 diff --git a/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-sst.md b/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-sst.md new file mode 100644 index 0000000..44fa2f5 --- /dev/null +++ b/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-sst.md @@ -0,0 +1,98 @@ +# 导入 SST 文件 + +Nebula Exchange 能将不同来源的数据转换成 SST 文件后再导入 Nebula Graph 数据库中。本文描述 Exchange 将源数据转换为 SST 文件并导入 Nebula Graph 的实现原理,并提供示例说明如何修改配置文件完成 SST 文件导入操作。 + +> **说明**:仅 Linux 系统支持导入 SST 文件。 + +## 实现方法 + +Nebula Graph 底层使用 RocksDB 作为键值型存储引擎。RocksDB 是基于磁盘的存储引擎,数据以 Sorted String Table(SSTable)格式存放。SSTable 是一个内部包含了任意长度、排好序的键值对 <key,value> 集合的文件,用于高效地存储大量的键值型数据。 + +RocksDB 提供了一系列 API 用于创建及导入 SST 文件,有助于您快速导入海量数据。 + +处理 SST 文件的整个过程主要由 Exchange 的 Reader、sstProcessor 和 sstWriter 完成。整个数据处理过程如下所示: + +1. Exchange 的 Reader 从数据源中读取数据。 + +2. sstProcessor 按照 Nebula Graph 要求的格式生成 SST 文件,存储到本地,并上传到 HDFS。SST 文件主要包含点和边两类数据,其中, + + - 表示点的键包括:分区信息、点 ID(VID)、标签类型信息和标签版本信息。 + - 表示边的键包括:分区信息、起点和终点 ID(`rsc_vid` 和 `dst_vid`)、边类型信息、边排序信息和边版本信息。 + - 对应的值主要包含各个属性键值对序列化信息。 + +3. SstFileWriter 创建 SST 文件:Exchange 会创建一个 SstFileWriter 对象,然后打开一个文件并插入数据。生成 SST 文件时,行数据必须严格按照增序进行写入。 + +4. 生成 SST 文件之后,RocksDB 通过 `IngestExternalFile()` 方法将 SST 文件导入到 Nebula Graph 之中。例如: + + ``` + IngestExternalFileOptions ifo; + // Ingest the 2 passed SST files into the DB + Status s = db_->IngestExternalFile({"/home/usr/file1.sst", "/home/usr/file2.sst"}, ifo); + if (!s.ok()) { + printf("Error while adding file %s and %s, Error %s\n", + file_path1.c_str(), file_path2.c_str(), s.ToString().c_str()); + return 1; + } + ``` + + 调用 `IngestExternalFile()` 方法时,RocksDB 默认会将文件拷贝到数据目录,并且阻塞 RocksDB 写入操作。如果 SST 文件中的键范围覆盖了 Memtable 键的范围,则将 Memtable 落盘(flush)到硬盘。将 SST 文件放置在 LSM 树最优位置后,为文件分配一个全局序列号,并打开写操作。 + +## 使用示例 + +不同来源的数据,导入 Nebula Graph 的操作与客户端形式导入操作基本相同,但是有以下差异: + +- 环境里必须部署 HDFS。 +- 在配置文件中,必须做以下修改: + - 源数据的标签和边类型配置:`tags.type.sink` 和 `edges.type.sink` 必须配置为 `sst`。 + - Nebula Graph 相关配置里,需要添加 Nebula Graph 数据库 Meta 服务的 IP 地址和端口,并添加 SST 文件在本地和 HDFS 的存储路径。 + + ```conf + # Nebula Graph 相关配置 + nebula: { + address: { + # 添加 Nebula Graph 数据库 Graph 服务的 IP 地址和端口 + graph: ["127.0.0.1:3699"] + # 添加 Nebula Graph 数据库 Meta 服务的 IP 地址和端口 + meta:["127.0.0.1:45500"] + } + user: user + pswd: password + space: test + path:{ + # 指定 SST 文件保存到本地的路径 + local:/Users/example/path + # 指定上传 SST 文件的 HDFS 路径 + remote:/example/ + } + + connection { + timeout: 3000 + retry: 3 + } + + execution { + retry: 3 + } + + error: { + max: 32 + output: /tmp/errors + } + + rate: { + limit: 64M + timeout: 1000 + } + } + ``` + +详细描述请参考不同数据源的操作示例: + +- [导入 Neo4j 数据](ex-ug-import-from-neo4j.md) +- [导入 HIVE 数据](ex-ug-import-hive.md) +- [导入 CSV 文件数据](ex-ug-import-from-csv.md) +- [导入 JSON 文件数据](ex-ug-import-json.md) +- 导入 HBase 数据[doc_TODO] +- 导入 HIVE 数据[doc_TODO] +- 导入 Kafka 数据[doc_TODO] +- 导入 MySQL 数据[doc_TODO] diff --git a/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-steps.md b/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-steps.md new file mode 100644 index 0000000..2d58140 --- /dev/null +++ b/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-steps.md @@ -0,0 +1,42 @@ +# 导入数据步骤 + +您可以按本文描述的步骤使用 Exchange 将指定来源的数据导入到 Nebula Graph 中。 + +## 前提条件 + +开始迁移数据之前,您需要确保以下信息: + +- 已经安装部署了 Nebula Graph 并获取查询引擎所在服务器的 IP 地址、用户名和密码。 + +- 已经完成 Exchange 编译。详细信息,参考 [编译 Nebula Exchange](../ex-ug-compile.md)。 + +- 已经安装 Spark。 + +- 在 Nebula Graph 中创建图数据模式需要的所有信息,包括标签和边类型的名称、属性等。 + +## 操作步骤 + +按以下步骤将不同来源的数据导入 Nebula Graph 数据库: + +1. 在 Nebula Graph 中构图,包括创建图空间、创建图数据模式(Schema)。 + +2. (可选)处理源数据。例如,在导入 Neo4j 时,为提高导出速度,在 Neo4j 数据库中为指定的标签属性创建索引。 + +3. 分别修改 Spark、Nebula Graph 以及点和边数据的配置文件。 + > **说明**:完成 Exchange 编译后,进入 `nebula-java/tools/exchange` 目录,您可以参考 `target/classes/server_application.conf`、`target/classes/application.conf` 和 `target/classes/stream_application.conf` 文件修改配置文件。 + +4. (可选)检查配置文件是否正确。 + +5. 向 Nebula Graph 导入数据。 + +6. 在 Nebula Graph 中验证数据是否已经完整导入。 + +7. (可选)在 Nebula Graph 中重构索引。 + +关于详细操作步骤,根据数据来源不同,您可以参考相应的操作示例: + +- [导入 Neo4j 数据](ex-ug-import-from-neo4j.md) +- [导入 HIVE 数据](ex-ug-import-hive.md) +- [导入 CSV 文件数据](ex-ug-import-from-csv.md) +- [导入 JSON 文件数据](ex-ug-import-json.md) +- [导入 SST 文件数据](ex-ug-import-sst.md) From 0b2afa1e2164afc2e36f7d4c28b40b0580d4af6f Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 9 Apr 2021 17:39:21 +0800 Subject: [PATCH 070/213] fix little endian --- nebula-exchange/pom.xml | 2 +- .../exchange/processor/EdgeProcessor.scala | 37 +++++++++++++++---- .../processor/VerticesProcessor.scala | 25 +++++++++---- .../nebula/exchange/utils/NebulaUtils.scala | 13 ++++--- nebula-spark-connector/pom.xml | 2 +- 5 files changed, 58 insertions(+), 21 deletions(-) diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml index e1b258f..009f036 100644 --- a/nebula-exchange/pom.xml +++ b/nebula-exchange/pom.xml @@ -28,7 +28,7 @@ 3.9.2 2.11.0-M4 3.7.1 - 2.0.0-SNAPSHOT + 2.0.0 1.0.0 2.4.5-M1 3.4.6 diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index dde85c0..db59e5a 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -11,7 +11,6 @@ import java.nio.file.{Files, Paths} import com.google.common.geometry.{S2CellId, S2LatLng} import com.vesoft.nebula.client.graph.data.HostAddress -import com.vesoft.nebula.client.meta.{MetaCache, MetaManager} import com.vesoft.nebula.encoder.NebulaCodecImpl import com.vesoft.nebula.exchange.config.{ Configs, @@ -106,9 +105,9 @@ class EdgeProcessor(data: DataFrame, if (edgeConfig.dataSinkConfigEntry.category == SinkCategory.SST) { val fileBaseConfig = edgeConfig.dataSinkConfigEntry.asInstanceOf[FileBaseSinkConfigEntry] val namenode = fileBaseConfig.fsName.orNull - val spaceName = config.databaseConfig.space val edgeName = edgeConfig.name + val vidType = metaProvider.getVidType(space) val spaceVidLen = metaProvider.getSpaceVidLen(space) val edgeItem = metaProvider.getEdgeItem(space, edgeName) @@ -159,20 +158,44 @@ class EdgeProcessor(data: DataFrame, hostAddrs.append(new HostAddress(addr.getHostText, addr.getPort)) } - val partitionId = NebulaUtils.getPartitionId(spaceName, srcId, partitionNum) + val partitionId = NebulaUtils.getPartitionId(srcId, partitionNum, vidType) val codec = new NebulaCodecImpl() + + import java.nio.ByteBuffer + val order = ByteOrder.nativeOrder + val srcBytes = if (vidType == VidType.INT) { + val bytes = ByteBuffer.allocate(8).putLong(srcId.toLong).array + if (order == ByteOrder.LITTLE_ENDIAN) { + return bytes.reverse + } else { + return bytes + } + } else { + srcId.getBytes() + } + + val dstBytes = if (vidType == VidType.INT) { + val bytes = ByteBuffer.allocate(8).putLong(dstId.toLong).array + if (order == ByteOrder.LITTLE_ENDIAN) { + return bytes.reverse + } else { + return bytes + } + } else { + dstId.getBytes() + } val positiveEdgeKey = codec.edgeKeyByDefaultVer(spaceVidLen, partitionId, - srcId.getBytes, + srcBytes, edgeItem.getEdge_type, ranking, - dstId.getBytes) + dstBytes) val reverseEdgeKey = codec.edgeKeyByDefaultVer(spaceVidLen, partitionId, - dstId.getBytes, + dstBytes, -edgeItem.getEdge_type, ranking, - srcId.getBytes) + srcBytes) val values = for { property <- fieldKeys if property.trim.length != 0 diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index 97ebab8..fff2003 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -10,8 +10,7 @@ import java.nio.file.{Files, Paths} import java.nio.{ByteBuffer, ByteOrder} import com.vesoft.nebula.client.graph.data.HostAddress -import com.vesoft.nebula.client.meta.{MetaCache, MetaManager} -import com.vesoft.nebula.encoder.{NebulaCodec, NebulaCodecImpl} +import com.vesoft.nebula.encoder.{NebulaCodecImpl} import com.vesoft.nebula.exchange.{ ErrorHandler, GraphProvider, @@ -114,8 +113,8 @@ class VerticesProcessor(data: DataFrame, if (tagConfig.dataSinkConfigEntry.category == SinkCategory.SST) { val fileBaseConfig = tagConfig.dataSinkConfigEntry.asInstanceOf[FileBaseSinkConfigEntry] val namenode = fileBaseConfig.fsName.orNull - val spaceName = config.databaseConfig.space val tagName = tagConfig.name + val vidType = metaProvider.getVidType(space) val spaceVidLen = metaProvider.getSpaceVidLen(space) val tagItem = metaProvider.getTagItem(space, tagName) @@ -125,7 +124,6 @@ class VerticesProcessor(data: DataFrame, iter.map { row => val index: Int = row.schema.fieldIndex(tagConfig.vertexField) var vertexId: String = row.get(index).toString - if (tagConfig.vertexPolicy.isDefined) { tagConfig.vertexPolicy.get match { case KeyPolicy.HASH => @@ -145,11 +143,24 @@ class VerticesProcessor(data: DataFrame, hostAddrs.append(new HostAddress(addr.getHostText, addr.getPort)) } - val partitionId = NebulaUtils.getPartitionId(spaceName, vertexId, partitionNum) + val partitionId = NebulaUtils.getPartitionId(vertexId, partitionNum, vidType) val codec = new NebulaCodecImpl() - val vertexKey = - codec.vertexKey(spaceVidLen, partitionId, vertexId.getBytes, tagItem.getTag_id) + + import java.nio.ByteBuffer + val vidBytes = if (vidType == VidType.INT) { + val bytes = ByteBuffer.allocate(8).putLong(vertexId.toLong).array + val order = ByteOrder.nativeOrder + if (order == ByteOrder.LITTLE_ENDIAN) { + return bytes.reverse + } else { + return bytes + } + } else { + vertexId.getBytes() + } + + val vertexKey = codec.vertexKey(spaceVidLen, partitionId, vidBytes, tagItem.getTag_id) val values = for { property <- fieldKeys if property.trim.length != 0 } yield diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala index 819bcd8..f95d42e 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala @@ -6,8 +6,7 @@ package com.vesoft.nebula.exchange.utils -import com.vesoft.nebula.exchange.MetaProvider -import com.vesoft.nebula.meta.PropertyType +import com.vesoft.nebula.exchange.{MetaProvider, VidType} import com.vesoft.nebula.exchange.MetaProvider import com.vesoft.nebula.exchange.config.{EdgeConfigEntry, SchemaConfigEntry, TagConfigEntry, Type} import org.apache.commons.codec.digest.MurmurHash2 @@ -77,9 +76,13 @@ object NebulaUtils { s } - def getPartitionId(spaceName: String, id: String, partitionSize: Int): Int = { - val hash = MurmurHash2.hash64(id.getBytes, id.length, 0xc70f6907) - val hashValue = java.lang.Long.parseUnsignedLong(java.lang.Long.toUnsignedString(hash)) + def getPartitionId(id: String, partitionSize: Int, vidType: VidType.Value): Int = { + val hashValue = if (vidType == VidType.INT) { + java.lang.Long.parseUnsignedLong(id) + } else { + val hash = MurmurHash2.hash64(id.getBytes, id.length, 0xc70f6907) + java.lang.Long.parseUnsignedLong(java.lang.Long.toUnsignedString(hash)) + } (Math.floorMod(hashValue, partitionSize) + 1).toInt } } diff --git a/nebula-spark-connector/pom.xml b/nebula-spark-connector/pom.xml index 9ff5a87..8859164 100644 --- a/nebula-spark-connector/pom.xml +++ b/nebula-spark-connector/pom.xml @@ -14,7 +14,7 @@ 2.4.4 - 2.0.0-rc1.20210129 + 2.0.0 1.8 1.8 3.2.3 From 44af22fc3e3451f4958a2c4321d721d7cc490ae0 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 9 Apr 2021 17:42:37 +0800 Subject: [PATCH 071/213] fix wrong fixed_string property --- .../scala/com/vesoft/nebula/exchange/processor/Processor.scala | 2 +- .../com/vesoft/nebula/connector/writer/NebulaExecutor.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala index 05ce0ea..72c599d 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala @@ -47,7 +47,7 @@ trait Processor extends Serializable { if (row.isNullAt(index)) return null fieldTypeMap(field) match { - case PropertyType.STRING => { + case PropertyType.STRING | PropertyType.FIXED_STRING => { val result = NebulaUtils.escapeUtil(row.get(index).toString).mkString("\"", "", "\"") if (toBytes) result.getBytes else result } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala index 914a457..935eb50 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala @@ -135,7 +135,7 @@ object NebulaExecutor { val fieldName = schema.fields(index).name fieldTypeMap(fieldName).toInt match { - case PropertyType.STRING => + case PropertyType.STRING | PropertyType.FIXED_STRING => NebulaUtils.escapeUtil(propValue.toString).mkString("\"", "", "\"") case PropertyType.DATE => "date(\"" + propValue + "\")" case PropertyType.DATETIME => "datatime(\"" + propValue + "\")" From e5e52ca6ecb8762104723496e5ee2cd8c8d8570f Mon Sep 17 00:00:00 2001 From: cooper-lzy <78672629+cooper-lzy@users.noreply.github.com> Date: Mon, 12 Apr 2021 11:19:37 +0800 Subject: [PATCH 072/213] Adjust catalog --- .../about-exchange/ex-ug-limitations.md | 0 .../{ => CN}/about-exchange/ex-ug-terms.md | 0 .../about-exchange/ex-ug-what-is-exchange.md | 61 +++ nebula-exchange/doc-2.0/{ => CN}/ex-ug-FAQ.md | 2 +- .../doc-2.0/{ => CN}/ex-ug-compile.md | 0 nebula-exchange/doc-2.0/{ => CN}/ex-ug-toc.md | 0 .../doc-2.0/{ => CN}/figs/ex-ug-001.png | Bin .../doc-2.0/{ => CN}/figs/ex-ug-002.png | Bin .../ex-ug-para-import-command.md | 0 .../ex-ug-paras-nebulagraph.md | 0 .../parameter-reference/ex-ug-paras-neo4j.md | 0 .../parameter-reference/ex-ug-paras-spark.md | 0 .../use-exchange/ex-ug-import-from-csv.md | 0 .../use-exchange/ex-ug-import-from-neo4j.md | 0 .../use-exchange/ex-ug-import-hive.md | 0 .../use-exchange/ex-ug-import-json.md | 0 .../{ => CN}/use-exchange/ex-ug-import-sst.md | 0 .../use-exchange/ex-ug-import-steps.md | 0 .../doc-2.0/EN/about-exchange/ex-ug-faq.md | 24 ++ .../EN/about-exchange/ex-ug-limitations.md | 32 ++ .../doc-2.0/EN/about-exchange/ex-ug-terms.md | 9 + .../about-exchange/ex-ug-what-is-exchange.md | 59 +++ nebula-exchange/doc-2.0/EN/ex-ug-compile.md | 47 +++ nebula-exchange/doc-2.0/EN/ex-ug-toc.md | 25 ++ nebula-exchange/doc-2.0/EN/figs/ex-ug-001.png | Bin 0 -> 151025 bytes nebula-exchange/doc-2.0/EN/figs/ex-ug-002.png | Bin 0 -> 60193 bytes .../ex-ug-para-import-command.md | 17 + .../ex-ug-paras-nebulagraph.md | 16 + .../parameter-reference/ex-ug-paras-spark.md | 10 + .../EN/use-exchange/ex-ug-import-from-csv.md | 320 +++++++++++++++ .../EN/use-exchange/ex-ug-import-hive.md | 374 ++++++++++++++++++ .../EN/use-exchange/ex-ug-import-json.md | 288 ++++++++++++++ .../EN/use-exchange/ex-ug-import-steps.md | 42 ++ .../about-exchange/ex-ug-what-is-exchange.md | 59 --- 34 files changed, 1325 insertions(+), 60 deletions(-) rename nebula-exchange/doc-2.0/{ => CN}/about-exchange/ex-ug-limitations.md (100%) rename nebula-exchange/doc-2.0/{ => CN}/about-exchange/ex-ug-terms.md (100%) create mode 100644 nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-what-is-exchange.md rename nebula-exchange/doc-2.0/{ => CN}/ex-ug-FAQ.md (96%) rename nebula-exchange/doc-2.0/{ => CN}/ex-ug-compile.md (100%) rename nebula-exchange/doc-2.0/{ => CN}/ex-ug-toc.md (100%) rename nebula-exchange/doc-2.0/{ => CN}/figs/ex-ug-001.png (100%) rename nebula-exchange/doc-2.0/{ => CN}/figs/ex-ug-002.png (100%) rename nebula-exchange/doc-2.0/{ => CN}/parameter-reference/ex-ug-para-import-command.md (100%) rename nebula-exchange/doc-2.0/{ => CN}/parameter-reference/ex-ug-paras-nebulagraph.md (100%) rename nebula-exchange/doc-2.0/{ => CN}/parameter-reference/ex-ug-paras-neo4j.md (100%) rename nebula-exchange/doc-2.0/{ => CN}/parameter-reference/ex-ug-paras-spark.md (100%) rename nebula-exchange/doc-2.0/{ => CN}/use-exchange/ex-ug-import-from-csv.md (100%) rename nebula-exchange/doc-2.0/{ => CN}/use-exchange/ex-ug-import-from-neo4j.md (100%) rename nebula-exchange/doc-2.0/{ => CN}/use-exchange/ex-ug-import-hive.md (100%) rename nebula-exchange/doc-2.0/{ => CN}/use-exchange/ex-ug-import-json.md (100%) rename nebula-exchange/doc-2.0/{ => CN}/use-exchange/ex-ug-import-sst.md (100%) rename nebula-exchange/doc-2.0/{ => CN}/use-exchange/ex-ug-import-steps.md (100%) create mode 100644 nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-faq.md create mode 100644 nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-limitations.md create mode 100644 nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-terms.md create mode 100644 nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-what-is-exchange.md create mode 100644 nebula-exchange/doc-2.0/EN/ex-ug-compile.md create mode 100644 nebula-exchange/doc-2.0/EN/ex-ug-toc.md create mode 100644 nebula-exchange/doc-2.0/EN/figs/ex-ug-001.png create mode 100644 nebula-exchange/doc-2.0/EN/figs/ex-ug-002.png create mode 100644 nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-para-import-command.md create mode 100644 nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-nebulagraph.md create mode 100644 nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-spark.md create mode 100644 nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-from-csv.md create mode 100644 nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-hive.md create mode 100644 nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-json.md create mode 100644 nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-steps.md delete mode 100644 nebula-exchange/doc-2.0/about-exchange/ex-ug-what-is-exchange.md diff --git a/nebula-exchange/doc-2.0/about-exchange/ex-ug-limitations.md b/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-limitations.md similarity index 100% rename from nebula-exchange/doc-2.0/about-exchange/ex-ug-limitations.md rename to nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-limitations.md diff --git a/nebula-exchange/doc-2.0/about-exchange/ex-ug-terms.md b/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-terms.md similarity index 100% rename from nebula-exchange/doc-2.0/about-exchange/ex-ug-terms.md rename to nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-terms.md diff --git a/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-what-is-exchange.md b/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-what-is-exchange.md new file mode 100644 index 0000000..6b86806 --- /dev/null +++ b/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-what-is-exchange.md @@ -0,0 +1,61 @@ +# 什么是Nebula Exchange + +[Nebula Exchange](https://github.com/vesoft-inc/nebula-spark-utils/tree/v2.0.0/nebula-exchange)(简称Exchange)是一款Apache Spark™应用,用于在分布式环境中将集群中的数据批量迁移到Nebula Graph中,能支持多种不同格式的批式数据和流式数据的迁移。 + +Exchange由Reader、Processor和Writer三部分组成。Reader读取不同来源的数据返回DataFrame后,Processor遍历DataFrame的每一行,根据配置文件中`fields`的映射关系,按列名获取对应的值。在遍历指定批处理的行数后,Writer会将获取的数据一次性写入到Nebula Graph中。下图描述了Exchange完成数据转换和迁移的过程。 + +![Nebula Graph® Exchange 由 Reader、Processor、Writer 组成,可以完成多种不同格式和来源的数据向 Nebula Graph 的迁移](../figs/ex-ug-001.png "Nebula Graph® Exchange 转数据转换和迁移的过程") + +## 适用场景 + +Exchange适用于以下场景: + +- 需要将来自Kafka、Pulsar平台的流式数据,如日志文件、网购数据、游戏内玩家活动、社交网站信息、金融交易大厅或地理空间服务,以及来自数据中心内所连接设备或仪器的遥测数据等转化为属性图的点或边数据,并导入Nebula Graph数据库。 + +- 需要从关系型数据库(如MySQL)或者分布式文件系统(如HDFS)中读取批式数据,如某个时间段内的数据,将它们转化为属性图的点或边数据,并导入 Nebula Graph数据库。 + +- 需要将大批量数据生成Nebula Graph能识别的SST文件,再导入Nebula Graph数据库。 + +## 产品优点 + +Exchange具有以下优点: + +- 适应性强:支持将多种不同格式或不同来源的数据导入Nebula Graph数据库,便于迁移数据。 + +- 支持导入SST:支持将不同来源的数据转换为SST文件,用于数据导入。 + + > **说明**:仅Linux系统支持导入SST文件。 + +- 支持断点续传:导入数据时支持断点续传,有助于您节省时间,提高数据导入效率。 + + > **说明**:目前仅迁移Neo4j数据时支持断点续传。 + +- 异步操作:会在源数据中生成一条插入语句,发送给Graph服务,最后再执行插入操作。 + +- 灵活性强:支持同时导入多个标签和边类型,不同标签和边类型可以是不同的数据来源或格式。 + +- 统计功能:使用Apache Spark™中的累加器统计插入操作的成功和失败次数。 + +- 易于使用:采用HOCON(Human-Optimized Config Object Notation)配置文件格式,具有面向对象风格,便于理解和操作。 + +## 数据格式和来源 + +Exchange 2.0支持将以下格式或来源的数据转换为Nebula Graph能识别的点和边数据: + +- 存储在HDFS的数据,包括: + - Apache Parquet + - Apache ORC + - JSON + - CSV + +- Apache HBase™ + +- 数据仓库:HIVE + +- 图数据库:Neo4j 2.4.5-M1 + +- 关系型数据库:MySQL + +- 流处理软件平台:Apache Kafka® + +- 发布/订阅消息平台:Apache Pulsar 2.4.5 diff --git a/nebula-exchange/doc-2.0/ex-ug-FAQ.md b/nebula-exchange/doc-2.0/CN/ex-ug-FAQ.md similarity index 96% rename from nebula-exchange/doc-2.0/ex-ug-FAQ.md rename to nebula-exchange/doc-2.0/CN/ex-ug-FAQ.md index c7ef03a..56c06ed 100644 --- a/nebula-exchange/doc-2.0/ex-ug-FAQ.md +++ b/nebula-exchange/doc-2.0/CN/ex-ug-FAQ.md @@ -31,7 +31,7 @@ ### Exchange导入Hive数据时报错`Exception in thread "main" org.apache.spark.sql.AnalysisException: Table or view not found` -检查table和database是否正确,在spark-sql中执行用户配置的exec语句,验证exec语句的正确性。 +检查提交exchange任务的命令中是否遗漏参数`-h`,检查table和database是否正确,在spark-sql中执行用户配置的exec语句,验证exec语句的正确性。 ### 运行时报错`com.facebook.thrift.protocol.TProtocolException: Expected protocol id xxx` diff --git a/nebula-exchange/doc-2.0/ex-ug-compile.md b/nebula-exchange/doc-2.0/CN/ex-ug-compile.md similarity index 100% rename from nebula-exchange/doc-2.0/ex-ug-compile.md rename to nebula-exchange/doc-2.0/CN/ex-ug-compile.md diff --git a/nebula-exchange/doc-2.0/ex-ug-toc.md b/nebula-exchange/doc-2.0/CN/ex-ug-toc.md similarity index 100% rename from nebula-exchange/doc-2.0/ex-ug-toc.md rename to nebula-exchange/doc-2.0/CN/ex-ug-toc.md diff --git a/nebula-exchange/doc-2.0/figs/ex-ug-001.png b/nebula-exchange/doc-2.0/CN/figs/ex-ug-001.png similarity index 100% rename from nebula-exchange/doc-2.0/figs/ex-ug-001.png rename to nebula-exchange/doc-2.0/CN/figs/ex-ug-001.png diff --git a/nebula-exchange/doc-2.0/figs/ex-ug-002.png b/nebula-exchange/doc-2.0/CN/figs/ex-ug-002.png similarity index 100% rename from nebula-exchange/doc-2.0/figs/ex-ug-002.png rename to nebula-exchange/doc-2.0/CN/figs/ex-ug-002.png diff --git a/nebula-exchange/doc-2.0/parameter-reference/ex-ug-para-import-command.md b/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-para-import-command.md similarity index 100% rename from nebula-exchange/doc-2.0/parameter-reference/ex-ug-para-import-command.md rename to nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-para-import-command.md diff --git a/nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-nebulagraph.md b/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-paras-nebulagraph.md similarity index 100% rename from nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-nebulagraph.md rename to nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-paras-nebulagraph.md diff --git a/nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-neo4j.md b/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-paras-neo4j.md similarity index 100% rename from nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-neo4j.md rename to nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-paras-neo4j.md diff --git a/nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-spark.md b/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-paras-spark.md similarity index 100% rename from nebula-exchange/doc-2.0/parameter-reference/ex-ug-paras-spark.md rename to nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-paras-spark.md diff --git a/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-from-csv.md b/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-csv.md similarity index 100% rename from nebula-exchange/doc-2.0/use-exchange/ex-ug-import-from-csv.md rename to nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-csv.md diff --git a/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-from-neo4j.md b/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-neo4j.md similarity index 100% rename from nebula-exchange/doc-2.0/use-exchange/ex-ug-import-from-neo4j.md rename to nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-neo4j.md diff --git a/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-hive.md b/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-hive.md similarity index 100% rename from nebula-exchange/doc-2.0/use-exchange/ex-ug-import-hive.md rename to nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-hive.md diff --git a/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-json.md b/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-json.md similarity index 100% rename from nebula-exchange/doc-2.0/use-exchange/ex-ug-import-json.md rename to nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-json.md diff --git a/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-sst.md b/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-sst.md similarity index 100% rename from nebula-exchange/doc-2.0/use-exchange/ex-ug-import-sst.md rename to nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-sst.md diff --git a/nebula-exchange/doc-2.0/use-exchange/ex-ug-import-steps.md b/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-steps.md similarity index 100% rename from nebula-exchange/doc-2.0/use-exchange/ex-ug-import-steps.md rename to nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-steps.md diff --git a/nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-faq.md b/nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-faq.md new file mode 100644 index 0000000..5792741 --- /dev/null +++ b/nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-faq.md @@ -0,0 +1,24 @@ +# FAQ + +**What version of Nebula Graph does Exchange v2.x support?** + +Read [Limitations](ex-ug-limitations.md) to get the latest information about supported Nebula Graph versions. + +**What are the differences between Exchange v1.x and Exchange v2.x?** + +Compared with Exchange v1.x, Exchange v2.x has these new features: + +- Importing vertex data with String type IDs. +- Importing data of the Null, Date, DateTime, and Time types. +- Importing data from other Hive sources besides Hive on Spark. +- Recording and retrying the INSERT statement after failures during data import. + +For more information, see [Exchange README](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/nebula-exchange). + +**What is the difference between Exchange and Spark Writer?** + +Both are Spark applications, and Exchange is based on Spark Writer. Both of them are designed for the migration of data into a Nebula Graph cluster in a distributed environment, but the later maintenance work will focus on Exchange. Compared with Spark Writer, Exchange has the following improvements: + +- Supporting more data sources, such as MySQL, Neo4j, HIVE, HBase, Kafka, and Pulsar. + +- Some problems with Spark Writer were fixed. For example, by default Spark reads source data from HDFS as strings, which is probably different from your graph schema defined in Nebula Graph. Exchange supports automatically matching and converting data types. With it, when a non-string data type is defined in Nebula Graph, Exchange converts the strings into data of the required data type. diff --git a/nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-limitations.md b/nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-limitations.md new file mode 100644 index 0000000..0becb16 --- /dev/null +++ b/nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-limitations.md @@ -0,0 +1,32 @@ +# Limitations + +This article introduces the limitations of Exchange v2.x. + +## Supported Nebula Graph versions + +Exchange v2.x supports Nebula Graph v2.x only. If you are using Nebula Graph v1.x, please use [Nebula Exchange v1.x](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools "Click to go to GitHub"). + +## Supported operation systems + +You can use Exchange v2.x in these operation systems: + +- CentOS 7 +- macOS + +> **NOTE**: Importing SST files with Exchange v2.x is supported in Linux only. + +## Software dependencies + +To make sure that Exchange v2.x works properly, make sure that these software applications are installed in your machine: + +- Apache Spark: 2.3.0 or later versions + +- Java: 1.8 + +- Scala: 2.10.7, 2.11.12, or 2.12.10 + +In these scenarios, Hadoop Distributed File System (HDFS) must be deployed: + +- Importing data from HDFS to Nebula Graph + +- Importing SST files into Nebula Graph diff --git a/nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-terms.md b/nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-terms.md new file mode 100644 index 0000000..323dc1e --- /dev/null +++ b/nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-terms.md @@ -0,0 +1,9 @@ +# Glossary + +This article gives explanations of some necessary terminologies in this user guide. + +- Nebula Exchange: Referred to as Exchange v2.x or Exchange in this user guide. It is a Spark application based on Apache Spark™ for batch or stream processing data migration. It supports converting data from different sources into vertex and edge data that can be recognized by Nebula Graph, and then concurrently importing data into Nebula Graph. + +- Apache Spark™: A fast and general computing engine designed for large-scale data processing. It is an open-source project of Apache Software Foundation. + +- Driver Program: Referred to as driver in this user guide. It is a program that runs the `main` function of an application and creates a new `SparkContext` instance. diff --git a/nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-what-is-exchange.md b/nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-what-is-exchange.md new file mode 100644 index 0000000..654911f --- /dev/null +++ b/nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-what-is-exchange.md @@ -0,0 +1,59 @@ +# What is Nebula Exchange + +[Nebula Exchange](https://github.com/vesoft-inc/nebula-spark-utils/tree/v2.0.0/nebula-exchange) (Exchange v2.x or Exchange in short) is an Apache Spark™ application. It can be used to migrate data from a cluster in a distributed environment to a Nebula Graph v2.x cluster. It supports processing different formats of batch data and streaming data. + +Exchange is composed of Reader, Processor, and Writer. Reader reads data of different sources and creates DataFrame. Processor traverses every row of the DataFrame and obtains the values for each column according to the mapping of the `fields` in the configuration file. And then after the specified rows of data to be batch processed are traversed, Writer writes the obtained data into Nebula Graph concurrently. This figure shows how the data is transformed and transferred in Exchange. + +![Nebula Exchange is composed of Reader, Processor, and Writer. It can be used to migrate data from different sources to Nebula Graph](../figs/ex-ug-001.png "How Nebula Exchange transforms and transfers data") + +## Scenarios + +You can use Exchange in these scenarios: + +- Converting streaming data from Kafka or Pulsar platforms to vertex or edge data of property graphs and importing them into Nebula Graph. For example, log files, online shopping data, in-game player activities, social networking information, financial trading services, geospatial services, or telemetry data from connected devices or instruments in the data center. + +- Converting batch data (such as data in a certain period of time) from a relational database (such as MySQL) or a distributed file system (such as HDFS) into vertex or edge data of property graphs, and importing them into Nebula Graph. + +- Converting a large amount of data into SST files and then importing them into Nebula Graph. + +## Features + +Exchange has these features: + +- Adaptable: Exchange supports importing data from different sources into Nebula Graph, which is convenient for you to migrate data. + +- SST files supported: Exchange supports converting data from different sources into SST files for data import. + > **NOTE**: Importing SST files with Exchange v2.x is supported in Linux only. + +- Resuming broken transfer: Exchange supports resuming an interrupted transfer from a broken point during the data import process, which saves your time and improves efficiency. + > **NOTE**: Exchange v2.x supports resuming broken transfer for Neo4j only. + +- Asynchronous: Exchange enables you to set an insertion statement for the source and sends it to the Graph Service of Nebula Graph for data insertion. + +- Flexible: Exchange supports importing multiple types of vertices and edges of different sources or formats simultaneously. + +- Statistics: Exchange uses the accumulator in Apache Spark™ to count the successes and failures during the insertion process. + +- Easy to use and user-friendly: Exchange supports HOCON (Human-Optimized Config Object Notation) configuration file format, which is object-oriented, and easy to understand and operate. + +## Supported data sources + +You can use Exchange v2.x to convert data of these sources into vertex and edge data and then import them to Nebula Graph v2.x: + +- Data of different formats stored on HDFS, including: + - Apache Parquet + - Apache ORC + - JSON + - CSV + +- Apache HBase™ + +- Data warehouses: HIVE + +- Graph databases: Neo4j 2.4.5-M1. + +- Relational databases: MySQL + +- Stream processing platforms: Apache Kafka® + +- Messaging and streaming platforms: Apache Pulsar 2.4.5 diff --git a/nebula-exchange/doc-2.0/EN/ex-ug-compile.md b/nebula-exchange/doc-2.0/EN/ex-ug-compile.md new file mode 100644 index 0000000..9c9fd71 --- /dev/null +++ b/nebula-exchange/doc-2.0/EN/ex-ug-compile.md @@ -0,0 +1,47 @@ +# Compile Exchange + +To compile Exchange, follow these steps: + +1. Run these commands to install Nebula Java Client v2.x. + + ```bash + $ git clone https://github.com/vesoft-inc/nebula-java.git + $ cd nebula-java + $ mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true + ``` + + > **NOTE**: After the installation, you can see the `/com/vesoft/client/2.0.0-beta/client-2.0.0-beta.jar` in your local Maven repository. + +2. Run these commands to package Nebula Exchange v2.x. + + ```bash + $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git + $ cd nebula-spark-utils/nebula-exchange + $ mvn clean package -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true + ``` + +After the compiling, you can see the structure of the Exchange directory as follows. + +```text +. +├── README-CN.md +├── README.md +├── pom.xml +├── src +│   ├── main +│   └── test +└── target + ├── classes + ├── classes.timestamp + ├── maven-archiver + ├── nebula-exchange-2.x.y-javadoc.jar + ├── nebula-exchange-2.x.y-sources.jar + ├── nebula-exchange-2.x.y.jar + ├── original-nebula-exchange-2.x.y.jar + └── site +``` + +In the `target` directory, you can see the `exchange-2.x.y.jar` file. +> **NOTE**: The version of the JAR file depends on the releases of Nebula Java Client. You can find the latest versions on the [Releases page of the nebula-spark-utils repository](https://github.com/vesoft-inc/nebula-spark-utils "Click to go to GitHub"). + +To import data, you can refer to the example configuration in the `target/classes/application.conf`, `target/classes/server_application.conf`, and `target/classes/stream_application.conf` files. diff --git a/nebula-exchange/doc-2.0/EN/ex-ug-toc.md b/nebula-exchange/doc-2.0/EN/ex-ug-toc.md new file mode 100644 index 0000000..15729b7 --- /dev/null +++ b/nebula-exchange/doc-2.0/EN/ex-ug-toc.md @@ -0,0 +1,25 @@ +# Nebula Exchange v2.x User Guide + +- About Nebula Exchange + - [What is Nebula Exchange](about-exchange/ex-ug-what-is-exchange.md) + - [Limitations](about-exchange/ex-ug-limitations.md) + - [Glossary](about-exchange/ex-ug-terms.md) + - [FAQ](about-exchange/ex-ug-faq.md) +- [Compile Exchange](ex-ug-compile.md) +- Use Exchange + - [Use Exchange](use-exchange/ex-ug-import-steps.md) + - [Import data from CSV files](use-exchange/ex-ug-import-from-csv.md) + - [Import data from JSON files](use-exchange/ex-ug-import-json.md) + - [Import data from HIVE](use-exchange/ex-ug-import-hive.md) + - [Import data from Apache Parquet][DOC_TODO] + - [Import data from Apache ORC][DOC_TODO] + - [Import data from Neo4j][DOC_TODO] + - [Import data from HBase][DOC_TODO] + - [Import data from MySQL][DOC_TODO] + - [Import data from Kafka][DOC_TODO] + - [Import data from Pulsar][DOC_TODO] + - [Import SST files][DOC_TODO] +- Parameter reference + - [Spark related parameters](parameter-reference/ex-ug-paras-spark.md) + - [Nebula Graph related parameters](parameter-reference/ex-ug-paras-nebulagraph.md) + - [Import command parameters](parameter-reference/ex-ug-para-import-command.md) diff --git a/nebula-exchange/doc-2.0/EN/figs/ex-ug-001.png b/nebula-exchange/doc-2.0/EN/figs/ex-ug-001.png new file mode 100644 index 0000000000000000000000000000000000000000..0e57d6f37d403a85e59ae6b842c289fbaa8ff791 GIT binary patch literal 151025 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≫nKt| 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

                                          j2=IkPm&a{Wb~$2{BQzg0g! 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 literal 0 HcmV?d00001 diff --git a/nebula-exchange/doc-2.0/EN/figs/ex-ug-002.png b/nebula-exchange/doc-2.0/EN/figs/ex-ug-002.png new file mode 100644 index 0000000000000000000000000000000000000000..a4abbef115da17e612b6f6d43ee9728aaa3232d7 GIT binary patch literal 60193 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�wMox-jhh9Z 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 literal 0 HcmV?d00001 diff --git a/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-para-import-command.md b/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-para-import-command.md new file mode 100644 index 0000000..ca4b68a --- /dev/null +++ b/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-para-import-command.md @@ -0,0 +1,17 @@ +# Import command parameters + +When the configuration file is ready, replace `master-node-url` and `exchange-2.x.y.jar` in this command and run it to import the data from the specified source into Nebula Graph. + +```bash +$SPARK_HOME/bin/spark-submit --master "master-node-url" --class com.vesoft.nebula.exchange.Exchange target/exchange-2.x.y.jar -c /path/to/conf/application.conf +``` + +This table lists all the parameters in the preceding command. + +| Parameters | Required? | Default | Description | +| :--- | :--- | :--- | :--- | +| `--master`  | Yes | None | Specifies the URL of the Master node of the specified Spark cluster. For more information, see [master-urls in Spark Documentation](https://spark.apache.org/docs/latest/submitting-applications.html#master-urls "Click to go to Apache Spark Documentation")。 | +| `--class`  | Yes | None | Specifies the entry point of Exchange. | +| `-c`  / `--config`  | Yes | None | Specifies the path of the Exchange configuration file. | +| `-h`  / `--hive`  | No | `false` | If you want to import data from HIVE, add this parameter. | +| `-D`  / `--dry`  | No | `false` | Before data import, add this parameter to do a check of the format of the configuration file, but not the configuration of `tags` and `edges`. Do not use this parameter when you import data. | diff --git a/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-nebulagraph.md b/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-nebulagraph.md new file mode 100644 index 0000000..8958b75 --- /dev/null +++ b/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-nebulagraph.md @@ -0,0 +1,16 @@ +# Nebula Graph related parameters + +To import data, you must set parameters for Nebula Graph. This table lists all the Nebula Graph related parameters. For more information, see the [examples](../use-exchange/ex-ug-import-steps.md). + +| Parameters | Default | Data Type | Required? | Description | +| :--- | :--- | :--- | :--- | :--- | +| `nebula.address.graph` | None | `list[string]` | Yes | Specifies the addresses and ports used by the Graph Service of Nebula Graph. Multiple addresses must be separated with commas. In the format of `"ip1:port","ip2:port","ip3:port"`. | +| `nebula.address.meta` | None | `list[string]` | Yes | Specifies the addresses and ports used by the Meta Service of Nebula Graph. Multiple addresses must be separated with commas. In the format of `"ip1:port","ip2:port","ip3:port"`. | +| `nebula.user` | `user` | `string` | Yes | Specifies an account of Nebula Graph. The default value is `user`. If authentication is enabled in Nebula Graph:
                                          - If no account is created, use `root`.
                                          - If a specified account is created and given the write permission to a graph space, you can use this account. | +| `nebula.pswd` | `password` | `string` | Yes | Specifies the password of the specified account. The default password for the `user` account is `password`. If authentication is enabled in Nebula Graph:
                                          - For the `root` account, use `nebula`.
                                          - For another account, use the specified password. | +| `nebula.space` | None | `string` | Yes | Specifies the name of the graph space to import data. | +| `nebula.connection.timeout` | 3000 | `int` | No | Specifies the period of timeout for Thrift connection. Unit: ms. | +| `nebula.connection.retry` | 3 | `int` | No | Specifies the number of retries for Thrift connection. | +| `nebula.execution.retry` | 3 | `int` | No | Specifies the number of execution retries of an nGQL statements | +| `nebula.error.max` | 32 | `int` | No | Specifies the maximum number of failures during the import process. When the specified number of failures occur, the submitted Spark job stops automatically. | +| `nebula.error.output` | None | `string` | Yes | Specifies a logging directory on the Nebula Graph cluster for the error message. | diff --git a/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-spark.md b/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-spark.md new file mode 100644 index 0000000..6bce5c1 --- /dev/null +++ b/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-spark.md @@ -0,0 +1,10 @@ +# Spark related parameters + +To import data, you must set parameters for Spark. This table lists some generally-used parameters. For more Spark-related parameters, see [Apache Spark documentation](https://spark.apache.org/docs/latest/configuration.html#application-properties "Click to go go Spark documenation"). For more information, see the [examples](../use-exchange/ex-ug-import-steps.md). + +| Parameters | Default | Data type | Required? | Description | +| :--- | :--- | :--- | :--- | :--- | +| `spark.app.name` | Nebula Exchange 2.0 | `string` | No | Specifies the name of the Spark Driver Program.| +| `spark.driver.cores` | 1 | `int` | No | Specifies the number of cores to use for the driver process, only in cluster mode. | +| `spark.driver.maxResultSize` | 1G | `string` | No | Specifies the limit of the total size of serialized results of all partitions for each Spark action (e.g. collect) in bytes. Should be at least 1M, or 0 for unlimited. | +| `spark.cores.max` | None | `int` | No | When the driver program runs on a standalone deployed cluster or a Mesos cluster in "coarse-grained" sharing mode, the maximum amount of CPU cores to request for the application from across the cluster (not from each machine). If not set, the default will be `spark.deploy.defaultCores` on the standalone cluster manager of Spark, or infinite (all available cores) on Mesos. | diff --git a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-from-csv.md b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-from-csv.md new file mode 100644 index 0000000..9e8bf22 --- /dev/null +++ b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-from-csv.md @@ -0,0 +1,320 @@ +# Import data from CSV files + +This article uses an example to show how to use Exchange to import data from CSV files stored on HDFS into Nebula Graph. + +If you want to import data from local CSV files into Nebula Graph v2.x, see [Nebula Importer](https://github.com/vesoft-inc/nebula-importer "Click to go to GitHub"). + +## Dataset + +In this article, the [Social Network: MOOC User Action Dataset](https://snap.stanford.edu/data/act-mooc.html "Click to go to Stanford Network Analysis Platform") provided by Stanford Network Analysis Platform (SNAP) and 97 unique course names obtained from the public network are used as the sample dataset. The dataset contains: + +- Two vertex types (`user` and `course`), 7,144 vertices in total. +- One edge type (`action`), 411,749 edges in total. + +You can download the example dataset from the [nebula-web-docker](https://github.com/vesoft-inc/nebula-web-docker/tree/master/example/mooc-actions "Click to go to GitHub") repository. + +## Environment + +The practice is done in macOS. Here is the environment information: + +- Hardware specifications: + - CPU: 1.7 GHz Quad-Core Intel Core i7 + - Memory: 16 GB + +- Spark 2.4.7, deployed in the Standalone mode + +- Hadoop 2.9.2, deployed in the Pseudo-Distributed mode + +- Nebula Graph v2-nightly, deployed with Docker Compose. For more information, see [Deploy Nebula Graph with Docker Compose](https://github.com/vesoft-inc/nebula-docker-compose "Click to go to GitHub"). + +## Prerequisites + +To import data from CSV files on HDFS with Exchange v2.x, do a check of these: + +- Exchange v2.x is compiled. For more information, see [Compile Exchange v2.x](../ex-ug-compile.md). Exchange 2.0.0 is used in this example. + +- Spark is installed. + +- Hadoop is installed and started. + +- Nebula Graph is deployed and started. Get the information: + - IP addresses and ports of the Graph Service and the Meta Service. + - A Nebula Graph account with the privilege of writing data and its password. + +- Get the necessary information for schema creation in Nebula Graph, including tags and edge types. + +## Procedure + +### Step 1. Create a schema in Nebula Graph + +Analyze the data in the CSV files and follow these steps to create a schema in Nebula Graph: + +1. Confirm the essential elements of the schema. + + | Elements | Names | Properties | + | :--- | :--- | :--- | + | Tag | `user` | `userId string` | + | Tag | `course` | `courseId int, courseName string` | + | Edge Type | `action` | `actionId int, duration double, label bool, feature0 double, feature1 double, feature2 double, feature3 double` | + +2. In Nebula Graph, create a graph space named **csv** and create a schema. + + ```ngql + -- Create a graph space named csv + CREATE SPACE [IF NOT EXISTS] + [(partition_num = , + replica_factor = , + vid_type = {FIXED_STRING()) | INT64}]; + + -- Choose the csv graph space + USE csv; + + -- Create the user tag + CREATE TAG user(userId string); + + -- Create the course tag + CREATE TAG course(courseId int, courseName string); + + -- Create the action edge type + CREATE EDGE action (actionId int, duration double, label bool, feature0 double, feature1 double, feature2 double, feature3 double); + ``` + +For more information, see [Quick Start of Nebula Graph Database](../../2.quick-start/4.nebula-graph-crud.md). + +### Step 2. Prepare CSV files + +Do a check of these: + +1. The CSV files are processed to meet the requirements of the schema. For more information, see [Quick Start of Nebula Graph Studio](../../nebula-studio/quick-start/st-ug-prepare-csv.md). + >**NOTE**: Exchange supports importing CSV files with or without headers. + +2. The CSV files must be stored in HDFS and get the file storage path. + +### Step 3. Edit configuration file + +After compiling of Exchange, copy the `target/classes/application.conf` file and edit the configuration for CSV files. In this example, a new configuration file is named `csv_ application.conf`. In this file, the vertex and edge related configuration is introduced in the comments and all the items that are not used in this example are commented out. For more information about the Spark and Nebula related parameters, see [Spark related parameters](../parameter-reference/ex-ug-paras-spark.md) and [Nebula Graph related parameters](../parameter-reference/ex-ug-paras-nebulagraph.md). + +```conf +{ + # Spark related configuration + spark: { + app: { + name: Nebula Exchange 2.0 + } + driver: { + cores: 1 + maxResultSize: 1G + } + executor: { + memory:1G + } + + cores { + max: 16 + } + } + + # Nebula Graph related configuration + nebula: { + address:{ + # Specifies the IP addresses and ports of the Graph Service and the Meta Service of Nebula Graph. + # If multiple servers are used, separate the addresses with commas. + # Format: "ip1:port","ip2:port","ip3:port". + graph:["127.0.0.1:9669"] + meta:["127.0.0.1:9559"] + } + + # Specifies an account that has the WriteData privilege in Nebula Graph and its password. + user: user + pswd: password + + # Specifies a graph space name + space: csv + connection { + timeout: 3000 + retry: 3 + } + execution { + retry: 3 + } + error: { + max: 32 + output: /tmp/errors + } + rate: { + limit: 1024 + timeout: 1000 + } + } + + # Process vertices + tags: [ + # Sets for the course tag + { + # Specifies a tag name defined in Nebula Graph. + name: course + type: { + # Specifies the data source. csv is used. + source: csv + + # Specifies how to import vertex data into Nebula Graph: client or sst. + # For more information about importing sst files, see Import SST files (doc_to_do). + sink: client + } + + # Specifies the HDFS path of the CSV file. + # Enclose the path with double quotes and start the path with hdfs://. + path: "hdfs://namenode_ip:port/path/to/course.csv" + + # If the CSV file has no header, use [_c0, _c1, _c2, ..., _cn] to + # represent its header and to indicate columns as the source of the property values. + fields: [_c0, _c1] + # If the CSV file has a header, use the actual column names. + + # Specifies property names defined in Nebula Graph. + # fields for the CSV file and nebula.fields for Nebula Graph must + # have the one-to-one correspondence relationship. + nebula.fields: [courseId, courseName] + + # Specifies a column as the source of VIDs. + # The value of vertex must be one column of the CSV file. + vertex: _c1 + # For now, only string type VIDs are supported in Nebula Graph v2.x. + # Do not use vertex.policy for mapping. + # vertex: { + # field: _c1, + # policy: "hash" + # } + + # Specifies the separator. The default value is commas. + separator: "," + + # If the CSV file has a header, set header to true. + # If the CSV file has no header, set header to false (default value). + header: false + + # Specifies the maximum number of vertex data to be written into + # Nebula Graph in a single batch. + batch: 256 + + # Specifies the partition number of Spark. + partition: 32 + } + + # Sets for the user tag + { + name: user + type: { + source: csv + sink: client + } + path: "hdfs://namenode_ip:port/path/to/user.csv" + + # fields for the CSV file and nebula.fields for Nebula Graph must + # have the one-to-one correspondence relationship. + fields: [userId] + + # Specifies property names defined in Nebula Graph. + # fields for the CSV file and nebula.fields for Nebula Graph must + # have the one-to-one correspondence relationship. + nebula.fields: [userId] + + # The value of vertex.field must be one column of the CSV file. + vertex: userId + separator: "," + header: true + batch: 256 + partition: 32 + } + + # If more tags are necessary, refer to the preceding configuration to add more. + ] + # Process edges + edges: [ + # Sets for the action edge type + { + # Specifies an edge type name defined in Nebula Graph + name: action + type: { + # Specifies the data source. csv is used. + source: csv + + # Specifies how to import vertex data into Nebula Graph: client or sst. + # For more information about importing sst files, see Import SST files (doc_to_do). + sink: client + } + + # Specifies the HDFS path of the CSV file. + # Enclose the path with double quotes and start the path with hdfs://. + path: "hdfs://namenode_ip:port/path/to/actions.csv" + + # If the CSV file has no header, use [_c0, _c1, _c2, ..., _cn] to + # represent its header and to indicate columns as the source of the property values. + fields: [_c0, _c3, _c4, _c5, _c6, _c7, _c8] + # If the CSV file has a header, use the actual column names. + + # Specifies property names defined in Nebula Graph. + # fields for the CSV file and nebula.fields for Nebula Graph must + # have the one-to-one correspondence relationship. + nebula.fields: [actionId, duration, feature0, feature1, feature2, feature3, label] + + # Specifies the columns as the source of the IDs of the source and target vertices. + source: _c1 + target: _c2 + # For now, only string type VIDs are supported in Nebula Graph v2.x. + # Do not use source.policy or target.policy for mapping. + #target: { + # field: _c2 + # policy: "hash" + #} + + # Specifies the separator. The default value is commas. + separator: "," + + # If the CSV file has a header, set header to true. + # If the CSV file has no header, set header to false (default value). + header: false + + # Specifies the maximum number of vertex data to be written into + # Nebula Graph in a single batch. + batch: 256 + + # Specifies the partition number of Spark. + partition: 32 + } + ] + # If more edge types are necessary, refer to the preceding configuration to add more. +} +``` + +### Step 4. (Optional) Verify the configuration + +After the configuration, run the import command with the `-D` parameter to verify the configuration file. For more information about the parameters, see [Import command parameters](../parameter-reference/ex-ug-para-import-command.md). + +```bash +$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange /path/to/nebula-exchange-2.0.0.jar -c /path/to/conf/csv_application.conf -D +``` + +### Step 5. Import data into Nebula Graph + +When the configuration is ready, run this command to import data from CSV files into Nebula Graph. For more information about the parameters, see [Import command parameters](../parameter-reference/ex-ug-para-import-command.md). + +```bash +$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange /path/to/nebula-exchange-2.0.0.jar -c /path/to/conf/csv_application.conf +``` + +### Step 6. (Optional) Verify data in Nebula Graph + +You can use a Nebula Graph client, such as Nebula Graph Studio, to verify the imported data. For example, in Nebula Graph Studio, run this statement. + +```ngql +GO FROM "1" OVER action; +``` + +If the queried destination vertices return, the data are imported into Nebula Graph. + +You can run the [`SHOW STATS`](../../3.ngql-guide/7.general-query-statements/6.show/14.show-stats.md) statement to count the data. + +### Step 7. (Optional) Create and rebuild indexes in Nebula Graph + +After the data is imported, you can create and rebuild indexes in Nebula Graph. For more information, see [nGQL User Guide](../../3.ngql-guide/14.native-index-statements/1.create-native-index.md). diff --git a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-hive.md b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-hive.md new file mode 100644 index 0000000..51ad759 --- /dev/null +++ b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-hive.md @@ -0,0 +1,374 @@ +# Import data from HIVE + +This article uses an example to show how to use Exchange to import data from HIVE into Nebula Graph. + +## Dataset + +In this article, the [Social Network: MOOC User Action Dataset](https://snap.stanford.edu/data/act-mooc.html "Click to go to Stanford Network Analysis Platform") provided by Stanford Network Analysis Platform (SNAP) and 97 unique course names obtained from the public network are used as the sample dataset. The dataset contains: + +- Two vertex types (`user` and `course`), 7,144 vertices in total. +- One edge type (`action`), 411,749 edges in total. + +You can download the example dataset from the [nebula-web-docker](https://github.com/vesoft-inc/nebula-web-docker/tree/master/example/mooc-actions "Click to go to GitHub") repository. + +In this example, the dataset is stored in a database named `mooc` in HIVE, and the information of all vertices and edges is stored in the `users`, `courses`, and `actions` tables. Here are the structures of all the tables. + +```sql +scala> sql("describe mooc.users").show ++--------+---------+-------+ +|col_name|data_type|comment| ++--------+---------+-------+ +| userid| string| null| ++--------+---------+-------+ + +scala> sql("describe mooc.courses").show ++----------+---------+-------+ +| col_name|data_type|comment| ++----------+---------+-------+ +| courseid| bigint| null| +|coursename| string| null| ++----------+---------+-------+ + +scala> sql("describe mooc.actions").show ++--------+---------+-------+ +|col_name|data_type|comment| ++--------+---------+-------+ +|actionid| bigint| null| +| srcid| string| null| +| dstid| string| null| +|duration| double| null| +|feature0| double| null| +|feature1| double| null| +|feature2| double| null| +|feature3| double| null| +| label| boolean| null| ++--------+---------+-------+ +``` + +> **NOTE**: `bigint` in HIVE equals to `int` in Nebula Graph. + +## Environment + +The practice is done in macOS. Here is the environment information: + +- Hardware specifications: + - CPU: 1.7 GHz Quad-Core Intel Core i7 + - Memory: 16 GB + +- Spark 2.4.7, deployed in the Standalone mode + +- Hadoop 2.9.2, deployed in the Pseudo-Distributed mode + +- HIVE 2.3.7, with MySQL 8.0.22 + +- Nebula Graph v2-nightly, deployed with Docker Compose. For more information, see [Deploy Nebula Graph with Docker Compose](https://github.com/vesoft-inc/nebula-docker-compose "Click to go to GitHub"). + +## Prerequisites + +To import data from HIVE with Exchange v2.x, do a check of these: + +- Exchange v2.x is compiled. For more information, see [Compile Exchange v2.x](../ex-ug-compile.md). Exchange 2.0.0 is used in this example. + +- Spark is installed. + +- Hadoop is installed and started and the hive metastore database (MySQL is used in this example) is started. + +- Nebula Graph is deployed and started. Get the information: + - IP addresses and ports of the Graph Service and the Meta Service. + - A Nebula Graph account with the privilege of writing data and its password. + +- Get the necessary information for schema creation in Nebula Graph, including tags and edge types. + +## Procedure + +### Step 1. Create a schema in Nebula Graph + +Follow these steps to create a schema in Nebula Graph: + +1. Confirm the essential elements of the schema. + + | Elements | Names | Properties | + | :--- | :--- | :--- | + | Tag | `user` | `userId string` | + | Tag | `course` | `courseId int, courseName string` | + | Edge Type | `action` | `actionId int, duration double, label bool, feature0 double, feature1 double, feature2 double, feature3 double` | + +2. In Nebula Graph, create a graph space named **hive** and create a schema. + + ```ngql + -- Create a graph space named hive + CREATE SPACE hive(partition_num=10, replica_factor=1, vid_type=fixed_string(100)); + + -- Choose the hive graph space + USE hive; + + -- Create the user tag + CREATE TAG user(userId string); + + -- Create the course tag + CREATE TAG course(courseId int, courseName string); + + -- Create the action edge type + CREATE EDGE action (actionId int, duration double, label bool, feature0 double, feature1 double, feature2 double, feature3 double); + ``` + +For more information, see [Quick Start of Nebula Graph](../../2.quick-start/4.nebula-graph-crud.md). + +### Step 2. Verify the HIVE SQL statements + +When spark-shell starts, run these statements one by one to make sure that Spark can read data from HIVE. + +```sql +scala> sql("select userid from mooc.users").show +scala> sql("select courseid, coursename from mooc.courses").show +scala> sql("select actionid, srcid, dstid, duration, feature0, feature1, feature2, feature3, label from mooc.actions").show +``` + +Here is an example of data read from the `mooc.actions` table. + +```sql ++--------+-----+--------------------+--------+------------+------------+-----------+-----------+-----+ +|actionid|srcid| dstid|duration| feature0| feature1| feature2| feature3|label| ++--------+-----+--------------------+--------+------------+------------+-----------+-----------+-----+ +| 0| 0|Environmental Dis...| 0.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 1| 0| History of Ecology| 6.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 2| 0| Women in Islam| 41.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 3| 0| History of Ecology| 49.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 4| 0| Women in Islam| 51.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 5| 0|Legacies of the A...| 55.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 6| 0| ITP Core 2| 59.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 7| 0|The Research Pape...| 62.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 8| 0| Neurobiology| 65.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 9| 0| Wikipedia| 113.0|-0.319991479|-0.435701433|1.108826104|12.77723482|false| +| 10| 0|Media History and...| 226.0|-0.319991479|-0.435701433|0.607804941|149.4512115|false| +| 11| 0| WIKISOO| 974.0|-0.319991479|-0.435701433|1.108826104|3.344522776|false| +| 12| 0|Environmental Dis...| 1000.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 13| 0| WIKISOO| 1172.0|-0.319991479|-0.435701433|1.108826104|1.136866766|false| +| 14| 0| Women in Islam| 1182.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 15| 0| History of Ecology| 1185.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 16| 0|Human Development...| 1687.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 17| 1|Human Development...| 7262.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 18| 1| History of Ecology| 7266.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| +| 19| 1| Women in Islam| 7273.0|-0.319991479|-0.435701433|0.607804941|0.936170765|false| ++--------+-----+--------------------+--------+------------+------------+-----------+-----------+-----+ +only showing top 20 rows +``` + +### Step 3. Edit configuration file + +After compiling of Exchange, copy the `target/classes/application.conf` file and edit the configuration for HIVE. In this example, a new configuration file is named `hive_ application.conf`. In this file, the vertex and edge related configuration is introduced as comments and all the items that are not used in this example are commented out. For more information about the Spark and Nebula related parameters, see [Spark related parameters](../parameter-reference/ex-ug-paras-spark.md) and [Nebula Graph related parameters](../parameter-reference/ex-ug-paras-nebulagraph.md). + +```conf +{ + # Spark related configuration + spark: { + app: { + name: Nebula Exchange 2.0 + } + driver: { + cores: 1 + maxResultSize: 1G + } + executor: { + memory:1G + } + cores { + max: 16 + } + } + + # If Spark and HIVE are deployed in the different clusters, + # configure these parameters for HIVE. Otherwise, ignore them. + #hive: { + # waredir: "hdfs://NAMENODE_IP:9000/apps/svr/hive-xxx/warehouse/" + # connectionURL: "jdbc:mysql://your_ip:3306/hive_spark?characterEncoding=UTF-8" + # connectionDriverName: "com.mysql.jdbc.Driver" + # connectionUserName: "user" + # connectionPassword: "password" + #} + + # Nebula Graph related configuration + nebula: { + address:{ + # Specifies the IP addresses and ports of the Graph Service and the Meta Service of Nebula Graph + # If multiple servers are used, separate the addresses with commas. + # Format: "ip1:port","ip2:port","ip3:port" + graph:["127.0.0.1:9669"] + meta:["127.0.0.1:9559"] + } + + # Specifies an account that has the WriteData privilege in Nebula Graph and its password + user: user + pswd: password + + # Specifies a graph space name + space: hive + connection { + timeout: 3000 + retry: 3 + } + execution { + retry: 3 + } + error: { + max: 32 + output: /tmp/errors + } + rate: { + limit: 1024 + timeout: 1000 + } + } + + # Process vertices + tags: [ + # Sets for the user tag + { + # Specifies a tag name defined in Nebula Graph + name: user + type: { + # Specifies the data source. hive is used. + source: hive + # Specifies how to import vertex data into Nebula Graph: client or sst. + # For more information about importing sst files, see Import SST files (doc to do). + sink: client + } + + # Specifies the SQL statement to read data from the users table in the mooc database + exec: "select userid from mooc.users" + + # Specifies the column names from the users table to fields. + # Their values are used as the source of the userId (nebula.fields) property defined in Nebula Graph. + # If more than one column name is specified, separate them with commas. + # fields for the HIVE and nebula.fields for Nebula Graph must have the one-to-one correspondence relationship. + fields: [userid] + nebula.fields: [userId] + + # Specifies a column as the source of VIDs. + # The value of vertex must be one column name in the exec sentence. + # If the values are not of the int type, use vertex.policy to + # set the mapping policy. "hash" is preferred. + # Refer to the configuration of the course tag. + vertex: userid + + # Specifies the maximum number of vertex data to be written into + # Nebula Graph in a single batch. + batch: 256 + + # Specifies the partition number of Spark. + partition: 32 + } + + # Sets for the course tag + { + name: course + type: { + source: hive + sink: client + } + exec: "select courseid, coursename from mooc.courses" + fields: [courseid, coursename] + nebula.fields: [courseId, courseName] + + # Specifies a column as the source of VIDs. + # The value of vertex.field must be one column name in the exec sentence. + vertex: coursename + # For now, only string type VIDs are supported in Nebula Graph v2.x. + # Do not use vertex.policy for mapping. + #vertex: { + # field: coursename + # policy: "hash" + #} + batch: 256 + partition: 32 + } + # If more tags are necessary, refer to the preceding configuration to add more. + ] + + # Process edges + edges: [ + # Sets for the action edge type + { + # Specifies an edge type name defined in Nebula Graph + name: action + + type: { + # Specifies the data source. hive is used. + source: hive + + # Specifies how to import vertex data into Nebula Graph: client or sst + # For more information about importing sst files, + # see Import SST files (doc to do). + sink: client + } + + # Specifies the SQL statement to read data from the actions table in + # the mooc database. + exec: "select actionid, srcid, dstid, duration, feature0, feature1, feature2, feature3, label from mooc.actions" + + # Specifies the column names from the actions table to fields. + # Their values are used as the source of the properties of + # the action edge type defined in Nebula Graph. + # If more than one column name is specified, separate them with commas. + # fields for the HIVE and nebula.fields for Nebula Graph must + # have the one-to-one correspondence relationship. + fields: [actionid, duration, feature0, feature1, feature2, feature3, label] + nebula.fields: [actionId, duration, feature0, feature1, feature2, feature3, label] + + # source specifies a column as the source of the IDs of + # the source vertex of an edge. + # target specifies a column as the source of the IDs of + # the target vertex of an edge. + # The value of source.field and target.field must be + # column names set in the exec sentence. + source: srcid + target: dstid + # For now, only string type VIDs are supported in Nebula Graph v2.x. + # Do not use vertex.policy for mapping. + #target: { + # field: dstid + # policy: "hash" + #} + + # Specifies the maximum number of vertex data to be + # written into Nebula Graph in a single batch. + batch: 256 + + # Specifies the partition number of Spark. + partition: 32 + } + ] +} +``` + +### Step 4. (Optional) Verify the configuration + +After the configuration, run the import command with the `-D` parameter to verify the configuration file. For more information about the parameters, see [Import command parameters](../parameter-reference/ex-ug-para-import-command.md). + +```bash +$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange /path/to/nebula-exchange-2.0.0.jar -c /path/to/conf/hive_application.conf -h -D +``` + +### Step 5. Import data into Nebula Graph + +When the configuration is ready, run this command to import data from HIVE into Nebula Graph. For more information about the parameters, see [Import command parameters](../parameter-reference/ex-ug-para-import-command.md). + +```bash +$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange /path/to/nebula-exchange-2.0.0.jar -c /path/to/conf/hive_application.conf -h +``` + +### Step 6. (Optional) Verify data in Nebula Graph + +You can use a Nebula Graph client, such as Nebula Graph Studio, to verify the imported data. For example, in Nebula Graph Studio, run this statement. + +```ngql +GO FROM "1" OVER action; +``` + +If the queried destination vertices return, the data are imported into Nebula Graph. + +You can run the [`SHOW STATS`](../../3.ngql-guide/7.general-query-statements/6.show/14.show-stats.md) statement to count the data. + +### Step 7. (Optional) Create and rebuild indexes in Nebula Graph + +After the data is imported, you can create and rebuild indexes in Nebula Graph. For more information, see [nGQL User Guide](../../3.ngql-guide/14.native-index-statements/1.create-native-index.md). diff --git a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-json.md b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-json.md new file mode 100644 index 0000000..48bb8d5 --- /dev/null +++ b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-json.md @@ -0,0 +1,288 @@ +# Import data from JSON files + +This article uses an example to show how to use Exchange to import data from JSON files stored on HDFS into Nebula Graph. + +## Dataset + +The JSON file (test.json) used in this example is like `{"source":string, "target":string, "likeness":double}`, representing a `like` relationship between `source` and `target`. 21,645 records in total. + +Here are some sample data: + +```json +{"source":53802643,"target":87847387,"likeness":0.34} +{"source":29509860,"target":57501950,"likeness":0.40} +{"source":97319348,"target":50240344,"likeness":0.77} +{"source":94295709,"target":8189720,"likeness":0.82} +{"source":78707720,"target":53874070,"likeness":0.98} +{"source":23399562,"target":20136097,"likeness":0.47} +``` + +## Environment + +The practice is done in macOS. Here is the environment information: + +- Hardware specifications: + - CPU: 1.7 GHz Quad-Core Intel Core i7 + - Memory: 16 GB + +- Spark 2.4.7, deployed in the Standalone mode + +- Hadoop 2.9.2, deployed in the Pseudo-Distributed mode + +- Nebula Graph v2-nightly, deployed with Docker Compose. For more information, see [Deploy Nebula Graph with Docker Compose](https://github.com/vesoft-inc/nebula-docker-compose "Click to go to GitHub"). + +## Prerequisites + +To import data from JSON files on HDFS with Exchange v2.x, do a check of these: + +- Exchange v2.x is compiled. For more information, see [Compile Exchange v2.x](../ex-ug-compile.md). Exchange 2.0.0 is used in this example. + +- Spark is installed. + +- Hadoop is installed and started. + +- Nebula Graph is deployed and started. Get the information: + - IP addresses and ports of the Graph Service and the Meta Service. + - A Nebula Graph account with the privilege of writing data and its password. + +- Get the necessary information for schema creation in Nebula Graph, including tags and edge types. + +## Procedure + +### Step 1. Create a schema in Nebula Graph + +Analyze the data in the JSON files and follow these steps to create a schema in Nebula Graph: + +1. Confirm the essential elements of the schema. + + | Elements | Names | Properties | + | :--- | :--- | :--- | + | Tag | `source` | `srcId string` | + | Tag | `target` | `dstId string` | + | Edge Type | `like` | `likeness double` | + +2. In Nebula Graph, create a graph space named **json** and create a schema. + + ```ngql + -- Create a graph space named json + CREATE SPACE json(partition_num=10, replica_factor=1, vid_type=fixed_string(30)); + + -- Choose the json graph space + USE json; + + -- Create the source tag + CREATE TAG source (srcId string); + + -- Create the target tag + CREATE TAG target (dstId string); + + -- Create the like edge type + CREATE EDGE like (likeness double); + ``` + +For more information, see [Quick Start of Nebula Graph](../../2.quick-start/4.nebula-graph-crud.md). + +### Step 2. Prepare JSON files + +Create separate JSON files for vertex and edge data. Store the JSON files in HDFS and get the HDFS path of the files. + +> **NOTE**: In this example, only one JSON file is used to import vertex and edge data at the same time. Some vertex data representing source and target are duplicate. Therefore, during the import process, these vertices are written repeatedly. In Nebula Graph, data is overwritten when repeated insertion occurs, and the last write is read out. In practice, to increase the write speed, creating separate files for vertex and edge data is recommended. + +### Step 3. Edit configuration file + +After compiling of Exchange, copy the `target/classes/application.conf` file and edit the configuration for JSON files. In this example, a new configuration file is named `json_ application.conf`. In this file, the vertex and edge related configuration is introduced as comments and all the items that are not used in this example are commented out. For more information about the Spark and Nebula related parameters, see [Spark related parameters](../parameter-reference/ex-ug-paras-spark.md) and [Nebula Graph related parameters](../parameter-reference/ex-ug-paras-nebulagraph.md). + +```conf +{ + # Spark related configuration + spark: { + app: { + name: Spark Writer + } + + driver: { + cores: 1 + maxResultSize: 1G + } + + executor: { + memory:1G + } + + cores { + max: 16 + } + } + + # Nebula Graph related configuration + nebula: { + address:{ + # Specifies the IP addresses and ports of the Graph Service and the Meta Service of Nebula Graph. + # If multiple servers are used, separate the addresses with commas. + # Format: "ip1:port","ip2:port","ip3:port" + graph:["127.0.0.1:9669"] + meta:["127.0.0.1:9559"] + } + # Specifies an account that has the WriteData privilege in Nebula Graph and its password. + user: user + pswd: password + + # Specifies a graph space name + space: json + + connection { + timeout: 3000 + retry: 3 + } + + execution { + retry: 3 + } + + error: { + max: 32 + output: /tmp/errors + } + + rate: { + limit: 1024 + timeout: 1000 + } + } + + # Process vertices + tags: [ + # Sets for the source tag + { + # Specifies a tag name defined in Nebula Graph + name: source + type: { + # Specifies the data source. json is used. + source: json + + # Specifies how to import vertex data into Nebula Graph: client or sst. + # For more information about importing sst files, see Import SST files (doc to do). + sink: client + } + + # Specifies the HDFS path of the JSON file. + # Enclose the path with double quotes and start the path with hdfs://. + path: "hdfs://namenode_ip:port/path/to/test.json" + + # Specifies the keys in the JSON file. + # Their values are used as the source of the srcId property + # defined in Nebula Graph. + # If more than one key is specified, separate them with commas. + fields: ["source"] + nebula.fields: ["srcId"] + + # Specifies the values of a key in the JSON file as + # the source of the VID in Nebula Graph. + # For now, only string type VIDs are supported in Nebula Graph v2.x. + # Do not use vertex.policy for mapping. + # vertex: { + # field: key_name_in_json + # policy: "hash" + # } + vertex: source + + batch: 256 + partition: 32 + } + # Sets for the target tag + { + name: target + type: { + source: json + sink: client + } + path: "hdfs://namenode_ip:port/path/to/test.json" + fields: ["target"] + nebula.fields: ["dstId"] + vertex: "target" + batch: 256 + partition: 32 + isImplicit: true + } + # If more tags are necessary, refer to the preceding configuration to add more. + ] + + # Process edges + edges: [ + # Sets for the like edge type + { + # Specifies an edge type name defined in Nebula Graph + name: like + type: { + # Specifies the data source. json is used. + source: json + + # Specifies how to import vertex data into Nebula Graph: client or sst. + # For more information about importing sst files, see Import SST files (doc to do). + sink: client + } + + # Specifies the HDFS path of the JSON file. + # Enclose the path with double quotes and start the path with hdfs://. + path: "hdfs://namenode_ip:port/path/to/test.json" + + # Specifies the keys in the JSON file. + # Their values are used as the source of the likeness property defined in Nebula Graph. + # If more than one key is specified, separate them with commas. + fields: ["likeness"] + nebula.fields: ["likeness"] + + # Specifies the values of two keys in the JSON file as the source + # of the IDs of source and destination vertices of the like edges in Nebula Graph. + # For now, only string type VIDs are supported in Nebula Graph v2.x. + # Do not use vertex.policy for mapping. + # source: { + # field: key_name_in_json + # policy: "hash" + # } + # target: { + # field: key_name_in_json + # policy: "hash" + # } + source: "source" + target: "target" + + batch: 256 + partition: 32 + } + # If more edge types are necessary, refer to the preceding configuration to add more. + ] +} +``` + +### Step 4. (Optional) Verify the configuration + +After the configuration, run the import command with the `-D` parameter to verify the configuration file. For more information about the parameters, see [Import command parameters](../parameter-reference/ex-ug-para-import-command.md). + +```bash +$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange /path/to/nebula-exchange-2.0.0.jar -c /path/to/conf/json_application.conf -D +``` + +### Step 5. Import data into Nebula Graph + +When the configuration is ready, run this command to import data from JSON files into Nebula Graph. For more information about the parameters, see [Import command parameters](../parameter-reference/ex-ug-para-import-command.md). + +```bash +$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange /path/to/nebula-exchange-2.0.0.jar -c /path/to/conf/json_application.conf +``` + +### Step 6. (Optional) Verify data in Nebula Graph + +You can use a Nebula Graph client, such as Nebula Graph Studio, to verify the imported data. For example, in Nebula Graph Studio, run this statement. + +```ngql +GO FROM "53802643" OVER like; +``` + +If the queried destination vertices return, the data are imported into Nebula Graph. + +You can run the [`SHOW STATS`](../../3.ngql-guide/7.general-query-statements/6.show/14.show-stats.md) statement to count the data. + +### Step 7. (Optional) Create and rebuild indexes in Nebula Graph + +After the data is imported, you can create and rebuild indexes in Nebula Graph. For more information, see [nGQL User Guide](../../3.ngql-guide/1.nGQL-overview/1.overview.md). diff --git a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-steps.md b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-steps.md new file mode 100644 index 0000000..ccda8cc --- /dev/null +++ b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-steps.md @@ -0,0 +1,42 @@ +# Use Exchange + +This article introduces the generally-used procedure on how to use Exchange to import data from a specified source to Nebula Graph. + +## Prerequisites + +To import data with Exchange, do a check of these: + +- Nebula Graph is deployed and started. Get the information: + - IP addresses and ports of the Graph Service and the Meta Service. + - A Nebula Graph account with the privilege of writing data and its password. + +- Exchange is compiled. For more information, see [Compile Exchange](../ex-ug-compile.md). + +- Spark is installed. + +- Get the necessary information for schema creation in Nebula Graph, including tags and edge types. + +## Procedure + +To import data from a source to Nebula Graph, follow these steps: + +1. Create a graph space and a schema in Nebula Graph. + +2. (Optional) Process the source data. For example, to import data from a Neo4j database, create indexes for the specified tags in Neo4j to export the data from Neo4j more quickly. + +3. Edit the configuration file for Spark, Nebula Graph, vertices, and edges. + > **NOTE**: After compiling of Exchange, refer to the example configuration files in the `nebula-exchange/target/classes` directory for the configuration for different sources. + +4. (Optional) Run the import command with the `-D` parameter to verify the configuration. For more information, see [Import command parameters](../parameter-reference/ex-ug-para-import-command.md). + +5. Run the import command to import data into Nebula Graph. + +6. Verify the imported data in Nebula Graph. + +7. (Optional) Create and rebuild indexes in Nebula Graph. + +For more information, see the examples: + +- [Import data from HIVE](ex-ug-import-hive.md) +- [Import data from CSV files](ex-ug-import-from-csv.md) +- [Import data from JSON files](ex-ug-import-json.md) diff --git a/nebula-exchange/doc-2.0/about-exchange/ex-ug-what-is-exchange.md b/nebula-exchange/doc-2.0/about-exchange/ex-ug-what-is-exchange.md deleted file mode 100644 index 5e4366a..0000000 --- a/nebula-exchange/doc-2.0/about-exchange/ex-ug-what-is-exchange.md +++ /dev/null @@ -1,59 +0,0 @@ -# 什么是 Nebula Exchange - -[Nebula Exchange](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools)(简称为 Exchange)是一款 Apache Spark™ 应用,用于在分布式环境中将集群中的数据批量迁移到 Nebula Graph 中,能支持多种不同格式的批式数据和流式数据的迁移。 - -Exchange 由 Reader、Processor 和 Writer 三部分组成。Reader 读取不同来源的数据返回 DataFrame 后,Processor 遍历 DataFrame 的每一行,根据配置文件中 `fields` 的映射关系,按列名获取对应的值。在遍历指定批处理的行数后,Writer 会将获取的数据一次性写入到 Nebula Graph 中。下图描述了 Exchange 完成数据转换和迁移的过程。 - -![Nebula Graph® Exchange 由 Reader、Pocessor、Writer 组成,可以完成多种不同格式和来源的数据向 Nebula Graph 的迁移](../figs/ex-ug-001.png "Nebula Graph® Exchange 转数据转换和迁移的过程") - -## 适用场景 - -Exchange 可被用于以下场景: - -- 您想将来自 Kafka、Pulsar 平台的流式数据,如日志文件、网购数据、游戏内玩家活动、社交网站信息、金融交易大厅或地理空间服务,以及来自数据中心内所连接设备或仪器的遥测数据等转化为属性图的点或边数据,并导入 Nebula Graph 数据库。 - -- 您想从关系型数据库(如 MySQL)或者分布式文件系统(如 HDFS)中读取批式数据,如某个时间段内的数据,将它们转化为属性图的点或边数据,并导入 Nebula Graph 数据库。 - -- 您想将大批量数据生成 Nebula Graph 能识别的 SST 文件,再导入 Nebula Graph 数据库。 - -## 产品优点 - -Exchange 具有以下优点: - -- 适应性强:支持将多种不同格式或不同来源的数据导入 Nebula Graph 数据库,便于您迁移数据。 - -- 支持导入 SST:支持将不同来源的数据转换为 SST 文件,用于数据导入。 - > **说明**:仅 Linux 系统支持导入 SST 文件。 - -- 支持断点续传:导入数据时支持断点续传,有助于您节省时间,提高数据导入效率。 - > **说明**:目前仅迁移 Neo4j 数据时支持断点续传。 - -- 异步操作:会在源数据中生成一条插入语句,发送给查询服务,最后再执行 Nebula Graph 的插入操作。 - -- 灵活性强:支持同时导入多个标签和边类型,不同标签和边类型可以是不同的数据来源或格式。 - -- 统计功能:使用 Apache Spark™ 中的累加器统计插入操作的成功和失败次数。 - -- 易于使用,对用户友好:采用 HOCON(Human-Optimized Config Object Notation)配置文件格式,具有面向对象风格,便于理解和操作。 - -## 数据格式和来源 - -Exchange v1.x 支持将以下格式或来源的数据转换为 Nebula Graph v1.x 能识别的点和边数据: - -- 存储在 HDFS 的数据,包括: - - Apache Parquet - - Apache ORC - - JSON - - CSV - -- Apache HBase™ - -- 数据仓库:HIVE - -- 图数据库:Neo4j 2.4.5-M1。仅 Neo4j 支持断点续传 - -- 关系型数据库:MySQL - -- 流处理软件平台:Apache Kafka® - -- 发布/订阅消息系统:Apache Pulsar 2.4.5 From 506a6da8bbb1108ad3aa59b79d4fb049820d3add Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 13 Apr 2021 19:20:32 +0800 Subject: [PATCH 073/213] remove judg for endian --- .../exchange/processor/EdgeProcessor.scala | 24 +++++++++---------- .../processor/VerticesProcessor.scala | 14 +++++------ 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index db59e5a..e230ee6 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -164,23 +164,21 @@ class EdgeProcessor(data: DataFrame, import java.nio.ByteBuffer val order = ByteOrder.nativeOrder val srcBytes = if (vidType == VidType.INT) { - val bytes = ByteBuffer.allocate(8).putLong(srcId.toLong).array - if (order == ByteOrder.LITTLE_ENDIAN) { - return bytes.reverse - } else { - return bytes - } + ByteBuffer + .allocate(8) + .order(ByteOrder.nativeOrder) + .putLong(srcId.toLong) + .array } else { srcId.getBytes() } val dstBytes = if (vidType == VidType.INT) { - val bytes = ByteBuffer.allocate(8).putLong(dstId.toLong).array - if (order == ByteOrder.LITTLE_ENDIAN) { - return bytes.reverse - } else { - return bytes - } + ByteBuffer + .allocate(8) + .order(ByteOrder.nativeOrder) + .putLong(dstId.toLong) + .array } else { dstId.getBytes() } @@ -222,7 +220,7 @@ class EdgeProcessor(data: DataFrame, val value = vertex.getAs[Array[Byte]](1) var part = ByteBuffer .wrap(key, 0, 4) - .order(ByteOrder.LITTLE_ENDIAN) + .order(ByteOrder.nativeOrder) .getInt >> 8 if (part <= 0) { part = part + partitionNum diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index fff2003..e1f6828 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -149,13 +149,11 @@ class VerticesProcessor(data: DataFrame, import java.nio.ByteBuffer val vidBytes = if (vidType == VidType.INT) { - val bytes = ByteBuffer.allocate(8).putLong(vertexId.toLong).array - val order = ByteOrder.nativeOrder - if (order == ByteOrder.LITTLE_ENDIAN) { - return bytes.reverse - } else { - return bytes - } + ByteBuffer + .allocate(8) + .order(ByteOrder.nativeOrder) + .putLong(vertexId.toLong) + .array } else { vertexId.getBytes() } @@ -184,7 +182,7 @@ class VerticesProcessor(data: DataFrame, val value = vertex.getAs[Array[Byte]](1) var part = ByteBuffer .wrap(key, 0, 4) - .order(ByteOrder.LITTLE_ENDIAN) + .order(ByteOrder.nativeOrder) .getInt >> 8 if (part <= 0) { part = part + partitionNum From 20173855373ee71bc9e947244e790f3c5e464149 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 14 Apr 2021 14:05:38 +0800 Subject: [PATCH 074/213] fix conflict --- .../vesoft/nebula/exchange/config/Configs.scala | 6 ++++-- .../com/vesoft/nebula/exchange/package.scala | 6 ++++-- .../nebula/exchange/utils/NebulaUtils.scala | 16 ++++++++++++++-- .../exchange/writer/ServerBaseWriter.scala | 2 +- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala index 355efe8..314c9d3 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala @@ -13,6 +13,7 @@ import com.google.common.net.HostAndPort import com.vesoft.nebula.exchange.KeyPolicy import com.typesafe.config.{Config, ConfigFactory} import com.vesoft.nebula.exchange.Argument +import com.vesoft.nebula.exchange.utils.NebulaUtils import org.apache.log4j.Logger import scala.collection.JavaConverters._ @@ -280,7 +281,7 @@ object Configs { val tagName = tagConfig.getString("name") val fields = tagConfig.getStringList("fields").asScala.toList - val nebulaFields = if (tagConfig.hasPath("nebula.fields")) { + var nebulaFields = if (tagConfig.hasPath("nebula.fields")) { tagConfig.getStringList("nebula.fields").asScala.toList } else { fields @@ -348,11 +349,12 @@ object Configs { val edgeName = edgeConfig.getString("name") val fields = edgeConfig.getStringList("fields").asScala.toList - val nebulaFields = if (edgeConfig.hasPath("nebula.fields")) { + var nebulaFields = if (edgeConfig.hasPath("nebula.fields")) { edgeConfig.getStringList("nebula.fields").asScala.toList } else { fields } + val isGeo = !edgeConfig.hasPath("source") && edgeConfig.hasPath("latitude") && edgeConfig.hasPath("longitude") diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/package.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/package.scala index 7370372..5e76ae3 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/package.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/package.scala @@ -8,6 +8,8 @@ package com.vesoft.nebula import com.google.common.base.Optional import com.google.common.util.concurrent.ListenableFuture +import com.vesoft.nebula.exchange.utils.NebulaUtils + import scala.collection.mutable.ListBuffer package object exchange { @@ -42,7 +44,7 @@ package object exchange { values: List[Vertex], policy: Option[KeyPolicy.Value] = None) { - def propertyNames: String = names.mkString(",") + def propertyNames: String = NebulaUtils.escapePropName(names).mkString(",") override def toString: String = { s"Vertices: " + @@ -72,7 +74,7 @@ package object exchange { values: List[Edge], sourcePolicy: Option[KeyPolicy.Value] = None, targetPolicy: Option[KeyPolicy.Value] = None) { - def propertyNames: String = names.mkString(",") + def propertyNames: String = NebulaUtils.escapePropName(names).mkString(",") override def toString: String = { "Edges:" + diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala index f95d42e..0998e30 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala @@ -7,13 +7,13 @@ package com.vesoft.nebula.exchange.utils import com.vesoft.nebula.exchange.{MetaProvider, VidType} -import com.vesoft.nebula.exchange.MetaProvider -import com.vesoft.nebula.exchange.config.{EdgeConfigEntry, SchemaConfigEntry, TagConfigEntry, Type} +import com.vesoft.nebula.exchange.config.{SchemaConfigEntry, Type} import org.apache.commons.codec.digest.MurmurHash2 import org.apache.log4j.Logger import scala.collection.JavaConversions.seqAsJavaList import scala.collection.mutable +import scala.collection.mutable.ListBuffer object NebulaUtils { private[this] val LOG = Logger.getLogger(this.getClass) @@ -85,4 +85,16 @@ object NebulaUtils { } (Math.floorMod(hashValue, partitionSize) + 1).toInt } + + def escapePropName(nebulaFields: List[String]): List[String] = { + val propNames: ListBuffer[String] = new ListBuffer[String] + for (key <- nebulaFields) { + val sb = new StringBuilder() + sb.append("`") + sb.append(key) + sb.append("`") + propNames.append(sb.toString()) + } + propNames.toList + } } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala index 7e98046..9911486 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala @@ -33,7 +33,7 @@ import org.apache.spark.util.LongAccumulator import scala.collection.JavaConverters._ abstract class ServerBaseWriter extends Writer { - private[this] val BATCH_INSERT_TEMPLATE = "INSERT %s %s(%s) VALUES %s" + private[this] val BATCH_INSERT_TEMPLATE = "INSERT %s `%s`(%s) VALUES %s" private[this] val INSERT_VALUE_TEMPLATE = "%s: (%s)" private[this] val INSERT_VALUE_TEMPLATE_WITH_POLICY = "%s(\"%s\"): (%s)" private[this] val ENDPOINT_TEMPLATE = "%s(\"%s\")" From 81472446105c48db123ce383bcbb47ca3228471a Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 14 Apr 2021 14:07:38 +0800 Subject: [PATCH 075/213] revert var --- .../scala/com/vesoft/nebula/exchange/config/Configs.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala index 314c9d3..01d1f9c 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala @@ -281,7 +281,7 @@ object Configs { val tagName = tagConfig.getString("name") val fields = tagConfig.getStringList("fields").asScala.toList - var nebulaFields = if (tagConfig.hasPath("nebula.fields")) { + val nebulaFields = if (tagConfig.hasPath("nebula.fields")) { tagConfig.getStringList("nebula.fields").asScala.toList } else { fields @@ -349,7 +349,7 @@ object Configs { val edgeName = edgeConfig.getString("name") val fields = edgeConfig.getStringList("fields").asScala.toList - var nebulaFields = if (edgeConfig.hasPath("nebula.fields")) { + val nebulaFields = if (edgeConfig.hasPath("nebula.fields")) { edgeConfig.getStringList("nebula.fields").asScala.toList } else { fields From 125d676845c0ea007fb3b5b22d82a7fcdd32f561 Mon Sep 17 00:00:00 2001 From: cooper-lzy <78672629+cooper-lzy@users.noreply.github.com> Date: Thu, 15 Apr 2021 11:55:38 +0800 Subject: [PATCH 076/213] use exchange --- .../CN/about-exchange/ex-ug-limitations.md | 24 +- .../doc-2.0/CN/about-exchange/ex-ug-terms.md | 8 +- nebula-exchange/doc-2.0/CN/ex-ug-FAQ.md | 2 +- nebula-exchange/doc-2.0/CN/ex-ug-compile.md | 2 +- .../CN/parameter-reference/ex-ug-parameter.md | 141 ++++++ .../CN/use-exchange/ex-ug-import-from-csv.md | 430 ++++++++++-------- .../CN/use-exchange/ex-ug-import-steps.md | 48 +- .../doc-2.0/EN/about-exchange/ex-ug-faq.md | 24 - .../EN/about-exchange/ex-ug-limitations.md | 8 +- .../about-exchange/ex-ug-what-is-exchange.md | 2 +- nebula-exchange/doc-2.0/EN/ex-ug-compile.md | 2 +- nebula-exchange/doc-2.0/EN/ex-ug-faq.md | 123 +++++ .../EN/use-exchange/ex-ug-import-from-csv.md | 20 +- .../EN/use-exchange/ex-ug-import-steps.md | 7 +- 14 files changed, 572 insertions(+), 269 deletions(-) create mode 100644 nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-parameter.md delete mode 100644 nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-faq.md create mode 100644 nebula-exchange/doc-2.0/EN/ex-ug-faq.md diff --git a/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-limitations.md b/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-limitations.md index c8efd8c..b4c1420 100644 --- a/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-limitations.md +++ b/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-limitations.md @@ -1,29 +1,31 @@ # 使用限制 -本文描述 Exchange v1.x 的一些使用限制。 +本文描述Exchange 2.0的一些使用限制。 -## Nebula Graph 版本 +## Nebula Graph版本 -Exchange v1.x 仅支持 Nebula Graph v1.x。如果您正在使用 Nebula Graph v2.x,请使用 [Nebula Exchange v2.x](https://github.com/vesoft-inc/nebula-spark-utils "点击前往 GitHub")。 +Exchange 2.0仅支持Nebula Graph 2.0.0。如果您正在使用Nebula Graph 1.x,请使用[Nebula Exchange 1.x](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools "Click to go to GitHub")。 ## 使用环境 -Exchange v1.x 支持以下操作系统: +Exchange 2.0 支持以下操作系统: - CentOS 7 - macOS -> **说明**:仅 Linux 系统支持导入 SST 文件。 +> **说明**:仅Linux系统支持导入SST文件。 ## 软件依赖 -为保证 Exchange v1.x 正常工作,确认您的机器上已经安装以下软件: +为保证Exchange正常工作,请确认您的机器上已经安装如下软件: + +- Apache Spark:2.3.0及以上版本 -- Apache Spark:2.3.0 及以上版本 - Java:1.8 -- Scala:2.10.7、2.11.12、2.12.10 -在以下使用场景,还需要部署 Hadoop Distributed File System (HDFS): +- Scala:2.10.7、2.11.12或2.12.10 + +在以下使用场景,还需要部署Hadoop Distributed File System (HDFS): -- 以客户端形式迁移 HDFS 上的数据 -- 以 SST 文件格式迁移数据 +- 迁移HDFS的数据 +- 迁移SST文件的数据 diff --git a/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-terms.md b/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-terms.md index 3a5746b..f61eac7 100644 --- a/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-terms.md +++ b/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-terms.md @@ -1,9 +1,9 @@ # 名词解释 -本文描述了您在使用 Exchange 时可能需要了解的名词解释。 +本文描述使用Exchange时可能需要了解的名词和解释。 -- Nebula Exchange:在本手册中简称为 Exchange 或 Exchange v1.x,一款基于 Apache Spark™ 的 Spark 应用,用于批量数据迁移。它支持将多种不同来源和格式的数据文件转换为 Nebula Graph 能识别的点和边数据,再并发导入 Nebula Graph。 +- Nebula Exchange:在本手册中简称为Exchange或Exchange 2.x,是一款基于Apache Spark™的Spark应用,用于批量数据迁移。它支持将多种不同来源和格式的数据文件转换为Nebula Graph能识别的点和边数据,再并发导入Nebula Graph。 -- Aparch Spark™:是专为大规模数据处理而设计的快速通用的计算引擎,是 Apache 软件基金会的一个开源项目。 +- Aparch Spark™:是专为大规模数据处理而设计的快速通用的计算引擎,是Apache软件基金会的一个开源项目。 -- Driver Program:在本手册中简称为 Driver,是运行应用的 main 函数并且新建 SparkContext 实例的程序。 +- Driver Program:在本手册中简称为Driver,是运行应用的main函数并且新建SparkContext实例的程序。 diff --git a/nebula-exchange/doc-2.0/CN/ex-ug-FAQ.md b/nebula-exchange/doc-2.0/CN/ex-ug-FAQ.md index 56c06ed..af3113f 100644 --- a/nebula-exchange/doc-2.0/CN/ex-ug-FAQ.md +++ b/nebula-exchange/doc-2.0/CN/ex-ug-FAQ.md @@ -84,7 +84,7 @@ ### Exchange支持哪些版本的Nebula Graph? -请参见Exchange的[使用限制](ex-ug-limitations.md)。 +请参见Exchange的[使用限制](about-exchange/ex-ug-limitations.md)。 ### Exchange与Spark Writer有什么关系? diff --git a/nebula-exchange/doc-2.0/CN/ex-ug-compile.md b/nebula-exchange/doc-2.0/CN/ex-ug-compile.md index 05b4872..5657625 100644 --- a/nebula-exchange/doc-2.0/CN/ex-ug-compile.md +++ b/nebula-exchange/doc-2.0/CN/ex-ug-compile.md @@ -82,4 +82,4 @@ > **说明**:`.jar`文件版本号会因Nebula Java Client的发布版本而变化。您可以在[Releases页面](https://github.com/vesoft-inc/nebula-java/releases)查看最新版本。 -迁移数据时,您可以参考配置文件`target/classes/application.conf`、`target/classes/server_application.conf`和`target/classes/stream_application.conf`。 +迁移数据时,您可以参考配置文件`target/classes/application.conf`。 diff --git a/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-parameter.md b/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-parameter.md new file mode 100644 index 0000000..9cd29cf --- /dev/null +++ b/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-parameter.md @@ -0,0 +1,141 @@ +# 配置说明 + +本文介绍使用Nebula Exchange时如何修改配置文件`application.conf`。 + +修改配置文件之前,建议您根据数据源复制并修改文件名称,便于区分。例如数据源为CSV文件,可以复制为`csv_application.conf`。 + +配置文件的内容主要分为如下几类: + +- Spark相关配置 + +- Nebula Graph相关配置 + +- 点配置 + +- 边配置 + +## Spark相关配置 + +本文只列出部分Spark参数,更多参数请参见[官方文档](https://spark.apache.org/docs/latest/configuration.html#application-properties)。 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`spark.app.name`|string|`Nebula Exchange 2.0`|否|Spark驱动程序名称。| +|`spark.driver.cores`|int|`1`|否|驱动程序使用的CPU核数,仅适用于集群模式。| +|`spark.driver.maxResultSize`|string|`1G`|否|单个Spark操作(例如collect)时,所有分区的序列化结果的总大小限制(字节为单位)。最小值为1M,0表示无限制。| +|`spark.executor.memory`|string|`1G`|否|Spark驱动程序使用的内存量,可以指定单位,例如512M、1G。| +|`spark.cores.max`|int|`16`|否|当驱动程序以“粗粒度”共享模式在独立部署集群或Mesos集群上运行时,跨集群(而非从每台计算机)请求应用程序的最大CPU核数。如果未设置,则值为Spark的独立集群管理器上的`spark.deploy.defaultCores`或Mesos上的infinite(所有可用的内核)。| + +## Nebula Graph相关配置 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`nebula.address.graph`|list\[string\]|`["127.0.0.1:9699"]`|是|Graph服务的地址,包括IP和端口,多个地址用英文逗号(,)分隔。格式为`["ip1:port1","ip2:port2","ip3:port3"]`。| +|`nebula.address.meta`|int|`["127.0.0.1:9559"]`|是|Meta服务的地址,包括IP和端口,多个地址用英文逗号(,)分隔。格式为`["ip1:port1","ip2:port2","ip3:port3"]`。| +|`nebula.user`|string|-|是|拥有Nebula Graph写权限的用户名。| +|`nebula.pswd`|string|-|是|用户名对应的密码。| +|`nebula.space`|string|-|是|需要导入数据的的图空间名称。| +|`nebula.path.local`|string|`"/tmp"`|否|(TODO:coding)导入SST文件时需要设置本地SST文件路径。| +|`nebula.path.remote`|string|`"/sst"`|否|(TODO:coding)导入SST文件时需要设置远端SST文件路径。| +|`nebula.path.hdfs.namenode`|string|`"hdfs://name_node:9000"`|否|(TODO:coding)导入SST文件时需要设置HDFS的namenode。| +|`nebula.connection.timeout`|int|`3000`|否|Thrift连接的超时时间,单位为 ms。| +|`nebula.connection.retry`|int|`3`|否|Thrift连接重试次数。| +|`nebula.execution.retry`|int|`3`|否|nGQL语句执行重试次数。| +|`nebula.error.max`|int|`32`|否|导入过程中的最大失败次数。当失败次数达到最大值时,提交的Spark作业将自动停止。| +|`nebula.error.output`|string|`/tmp/errors`|否|输出错误信息的日志路径。您可以在这个文件里查看发生的所有错误信息。| +|`nebula.rate.limit`|int|`1024`|否|导入数据时令牌桶的令牌数量限制。| +|`nebula.rate.timeout`|int|`1000`|否|令牌桶中拿取令牌的超时时间,单位:毫秒。| + +## 点配置 + +对于不同的数据源,点的配置也有所不同,有很多通用参数,也有部分特有参数,配置时需要配置通用参数和不同数据源的特有参数。 + +### 通用参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.name`|string|-|是|Nebula Graph中定义的标签名称。| +|`tags.type.source`|string|-|是|指定数据源。例如`csv`。| +|`tags.type.sink`|string|`client`|是|指定导入方式,可选值为`client`和`SST`(暂不支持)。| +|`tags.fields`|list\[string\]|-|是|属性对应的列的表头。如果没有表头,用`[_c0, _c1, _c2]`的形式表示第一列、第二列、第三列,以此类推;如果有表头,使用实际的列名。| +|`tags.nebula.fields`|list\[string\]|-|是|Nebula Graph中定义的属性名称,顺序必须和`tags.fields`一一对应。例如`[_c1, _c2]`对应`[name, age]`,表示第二列为属性name的值,第三列为属性age的值。| +|`tags.vertex.field`|string|-|是|点ID的列。例如`_c0`表示第一列的值作为点ID。| +|`tags.batch`|int|`256`|是|单次写入Nebula Graph的最大点数量。| +|`tags.partition`|int|`32`|是|Spark分片数量。| + +### Parquet/JSON/ORC源特有参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.path`|string|-|是|HDFS中点数据文件的路径。用双引号括起路径,以`hdfs://`开头。| + +### CSV源特有参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.path`|string|-|是|HDFS中点数据文件的路径。用双引号括起路径,以`hdfs://`开头。| +|`tags.separator`|string|`,`|是|分隔符。默认值为英文逗号(,)。| +|`tags.header`|bool|`true`|是|文件是否有表头。| + +### HIVE源特有参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.exec`|string|-|是|查询数据源的语句。例如`select name,age from mooc.users`。| + +### Neo4j源特有参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.exec`|string|-|是|查询数据源的语句。例如`match (n:label) return n.neo4j-field-0`。| +|`tags.server`|string|`"bolt://127.0.0.1:7687"`|是|Neo4j服务器地址。| +|`tags.user`|string|-|是|拥有读取权限的Neo4j用户名。| +|`tags.password`|string|-|是|用户名对应密码。| +|`tags.check_point_path`|string|`/tmp/test`|是|检查点路径。| + +### Hbase源特有参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.host`|string|`127.0.0.1`|是|Hbase服务器地址。| +|`tags.port`|string|`2181`|是|Hbase服务器端口。| +|`tags.table`|string|-|是|需要作为数据源的表名称。| +|`tags.columnFamily`|string|-|是|表所属的列族(column family)。| + +### Pulsar源特有参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.service`|string|`"pulsar://localhost:6650"`|是|Pulsar服务器地址。| +|`tags.admin`|string|`"http://localhost:8081"`|是|连接pulsar的admin.url。| +|`tags.options.`|string|-|是|Pulsar的选项,可以从`topic`、`topics`和`topicsPattern`选择一个进行配置。| +|`tags.interval.seconds`|int|`10`|是|读取消息的间隔。单位:秒。| + +### Kafka源特有参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.service`|string|-|是|Kafka服务器地址。| +|`tags.topic`|string|-|是|消息类别。| +|`tags.interval.seconds`|int|`10`|是|读取消息的间隔。单位:秒。| + +## 边配置 + +对于不同的数据源,边的配置也有所不同,有很多通用参数,也有部分特有参数,配置时需要配置通用参数和不同数据源的特有参数。 + +边配置的不同数据源特有参数请参见上方点配置内的特有参数介绍。 + +### 通用参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`edges.name`| string|-|是|Nebula Graph中定义的边类型名称。| +|`edges.type.source`|string|-|是|指定数据源。例如`csv`。| +|`edges.type.sink`|string|`client`|是|指定导入方式,可选值为`client`和`SST`(暂不支持)。| +|`edges.fields`|list\[string\]|-|是|属性对应的列的表头。如果没有表头,用`[_c0, _c1, _c2]`的形式表示第一列、第二列、第三列,以此类推;如果有表头,使用实际的列名。| +|`edges.nebula.fields`|list\[string\]|-|是|Nebula Graph中定义的属性名称,顺序必须和`edges.fields`一一对应。例如`[_c2, _c3]`对应`[start_year, end_year]`,表示第三列为开始年份的值,第四列为结束年份的值。| +|`edges.source.field`|string|-|是|边的起始点的列。例如`_c0`表示第一列的值作为边的起始点。| +|`edges.target.field`|string|-|是|边的目的点的列。例如`_c1`表示第二列的值作为边的目的点。| +|`edges.ranking`|int|-|否|rank值的列。没有指定时,默认所有rank值为`0`。| +|`edges.batch`|int|`256`|是|单次写入Nebula Graph的最大边数量。| +|`edges.partition`|int|`32`|是|Spark分片数量。| \ No newline at end of file diff --git a/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-csv.md b/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-csv.md index b47c66b..b467813 100644 --- a/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-csv.md +++ b/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-csv.md @@ -1,125 +1,136 @@ -# 导入 CSV 文件数据 +# 导入CSV文件数据 -本文以一个示例说明如何使用 Exchange 将存储在 HDFS 上的 CSV 文件数据导入 Nebula Graph。 +本文以一个示例说明如何使用Exchange将存储在HDFS上的CSV文件数据导入Nebula Graph。 -如果您要向 Nebula Graph 导入本地 CSV 文件,参考 [CSV 文件导入示例](../../manual-CN/1.overview/2.quick-start/4.import-csv-file.md)。 +如果您要向Nebula Graph导入本地CSV文件,请参见[Nebula Importer](https://github.com/vesoft-inc/nebula-importer "Click to go to GitHub")。 ## 数据集 -本文以美国 Stanford Network Analysis Platform (SNAP) 提供的 [Social Network: MOOC User Action Dataset](https://snap.stanford.edu/data/act-mooc.html "点击前往 Stanford Network Analysis Platform (SNAP) 网站") 以及由公开网络上获取的不重复的 97 个课程名称作为示例数据集,包括: - -- 两类点(`user` 和 `course`),共计 7,144 个点。 -- 一种关系(`action`),共计 411,749 条边。 - -详细的数据集,您可以从 [nebula-web-docker](https://github.com/vesoft-inc/nebula-web-docker/tree/master/example/mooc-actions "点击前往 GitHub") 仓库中下载。 +本文以basketballplayer数据集为例。您可以从[nebula-web-docker](https://github.com/vesoft-inc/nebula-web-docker/tree/master/example/mooc-actions "点击前往 GitHub")仓库中下载。 ## 环境配置 -本文示例在 MacOS 下完成,以下是相关的环境配置信息: +本文示例在MacOS下完成,以下是相关的环境配置信息: - 硬件规格: - CPU:1.7 GHz Quad-Core Intel Core i7 - 内存:16 GB -- Spark:2.3.0,单机版 +- Spark:2.4.7 单机版 -- Hadoop:2.9.2,伪分布式部署 +- Hadoop:2.9.2 伪分布式部署 -- Nebula Graph:V1.1.0,使用 Docker Compose 部署。详细信息,参考 [使用 Docker Compose 部署 Nebula Graph](https://github.com/vesoft-inc/nebula-docker-compose/blob/master/README_zh-CN.md) +- Nebula Graph:2.0.0。使用[Docker Compose部署](https://github.com/vesoft-inc/nebula-docker-compose/blob/master/README_zh-CN.md)。 ## 前提条件 开始导入数据之前,您需要确认以下信息: -- 已经完成 Exchange 编译。详细信息,参考 [编译 Exchange](../ex-ug-compile.md)。本示例中使用 Exchange v1.1.0。 +- 已经[安装部署Nebula Graph](https://docs.nebula-graph.com.cn/2.0/#dba)并获取如下信息: + + - Graph服务和Meta服务的的IP地址和端口。 -- 已经安装 Spark。 + - 拥有Nebula Graph写权限的用户名和密码。 -- 已经安装并开启 Hadoop 服务。 +- 已经编译Exchange。详情请参见[编译Exchange](../ex-ug-compile.md)。本示例中使用Exchange 2.0。 -- 已经部署并启动 Nebula Graph,并获取: - - Graph 服务、Meta 服务所在机器的 IP 地址和端口信息。 - - Nebula Graph 数据库的拥有写权限的用户名及其密码。 +- 已经安装Spark。 -- 在 Nebula Graph 中创建图数据模式(Schema)所需的所有信息,包括标签和边类型的名称、属性等。 +- 了解Nebula Graph中创建Schema的信息,包括标签和边类型的名称、属性等。 + +- 已经安装并开启Hadoop服务。 ## 操作步骤 -### 步骤 1. 在 Nebula Graph 中创建 Schema +### 步骤 1:在Nebula Graph中创建Schema -分析 CSV 文件中的数据,按以下步骤在 Nebula Graph 中创建 Schema: +分析CSV文件中的数据,按以下步骤在Nebula Graph中创建Schema: -1. 确认 Schema 要素:Nebula Graph 中的 Schema 要素如下表所示。 +1. 确认Schema要素。Nebula Graph中的Schema要素如下表所示。 | 要素 | 名称 | 属性 | | :--- | :--- | :--- | - | 标签(Tag) | `user` | `userId int` | - | 标签(Tag) | `course` | `courseId int, courseName string` | - | 边类型(Edge Type) | `action` | `actionId int, duration double, label bool, feature0 double, feature1 double, feature2 double, feature3 double` | + | 标签(Tag) | `player` | `name string, age int` | + | 标签(Tag) | `team` | `name string` | + | 边类型(Edge Type) | `follow` | `degree int` | + | 边类型(Edge Type) | `serve` | `start_year int, end_year int` | -2. 在 Nebula Graph 里创建一个图空间 **csv**,并创建一个 Schema,如下所示。 +2. 在Nebula Graph中创建一个图空间**csv**,并创建一个Schema,如下所示。 ```ngql - -- 创建图空间 - CREATE SPACE csv(partition_num=10, replica_factor=1); + ## 创建图空间 + nebula> CREATE SPACE csv \ + (partition_num = 10, \ + replica_factor = 1, \ + vid_type = FIXED_STRING(30)); - -- 选择图空间 csv - USE csv; + ## 选择图空间csv + nebula> USE csv; - -- 创建标签 user - CREATE TAG user(userId int); + ## 创建标签player + nebula> CREATE TAG player(name string, age int); - -- 创建标签 course - CREATE TAG course(courseId int, courseName string); + ## 创建标签team + nebula> CREATE TAG team(name string); - -- 创建边类型 action - CREATE EDGE action (actionId int, duration double, label bool, feature0 double, feature1 double, feature2 double, feature3 double); + ## 创建边类型follow + nebula> CREATE EDGE follow(degree int); + + ## 创建边类型serve + nebula> CREATE EDGE serve(start_year int, end_year int); ``` -关于 Nebula Graph 构图的更多信息,参考《Nebula Graph Database 手册》的 [快速开始](../../manual-CN/1.overview/2.quick-start/1.get-started/ "点击前往 Nebula Graph 网站")。 +更多信息,请参见[快速开始](https://docs.nebula-graph.com.cn/2.0/2.quick-start/1.quick-start-workflow/)。 -### 步骤 2. 处理 CSV 文件 +### 步骤 2:处理CSV文件 确认以下信息: -1. CSV 文件已经根据 Schema 作了处理。详细操作请参考 [Nebula Graph Studio 快速开始](../../nebula-studio/quick-start/st-ug-prepare-csv.md)。 - > **说明**:Exchange 支持上传有表头或者无表头的 CSV 文件。 +1. 处理CSV文件以满足Schema的要求。 + > **说明**:Exchange支持上传有表头或者无表头的CSV文件。 -2. CSV 文件必须存储在 HDFS 中,并已获取文件存储路径。 +2. CSV文件必须存储在HDFS中,并已获取文件存储路径。 -### 步骤 3. 修改配置文件 +### 步骤 3:修改配置文件 -完成 Exchange 编译后,进入 `nebula-java/tools/exchange` 目录,根据 `target/classes/application.conf` 文件修改 CSV 数据源相关的配置文件。在本示例中,文件被重命名为 `csv_application.conf`。以下仅详细说明点和边数据的配置信息,本次示例中未使用的配置项已被注释,但是提供了配置说明。Spark 和 Nebula Graph 相关配置,参考 [Spark 参数](../parameter-reference/ex-ug-paras-spark.md)和 [Nebula Graph 参数](../parameter-reference/ex-ug-paras-nebulagraph.md)。 +编译Exchange后,复制`target/classes/application.conf`文件设置CSV数据源相关的配置。在本示例中,复制的文件名为`csv_application.conf`。以下仅详细说明点和边数据的配置信息,未使用的配置项已被注释,但是提供了配置说明。Spark和Nebula Graph相关配置,请参见[Spark参数](../parameter-reference/ex-ug-paras-spark.md)和 [Nebula Graph参数](../parameter-reference/ex-ug-paras-nebulagraph.md)。 ```conf { - # Spark 相关配置 + # Spark相关配置 spark: { app: { - name: Spark Writer + name: Nebula Exchange 2.0 } driver: { cores: 1 maxResultSize: 1G } + executor: { + memory:1G + } + cores { max: 16 } } - # Nebula Graph 相关配置 + + # Nebula Graph相关配置 nebula: { address:{ - # 以下为 Nebula Graph 的 Graph 服务和 Meta 服务所在机器的 IP 地址及端口 - # 如果有多个地址,格式为 "ip1:port","ip2:port","ip3:port" - # 不同地址之间以英文逗号 (,) 隔开 - graph:["127.0.0.1:3699"] - meta:["127.0.0.1:45500"] + # 指定Graph服务和Meta服务的IP地址和端口。 + # 如果有多台服务器,地址之间用英文逗号(,)分隔。 + # 格式: "ip1:port","ip2:port","ip3:port" + graph:["127.0.0.1:9669"] + meta:["127.0.0.1:9559"] } - # 填写的账号必须拥有 Nebula Graph 相应图空间的写数据权限 - user: user - pswd: password - # 填写 Nebula Graph 中需要写入数据的图空间名称 - space: csv + + # 指定拥有Nebula Graph写权限的用户名和密码。 + user: root + pswd: nebula + + # 指定图空间名称。 + space: basketballplayer connection { timeout: 3000 retry: 3 @@ -136,196 +147,245 @@ timeout: 1000 } } - # 处理标签 + + # 处理点 tags: [ - # 设置标签 course 相关信息 + # 设置标签player相关信息。 { - # Nebula Graph 中对应的标签名称。 - name: course + # 指定Nebula Graph中定义的标签名称。 + name: player type: { - # 指定数据源文件格式,设置为 csv。 + # 指定数据源,使用CSV。 source: csv - # 指定点数据导入 Nebula Graph 的方式, - # 可以设置为:client(以客户端形式导入)和 sst(以 SST 文件格式导入)。 - # 关于 SST 文件导入配置,参考文档:导入 SST 文件(https:// - # docs.nebula-graph.com.cn/nebula-exchange/ - # use-exchange/ex-ug-import-sst/)。 + + # 指定如何将点数据导入Nebula Graph:Client或SST。 sink: client } - # CSV 文件所在的 HDFS 路径,String 类型,必须以 hdfs:// 开头。 - path: "hdfs://namenode_ip:port/path/to/course.csv" - - # 如果 CSV 文件里不带表头,则写入 [_c0, _c1, _c2, ... _cn], - # 表示 CSV 文件中的数据列名,作为 course 各属性值来源。 - # 如果 CSV 文件里有表头,则写入各列名。 - # fields 与 nebula.fields 的顺序必须一一对应。 - fields: [_c0, _c1] - - # 设置 Nebula Graph 中与 CSV 文件各列对应的属性名称, - # fields 与 nebula.fields 的顺序必须一一对应。 - nebula.fields: [courseId, courseName] - - # Exchange 1.1.0 添加了 csv.fields 参数: - # 如果配置了 csv.fields,无论 CSV 文件是否有表头, - # fields 的配置必须与 csv.fields 的配置保持一致。 - # csv.fields: [courseId, courseName] - - # 指定 CSV 中的某一列数据为 Nebula Graph 中点 VID 的来源。 - # vertex.field 的值必须与上述 fields 或者 csv.fields 中的列名保持一致。 - # 如果数据不是 int 类型,则添加 vertex.policy 指定 VID 映射策略,建议设置为 "hash"。 - vertex: { - field: _c1, - policy: "hash" - } - # 标明数据源中数据分隔方式,默认为英文逗号(,)。 + # 指定CSV文件的HDFS路径。 + # 用双引号括起路径,以hdfs://开头。 + path: "hdfs://192.168.153.10:9000/data/vertex_player.csv" + + # 如果CSV文件没有表头,使用[_c0, _c1, _c2, ..., _cn]表示其表头,并将列指示为属性值的源。 + # 如果CSV文件有表头,则使用实际的列名。 + fields: [_c1, _c2] + + # 指定Nebula Graph中定义的属性名称。 + # fields与nebula.fields的顺序必须一一对应。 + nebula.fields: [age, name] + + # 指定一个列作为VID的源。 + # vertex的值必须与上述fields或者csv.fields中的列名保持一致。 + # 目前,Nebula Graph 2.0.0仅支持字符串类型的VID。 + # 不要使用vertex.policy映射。例如: + # vertex: { + # field: _c0, + # policy: "hash" + # } + vertex: _c0 + + # 指定的分隔符。默认值为英文逗号(,)。 separator: "," - # 如果 CSV 文件中有表头,header 设置为 true。 - # 如果 CSV 文件中没有表头,header 设置为 false(默认值)。 + # 如果CSV文件有表头,请将header设置为true。 + # 如果CSV文件没有表头,请将header设置为false。默认值为false。 header: false - # 单次写入 Nebula Graph 的最大点数据量。 + # 指定单次写入Nebula Graph的最大点数量。 batch: 256 - # Spark 分区数量 + # 指定Spark分片数量。 partition: 32 - - # isImplicit 的设置说明参考:https://github.com/vesoft-inc/nebula-java/ - # blob/v1.0/tools/exchange/src/main/resources/application.conf - isImplicit: true } - # 设置标签 user 相关信息 + # 设置标签team相关信息。 { - name: user + # 指定Nebula Graph中定义的标签名称。 + name: team type: { + # 指定数据源,使用CSV。 source: csv + + # 指定如何将点数据导入Nebula Graph:Client或SST。 sink: client } - path: "hdfs://namenode_ip:port/path/to/user.csv" - - # Exchange 1.1.0 添加了 csv.fields 参数 - # 如果 CSV 文件里不带表头,但是配置了 csv.fields, - # 则 fields 的配置必须与 csv.fields 保持一致, - # Exchange 会将 csv.fields 里的设置作为表头。 - # fields 与 nebula.fields 的顺序必须一一对应。 - fields: [userId] - - # 设置 Nebula Graph 中与 CSV 文件各列对应的属性名称, - # 必须与 fields 或者 csv.fields 的顺序一一对应。 - nebula.fields: [userId] - - # 如果配置了 csv.fields,无论 CSV 文件是否有表头, - # 均以这个参数指定的名称作为表头, - # fields 的配置必须与 csv.fields 的配置保持一致, - # 同时,vertex 的设置必须与 csv.fields 的设置相同。 - csv.fields: [userId] - - # vertex 的值必须与 fields 或者 csv.fields 中相应的列名保持一致。 - vertex: userId + + # 指定CSV文件的HDFS路径。 + # 用双引号括起路径,以hdfs://开头。 + path: "hdfs://192.168.153.10:9000/data/vertex_team.csv" + + # 如果CSV文件没有表头,使用[_c0, _c1, _c2, ..., _cn]表示其表头,并将列指示为属性值的源。 + # 如果CSV文件有表头,则使用实际的列名。 + fields: [_c1] + + # 指定Nebula Graph中定义的属性名称。 + # fields与nebula.fields的顺序必须一一对应。 + nebula.fields: [name] + + # 指定一个列作为VID的源。 + # vertex的值必须与上述fields或者csv.fields中的列名保持一致。 + # 目前,Nebula Graph 2.0.0仅支持字符串类型的VID。 + # 不要使用vertex.policy映射。例如: + # vertex: { + # field: _c0, + # policy: "hash" + # } + vertex: _c0 + + # 指定的分隔符。默认值为英文逗号(,)。 separator: "," + + # 如果CSV文件有表头,请将header设置为true。 + # 如果CSV文件没有表头,请将header设置为false。默认值为false。 header: false + + # 指定单次写入Nebula Graph的最大点数量。 batch: 256 - partition: 32 - # isImplicit 设置说明,详见 https://github.com/vesoft-inc/nebula-java/blob - # /v1.0/tools/exchange/src/main/resources/application.conf - isImplicit: true + # 指定Spark分片数量。 + partition: 32 } + + + # 如果需要添加更多标签,请参考前面的配置进行添加。 ] - # 处理边数据 + # 处理边 edges: [ - # 设置边类型 action 相关信息 + # 设置边类型follow相关信息。 { - # Nebula Graph 中对应的边类型名称。 - name: action + # 指定Nebula Graph中定义的边类型名称。 + name: follow type: { - # 指定数据源文件格式,设置为 csv。 + # 指定数据源,使用CSV。 source: csv - # 指定边数据导入 Nebula Graph 的方式, - # 可以设置为:client(以客户端形式导入)和 sst(以 SST 文件格式导入)。 - # 关于 SST 文件导入配置,参考文档:导入 SST 文件(https:// - # docs.nebula-graph.com.cn/nebula-exchange/ - # use-exchange/ex-ug-import-sst/)。 + # 指定如何将点数据导入Nebula Graph:Client或SST。 sink: client } - # 指定 CSV 文件所在的 HDFS 路径,String 类型,必须以 hdfs:// 开头。 - path: "hdfs://namenode_ip:port/path/to/actions.csv" - - # 如果 CSV 文件里不带表头, - # 则写入 [_c0, _c1, _c2, ... _cn], - # 依次表示 CSV 文件中各数据列,作为 action 各属性值来源。 - # 如果 CSV 文件里有表头,则写入各列名。 - # fields 与 nebula.fields 的顺序必须一一对应。 - fields: [_c0, _c3, _c4, _c5, _c6, _c7, _c8] - - # Nebula Graph 中 action 的属性名称,必须与 fields 里的列顺序一一对应。 - nebula.fields: [actionId, duration, feature0, feature1, feature2, feature3, label] - - # Exchange 1.1.0 添加了 csv.fields 参数: - # 如果配置了 csv.fields,无论 CSV 文件是否有表头, - # 均以这个参数指定的名称作为表头, - # fields 的配置必须与 csv.fields 的配置保持一致。 - # csv.fields: [actionId, duration, feature0, feature1, feature2, feature3, label] - - # 边起点和边终点 VID 数据来源, - # 如果不是 int 类型数据,则添加 policy 指定 VID 映射策略,建议设置为 "hash"。 - source: _c1 - target: { - field: _c2 - policy: "hash" + # 指定CSV文件的HDFS路径。 + # 用双引号括起路径,以hdfs://开头。 + path: "hdfs://192.168.153.10:9000/data/edge_follow.csv" + + # 如果CSV文件没有表头,使用[_c0, _c1, _c2, ..., _cn]表示其表头,并将列指示为属性值的源。 + # 如果CSV文件有表头,则使用实际的列名。 + fields: [_c2] + + # 指定Nebula Graph中定义的属性名称。 + # fields与nebula.fields的顺序必须一一对应。 + nebula.fields: [degree] + + # 指定一个列作为起始点和目的点的源。 + # vertex的值必须与上述fields或者csv.fields中的列名保持一致。 + # 目前,Nebula Graph 2.0.0仅支持字符串类型的VID。 + # 不要使用vertex.policy映射。例如: + # vertex: { + # field: _c1, + # policy: "hash" + # } + source: _c0 + target: _c1 + + # 指定的分隔符。默认值为英文逗号(,)。 + separator: "," + + # 指定一个列作为rank的源(可选)。 + #ranking: _c4 + + # 如果CSV文件有表头,请将header设置为true。 + # 如果CSV文件没有表头,请将header设置为false。默认值为false。 + header: false + + # 指定单次写入Nebula Graph的最大点数量。 + batch: 256 + + # 指定Spark分片数量。 + partition: 32 + } + + # 设置边类型serve相关信息。 + { + # 指定Nebula Graph中定义的边类型名称。 + name: serve + type: { + # 指定数据源,使用CSV。 + source: csv + + # 指定如何将点数据导入Nebula Graph:Client或SST。 + sink: client } - # 标明数据源中数据分隔方式,默认为英文逗号(,)。 + # 指定CSV文件的HDFS路径。 + # 用双引号括起路径,以hdfs://开头。 + path: "hdfs://192.168.153.10:9000/data/edge_serve.csv" + + # 如果CSV文件没有表头,使用[_c0, _c1, _c2, ..., _cn]表示其表头,并将列指示为属性值的源。 + # 如果CSV文件有表头,则使用实际的列名。 + fields: [_c2,_c3] + + # 指定Nebula Graph中定义的属性名称。 + # fields与nebula.fields的顺序必须一一对应。 + nebula.fields: [start_year, end_year] + + # 指定一个列作为起始点和目的点的源。 + # vertex的值必须与上述fields或者csv.fields中的列名保持一致。 + # 目前,Nebula Graph 2.0.0仅支持字符串类型的VID。 + # 不要使用vertex.policy映射。例如: + # vertex: { + # field: _c1, + # policy: "hash" + # } + source: _c0 + target: _c1 + + # 指定的分隔符。默认值为英文逗号(,)。 separator: "," - # 如果 CSV 文件中有表头,header 设置为 true。 - # 如果 CSV 文件中没有表头,header 设置为 false(默认)。 + # 指定一个列作为rank的源(可选)。 + #ranking: _c5 + + # 如果CSV文件有表头,请将header设置为true。 + # 如果CSV文件没有表头,请将header设置为false。默认值为false。 header: false - # 单次向 Nebula Graph 写入的最大边数据量。 + # 指定单次写入Nebula Graph的最大点数量。 batch: 256 - # 设置 Spark 分区数量。 + # 指定Spark分片数量。 partition: 32 - isImplicit: true } + ] - # 如果还有其他边,再添加其他边类型相关的设置。 + # 如果需要添加更多边类型,请参考前面的配置进行添加。 } ``` -### 步骤 4. (可选)检查配置文件是否正确 +### 步骤 4:向Nebula Graph导入数据 -完成配置后,运行以下命令检查配置文件格式是否正确。关于参数的说明,参考 [导入命令参数](../parameter-reference/ex-ug-para-import-command.md)。 +运行如下命令将CSV文件数据导入到Nebula Graph中。关于参数的说明,参考[导入命令参数](../parameter-reference/ex-ug-para-import-command.md)。 ```bash -$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.tools.importer.Exchange /path/to/exchange-1.1.0.jar -c /path/to/conf/csv_application.conf -D +/bin/spark-submit --master "local" --class com.vesoft.nebula.tools.importer.Exchange -c ``` -### 步骤 5. 向 Nebula Graph 导入数据 - -运行以下命令将 CSV 文件数据导入到 Nebula Graph 中。关于参数的说明,参考 [导入命令参数](../parameter-reference/ex-ug-para-import-command.md)。 +示例: ```bash -$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.tools.importer.Exchange /path/to/exchange-1.1.0.jar -c /path/to/conf/csv_application.conf +/usr/local/spark-2.4.7-bin-hadoop2.7/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange /root/nebula-spark-utils/nebula-exchange/target/nebula-exchange-2.0.0.jar -c /root/nebula-spark-utils/nebula-exchange/target/classes/csv_application.conf ``` -### 步骤 6. (可选)验证数据 +您可以在返回信息中搜索`batchSuccess.`,确认成功的数量。例如例如`batchSuccess.follow: 300`。 -您可以在 Nebula Graph 客户端(例如 Nebula Graph Studio)里执行语句,确认数据是否已导入,例如: +### 步骤 5:(可选)验证数据 + +您可以在Nebula Graph客户端(例如Nebula Graph Studio)中执行查询语句,确认数据是否已导入。例如: ```ngql -GO FROM 1 OVER action; +GO FROM "player100" OVER follow; ``` -如果返回边终点(`action._dst`)即表明数据已导入。 - -您也可以使用 db_dump 工具统计数据是否已经全部导入。详细的使用信息参考 [Dump Tool](https://docs.nebula-graph.com.cn/manual-CN/3.build-develop-and-administration/5.storage-service-administration/data-export/dump-tool/)。 +您也可以使用命令[`SHOW STATS`](https://docs.nebula-graph.com.cn/2.0/3.ngql-guide/7.general-query-statements/6.show/14.show-stats/)查看统计数据。 -### 步骤 7. (可选)在 Nebula Graph 中重构索引 +### 步骤 6:(可选)在Nebula Graph中重建索引 -导入数据后,您可以在 Nebula Graph 中重新创建并重构索引。详细信息,参考[《Nebula Graph Database 手册》](https://docs.nebula-graph.com.cn/manual-CN/2.query-language/4.statement-syntax/1.data-definition-statements/ "点击前往 Nebula Graph 网站")。 +导入数据后,您可以在Nebula Graph中重新创建并重建索引。详情请参见[索引介绍](https://docs.nebula-graph.com.cn/2.0/3.ngql-guide/14.native-index-statements/)。 diff --git a/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-steps.md b/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-steps.md index 2d58140..b8d4391 100644 --- a/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-steps.md +++ b/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-steps.md @@ -1,42 +1,48 @@ # 导入数据步骤 -您可以按本文描述的步骤使用 Exchange 将指定来源的数据导入到 Nebula Graph 中。 +本文介绍如何使用Exchange从指定的数据源导入数据到Nebula Graph。 ## 前提条件 -开始迁移数据之前,您需要确保以下信息: +- 已经[安装部署Nebula Graph](https://docs.nebula-graph.com.cn/2.0/#dba)并获取如下信息: -- 已经安装部署了 Nebula Graph 并获取查询引擎所在服务器的 IP 地址、用户名和密码。 + - Graph服务和Meta服务的的IP地址和端口。 -- 已经完成 Exchange 编译。详细信息,参考 [编译 Nebula Exchange](../ex-ug-compile.md)。 + - 拥有Nebula Graph写权限的用户名和密码。 -- 已经安装 Spark。 +- 已经编译Exchange。详情请参见[编译Exchange](../ex-ug-compile.md)。 -- 在 Nebula Graph 中创建图数据模式需要的所有信息,包括标签和边类型的名称、属性等。 +- 已经安装Spark。 + +- 了解Nebula Graph中创建Schema的信息,包括标签和边类型的名称、属性等。 ## 操作步骤 -按以下步骤将不同来源的数据导入 Nebula Graph 数据库: +按以下步骤将不同来源的数据导入Nebula Graph数据库。 + +1. 在Nebula Graph中创建数据模型,包括图空间和Schema。 + +2. (可选)处理源数据。例如,在导入Neo4j数据时,为提高导出速度,在Neo4j数据库中为指定的标签属性创建索引。 + +3. 分别修改Spark、Nebula Graph以及点和边数据的配置文件。 -1. 在 Nebula Graph 中构图,包括创建图空间、创建图数据模式(Schema)。 + > **说明**:编译Exchange后,进入`nebula-java/tools/exchange`目录,您可以参考`target/classes/server_application.conf`文件修改配置文件。 -2. (可选)处理源数据。例如,在导入 Neo4j 时,为提高导出速度,在 Neo4j 数据库中为指定的标签属性创建索引。 +4. 导入数据至Nebula Graph。 -3. 分别修改 Spark、Nebula Graph 以及点和边数据的配置文件。 - > **说明**:完成 Exchange 编译后,进入 `nebula-java/tools/exchange` 目录,您可以参考 `target/classes/server_application.conf`、`target/classes/application.conf` 和 `target/classes/stream_application.conf` 文件修改配置文件。 +5. 验证导入数据的完整性。 -4. (可选)检查配置文件是否正确。 +6. (可选)在Nebula Graph中重建索引。 -5. 向 Nebula Graph 导入数据。 +关于详细操作步骤,根据数据来源不同,您可以参见如下文档: -6. 在 Nebula Graph 中验证数据是否已经完整导入。 +- [导入HIVE数据](ex-ug-import-hive.md) -7. (可选)在 Nebula Graph 中重构索引。 +- [导入CSV文件数据](ex-ug-import-from-csv.md) -关于详细操作步骤,根据数据来源不同,您可以参考相应的操作示例: +- [导入JSON文件数据](ex-ug-import-json.md) -- [导入 Neo4j 数据](ex-ug-import-from-neo4j.md) -- [导入 HIVE 数据](ex-ug-import-hive.md) -- [导入 CSV 文件数据](ex-ug-import-from-csv.md) -- [导入 JSON 文件数据](ex-ug-import-json.md) -- [导入 SST 文件数据](ex-ug-import-sst.md) + diff --git a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-from-csv.md b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-from-csv.md index 9e8bf22..171e51d 100644 --- a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-from-csv.md +++ b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-from-csv.md @@ -31,7 +31,7 @@ The practice is done in macOS. Here is the environment information: To import data from CSV files on HDFS with Exchange v2.x, do a check of these: -- Exchange v2.x is compiled. For more information, see [Compile Exchange v2.x](../ex-ug-compile.md). Exchange 2.0.0 is used in this example. +- Exchange v2.x is compiled. For more information, see [Compile Exchange v2.x](../ex-ug-compile.md). Exchange 2.0 is used in this example. - Spark is installed. @@ -79,13 +79,13 @@ Analyze the data in the CSV files and follow these steps to create a schema in N CREATE EDGE action (actionId int, duration double, label bool, feature0 double, feature1 double, feature2 double, feature3 double); ``` -For more information, see [Quick Start of Nebula Graph Database](../../2.quick-start/4.nebula-graph-crud.md). +For more information, see [Quick Start of Nebula Graph Database](https://docs.nebula-graph.io/2.0/2.quick-start/1.quick-start-workflow/). ### Step 2. Prepare CSV files Do a check of these: -1. The CSV files are processed to meet the requirements of the schema. For more information, see [Quick Start of Nebula Graph Studio](../../nebula-studio/quick-start/st-ug-prepare-csv.md). +1. The CSV files are processed to meet the requirements of the schema. >**NOTE**: Exchange supports importing CSV files with or without headers. 2. The CSV files must be stored in HDFS and get the file storage path. @@ -287,15 +287,7 @@ After compiling of Exchange, copy the `target/classes/application.conf` file and } ``` -### Step 4. (Optional) Verify the configuration - -After the configuration, run the import command with the `-D` parameter to verify the configuration file. For more information about the parameters, see [Import command parameters](../parameter-reference/ex-ug-para-import-command.md). - -```bash -$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange /path/to/nebula-exchange-2.0.0.jar -c /path/to/conf/csv_application.conf -D -``` - -### Step 5. Import data into Nebula Graph +### Step 4. Import data into Nebula Graph When the configuration is ready, run this command to import data from CSV files into Nebula Graph. For more information about the parameters, see [Import command parameters](../parameter-reference/ex-ug-para-import-command.md). @@ -303,7 +295,7 @@ When the configuration is ready, run this command to import data from CSV files $SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange /path/to/nebula-exchange-2.0.0.jar -c /path/to/conf/csv_application.conf ``` -### Step 6. (Optional) Verify data in Nebula Graph +### Step 5. (Optional) Verify data in Nebula Graph You can use a Nebula Graph client, such as Nebula Graph Studio, to verify the imported data. For example, in Nebula Graph Studio, run this statement. @@ -315,6 +307,6 @@ If the queried destination vertices return, the data are imported into Nebula Gr You can run the [`SHOW STATS`](../../3.ngql-guide/7.general-query-statements/6.show/14.show-stats.md) statement to count the data. -### Step 7. (Optional) Create and rebuild indexes in Nebula Graph +### Step 6. (Optional) Create and rebuild indexes in Nebula Graph After the data is imported, you can create and rebuild indexes in Nebula Graph. For more information, see [nGQL User Guide](../../3.ngql-guide/14.native-index-statements/1.create-native-index.md). diff --git a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-steps.md b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-steps.md index ccda8cc..c7108e8 100644 --- a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-steps.md +++ b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-steps.md @@ -4,8 +4,6 @@ This article introduces the generally-used procedure on how to use Exchange to i ## Prerequisites -To import data with Exchange, do a check of these: - - Nebula Graph is deployed and started. Get the information: - IP addresses and ports of the Graph Service and the Meta Service. - A Nebula Graph account with the privilege of writing data and its password. @@ -40,3 +38,8 @@ For more information, see the examples: - [Import data from HIVE](ex-ug-import-hive.md) - [Import data from CSV files](ex-ug-import-from-csv.md) - [Import data from JSON files](ex-ug-import-json.md) + +
                                              }
                                          } | 无 | `string` | 是 | 将源数据中某个属性的值作为 Nebula Graph 点 VID 的来源。
                                          如果属性为 `int` 或者 `long` 类型,使用 `tags.vertex: [field name]` 设置 VID 列。
                                          如果不是上述类型的属性,您可以通过 `tags.vertex.field` 和 `tags.vertex.policy`  对 VID 进行预处理。其中,`tags.vertex.policy` 可以设置为 `"hash"`。 | +| `tags.batch` | 256 | `int` | 是 | 单次写入 Nebula Graph 的点数据量。 | +| `tags.partition` | 32 | `int` | 是 | Spark 的分区数量。 | +| `tags.check_point_path` | 无 | `string` | 否 | 设置保存导入进度信息的目录,用于断点续传。如果未设置,表示不启用断点续传。 | +| `edges.name` | 无 | `string` | 是 | 指定 Nebula Graph 中的边类型名称。 | +| `edges.type.source` | 无 | `string` | 是 | 指定源数据格式,设置为 neo4j。 | +| `edges.type.sink` | 无 | `string` | 是 | 指定边数据导入 Nebula Graph 的方式。可以设置为:
                                          - `client`:以客户端形式导入
                                          - `sst`:以 SST 文件格式导入
                                          | +| `edges.server` | 无 | `string` | 是 | 指定 Neo4j 数据库服务器地址,格式必须为 `bolt://:7687` 。 | +| `edges.user` | 无 | `string` | 是 | 指定 Neo4j 数据库登录账号。 | +| `edges.password` | 无 | `string` | 是 | 指定 Neo4j 数据库账号登录密码。 | +| `edges.exec` | 无 | `string` | 是 | 写入 Cypher 语句,表示从 Neo4j 数据库中查询关系属性。Cypher 语句不能以英文分号(`;`)结尾。
                                          例如,写入 Cypher 语句 `match (a:vertex_label)-[r:edge_label]->(b:vertex_label) return a.neo4j-source-field, b.neo4j-target-field, r.neo4j-field-0 as neo4j-field-0, r.neo4j-field-1 as neo4j-field-1 order by id(r)`。 | +| `edges.fields` | 无 | `list[string]` | 是 | 指定源数据中与 Nebula Graph 边类型对应的属性名称。以列表形式列出,多个属性名称之间以英文逗号(`,`)隔开。列出的属性名称必须与 `edges.exec` 中列出的属性名称保持一致。 | +| `edges.nebula.fields` | 无 | `list[string]` | 是 | Nebula Graph Schema 中边类型对应的属性名称。以列表形式列出,与 `edges.fields` 列表中的属性名称一一对应,形成映射关系。多个属性名称之间以英文逗号(`,`)隔开。 | +| `edges.source`
                                          或者 
                                          edges: {
                                              source: {
                                                  field: [name]
                                                  policy:   "hash" 
                                              }
                                          }
                                          | 无 | `string` | 否 | 指定源数据中某个属性,将它的值用作 Nebula Graph 边的起始点 VID。
                                          如果是上述类型的属性,使用 `edges.source = field` 设置起始点 VID 列。
                                          如果不是上述类型的属性,您可以通过 `edges.source.field` 和 `edges.source.policy`  对 VID 进行预处理,即使用 `hash()`函数处理属性名称,生成的数值用作 VID。其中,`edges.source.policy` 可以设置为 `"hash"`。 | +| `edges.target`
                                          或者
                                          edges: {
                                              target: {
                                                  field: [name]
                                                  policy: "hash"   
                                              }
                                          }
                                          | 无 | `string` | 否 | 指定源数据中某个属性,将它的值用作 Nebula Graph 边的目标点 VID。必须为 `int` 或 `long` 类型的属性。
                                          如果属性为 `int` 或者 `long` 类型,使用 `edges.target: [field name]` 设置目标点 VID 列。
                                          如果不是上述类型的属性,您可以通过 `edges.target.field` 和 `edges.target.policy`  对 VID 进行预处理。其中,`edges.target.policy` 设置为 `"hash"`。 | +| `edges.ranking` | 无 | `string` | 否 | 将源数据中某一列数据作为 Nebula Graph 中边的 Rank 值。 | +| `edges.batch` | 256 | `int` | 是 | 单次写入 Nebula Graph 的边数据量。 | +| `edges.partition` | 32 | `int` | 是 | Spark 的分区数量。 | +| `edges.check_point_path` | 无 | `string` | 否 | 设置保存导入进度信息的目录,用于断点续传。如果未设置,表示不启用断点续传。 | diff --git a/nebula-exchange/doc-2.0/CN/parameter-reference/.ex-ug-paras-spark.md b/nebula-exchange/doc-2.0/CN/parameter-reference/.ex-ug-paras-spark.md new file mode 100644 index 0000000..a5e26e9 --- /dev/null +++ b/nebula-exchange/doc-2.0/CN/parameter-reference/.ex-ug-paras-spark.md @@ -0,0 +1,10 @@ +# Spark 参数 + +在使用 Exchange 导入数据时,您可以根据需要设置 Spark 参数,详细信息的 Spark 参数信息,参考[《Apache Spark 文档》](https://spark.apache.org/docs/latest/configuration.html#application-properties "点击前往 Apache Spark 文档")。下表仅提供部分参数的配置说明。实际应用时的参数设置,参考不同来源数据的 [操作示例](../use-exchange/ex-ug-import-from-neo4j.md)。 + +| 参数 | 默认值 | 数据类型 | 是否必需 | 说明 | +| :--- | :--- | :--- | :--- | :--- | +| `spark.app.name` | Spark Writer | `string` | 否 | Spark Driver Program 名称。 | +| `spark.driver.cores` | 1 | `int` | 否 | Driver 进程的核数,仅适用于集群模式。 | +| `spark.driver.maxResultSize` | 1G | `string` | 否 | 每个 Spark 操作(例如收集)中所有分区的序列化结果的上限(以字节为单位)。最小值为 1M,设为 0 则表示无限制上限。 | +| `spark.cores.max` | 无 | `int` | 否 | 当以“粗粒度”共享模式在独立部署集群或 Mesos 集群上运行时,跨集群(而非从每台计算机)请求应用程序的最大 CPU 核数。如果未设置,则默认值为 Spark 的独立集群管理器上的 `spark.deploy.defaultCores` 或 Mesos 上的 infinite(所有可用的内核)。 | diff --git a/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-para-import-command.md b/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-para-import-command.md new file mode 100644 index 0000000..90be03f --- /dev/null +++ b/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-para-import-command.md @@ -0,0 +1,19 @@ +# 导入命令参数 + +完成配置文件修改后,可以运行以下命令将指定来源的数据导入Nebula Graph数据库。 + +```bash +/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange -c +``` + +> **说明**:JAR文件版本号以您实际编译得到的JAR文件名称为准。 + +下表列出了命令的相关参数。 + +| 参数 | 是否必需 | 默认值 | 说明 | +| :--- | :--- | :--- | :--- | +| `--class`  | 是 | 无 | 指定驱动的主类。 | +| `--master`  | 是 | 无 | 指定Spark集群中master进程的URL。详情请参见[master-urls](https://spark.apache.org/docs/latest/submitting-applications.html#master-urls "点击前往 Apache Spark 文档")。 | +| `-c`  / `--config`  | 是 | 无 | 指定配置文件的路径。 | +| `-h`  / `--hive`  | 否 | `false` | 添加这个参数表示支持从Hive中导入数据。 | +| `-D`  / `--dry`  | 否 | `false` | 添加这个参数表示检查配置文件的格式是否符合要求,但不会校验`tags`和`edges`的配置项是否正确。正式导入数据时不能添加这个参数。 | diff --git a/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-parameter.md b/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-parameter.md new file mode 100644 index 0000000..622be3c --- /dev/null +++ b/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-parameter.md @@ -0,0 +1,168 @@ +# 配置说明 + +本文介绍使用Nebula Exchange时如何修改配置文件[`application.conf`](https://github.com/vesoft-inc/nebula-spark-utils/blob/master/nebula-exchange/src/main/resources/application.conf)。 + +修改配置文件之前,建议您根据数据源复制并修改文件名称,便于区分。例如数据源为CSV文件,可以复制为`csv_application.conf`。 + +配置文件的内容主要分为如下几类: + +- Spark相关配置 + +- Hive配置(可选) + +- Nebula Graph相关配置 + +- 点配置 + +- 边配置 + +## Spark相关配置 + +本文只列出部分Spark参数,更多参数请参见[官方文档](https://spark.apache.org/docs/latest/configuration.html#application-properties)。 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`spark.app.name`|string|`Nebula Exchange 2.0`|否|Spark驱动程序名称。| +|`spark.driver.cores`|int|`1`|否|驱动程序使用的CPU核数,仅适用于集群模式。| +|`spark.driver.maxResultSize`|string|`1G`|否|单个Spark操作(例如collect)时,所有分区的序列化结果的总大小限制(字节为单位)。最小值为1M,0表示无限制。| +|`spark.executor.memory`|string|`1G`|否|Spark驱动程序使用的内存量,可以指定单位,例如512M、1G。| +|`spark.cores.max`|int|`16`|否|当驱动程序以“粗粒度”共享模式在独立部署集群或Mesos集群上运行时,跨集群(而非从每台计算机)请求应用程序的最大CPU核数。如果未设置,则值为Spark的独立集群管理器上的`spark.deploy.defaultCores`或Mesos上的infinite(所有可用的内核)。| + +## Hive配置(可选) + +如果Spark和Hive部署在不同集群,才需要配置连接Hive的参数,否则请忽略这些配置。 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`hive.warehouse`|string|-|是|HDFS中的warehouse路径。用双引号括起路径,以`hdfs://`开头。| +|`hive.connectionURL`|string|-|是|JDBC连接的URL。例如`"jdbc:mysql://127.0.0.1:3306/hive_spark?characterEncoding=UTF-8"`。| +|`hive.connectionDriverName`|string|`"com.mysql.jdbc.Driver"`|是|驱动名称。| +|`hive.connectionUserName`|list\[string\]|-|是|连接的用户名。| +|`hive.connectionPassword`|list\[string\]|-|是|用户名对应的密码。| + +## Nebula Graph相关配置 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`nebula.address.graph`|list\[string\]|`["127.0.0.1:9669"]`|是|所有Graph服务的地址,包括IP和端口,多个地址用英文逗号(,)分隔。格式为`["ip1:port1","ip2:port2","ip3:port3"]`。| +|`nebula.address.meta`|list\[string\]|`["127.0.0.1:9559"]`|是|所有Meta服务的地址,包括IP和端口,多个地址用英文逗号(,)分隔。格式为`["ip1:port1","ip2:port2","ip3:port3"]`。| +|`nebula.user`|string|-|是|拥有Nebula Graph写权限的用户名。| +|`nebula.pswd`|string|-|是|用户名对应的密码。| +|`nebula.space`|string|-|是|需要导入数据的的图空间名称。| +|`nebula.path.local`|string|`"/tmp"`|否|(TODO:coding)导入SST文件时需要设置本地SST文件路径。| +|`nebula.path.remote`|string|`"/sst"`|否|(TODO:coding)导入SST文件时需要设置远端SST文件路径。| +|`nebula.path.hdfs.namenode`|string|`"hdfs://name_node:9000"`|否|(TODO:coding)导入SST文件时需要设置HDFS的namenode。| +|`nebula.connection.timeout`|int|`3000`|否|Thrift连接的超时时间,单位为 ms。| +|`nebula.connection.retry`|int|`3`|否|Thrift连接重试次数。| +|`nebula.execution.retry`|int|`3`|否|nGQL语句执行重试次数。| +|`nebula.error.max`|int|`32`|否|导入过程中的最大失败次数。当失败次数达到最大值时,提交的Spark作业将自动停止。| +|`nebula.error.output`|string|`/tmp/errors`|否|输出错误日志的路径。错误日志保存执行失败的nGQL语句。| +|`nebula.rate.limit`|int|`1024`|否|导入数据时令牌桶的令牌数量限制。| +|`nebula.rate.timeout`|int|`1000`|否|令牌桶中拿取令牌的超时时间,单位:毫秒。| + +## 点配置 + +对于不同的数据源,点的配置也有所不同,有很多通用参数,也有部分特有参数,配置时需要配置通用参数和不同数据源的特有参数。 + +### 通用参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.name`|string|-|是|Nebula Graph中定义的标签名称。| +|`tags.type.source`|string|-|是|指定数据源。例如`csv`。| +|`tags.type.sink`|string|`client`|是|指定导入方式,可选值为`client`和`SST`(暂不支持)。| +|`tags.fields`|list\[string\]|-|是|属性对应的列的表头或列名。如果有表头或列名,请直接使用该名称。如果CSV文件没有表头,用`[_c0, _c1, _c2]`的形式表示第一列、第二列、第三列,以此类推。| +|`tags.nebula.fields`|list\[string\]|-|是|Nebula Graph中定义的属性名称,顺序必须和`tags.fields`一一对应。例如`[_c1, _c2]`对应`[name, age]`,表示第二列为属性name的值,第三列为属性age的值。| +|`tags.vertex.field`|string|-|是|点ID的列。例如CSV文件没有表头时,可以用`_c0`表示第一列的值作为点ID。| +|`tags.batch`|int|`256`|是|单批次写入Nebula Graph的最大点数量。| +|`tags.partition`|int|`32`|是|Spark分片数量。| + +### Parquet/JSON/ORC源特有参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.path`|string|-|是|HDFS中点数据文件的路径。用双引号括起路径,以`hdfs://`开头。| + +### CSV源特有参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.path`|string|-|是|HDFS中点数据文件的路径。用双引号括起路径,以`hdfs://`开头。| +|`tags.separator`|string|`,`|是|分隔符。默认值为英文逗号(,)。| +|`tags.header`|bool|`true`|是|文件是否有表头。| + +### Hive源特有参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.exec`|string|-|是|查询数据源的语句。例如`select name,age from mooc.users`。| + +### Neo4j源特有参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.exec`|string|-|是|查询数据源的语句。例如`match (n:label) return n.neo4j-field-0`。| +|`tags.server`|string|`"bolt://127.0.0.1:7687"`|是|Neo4j服务器地址。| +|`tags.user`|string|-|是|拥有读取权限的Neo4j用户名。| +|`tags.password`|string|-|是|用户名对应密码。| +|`tags.database`|string|-|是|Neo4j中保存源数据的数据库名。| +|`tags.check_point_path`|string|`/tmp/test`|否|设置保存导入进度信息的目录,用于断点续传。如果未设置,表示不启用断点续传。| + +### MySQL源特有参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.host`|string|-|是|MySQL服务器地址。| +|`tags.port`|string|-|是|MySQL服务器端口。| +|`tags.database`|string|-|是|数据库名称。| +|`tags.table`|string|-|是|需要作为数据源的表名称。| +|`tags.user`|string|-|是|拥有读取权限的MySQL用户名。| +|`tags.password`|string|-|是|用户名对应密码。| +|`tags.sentence`|string|-|是|查询数据源的语句。例如`"select teamid, name from basketball.team order by teamid;"`。| + +### Hbase源特有参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.host`|string|`127.0.0.1`|是|Hbase服务器地址。| +|`tags.port`|string|`2181`|是|Hbase服务器端口。| +|`tags.table`|string|-|是|需要作为数据源的表名称。| +|`tags.columnFamily`|string|-|是|表所属的列族(column family)。| + +### Pulsar源特有参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.service`|string|`"pulsar://localhost:6650"`|是|Pulsar服务器地址。| +|`tags.admin`|string|`"http://localhost:8081"`|是|连接pulsar的admin.url。| +|`tags.options.`|string|-|是|Pulsar的选项,可以从`topic`、`topics`和`topicsPattern`选择一个进行配置。| +|`tags.interval.seconds`|int|`10`|是|读取消息的间隔。单位:秒。| + +### Kafka源特有参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`tags.service`|string|-|是|Kafka服务器地址。| +|`tags.topic`|string|-|是|消息类别。| +|`tags.interval.seconds`|int|`10`|是|读取消息的间隔。单位:秒。| + +## 边配置 + +对于不同的数据源,边的配置也有所不同,有很多通用参数,也有部分特有参数,配置时需要配置通用参数和不同数据源的特有参数。 + +边配置的不同数据源特有参数请参见上方点配置内的特有参数介绍,注意区分tags和edges即可。 + +### 通用参数 + +|参数|数据类型|默认值|是否必须|说明| +|:---|:---|:---|:---|:---| +|`edges.name`| string|-|是|Nebula Graph中定义的边类型名称。| +|`edges.type.source`|string|-|是|指定数据源。例如`csv`。| +|`edges.type.sink`|string|`client`|是|指定导入方式,可选值为`client`和`SST`(暂不支持)。| +|`edges.fields`|list\[string\]|-|是|属性对应的列的表头或列名。如果有表头或列名,请直接使用该名称。如果CSV文件没有表头,用`[_c0, _c1, _c2]`的形式表示第一列、第二列、第三列,以此类推。| +|`edges.nebula.fields`|list\[string\]|-|是|Nebula Graph中定义的属性名称,顺序必须和`edges.fields`一一对应。例如`[_c2, _c3]`对应`[start_year, end_year]`,表示第三列为开始年份的值,第四列为结束年份的值。| +|`edges.source.field`|string|-|是|边的起始点的列。例如`_c0`表示第一列的值作为边的起始点。| +|`edges.target.field`|string|-|是|边的目的点的列。例如`_c1`表示第二列的值作为边的目的点。| +|`edges.ranking`|int|-|否|rank值的列。没有指定时,默认所有rank值为`0`。| +|`edges.batch`|int|`256`|是|单批次写入Nebula Graph的最大边数量。| +|`edges.partition`|int|`32`|是|Spark分片数量。| \ No newline at end of file diff --git a/nebula-exchange/doc-2.0/CN/use-exchange/.ex-ug-import-from-sst.md b/nebula-exchange/doc-2.0/CN/use-exchange/.ex-ug-import-from-sst.md new file mode 100644 index 0000000..b614862 --- /dev/null +++ b/nebula-exchange/doc-2.0/CN/use-exchange/.ex-ug-import-from-sst.md @@ -0,0 +1,98 @@ +# 导入 SST 文件 + +Nebula Exchange 能将不同来源的数据转换成 SST 文件后再导入 Nebula Graph 数据库中。本文描述 Exchange 将源数据转换为 SST 文件并导入 Nebula Graph 的实现原理,并提供示例说明如何修改配置文件完成 SST 文件导入操作。 + +> **说明**:仅 Linux 系统支持导入 SST 文件。 + +## 实现方法 + +Nebula Graph 底层使用 RocksDB 作为键值型存储引擎。RocksDB 是基于磁盘的存储引擎,数据以 Sorted String Table(SSTable)格式存放。SSTable 是一个内部包含了任意长度、排好序的键值对 <key,value> 集合的文件,用于高效地存储大量的键值型数据。 + +RocksDB 提供了一系列 API 用于创建及导入 SST 文件,有助于您快速导入海量数据。 + +处理 SST 文件的整个过程主要由 Exchange 的 Reader、sstProcessor 和 sstWriter 完成。整个数据处理过程如下所示: + +1. Exchange 的 Reader 从数据源中读取数据。 + +2. sstProcessor 按照 Nebula Graph 要求的格式生成 SST 文件,存储到本地,并上传到 HDFS。SST 文件主要包含点和边两类数据,其中, + + - 表示点的键包括:分区信息、点 ID(VID)、标签类型信息和标签版本信息。 + - 表示边的键包括:分区信息、起点和终点 ID(`rsc_vid` 和 `dst_vid`)、边类型信息、边排序信息和边版本信息。 + - 对应的值主要包含各个属性键值对序列化信息。 + +3. SstFileWriter 创建 SST 文件:Exchange 会创建一个 SstFileWriter 对象,然后打开一个文件并插入数据。生成 SST 文件时,行数据必须严格按照增序进行写入。 + +4. 生成 SST 文件之后,RocksDB 通过 `IngestExternalFile()` 方法将 SST 文件导入到 Nebula Graph 之中。例如: + + ``` + IngestExternalFileOptions ifo; + // Ingest the 2 passed SST files into the DB + Status s = db_->IngestExternalFile({"/home/usr/file1.sst", "/home/usr/file2.sst"}, ifo); + if (!s.ok()) { + printf("Error while adding file %s and %s, Error %s\n", + file_path1.c_str(), file_path2.c_str(), s.ToString().c_str()); + return 1; + } + ``` + + 调用 `IngestExternalFile()` 方法时,RocksDB 默认会将文件拷贝到数据目录,并且阻塞 RocksDB 写入操作。如果 SST 文件中的键范围覆盖了 Memtable 键的范围,则将 Memtable 落盘(flush)到硬盘。将 SST 文件放置在 LSM 树最优位置后,为文件分配一个全局序列号,并打开写操作。 + +## 使用示例 + +不同来源的数据,导入 Nebula Graph 的操作与客户端形式导入操作基本相同,但是有以下差异: + +- 环境里必须部署 HDFS。 +- 在配置文件中,必须做以下修改: + - 源数据的标签和边类型配置:`tags.type.sink` 和 `edges.type.sink` 必须配置为 `sst`。 + - Nebula Graph 相关配置里,需要添加 Nebula Graph 数据库 Meta 服务的 IP 地址和端口,并添加 SST 文件在本地和 HDFS 的存储路径。 + + ```conf + # Nebula Graph 相关配置 + nebula: { + address: { + # 添加 Nebula Graph 数据库 Graph 服务的 IP 地址和端口 + graph: ["127.0.0.1:3699"] + # 添加 Nebula Graph 数据库 Meta 服务的 IP 地址和端口 + meta:["127.0.0.1:45500"] + } + user: user + pswd: password + space: test + path:{ + # 指定 SST 文件保存到本地的路径 + local:/Users/example/path + # 指定上传 SST 文件的 HDFS 路径 + remote:/example/ + } + + connection { + timeout: 3000 + retry: 3 + } + + execution { + retry: 3 + } + + error: { + max: 32 + output: /tmp/errors + } + + rate: { + limit: 64M + timeout: 1000 + } + } + ``` + +详细描述请参考不同数据源的操作示例: + +- [导入 Neo4j 数据](ex-ug-import-from-neo4j.md) +- [导入 Hive 数据](ex-ug-import-hive.md) +- [导入 CSV 文件数据](ex-ug-import-from-csv.md) +- [导入 JSON 文件数据](ex-ug-import-json.md) +- 导入 HBase 数据[doc_TODO] +- 导入 Hive 数据[doc_TODO] +- 导入 Kafka 数据[doc_TODO] +- 导入 MySQL 数据[doc_TODO] diff --git a/nebula-exchange/doc-2.0/CN/use-exchange/.ex-ug-import-steps.md b/nebula-exchange/doc-2.0/CN/use-exchange/.ex-ug-import-steps.md new file mode 100644 index 0000000..44f3c89 --- /dev/null +++ b/nebula-exchange/doc-2.0/CN/use-exchange/.ex-ug-import-steps.md @@ -0,0 +1,55 @@ +# 导入数据步骤 + +本文介绍如何使用Exchange从指定的数据源导入数据到Nebula Graph。 + +## 前提条件 + +- 已经[安装部署Nebula Graph](https://docs.nebula-graph.com.cn/2.0/4.deployment-and-installation/2.compile-and-install-nebula-graph/2.install-nebula-graph-by-rpm-or-deb/)并获取如下信息: + + - Graph服务和Meta服务的的IP地址和端口。 + + - 拥有Nebula Graph写权限的用户名和密码。 + +- 已经编译Exchange。详情请参见[编译Exchange](../ex-ug-compile.md)。 + +- 已经安装Spark。 + +- 了解Nebula Graph中创建Schema的信息,包括标签和边类型的名称、属性等。 + +## 操作步骤 + +按以下步骤将不同来源的数据导入Nebula Graph数据库。 + +1. 在Nebula Graph中创建数据模型,包括图空间和Schema。 + +2. (可选)处理源数据。例如,在导入Neo4j数据时,为提高导出速度,在Neo4j数据库中为指定的标签属性创建索引。 + +3. 分别修改Spark、Nebula Graph以及点和边数据的配置文件。 + + > **说明**:编译Exchange后,进入`nebula-java/tools/exchange`目录,您可以参考`target/classes/server_application.conf`文件修改配置文件。 + +4. 导入数据至Nebula Graph。 + +5. 验证导入数据的完整性。 + +6. (可选)在Nebula Graph中重建索引。 + +关于详细操作步骤,根据数据来源不同,您可以参见如下文档: + +- [导入Neo4j数据](ex-ug-import-neo4j.md) + +- [导入Hive数据](ex-ug-import-hive.md) + +- [导入CSV文件数据](ex-ug-import-from-csv.md) + +- [导入JSON文件数据](ex-ug-import-json.md) + +- [导入Parquet文件数据](ex-ug-import-parquet.md) + +- [导入ORC文件数据](ex-ug-import-orc.md) + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + test-jar + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${compiler.source.version} + ${compiler.target.version} + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.1 + + + package + + shade + + + false + + + org.apache.spark:* + org.apache.hadoop:* + org.apache.hive:* + log4j:log4j + org.apache.orc:* + xml-apis:xml-apis + javax.inject:javax.inject + org.spark-project.hive:hive-exec + stax:stax-api + org.glassfish.hk2.external:aopalliance-repackaged + + + + + *:* + + com/vesoft/tools/** + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + + net.alchim31.maven + scala-maven-plugin + 3.2.2 + + + + compile + testCompile + + + + + + + + org.scalatest + scalatest-maven-plugin + 2.0.0 + + + test + + test + + + + + + + + + \ No newline at end of file diff --git a/nebula-algorithm/src/main/resources/application.conf b/nebula-algorithm/src/main/resources/application.conf new file mode 100644 index 0000000..1b1e17a --- /dev/null +++ b/nebula-algorithm/src/main/resources/application.conf @@ -0,0 +1,126 @@ +{ + # Spark relation config + spark: { + app: { + name: LPA + # spark.app.partitionNum + partitionNum:100 + } + master:local + } + + data: { + # data source. optional of nebula,csv,json + source: csv + # data sink, means the algorithm result will be write into this sink. optional of nebula,csv,text + sink: nebula + # if your algorithm needs weight + hasWeight: false + } + + # Nebula Graph relation config + nebula: { + # algo's data source from Nebula. If data.source is nebula, then this nebula.read config can be valid. + read: { + # Nebula metad server address, multiple addresses are split by English comma + metaAddress: "127.0.0.1:9559" + # Nebula space + space: nb + # Nebula edge types, multiple labels means that data from multiple edges will union together + labels: ["serve"] + # Nebula edge property name for each edge type, this property will be as weight col for algorithm. + # Make sure the weightCols are corresponding to labels. + weightCols: ["start_year"] + } + + # algo result sink into Nebula. If data.sink is nebula, then this nebula.write config can be valid. + write:{ + # Nebula graphd server address, multiple addresses are split by English comma + graphAddress: "127.0.0.1:9669" + # Nebula metad server address, multiple addresses are split by English comma + metaAddress: "127.0.0.1:9559,127.0.0.1:9560" + user:root + pswd:nebula + # Nebula space name + space:nb + # Nebula tag name, the algorithm result will be write into this tag + tag:pagerank + } + } + + local: { + # algo's data source from Nebula. If data.source is csv or json, then this local.read can be valid. + read:{ + filePath: "hdfs://127.0.0.1:9000/edge/work_for.csv" + # srcId column + srcId:"_c0" + # dstId column + dstId:"_c1" + # weight column + #weight: "col3" + # if csv file has header + header: false + # csv file's delimiter + delimiter:"," + } + + # algo result sink into local file. If data.sink is csv or text, then this local.write can be valid. + write:{ + resultPath:/tmp/ + } + } + + + algorithm: { + # the algorithm that you are going to execute,pick one from [pagerank, louvain, connectedcomponent, + # labelpropagation, shortestpaths, degreestatic, kcore, stronglyconnectedcomponent, trianglecount, + # betweenness] + executeAlgo: pagerank + + # pagerank parameter + pagerank: { + maxIter: 10 + resetProb: 0.15 # default 0.15 + } + + # louvain parameter + louvain: { + maxIter: 20 + internalIter: 10 + tol: 0.5 + } + + # connected component parameter TODO not implemented yet. + connectedcomponent: { + maxIter: 20 + } + + # LabelPropagation + labelpropagation: { + maxIter: 20 + } + + # ShortestPaths + shortestpaths: { + # several vertices to compute the shortest path to all vertices. + landmarks: "1" + } + + # vertex degree static + degreestatic: {} + + # kcore + kcore:{ + maxIter:10 + degree:1 + } + + # trianglecount + trianglecount:{} + + # betweenness centrality + betweenness:{ + maxIter:5 + } + } +} diff --git a/nebula-algorithm/src/main/resources/edge b/nebula-algorithm/src/main/resources/edge new file mode 100644 index 0000000..0681588 --- /dev/null +++ b/nebula-algorithm/src/main/resources/edge @@ -0,0 +1,10 @@ +{"src":12345,"dst":23456,"degree":34, "descr": "aaa","timep": "2020-01-01"} +{"src":11111,"dst":22222,"degree":33, "descr": "aaa","timep": "2020-01-01"} +{"src":11111,"dst":33333,"degree":32, "descr": "a\baa","timep": "2020-01-01"} +{"src":11111,"dst":44444,"degree":31, "descr": "aaa","timep": "2020-01-01"} +{"src":22222,"dst":55555,"degree":30, "descr": "a\naa","timep": "2020-01-01"} +{"src":33333,"dst":44444,"degree":29, "descr": "aaa","timep": "2020-01-01"} +{"src":33333,"dst":55555,"degree":28, "descr": "aa\ta","timep": "2020-01-01"} +{"src":44444,"dst":22222,"degree":27, "descr": "aaa","timep": "2020-01-01"} +{"src":44444,"dst":55555,"degree":26, "descr": "aaa","timep": "2020-01-01"} +{"src":22222,"dst":66666,"degree":25, "descr": "aaa","timep": "2020-01-01"} \ No newline at end of file diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/Main.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/Main.scala new file mode 100644 index 0000000..9992682 --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/Main.scala @@ -0,0 +1,187 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm + +import com.vesoft.nebula.algorithm.config.Configs.Argument +import com.vesoft.nebula.algorithm.config.{ + AlgoConfig, + BetweennessConfig, + CcConfig, + Configs, + KCoreConfig, + LPAConfig, + LouvainConfig, + PRConfig, + ShortestPathConfig, + SparkConfig +} +import com.vesoft.nebula.algorithm.lib.{ + BetweennessCentralityAlgo, + ConnectedComponentsAlgo, + DegreeStaticAlgo, + KCoreAlgo, + LabelPropagationAlgo, + LouvainAlgo, + PageRankAlgo, + ShortestPathAlgo, + StronglyConnectedComponentsAlgo, + TriangleCountAlgo +} +import com.vesoft.nebula.algorithm.reader.{CsvReader, JsonReader, NebulaReader} +import com.vesoft.nebula.algorithm.writer.{CsvWriter, NebulaWriter, TextWriter} +import org.apache.commons.math3.ode.UnknownParameterException +import org.apache.log4j.Logger +import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession} + +/** + * This object is the entry of all graph algorithms. + * + * How to use this tool to run algorithm: + * 1. Configure application.conf file. + * 2. Make sure your environment has installed spark and started spark service. + * 3. Submit nebula algorithm application using this command: + * spark-submit --class com.vesoft.nebula.tools.algorithm.Main /your-jar-path/nebula-algorithm-1.1.0.jar -p /your-application.conf-path/application.conf + */ +object Main { + + private val LOGGER = Logger.getLogger(this.getClass) + + def main(args: Array[String]): Unit = { + val PROGRAM_NAME = "Nebula graphx" + val options = Configs.parser(args, PROGRAM_NAME) + val p: Argument = options match { + case Some(config) => config + case _ => + LOGGER.error("Argument parse failed") + sys.exit(-1) + } + val configs = Configs.parse(p.config) + LOGGER.info(s"configs = ${configs}") + + val algoName: String = AlgoConfig.getAlgoName(configs) + LOGGER.info(s"algoName= ${algoName}") + + val sparkConfig = SparkConfig.getSpark(configs) + val partitionNum = sparkConfig.partitionNum + + // reader + val dataSet = createDataSource(sparkConfig.spark, configs, partitionNum) + + // algorithm + val algoResult = executeAlgorithm(sparkConfig.spark, algoName, configs, dataSet) + // writer + saveAlgoResult(algoResult, configs) + + sys.exit(0) + } + + /** + * create data from datasource + * + * @param spark + * @param configs + * @return DataFrame + */ + private[this] def createDataSource(spark: SparkSession, + configs: Configs, + partitionNum: String): DataFrame = { + val dataSource = configs.dataSourceSinkEntry.source + val dataSet: Dataset[Row] = dataSource.toLowerCase match { + case "nebula" => { + val reader = new NebulaReader(spark, configs, partitionNum) + reader.read() + } + case "csv" => { + val reader = new CsvReader(spark, configs, partitionNum) + reader.read() + } + case "json" => { + val reader = new JsonReader(spark, configs, partitionNum) + reader.read() + } + } + dataSet + } + + /** + * execute algorithms + * @param spark + * @param algoName + * @param configs + * @param dataSet + * @return DataFrame + */ + private[this] def executeAlgorithm(spark: SparkSession, + algoName: String, + configs: Configs, + dataSet: DataFrame): DataFrame = { + val hasWeight = configs.dataSourceSinkEntry.hasWeight + val algoResult = { + algoName.toLowerCase match { + case "pagerank" => { + val pageRankConfig = PRConfig.getPRConfig(configs) + PageRankAlgo(spark, dataSet, pageRankConfig, hasWeight) + } + case "louvain" => { + val louvainConfig = LouvainConfig.getLouvainConfig(configs) + LouvainAlgo(spark, dataSet, louvainConfig, hasWeight) + } + case "connectedcomponent" => { + val ccConfig = CcConfig.getCcConfig(configs) + ConnectedComponentsAlgo(spark, dataSet, ccConfig, hasWeight) + } + case "labelpropagation" => { + val lpaConfig = LPAConfig.getLPAConfig(configs) + LabelPropagationAlgo(spark, dataSet, lpaConfig, hasWeight) + } + case "shortestpaths" => { + val spConfig = ShortestPathConfig.getShortestPathConfig(configs) + ShortestPathAlgo(spark, dataSet, spConfig, hasWeight) + } + case "degreestatic" => { + DegreeStaticAlgo(spark, dataSet) + } + case "kcore" => { + val kCoreConfig = KCoreConfig.getKCoreConfig(configs) + KCoreAlgo(spark, dataSet, kCoreConfig) + } + case "stronglyconnectedcomponent" => { + val ccConfig = CcConfig.getCcConfig(configs) + StronglyConnectedComponentsAlgo(spark, dataSet, ccConfig, hasWeight) + } + case "betweenness" => { + val betweennessConfig = BetweennessConfig.getBetweennessConfig(configs) + BetweennessCentralityAlgo(spark, dataSet, betweennessConfig, hasWeight) + } + case "trianglecount" => { + TriangleCountAlgo(spark, dataSet) + } + case _ => throw new UnknownParameterException("unknown executeAlgo name.") + } + } + algoResult + } + + private[this] def saveAlgoResult(algoResult: DataFrame, configs: Configs): Unit = { + val dataSink = configs.dataSourceSinkEntry.sink + dataSink.toLowerCase match { + case "nebula" => { + val writer = new NebulaWriter(algoResult, configs) + writer.write() + } + case "csv" => { + val writer = new CsvWriter(algoResult, configs) + writer.write() + } + case "text" => { + val writer = new TextWriter(algoResult, configs) + writer.write() + } + case _ => throw new UnsupportedOperationException("unsupported data sink") + } + } +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/config/AlgoConfig.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/config/AlgoConfig.scala new file mode 100644 index 0000000..3077214 --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/config/AlgoConfig.scala @@ -0,0 +1,171 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.config + +import org.apache.spark.graphx.VertexId + +case class PRConfig(maxIter: Int, resetProb: Double) + +/** + * pagerank algorithm configuration + */ +object PRConfig { + var maxIter: Int = _ + var resetProb: Double = _ + + def getPRConfig(configs: Configs): PRConfig = { + val prConfig = configs.algorithmConfig.map + + maxIter = prConfig("algorithm.pagerank.maxIter").toInt + resetProb = + if (prConfig.contains("algorithm.pagerank.resetProb")) + prConfig("algorithm.pagerank.resetProb").toDouble + else 0.15 + + PRConfig(maxIter, resetProb) + } +} + +case class LPAConfig(maxIter: Int) + +/** + * labelPropagation algorithm configuration + */ +object LPAConfig { + var maxIter: Int = _ + + def getLPAConfig(configs: Configs): LPAConfig = { + val lpaConfig = configs.algorithmConfig.map + + maxIter = lpaConfig("algorithm.labelpropagation.maxIter").toInt + LPAConfig(maxIter) + } +} + +case class CcConfig(maxIter: Int) + +/** + * ConnectedComponect algorithm configuration + */ +object CcConfig { + var maxIter: Int = _ + + def getCcConfig(configs: Configs): CcConfig = { + val ccConfig = configs.algorithmConfig.map + + maxIter = ccConfig("algorithm.connectedcomponent.maxIter").toInt + CcConfig(maxIter) + } +} + +case class ShortestPathConfig(landmarks: Seq[VertexId]) + +/** + * ConnectedComponect algorithm configuration + */ +object ShortestPathConfig { + var landmarks: Seq[Long] = _ + + def getShortestPathConfig(configs: Configs): ShortestPathConfig = { + val spConfig = configs.algorithmConfig.map + + landmarks = spConfig("algorithm.shortestpaths.landmarks").split(",").toSeq.map(_.toLong) + ShortestPathConfig(landmarks) + } +} + +case class LouvainConfig(maxIter: Int, internalIter: Int, tol: Double) + +/** + * louvain algorithm configuration + */ +object LouvainConfig { + var maxIter: Int = _ + var internalIter: Int = _ + var tol: Double = _ + + def getLouvainConfig(configs: Configs): LouvainConfig = { + val louvainConfig = configs.algorithmConfig.map + + maxIter = louvainConfig("algorithm.louvain.maxIter").toInt + internalIter = louvainConfig("algorithm.louvain.internalIter").toInt + tol = louvainConfig("algorithm.louvain.tol").toDouble + + LouvainConfig(maxIter, internalIter, tol) + } +} + +/** + * degree static + */ +case class DegreeStaticConfig(degree: Boolean, inDegree: Boolean, outDegree: Boolean) + +object DegreeStaticConfig { + var degree: Boolean = false + var inDegree: Boolean = false + var outDegree: Boolean = false + + def getDegreeStaticConfig(configs: Configs): DegreeStaticConfig = { + val degreeConfig = configs.algorithmConfig.map + degree = ConfigUtil.getOrElseBoolean(degreeConfig, "algorithm.degreestatic.degree", false) + inDegree = ConfigUtil.getOrElseBoolean(degreeConfig, "algorithm.degreestatic.indegree", false) + outDegree = ConfigUtil.getOrElseBoolean(degreeConfig, "algorithm.degreestatic.outdegree", false) + DegreeStaticConfig(degree, inDegree, outDegree) + } +} + +/** + * k-core + */ +case class KCoreConfig(maxIter: Int, degree: Int) + +object KCoreConfig { + var maxIter: Int = _ + var degree: Int = _ + + def getKCoreConfig(configs: Configs): KCoreConfig = { + val kCoreConfig = configs.algorithmConfig.map + maxIter = kCoreConfig("algorithm.kcore.maxIter").toInt + degree = kCoreConfig("algorithm.kcore.degree").toInt + KCoreConfig(maxIter, degree) + } +} + +/** + * Betweenness + */ +case class BetweennessConfig(maxIter: Int) + +object BetweennessConfig { + var maxIter: Int = _ + + def getBetweennessConfig(configs: Configs): BetweennessConfig = { + val betweennessConfig = configs.algorithmConfig.map + maxIter = betweennessConfig("algorithm.betweenness.maxIter").toInt + BetweennessConfig(maxIter) + } +} + +case class AlgoConfig(configs: Configs) + +object AlgoConfig { + def getAlgoName(configs: Configs): String = { + val algoConfig = configs.algorithmConfig.map + algoConfig("algorithm.executeAlgo") + } +} + +object ConfigUtil { + def getOrElseBoolean(config: Map[String, String], key: String, defaultValue: Boolean): Boolean = { + if (config.contains(key)) { + config(key).toBoolean + } else { + defaultValue + } + } + +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/config/Configs.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/config/Configs.scala new file mode 100644 index 0000000..05664d5 --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/config/Configs.scala @@ -0,0 +1,365 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.config + +import java.io.File +import java.nio.file.Files +import org.apache.log4j.Logger +import scala.collection.JavaConverters._ +import com.typesafe.config.{Config, ConfigFactory} +import scala.collection.mutable + +/** + * sparkConfig is used to submit spark application, such as graph algorithm + */ +object SparkConfigEntry { + def apply(config: Config): SparkConfigEntry = { + val map = mutable.Map[String, String]() + val sparkConfig = config.getObject("spark") + for (key <- sparkConfig.unwrapped().keySet().asScala) { + val sparkKey = s"spark.${key}" + if (config.getAnyRef(sparkKey).isInstanceOf[String]) { + val sparkValue = config.getString(sparkKey) + map += sparkKey -> sparkValue + } else { + for (subKey <- config.getObject(sparkKey).unwrapped().keySet().asScala) { + val key = s"${sparkKey}.${subKey}" + val sparkValue = config.getString(key) + map += key -> sparkValue + } + } + } + SparkConfigEntry(map.toMap) + } +} + +/** + * AlgorithmConfig is used to run graph algorithm + */ +object AlgorithmConfigEntry { + def apply(config: Config): AlgorithmConfigEntry = { + val map = mutable.Map[String, String]() + val algoConfig = config.getObject("algorithm") + for (key <- algoConfig.unwrapped().keySet().asScala) { + val algorithmKey = s"algorithm.${key}" + if (config.getAnyRef(algorithmKey).isInstanceOf[String]) { + val algorithmValue = config.getString(algorithmKey) + map += algorithmKey -> algorithmValue + } else { + for (subkey <- config.getObject(algorithmKey).unwrapped().keySet().asScala) { + val key = s"${algorithmKey}.${subkey}" + val value = config.getString(key) + map += key -> value + } + } + } + AlgorithmConfigEntry(map.toMap) + } +} + +/** DataSourceEntry is used to determine the data source , nebula or local */ +object DataSourceSinkEntry { + def apply(config: Config): DataSourceSinkEntry = { + val dataSource = config.getString("data.source") + val dataSink = config.getString("data.sink") + val hasWeight = if (config.hasPath("data.hasWeight")) { + config.getBoolean("data.hasWeight") + } else false + DataSourceSinkEntry(dataSource, dataSink, hasWeight) + } +} + +/** + * NebulaConfig is used to read edge data + */ +object NebulaConfigEntry { + def apply(config: Config): NebulaConfigEntry = { + if (!config.hasPath("nebula")) { + return NebulaConfigEntry(NebulaReadConfigEntry(), NebulaWriteConfigEntry()) + } + val nebulaConfig = config.getConfig("nebula") + + val readMetaAddress = nebulaConfig.getString("read.metaAddress") + val readSpace = nebulaConfig.getString("read.space") + val readLabels = nebulaConfig.getStringList("read.labels").asScala.toList + val readWeightCols = if (nebulaConfig.hasPath("read.weightCols")) { + nebulaConfig.getStringList("read.weightCols").asScala.toList + } else { + List() + } + val readConfigEntry = + NebulaReadConfigEntry(readMetaAddress, readSpace, readLabels, readWeightCols) + + val graphAddress = nebulaConfig.getString("write.graphAddress") + val writeMetaAddress = nebulaConfig.getString("write.metaAddress") + val user = nebulaConfig.getString("write.user") + val pswd = nebulaConfig.getString("write.pswd") + val writeSpace = nebulaConfig.getString("write.space") + val writeTag = nebulaConfig.getString("write.tag") + val writeConfigEntry = + NebulaWriteConfigEntry(graphAddress, writeMetaAddress, user, pswd, writeSpace, writeTag) + NebulaConfigEntry(readConfigEntry, writeConfigEntry) + } +} + +object LocalConfigEntry { + def apply(config: Config): LocalConfigEntry = { + + var filePath: String = "" + var src: String = "" + var dst: String = "" + var weight: String = null + var resultPath: String = null + var header: Boolean = false + var delimiter: String = "," + + if (config.hasPath("local.read.filePath")) { + filePath = config.getString("local.read.filePath") + src = config.getString("local.read.srcId") + dst = config.getString("local.read.dstId") + if (config.hasPath("local.read.weight")) { + weight = config.getString("local.read.weight") + } + if (config.hasPath("local.read.delimiter")) { + delimiter = config.getString("local.read.delimiter") + } + if (config.hasPath("local.read.header")) { + header = config.getBoolean("local.read.header") + } + } + if (config.hasPath("local.write.resultPath")) { + resultPath = config.getString("local.write.resultPath") + } + LocalConfigEntry(filePath, src, dst, weight, resultPath, header, delimiter) + } +} + +/** + * SparkConfigEntry support key-value pairs for spark session. + * + * @param map + */ +case class SparkConfigEntry(map: Map[String, String]) { + override def toString: String = { + map.toString() + } +} + +/** + * AlgorithmConfigEntry support key-value pairs for algorithms. + * + * @param map + */ +case class AlgorithmConfigEntry(map: Map[String, String]) { + override def toString: String = { + map.toString() + } +} + +/** + * DataSourceEntry + */ +case class DataSourceSinkEntry(source: String, sink: String, hasWeight: Boolean) { + override def toString: String = { + s"DataSourceEntry: {source:$source, sink:$sink, hasWeight:$hasWeight}" + } +} + +case class LocalConfigEntry(filePath: String, + srcId: String, + dstId: String, + weight: String, + resultPath: String, + header: Boolean, + delimiter: String) { + override def toString: String = { + s"LocalConfigEntry: {filePath: $filePath, srcId: $srcId, dstId: $dstId, " + + s"weight:$weight, resultPath:$resultPath, delimiter:$delimiter}" + } +} + +/** + * NebulaConfigEntry + * @param readConfigEntry config for nebula-spark-connector reader + * @param writeConfigEntry config for nebula-spark-connector writer + */ +case class NebulaConfigEntry(readConfigEntry: NebulaReadConfigEntry, + writeConfigEntry: NebulaWriteConfigEntry) { + override def toString: String = { + s"NebulaConfigEntry:{${readConfigEntry.toString}, ${writeConfigEntry.toString}" + } +} + +case class NebulaReadConfigEntry(address: String = "", + space: String = "", + labels: List[String] = List(), + weightCols: List[String] = List()) { + override def toString: String = { + s"NebulaReadConfigEntry: " + + s"{address: $address, space: $space, labels: ${labels.mkString(",")}, " + + s"weightCols: ${weightCols.mkString(",")}}" + } +} + +case class NebulaWriteConfigEntry(graphAddress: String = "", + metaAddress: String = "", + user: String = "", + pswd: String = "", + space: String = "", + tag: String = "") { + override def toString: String = { + s"NebulaWriteConfigEntry: " + + s"{graphAddress: $graphAddress, user: $user, password: $pswd, space: $space, tag: $tag}" + } +} + +/** + * Configs + */ +case class Configs(sparkConfig: SparkConfigEntry, + dataSourceSinkEntry: DataSourceSinkEntry, + nebulaConfig: NebulaConfigEntry, + localConfigEntry: LocalConfigEntry, + algorithmConfig: AlgorithmConfigEntry) + +object Configs { + private[this] val LOG = Logger.getLogger(this.getClass) + + /** + * + * @param configPath + * @return + */ + def parse(configPath: File): Configs = { + if (!Files.exists(configPath.toPath)) { + throw new IllegalArgumentException(s"${configPath} not exist") + } + + val config = ConfigFactory.parseFile(configPath) + val dataSourceEntry = DataSourceSinkEntry(config) + val localConfigEntry = LocalConfigEntry(config) + val nebulaConfigEntry = NebulaConfigEntry(config) + val sparkEntry = SparkConfigEntry(config) + val algorithmEntry = AlgorithmConfigEntry(config) + + Configs(sparkEntry, dataSourceEntry, nebulaConfigEntry, localConfigEntry, algorithmEntry) + } + + /** + * Get the config list by the path. + * + * @param config The config. + * @param path The path of the config. + * + * @return + */ + private[this] def getConfigsOrNone(config: Config, + path: String): Option[java.util.List[_ <: Config]] = { + if (config.hasPath(path)) { + Some(config.getConfigList(path)) + } else { + None + } + } + + /** + * Get the config by the path. + * + * @param config + * @param path + * + * @return + */ + def getConfigOrNone(config: Config, path: String): Option[Config] = { + if (config.hasPath(path)) { + Some(config.getConfig(path)) + } else { + None + } + } + + /** + * Get the value from config by the path. If the path not exist, return the default value. + * + * @param config The config. + * @param path The path of the config. + * @param defaultValue The default value for the path. + * + * @return + */ + private[this] def getOrElse[T](config: Config, path: String, defaultValue: T): T = { + if (config.hasPath(path)) { + config.getAnyRef(path).asInstanceOf[T] + } else { + defaultValue + } + } + + private[this] def getOptOrElse(config: Config, path: String): Option[String] = { + if (config.hasPath(path)) { + Some(config.getString(path)) + } else { + None + } + } + + /** + * Get the value from config by the path which is optional. + * If the path not exist, return the default value. + * + * @param config + * @param path + * @param defaultValue + * @tparam T + * @return + */ + private[this] def getOrElse[T](config: Option[Config], path: String, defaultValue: T): T = { + if (config.isDefined && config.get.hasPath(path)) { + config.get.getAnyRef(path).asInstanceOf[T] + } else { + defaultValue + } + } + + final case class Argument(config: File = new File("application.conf")) + + /** + * Use to parse command line arguments. + * + * @param args + * @param programName + * @return Argument + */ + def parser(args: Array[String], programName: String): Option[Argument] = { + val parser = new scopt.OptionParser[Argument](programName) { + head(programName, "1.0.0") + + opt[File]('p', "prop") + .required() + .valueName("") + .action((x, c) => c.copy(config = x)) + .text("config file") + } + parser.parse(args, Argument()) + } +} + +object AlgoConstants { + val ALGO_ID_COL: String = "_id" + val PAGERANK_RESULT_COL: String = "_pagerank" + val LOUVAIN_RESULT_COL: String = "_louvain" + val KCORE_RESULT_COL: String = "_kcore" + val LPA_RESULT_COL: String = "_lpa" + val CC_RESULT_COL: String = "_cc" + val SCC_RESULT_COL: String = "_scc" + val BETWEENNESS_RESULT_COL: String = "_betweennedss" + val SHORTPATH_RESULT_COL: String = "_shortestpath" + val DEGREE_RESULT_COL: String = "_degree" + val INDEGREE_RESULT_COL: String = "_inDegree" + val OUTDEGREE_RESULT_COL: String = "_outDegree" + val TRIANGLECOUNT_RESULT_COL: String = "_tranglecount" +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/config/NebulaConfig.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/config/NebulaConfig.scala new file mode 100644 index 0000000..8156d78 --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/config/NebulaConfig.scala @@ -0,0 +1,20 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.config + +object NebulaConfig { + + def getReadNebula(configs: Configs): NebulaReadConfigEntry = { + val nebulaConfigs = configs.nebulaConfig + nebulaConfigs.readConfigEntry + } + + def getWriteNebula(configs: Configs): NebulaWriteConfigEntry = { + val nebulaConfigs = configs.nebulaConfig + nebulaConfigs.writeConfigEntry + } +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/config/SparkConfig.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/config/SparkConfig.scala new file mode 100644 index 0000000..c073b84 --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/config/SparkConfig.scala @@ -0,0 +1,31 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.config + +import org.apache.spark.sql.SparkSession + +case class SparkConfig(spark: SparkSession, partitionNum: String) + +object SparkConfig { + + var spark: SparkSession = _ + + var partitionNum: String = _ + + def getSpark(configs: Configs, defaultAppName: String = "algorithm"): SparkConfig = { + val sparkConfigs = configs.sparkConfig.map + val session = SparkSession.builder + .appName(defaultAppName) + .config("spark.serializer", "org.apache.spark.serializer.KryoSerializer") + + for (key <- sparkConfigs.keySet) { + session.config(key, sparkConfigs(key)) + } + partitionNum = sparkConfigs.getOrElse("spark.app.partitionNum", "0") + SparkConfig(session.getOrCreate(), partitionNum) + } +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/BetweennessCentralityAlgo.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/BetweennessCentralityAlgo.scala new file mode 100644 index 0000000..e6284e1 --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/BetweennessCentralityAlgo.scala @@ -0,0 +1,375 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.config.{AlgoConstants, BetweennessConfig} +import com.vesoft.nebula.algorithm.utils.NebulaUtil +import org.apache.log4j.Logger +import org.apache.spark.SparkContext +import org.apache.spark.graphx.{Edge, EdgeDirection, EdgeTriplet, Graph, Pregel, VertexId} +import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession} +import org.apache.spark.sql.types.{DoubleType, LongType, StructField, StructType} + +import scala.collection.mutable +import scala.collection.mutable.ListBuffer + +object BetweennessCentralityAlgo { + private val LOGGER = Logger.getLogger(this.getClass) + + val ALGORITHM: String = "BetweennessCentrality" + + /** + * run the BetweennessCentrality algorithm for nebula graph + */ + def apply(spark: SparkSession, + dataset: Dataset[Row], + betweennessConfig: BetweennessConfig, + hasWeight: Boolean): DataFrame = { + + val graph: Graph[None.type, Double] = NebulaUtil.loadInitGraph(dataset, false) + val betweennessGraph = execute(graph, betweennessConfig.maxIter, hasWeight) + + val schema = StructType( + List( + StructField(AlgoConstants.ALGO_ID_COL, LongType, nullable = false), + StructField(AlgoConstants.BETWEENNESS_RESULT_COL, DoubleType, nullable = true) + )) + val resultRDD = betweennessGraph.vertices.map(vertex => Row(vertex._1, vertex._2)) + val algoResult = spark.sqlContext.createDataFrame(resultRDD, schema) + algoResult + } + + /** + * execute betweenness centrality 算法 + */ + def execute(graph: Graph[None.type, Double], + k: Integer, + isWeighted: Boolean): Graph[Double, Double] = { + val initBCgraph = createBetweenGraph(graph, k) + //有权图计算方法 + if (isWeighted) { + val vertexBCGraph = initBCgraph.mapVertices((id, attr) => { + val a = betweennessCentralityForWeightedGraph(id, attr) + (id, a) + }) + val BCGraph = aggregateBetweennessScores(vertexBCGraph) + BCGraph + } + //无权图计算方法 + else { + val vertexBCGraph = initBCgraph.mapVertices((id, attr) => { + (id, betweennessCentralityForUnweightedGraph(id, attr)) + }) + val BCGraph = aggregateBetweennessScores(vertexBCGraph) + BCGraph + } + } + + /** + * betweennessCentralityForUnweightedGraph + * + * 对无权图计算顶点的介数中心性 + * 对每个顶点vid计算从该节点出发时其他节点的介数中心性,返回对于顶点vid而言图中节点所计算出来的介数中心性 + * + * 对图中所有节点都会计算一次全局的介数中心性,最后进行汇总 + * + * @param vid:顶点id + * @param vAttr:顶点对应的属性信息 + * + *@return List((Vid, betweennessValue)) + * + * */ + def betweennessCentralityForUnweightedGraph(vid: VertexId, + vAttr: VertexProperty): List[(VertexId, Double)] = { + //无权图的计算方法 + println("enter betweennessCentrality for vertex: " + vid) + + //对图中每个顶点做如下操作 + val S = mutable.Stack[VertexId]() //每次访问过的节点入栈 + val P = new mutable.HashMap[VertexId, ListBuffer[VertexId]]() //存储源顶点到某个顶点中间经过哪些顶点 + //如[5,[2,3]],表示源顶点到顶点5的最短路径会经过顶点2,3 + val Q = mutable.Queue[VertexId]() //BFS遍历时将顶点入队列 + val dist = new mutable.HashMap[VertexId, Double]() + val sigma = new mutable.HashMap[VertexId, Double]() + val delta = new mutable.HashMap[VertexId, Double]() + val neighborMap = getNeighborMap(vAttr.vlist, vAttr.elist) + val medBC = new ListBuffer[(VertexId, Double)]() + + for (vertex <- vAttr.vlist) { + dist.put(vertex, -1) + sigma.put(vertex, 0.0) + delta.put(vertex, 0.0) + P.put(vertex, ListBuffer[VertexId]()) + } + //对于当前节点,有特殊对待 + dist(vid) = 0.0 + sigma(vid) = 1.0 + Q.enqueue(vid) + + while (Q.nonEmpty) { + val v = Q.dequeue() + S.push(v) + for (w <- neighborMap(v)) { + if (dist(w) < 0) { //节点w未被访问过 + Q.enqueue(w) + dist(w) = dist(v) + 1 + } + if (dist(w) == dist(v) + 1) { + sigma(w) += sigma(v) + P(w).+=(v) + } + } + } + + while (S.nonEmpty) { + val w = S.pop() + for (v <- P(w)) { + delta(v) += sigma(v) / sigma(w) * (1 + delta(w)) + } + if (w != vid) + medBC.append((w, delta(w) / 2)) //一条边会被两个节点各自计算一次,所以需要对求出来的值除以2 + } + medBC.toList + } + + /** + * betweennessCentralityForWeightedGraph + * + * 有权图求介数中心性 + * + * 与无权图求介数中心性的区别在于“存储邻居节点信息”的数据结构不同 + * 有权图不是用队列,而是采用scala的优先级队列PriorityQueue,即最小堆 + * 利用最小堆维护顶点的邻居节点以及与邻居节点的边权重元组:(vw_dist, v, w)其中v是w的前驱节点,即w是v的往深处走的邻居节点 + * 当遍历完顶点v的所有邻居节点后,需要从中选择一个最近的邻居继续进行深度遍历,所以让最小堆根据wv_dist降序排列, + * 每次pop出来的即是最小边对应的顶点信息,也就是每次选出来的邻居节点都是距离最近的邻居。 + * + * @param vid:顶点id + * @param vAttr:顶点对应的属性信息 + * + *@return List((Vid, betweennessValue)) + * */ + def betweennessCentralityForWeightedGraph(vid: VertexId, + vAttr: VertexProperty): List[(VertexId, Double)] = { + println("enter betweennessCentralityForWeightedGraph function") + //对图中每个顶点做如下操作 + val S = mutable.Stack[VertexId]() //每次访问过的节点入栈 + val P = new mutable.HashMap[VertexId, ListBuffer[VertexId]]() //存储源顶点到某个顶点中间经过哪些顶点 + //如[5,[2,3]],表示源顶点到顶点5的最短路径会经过顶点2,3 + + //下面定义一个优先级队列,即最小堆,根据第一个元素进行倒排 + val ord = Ordering.by[(Double, VertexId, VertexId), Double](_._1).reverse + val Q = new mutable.PriorityQueue[(Double, VertexId, VertexId)]()(ord) //遍历时将顶点及对应的路径长度入队列 + + val dist = new mutable.HashMap[VertexId, Double]() + val sigma = new mutable.HashMap[VertexId, Double]() + val delta = new mutable.HashMap[VertexId, Double]() + val neighborMap = getNeighborMap(vAttr.vlist, vAttr.elist) + val medBC = new ListBuffer[(VertexId, Double)]() + + for (vertex <- vAttr.vlist) { + dist.put(vertex, -1) + sigma.put(vertex, 0.0) + delta.put(vertex, 0.0) + P.put(vertex, ListBuffer[VertexId]()) + } + //对于当前节点,有特殊对待 + sigma(vid) = 1.0 + val seen = new mutable.HashMap[VertexId, Double]() + seen(vid) = 0 + Q.enqueue((0.0, vid, vid)) + + //获取两个相邻节点之间的距离 + def getDist(v: VertexId, w: VertexId) = { + vAttr.elist + .filter(e => (e._1 == v && e._2 == w) || (e._2 == v && e._1 == w)) + .map(x => x._3) + .reduce(_.min(_)) + } + + while (Q.nonEmpty) { + val (d, pred, v) = Q.dequeue() + if (dist(v) > 0) { //节点v已经访问过了 + null + } else { + sigma(v) += sigma(pred) + S.push(v) + dist(v) = d + for (w <- neighborMap(v)) { + val vw_dist = d + getDist(v, w) + if (dist(w) < 0 && (!seen.contains(w) || vw_dist < seen(w))) { + seen(w) = vw_dist + Q.enqueue((vw_dist, v, w)) + sigma(w) = 0.0 + P(w) = ListBuffer[VertexId](v) + } else if (vw_dist == seen(w)) { + sigma(w) += sigma(v) + P(w).+=(v) + } + } + } + } + + while (S.nonEmpty) { + val w = S.pop() + for (v <- P(w)) { + delta(v) += sigma(v) / sigma(w) * (1 + delta(w)) + } + if (w != vid) + medBC.append((w, delta(w) / 2)) + } + medBC.toList + } + + /** + * 为每个顶点收集其邻居节点信息 + * 尝试过用收集邻居节点的api,但在计算介数中心性内部又需要每个节点都维护所有节点信息和边信息,所以采用对每个节点根据边来计算邻居节点的方式 + * + * @param vlist, elist 所有顶点信息和所有边信息 + * @return [vid, [ 邻居id, 邻居id ...] ] + * */ + def getNeighborMap( + vlist: List[VertexId], + elist: List[(VertexId, VertexId, Double)]): mutable.HashMap[VertexId, List[VertexId]] = { + val neighborList = new mutable.HashMap[VertexId, List[VertexId]]() + vlist.map(v => { + val nlist = (elist + .filter(e => (e._1 == v || e._2 == v))) + .map(e => { + if (v == e._1) e._2 + else e._1 + }) + neighborList.+=((v, nlist.distinct)) + }) + neighborList + } + + /** + * 根据原始数据构建初始图 + * + * @param sc + * @param path 原始数据所在的hdfs路径 + * @param separator 数据不同字段间的分隔符 + * @param weightCol 用于标识哪一列作为权重列,给出列号,从0开始。 + * 对权重列的限制: 权重列为-1时,表示没有权重列,即该图是无权图,默认设权重为1.0 + * 为非-1的整数时,表示图数据中的第weightCol列为权重列 + * 要求:其值小于数据中列的数目,且该权重列对应的数据必须是double数值 + * + * @return Graph + * */ + def loadInitGraph(sc: SparkContext, + path: String, + separator: String, + weightCol: Int): Graph[None.type, Double] = { + val data = sc.textFile(path) + val edges = data.map(line => { + val items = line.split(separator) + require(items.length > weightCol, + "权重列超过了图数据的字段数,图数据字段数目为 " + items.length + ", 选择的权重列为 " + weightCol) + var weightValue = 0.0 + if (weightCol == -1) { + weightValue = 1.0 + } else { + require(isNumic(items(weightCol)), "权重列必须为double数值") + weightValue = items(weightCol).toDouble + } + Edge(items(0).toLong, items(1).toLong, weightValue) + }) + Graph.fromEdges(edges, None) + } + + /** + * 工具方法,验证权重列中的值可以转为double + * */ + def isNumic(str: String): Boolean = { + var result = true + for (s <- str.replaceAll(".", "")) { + if (!s.isDigit) + result = false + } + result + } + + /** + * 构建BetweennessCentrality图,图中顶点属性维护了图中所有顶点id的列表和所有边(srcId, dstId, attr)的列表 + * + * @param initG 原始数据构造的图 + * @param k 最大迭代次数 + * @return Graph + * */ + def createBetweenGraph(initG: Graph[None.type, Double], k: Int): Graph[VertexProperty, Double] = { + val betweenG = initG + .mapTriplets[Double]({ x: EdgeTriplet[None.type, Double] => + x.attr + }) + .mapVertices((id, attr) => new VertexProperty) + .cache + //准备进入pregel前的初始化消息、vertexProgram方法、 sendMessage方法、mergeMessage方法 + val initMessage = (List[VertexId](), List[(VertexId, VertexId, Double)]()) + //将发送过来的邻居节点信息以及当前点与邻居点的边,更新到当前点的属性中 + def vertexProgram( + id: VertexId, + attr: VertexProperty, + msgSum: (List[VertexId], List[(VertexId, VertexId, Double)])): VertexProperty = { + val newAttr = new VertexProperty() + newAttr.CB = attr.CB + newAttr.vlist = (msgSum._1 ++ attr.vlist).distinct + newAttr.elist = (msgSum._2 ++ attr.elist).distinct + newAttr + } + //向邻居节点发送自身节点的id和自身与邻居点的边 + def sendMessage(edge: EdgeTriplet[VertexProperty, Double]) + : Iterator[(VertexId, (List[VertexId], List[(VertexId, VertexId, Double)]))] = Iterator( + (edge.dstId, + (edge.srcId +: edge.srcAttr.vlist, + (edge.srcId, edge.dstId, edge.attr) +: edge.srcAttr.elist)), + (edge.srcId, + (edge.dstId +: edge.dstAttr.vlist, + (edge.srcId, edge.dstId, edge.attr) +: edge.dstAttr.elist)) + ) + //合并接受到的多条消息 + def mergeMessage(a: (List[VertexId], List[(VertexId, VertexId, Double)]), + b: (List[VertexId], List[(VertexId, VertexId, Double)])) + : (List[VertexId], List[(VertexId, VertexId, Double)]) = { + ((a._1 ++ b._1).distinct, (a._2 ++ b._2).distinct) + } + + Pregel(betweenG, initMessage, k, EdgeDirection.Either)(vertexProgram, sendMessage, mergeMessage) + } + + /** + * 将每个节点分别计算出来的BC值进行统计 + * */ + def aggregateBetweennessScores( + BCgraph: Graph[(VertexId, List[(VertexId, Double)]), Double]): Graph[Double, Double] = { + //将图中顶点属性所维护的listBC信息单独提取出来 + val BCaggregate = BCgraph.vertices.flatMap { + case (v, (id, listBC)) => { + listBC.map { case (w, bc) => (w, bc) } + } + } + //对BCaggregate的信息 (w, bc)根据顶点id做汇总 + val vertexBC = BCaggregate.reduceByKey(_ + _) + val resultG = BCgraph.outerJoinVertices(vertexBC)((vid, oldAttr, vBC) => { + vBC.getOrElse(0.0) + }) + resultG + } +} + +/** + * 定义顶点的属性类 + * CB: 定义初始的betweennessCentrality + * vlist: 每个顶点需维护图中所有的顶点信息 + * elist: 每个顶点需维护图中所有的边信息 + * + * 维护所有边信息是为了在计算介数中心性的时候可以从每个顶点依次根据邻居节点走下去(空间复杂度很高,O(n2)) + * */ +class VertexProperty() extends Serializable { + var CB = 0.0 + var vlist = List[VertexId]() + var elist = List[(VertexId, VertexId, Double)]() +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/ConnectedComponentsAlgo.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/ConnectedComponentsAlgo.scala new file mode 100644 index 0000000..66f4e6a --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/ConnectedComponentsAlgo.scala @@ -0,0 +1,59 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.utils.NebulaUtil +import com.vesoft.nebula.algorithm.config.{ + AlgoConstants, + CcConfig, + Configs, + LPAConfig, + NebulaConfig, + PRConfig, + SparkConfig +} +import org.apache.log4j.Logger +import org.apache.spark.graphx.{Graph, VertexId, VertexRDD} +import org.apache.spark.rdd.RDD +import com.vesoft.nebula.algorithm.utils.NebulaUtil +import org.apache.spark.graphx.lib.ConnectedComponents +import org.apache.spark.sql.types.{DoubleType, LongType, StructField, StructType} +import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession} + +object ConnectedComponentsAlgo { + private val LOGGER = Logger.getLogger(this.getClass) + + val ALGORITHM: String = "ConnectedComponents" + + /** + * run the ConnectedComponents algorithm for nebula graph + */ + def apply(spark: SparkSession, + dataset: Dataset[Row], + ccConfig: CcConfig, + hasWeight: Boolean): DataFrame = { + + val graph: Graph[None.type, Double] = NebulaUtil.loadInitGraph(dataset, hasWeight) + + val ccResultRDD = execute(graph, ccConfig.maxIter) + + val schema = StructType( + List( + StructField(AlgoConstants.ALGO_ID_COL, LongType, nullable = false), + StructField(AlgoConstants.CC_RESULT_COL, LongType, nullable = true) + )) + val algoResult = spark.sqlContext + .createDataFrame(ccResultRDD, schema) + + algoResult + } + + def execute(graph: Graph[None.type, Double], maxIter: Int): RDD[Row] = { + val ccResultRDD: VertexRDD[VertexId] = ConnectedComponents.run(graph, maxIter).vertices + ccResultRDD.map(row => Row(row._1, row._2)) + } +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/DegreeStaticAlgo.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/DegreeStaticAlgo.scala new file mode 100644 index 0000000..1001f3c --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/DegreeStaticAlgo.scala @@ -0,0 +1,58 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.config.AlgoConstants +import com.vesoft.nebula.algorithm.utils.NebulaUtil +import org.apache.log4j.Logger +import org.apache.spark.graphx.{Graph, VertexRDD} +import org.apache.spark.rdd.RDD +import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession} +import org.apache.spark.sql.types.{IntegerType, LongType, StructField, StructType} + +object DegreeStaticAlgo { + + private val LOGGER = Logger.getLogger(this.getClass) + + val ALGORITHM: String = "DegreeStatic" + + /** + * run the pagerank algorithm for nebula graph + */ + def apply(spark: SparkSession, dataset: Dataset[Row]): DataFrame = { + + val graph: Graph[None.type, Double] = NebulaUtil.loadInitGraph(dataset, false) + + val degreeResultRDD = execute(graph) + + val schema = StructType( + List( + StructField(AlgoConstants.ALGO_ID_COL, LongType, nullable = false), + StructField(AlgoConstants.DEGREE_RESULT_COL, IntegerType, nullable = true), + StructField(AlgoConstants.INDEGREE_RESULT_COL, IntegerType, nullable = true), + StructField(AlgoConstants.OUTDEGREE_RESULT_COL, IntegerType, nullable = true) + )) + val algoResult = spark.sqlContext + .createDataFrame(degreeResultRDD, schema) + + algoResult + } + + def execute(graph: Graph[None.type, Double]): RDD[Row] = { + val degreeRdd: VertexRDD[Int] = graph.degrees + val inDegreeRdd: VertexRDD[Int] = graph.inDegrees + val outDegreeRdd: VertexRDD[Int] = graph.outDegrees + + val degreeAndInDegree: VertexRDD[(Int, Int)] = + degreeRdd.leftJoin(inDegreeRdd)((id, d, inD) => (d, inD.getOrElse(0))) + + val result = degreeAndInDegree.leftJoin(outDegreeRdd)((id, dAndInD, opt) => + (dAndInD._1, dAndInD._2, opt.getOrElse(0))) + result.map(vertex => Row(vertex._1, vertex._2._1, vertex._2._2, vertex._2._3)) + } + +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/KCoreAlgo.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/KCoreAlgo.scala new file mode 100644 index 0000000..421b412 --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/KCoreAlgo.scala @@ -0,0 +1,74 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.config.{AlgoConstants, KCoreConfig} +import org.apache.log4j.Logger +import org.apache.spark.graphx.Graph +import com.vesoft.nebula.algorithm.utils.NebulaUtil +import org.apache.spark.sql.types.{IntegerType, LongType, StructField, StructType} +import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession} + +object KCoreAlgo { + private val LOGGER = Logger.getLogger(this.getClass) + + val ALGORITHM: String = "LabelPropagation" + + /** + * run the louvain algorithm for nebula graph + */ + def apply(spark: SparkSession, dataset: Dataset[Row], kCoreConfig: KCoreConfig): DataFrame = { + + val graph: Graph[None.type, Double] = NebulaUtil.loadInitGraph(dataset, false) + val kCoreGraph = execute(graph, kCoreConfig.maxIter, kCoreConfig.degree) + + val schema = StructType( + List( + StructField(AlgoConstants.ALGO_ID_COL, LongType, nullable = false), + StructField(AlgoConstants.KCORE_RESULT_COL, IntegerType, nullable = true) + )) + val resultRDD = kCoreGraph.vertices.map(vertex => Row(vertex._1, vertex._2)) + val algoResult = spark.sqlContext.createDataFrame(resultRDD, schema) + algoResult + } + + /** + * extract k-core sub-graph + */ + def execute(graph: Graph[None.type, Double], maxIter: Int, k: Int): Graph[Int, Double] = { + var lastVertexNum: Long = graph.numVertices + var currentVertexNum: Long = -1 + var isStable: Boolean = false + var iterNum: Int = 1 + + var degreeGraph = graph + .outerJoinVertices(graph.degrees) { (vid, vd, degree) => + degree.getOrElse(0) + } + .cache + var subGraph: Graph[Int, Double] = null + + while (iterNum < maxIter) { + subGraph = degreeGraph.subgraph(vpred = (vid, degree) => degree >= k) + degreeGraph = subGraph + .outerJoinVertices(subGraph.degrees) { (vid, vd, degree) => + degree.getOrElse(0) + } + .cache + + currentVertexNum = degreeGraph.numVertices + if (currentVertexNum == lastVertexNum) { + isStable = true; + } else { + lastVertexNum = currentVertexNum + } + + iterNum += 1 + } + subGraph + } +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/LabelPropagationAlgo.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/LabelPropagationAlgo.scala new file mode 100644 index 0000000..3c78fca --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/LabelPropagationAlgo.scala @@ -0,0 +1,50 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.utils.NebulaUtil +import com.vesoft.nebula.algorithm.config.{AlgoConstants, LPAConfig} +import org.apache.log4j.Logger +import org.apache.spark.graphx.{Graph, VertexId, VertexRDD} +import org.apache.spark.rdd.RDD +import com.vesoft.nebula.algorithm.utils.NebulaUtil +import org.apache.spark.graphx.lib.LabelPropagation +import org.apache.spark.sql.types.{LongType, StructField, StructType} +import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession} + +object LabelPropagationAlgo { + private val LOGGER = Logger.getLogger(this.getClass) + + val ALGORITHM: String = "LabelPropagation" + + /** + * run the LabelPropagation algorithm for nebula graph + */ + def apply(spark: SparkSession, + dataset: Dataset[Row], + lpaConfig: LPAConfig, + hasWeight: Boolean): DataFrame = { + val graph: Graph[None.type, Double] = NebulaUtil.loadInitGraph(dataset, hasWeight) + + val lpaResultRDD = execute(graph, lpaConfig.maxIter) + + val schema = StructType( + List( + StructField(AlgoConstants.ALGO_ID_COL, LongType, nullable = false), + StructField(AlgoConstants.LPA_RESULT_COL, LongType, nullable = true) + )) + val algoResult = spark.sqlContext + .createDataFrame(lpaResultRDD, schema) + + algoResult + } + + def execute(graph: Graph[None.type, Double], maxIter: Int): RDD[Row] = { + val lpaResultRDD: VertexRDD[VertexId] = LabelPropagation.run(graph, maxIter).vertices + lpaResultRDD.map(row => Row(row._1, row._2)) + } +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/LouvainAlgo.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/LouvainAlgo.scala new file mode 100644 index 0000000..99b17de --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/LouvainAlgo.scala @@ -0,0 +1,379 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.utils.NebulaUtil +import com.vesoft.nebula.algorithm.config.{ + AlgoConstants, + Configs, + LouvainConfig, + NebulaConfig, + SparkConfig +} +import com.vesoft.nebula.algorithm.utils.NebulaUtil +import org.apache.log4j.Logger +import org.apache.spark.graphx.{Edge, Graph, VertexId, VertexRDD} +import org.apache.spark.rdd.RDD +import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession} +import org.apache.spark.sql.types.{LongType, StructField, StructType} + +import scala.collection.mutable +import scala.collection.mutable.{HashMap, HashSet} + +object LouvainAlgo { + private val LOGGER = Logger.getLogger(this.getClass) + + val ALGORITHM: String = "Louvain" + + /** + * run the louvain algorithm for nebula graph + */ + def apply(spark: SparkSession, + dataset: Dataset[Row], + louvainConfig: LouvainConfig, + hasWeight: Boolean): DataFrame = { + + val graph: Graph[None.type, Double] = NebulaUtil.loadInitGraph(dataset, hasWeight) + + val louvainResultRDD: RDD[Row] = + execute(spark, graph, louvainConfig.maxIter, louvainConfig.internalIter, louvainConfig.tol) + + val schema = StructType( + List( + StructField(AlgoConstants.ALGO_ID_COL, LongType, nullable = false), + StructField(AlgoConstants.LOUVAIN_RESULT_COL, LongType, nullable = false) + )) + + val louvainResult = spark.sqlContext + .createDataFrame(louvainResultRDD, schema) + louvainResult + } + + def execute(spark: SparkSession, + graph: Graph[None.type, Double], + maxIter: Int, + internalIter: Int, + tol: Double): RDD[Row] = { + + val sc = spark.sparkContext + + // convert origin graph to Louvain Graph, Louvain Graph records vertex's community、innerVertices and innerDegrees + var louvainG: Graph[VertexData, Double] = LouvainGraphUtil.createLouvainGraph(graph) + + // compute and broadcast the sum of all edges + val m = sc.broadcast(louvainG.edges.map(e => e.attr).sum()) + var curIter = 0 + var res = step1(internalIter, louvainG, m.value, tol) + while (res._2 != 0 && curIter < maxIter) { + louvainG = res._1 + louvainG = step2(louvainG) + res = step1(internalIter, louvainG, m.value, tol) + curIter += 1 + } + CommUtil.getCommunities(louvainG) + } + + /** + * Louvain step1:Traverse the vertices and get the new community information of each node遍历节点,获取每个节点对应的所属新社区信息 + * + * 1. Calculate the information of the community that each vertex currently belongs to. + * 2. Calculate the community modularity deference and get the community info which has max modularity deference. + * 3. Count the number of vertices that have changed in the community, used to determine whether the internal iteration can stop. + * 4. Update vertices' community id and update each community's innerVertices. + * + * This step update vertexData's cid and commVertex. + * + * @param maxIter max interation + * @param louvainG + * @param m The sum of the weights of all edges in the graph + * + * @return (Graph[VertexData,Double],Int) + */ + def step1( + maxIter: Int, + louvainG: Graph[VertexData, Double], + m: Double, + tol: Double + ): (Graph[VertexData, Double], Int) = { + LOGGER.info("============================== step 1 =======================") + var G = louvainG + var iterTime = 0 + var canStop = false + while (iterTime < maxIter && !canStop) { + val neighborComm = getNeighCommInfo(G) + val changeInfo = getChangeInfo(G, neighborComm, m, tol) + // Count the number of vertices that have changed in the community + val changeCount = + G.vertices.zip(changeInfo).filter(x => x._1._2.cId != x._2._2).count() + if (changeCount == 0) + canStop = true + // use connectedComponents algorithm to solve the problem of community attribution delay. + else { + val newChangeInfo = Graph + .fromEdgeTuples(changeInfo.map(x => (x._1, x._2)), 0) + .connectedComponents() + .vertices + G = LouvainGraphUtil.updateGraph(G, newChangeInfo) + iterTime += 1 + } + } + (G, iterTime) + } + + /** + * Louvain step 2:Combine the new graph node obtained in the first step into a super node according to + * the community information to which it belongs. + * + * @param G graph + * @return graph + */ + def step2(G: Graph[VertexData, Double]): Graph[VertexData, Double] = { + LOGGER.info("============================== step 2 =======================") + //get edges between different communities + val edges = G.triplets + .filter(trip => trip.srcAttr.cId != trip.dstAttr.cId) + .map(trip => { + val cid1 = trip.srcAttr.cId + val cid2 = trip.dstAttr.cId + val weight = trip.attr + ((math.min(cid1, cid2), math.max(cid1, cid2)), weight) + }) + .reduceByKey(_ + _) + .map(x => Edge(x._1._1, x._1._2, x._2)) //sum the edge weights between communities + + // sum kin of all vertices within the same community + val vInnerKin = G.vertices + .map(v => (v._2.cId, (v._2.innerVertices.toSet, v._2.innerDegree))) + .reduceByKey((x, y) => { + val vertices = (x._1 ++ y._1).toSet + val kIn = x._2 + y._2 + (vertices, kIn) + }) + + // get all edge weights within the same community + val v2vKin = G.triplets + .filter(trip => trip.srcAttr.cId == trip.dstAttr.cId) + .map(trip => { + val cid = trip.srcAttr.cId + val vertices1 = trip.srcAttr.innerVertices + val vertices2 = trip.dstAttr.innerVertices + val weight = trip.attr * 2 + (cid, (vertices1.union(vertices2).toSet, weight)) + }) + .reduceByKey((x, y) => { + val vertices = new HashSet[VertexId].toSet + val kIn = x._2 + y._2 + (vertices, kIn) + }) + + // new super vertex + val superVertexInfo = vInnerKin + .union(v2vKin) + .reduceByKey((x, y) => { + val vertices = x._1 ++ y._1 + val kIn = x._2 + y._2 + (vertices, kIn) + }) + + // reconstruct graph based on new edge info + val initG = Graph.fromEdges(edges, None) + var louvainGraph = LouvainGraphUtil.createLouvainGraph(initG) + // get new louvain graph + louvainGraph = louvainGraph.outerJoinVertices(superVertexInfo)((vid, data, opt) => { + var innerVerteices = new HashSet[VertexId]() + val kIn = opt.get._2 + for (vid <- opt.get._1) + innerVerteices += vid + data.innerVertices = innerVerteices + data.innerDegree = kIn + data + }) + louvainGraph + } + + /** + * get new community's basic info after the vertex joins the community + * 1. get each vertex's community id and the community's tot. + * 2. compute each vertex's k_in. (The sum of the edge weights between vertex and vertex i in the community) + * + * @param G + */ + def getNeighCommInfo( + G: Graph[VertexData, Double] + ): RDD[(VertexId, Iterable[(Long, Double, Double)])] = { + + val commKIn = G.triplets + .flatMap(trip => { + Array( + ( + trip.srcAttr.cId, + ( + (trip.dstId -> trip.attr), + (trip.srcId, trip.srcAttr.innerDegree + trip.srcAttr.degree) + ) + ), + ( + trip.dstAttr.cId, + ( + (trip.srcId -> trip.attr), + (trip.dstId, trip.dstAttr.innerDegree + trip.dstAttr.degree) + ) + ) + ) + }) + .groupByKey() + .map(t => { + val cid = t._1 + // add the weight of the same vid in one community. + val m = new HashMap[VertexId, Double]() // store community's vertexId and vertex kin + val degrees = new HashSet[VertexId]() // record if all vertices has computed the tot + var tot = 0.0 + for (x <- t._2) { + if (m.contains(x._1._1)) + m(x._1._1) += x._1._2 + else + m(x._1._1) = x._1._2 + // compute vertex's tot + if (!degrees.contains(x._2._1)) { + tot += x._2._2 + degrees += x._2._1 + } + } + (cid, (tot, m)) + }) + + // convert commKIn + val neighCommInfo = commKIn + .flatMap(x => { + val cid = x._1 + val tot = x._2._1 + x._2._2.map(t => { + val vid = t._1 + val kIn = t._2 + (vid, (cid, kIn, tot)) + }) + }) + .groupByKey() + + neighCommInfo + } + + /** + * Calculate the influence of each vertex on the modularity change of neighbor communities, and find the most suitable community for the vertex + * △Q = [Kin - Σtot * Ki / m] + * + * @param G graph + * @param neighCommInfo neighbor community info + * @param m broadcast value + * @param tol threshold for modularity deference + * + * @return RDD + */ + def getChangeInfo(G: Graph[VertexData, Double], + neighCommInfo: RDD[(VertexId, Iterable[(Long, Double, Double)])], + m: Double, + tol: Double): RDD[(VertexId, Long, Double)] = { + val changeInfo = G.vertices + .join(neighCommInfo) + .map(x => { + val vid = x._1 + val data = x._2._1 + val commIter = x._2._2 + val vCid = data.cId + val k_v = data.degree + data.innerDegree + + val dertaQs = commIter.map(t => { + val nCid = t._1 // neighbor community id + val k_v_in = t._2 + var tot = t._3 + if (vCid == nCid) + tot -= k_v + val q = (k_v_in - tot * k_v / m) + (vid, nCid, q) + }) + val maxQ = + dertaQs.max(Ordering.by[(VertexId, Long, Double), Double](_._3)) + if (maxQ._3 > tol) + maxQ + else // if entering other communities reduces its modularity, then stays in the current community + (vid, vCid, 0.0) + }) + + changeInfo //(vid,wCid,△Q) + } + +} + +object LouvainGraphUtil { + + /** + * Construct louvain graph + * + * @param initG + * @return Graph + */ + def createLouvainGraph( + initG: Graph[None.type, Double] + ): Graph[VertexData, Double] = { + // sum of the weights of the links incident to node i + val nodeWeights: VertexRDD[Double] = initG.aggregateMessages( + trip => { + trip.sendToSrc(trip.attr) + trip.sendToDst(trip.attr) + }, + (a, b) => a + b + ) + // update graph vertex's property + val louvainG = initG.outerJoinVertices(nodeWeights)((vid, oldData, opt) => { + val vData = new VertexData(vid, vid) + val weights = opt.getOrElse(0.0) + vData.degree = weights + vData.innerVertices += vid + vData + }) + louvainG + } + + /** + * update graph using new community info + * + * @param G Louvain graph + * @param changeInfo (vid,new_cid) + * + * @return Graph[VertexData, Double] + */ + def updateGraph( + G: Graph[VertexData, Double], + changeInfo: RDD[(VertexId, Long)] + ): Graph[VertexData, Double] = { + // update community id + G.joinVertices(changeInfo)((vid, data, newCid) => { + val vData = new VertexData(vid, newCid) + vData.innerDegree = data.innerDegree + vData.innerVertices = data.innerVertices + vData.degree = data.degree + vData + }) + } +} + +object CommUtil { + // return the collections of communities + def getCommunities(G: Graph[VertexData, Double]): RDD[Row] = { + val communities = G.vertices + .map(x => { + Row(x._1, x._2.cId) + }) + communities + } +} + +class VertexData(val vId: Long, var cId: Long) extends Serializable { + var innerDegree = 0.0 + var innerVertices = new mutable.HashSet[Long]() + var degree = 0.0 +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/PageRankAlgo.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/PageRankAlgo.scala new file mode 100644 index 0000000..2bf9254 --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/PageRankAlgo.scala @@ -0,0 +1,56 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.config.{ + AlgoConstants, + Configs, + NebulaConfig, + PRConfig, + SparkConfig +} +import org.apache.log4j.Logger +import org.apache.spark.graphx.{Graph, VertexRDD} +import org.apache.spark.rdd.RDD +import com.vesoft.nebula.algorithm.utils.NebulaUtil +import org.apache.spark.graphx.lib.PageRank +import org.apache.spark.sql.types.{DoubleType, LongType, StructField, StructType} +import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession} + +object PageRankAlgo { + private val LOGGER = Logger.getLogger(this.getClass) + + val ALGORITHM: String = "PageRank" + + /** + * run the pagerank algorithm for nebula graph + */ + def apply(spark: SparkSession, + dataset: Dataset[Row], + pageRankConfig: PRConfig, + hasWeight: Boolean): DataFrame = { + + val graph: Graph[None.type, Double] = NebulaUtil.loadInitGraph(dataset, hasWeight) + + val prResultRDD = execute(graph, pageRankConfig.maxIter, pageRankConfig.resetProb) + + val schema = StructType( + List( + StructField(AlgoConstants.ALGO_ID_COL, LongType, nullable = false), + StructField(AlgoConstants.PAGERANK_RESULT_COL, DoubleType, nullable = true) + )) + val algoResult = spark.sqlContext + .createDataFrame(prResultRDD, schema) + + algoResult + } + + def execute(graph: Graph[None.type, Double], maxIter: Int, resetProb: Double): RDD[Row] = { + val prResultRDD: VertexRDD[Double] = PageRank.run(graph, maxIter, resetProb).vertices + prResultRDD.map(row => Row(row._1, row._2)) + } +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/ShortestPathAlgo.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/ShortestPathAlgo.scala new file mode 100644 index 0000000..e4a5771 --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/ShortestPathAlgo.scala @@ -0,0 +1,60 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.utils.NebulaUtil +import com.vesoft.nebula.algorithm.config.{ + AlgoConstants, + CcConfig, + Configs, + NebulaConfig, + PRConfig, + ShortestPathConfig, + SparkConfig +} +import org.apache.log4j.Logger +import org.apache.spark.graphx.{Graph, VertexId, VertexRDD} +import org.apache.spark.rdd.RDD +import com.vesoft.nebula.algorithm.utils.NebulaUtil +import org.apache.spark.graphx.lib.ShortestPaths +import org.apache.spark.graphx.lib.ShortestPaths.SPMap +import org.apache.spark.sql.types.{LongType, StringType, StructField, StructType} +import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession} + +object ShortestPathAlgo { + private val LOGGER = Logger.getLogger(this.getClass) + + val ALGORITHM: String = "ShortestPath" + + /** + * run the ShortestPath algorithm for nebula graph + */ + def apply(spark: SparkSession, + dataset: Dataset[Row], + shortestPathConfig: ShortestPathConfig, + hasWeight: Boolean): DataFrame = { + + val graph: Graph[None.type, Double] = NebulaUtil.loadInitGraph(dataset, hasWeight) + + val prResultRDD = execute(graph, shortestPathConfig.landmarks) + + val schema = StructType( + List( + StructField(AlgoConstants.ALGO_ID_COL, LongType, nullable = false), + StructField(AlgoConstants.SHORTPATH_RESULT_COL, StringType, nullable = true) + )) + val algoResult = spark.sqlContext + .createDataFrame(prResultRDD, schema) + + algoResult + } + + def execute(graph: Graph[None.type, Double], landmarks: Seq[VertexId]): RDD[Row] = { + val spResultRDD: VertexRDD[SPMap] = ShortestPaths.run(graph, landmarks).vertices + spResultRDD.map(row => Row(row._1, row._2.toString())) + } +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/StronglyConnectedComponentsAlgo.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/StronglyConnectedComponentsAlgo.scala new file mode 100644 index 0000000..720c379 --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/StronglyConnectedComponentsAlgo.scala @@ -0,0 +1,50 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.utils.NebulaUtil +import com.vesoft.nebula.algorithm.config.{AlgoConstants, CcConfig} +import com.vesoft.nebula.algorithm.utils.NebulaUtil +import org.apache.spark.graphx.{Graph, VertexId, VertexRDD} +import org.apache.spark.graphx.lib.{ConnectedComponents, StronglyConnectedComponents} +import org.apache.spark.rdd.RDD +import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession} +import org.apache.spark.sql.types.{LongType, StructField, StructType} + +object StronglyConnectedComponentsAlgo { + + val ALGORITHM: String = "StronglyConnectedComponents" + + /** + * run the StronglyConnectedComponents algorithm for nebula graph + */ + def apply(spark: SparkSession, + dataset: Dataset[Row], + ccConfig: CcConfig, + hasWeight: Boolean): DataFrame = { + + val graph: Graph[None.type, Double] = NebulaUtil.loadInitGraph(dataset, hasWeight) + + val ccResultRDD = execute(graph, ccConfig.maxIter) + + val schema = StructType( + List( + StructField(AlgoConstants.ALGO_ID_COL, LongType, nullable = false), + StructField(AlgoConstants.SCC_RESULT_COL, LongType, nullable = true) + )) + val algoResult = spark.sqlContext + .createDataFrame(ccResultRDD, schema) + + algoResult + } + + def execute(graph: Graph[None.type, Double], maxIter: Int): RDD[Row] = { + val ccResultRDD: VertexRDD[VertexId] = StronglyConnectedComponents.run(graph, maxIter).vertices + ccResultRDD.map(row => Row(row._1, row._2)) + } + +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/TriangleCountAlgo.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/TriangleCountAlgo.scala new file mode 100644 index 0000000..93d08a1 --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/lib/TriangleCountAlgo.scala @@ -0,0 +1,47 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.config.AlgoConstants +import com.vesoft.nebula.algorithm.utils.NebulaUtil +import org.apache.log4j.Logger +import org.apache.spark.graphx.{Graph, VertexRDD} +import org.apache.spark.graphx.lib.TriangleCount +import org.apache.spark.rdd.RDD +import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession} +import org.apache.spark.sql.types.{IntegerType, LongType, StructField, StructType} + +object TriangleCountAlgo { + private val LOGGER = Logger.getLogger(this.getClass) + + val ALGORITHM: String = "TriangleCount" + + /** + * run the TriangleCount algorithm for nebula graph + */ + def apply(spark: SparkSession, dataset: Dataset[Row]): DataFrame = { + + val graph: Graph[None.type, Double] = NebulaUtil.loadInitGraph(dataset, false) + + val triangleResultRDD = execute(graph) + + val schema = StructType( + List( + StructField(AlgoConstants.ALGO_ID_COL, LongType, nullable = false), + StructField(AlgoConstants.TRIANGLECOUNT_RESULT_COL, IntegerType, nullable = true) + )) + val algoResult = spark.sqlContext + .createDataFrame(triangleResultRDD, schema) + + algoResult + } + + def execute(graph: Graph[None.type, Double]): RDD[Row] = { + val resultRDD: VertexRDD[Int] = TriangleCount.run(graph).vertices + resultRDD.map(row => Row(row._1, row._2)) + } +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/reader/DataReader.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/reader/DataReader.scala new file mode 100644 index 0000000..9b6fc2b --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/reader/DataReader.scala @@ -0,0 +1,111 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.reader + +import com.vesoft.nebula.connector.connector.NebulaDataFrameReader +import com.vesoft.nebula.connector.{NebulaConnectionConfig, ReadNebulaConfig} +import com.vesoft.nebula.algorithm.config.Configs +import org.apache.spark.sql.{DataFrame, SparkSession} + +import scala.collection.mutable.ListBuffer + +abstract class DataReader(spark: SparkSession, configs: Configs) { + def read(): DataFrame +} + +class NebulaReader(spark: SparkSession, configs: Configs, partitionNum: String) + extends DataReader(spark, configs) { + override def read(): DataFrame = { + val metaAddress = configs.nebulaConfig.readConfigEntry.address + val space = configs.nebulaConfig.readConfigEntry.space + val labels = configs.nebulaConfig.readConfigEntry.labels + val weights = configs.nebulaConfig.readConfigEntry.weightCols + val partition = partitionNum.toInt + + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress(metaAddress) + .withConenctionRetry(2) + .build() + + val noColumn = weights.isEmpty + + var dataset: DataFrame = null + for (i <- labels.indices) { + val returnCols: ListBuffer[String] = new ListBuffer[String] + if (configs.dataSourceSinkEntry.hasWeight && weights.nonEmpty) { + returnCols.append(weights(i)) + } + val nebulaReadEdgeConfig: ReadNebulaConfig = ReadNebulaConfig + .builder() + .withSpace(space) + .withLabel(labels(i)) + .withNoColumn(noColumn) + .withReturnCols(returnCols.toList) + .withPartitionNum(partition) + .build() + if (dataset == null) { + dataset = spark.read.nebula(config, nebulaReadEdgeConfig).loadEdgesToDF() + } else { + dataset = dataset.union(spark.read.nebula(config, nebulaReadEdgeConfig).loadEdgesToDF()) + } + } + dataset + } +} + +class CsvReader(spark: SparkSession, configs: Configs, partitionNum: String) + extends DataReader(spark, configs) { + override def read(): DataFrame = { + val delimiter = configs.localConfigEntry.delimiter + val header = configs.localConfigEntry.header + val localPath = configs.localConfigEntry.filePath + + val partition = partitionNum.toInt + + val data = + spark.read + .option("header", header) + .option("delimiter", delimiter) + .csv(localPath) + val weight = configs.localConfigEntry.weight + val src = configs.localConfigEntry.srcId + val dst = configs.localConfigEntry.dstId + if (configs.dataSourceSinkEntry.hasWeight && weight != null && !weight.trim.isEmpty) { + data.select(src, dst, weight) + } else { + data.select(src, dst) + } + if (partition != 0) { + data.repartition(partition) + } + data + } +} + +class JsonReader(spark: SparkSession, configs: Configs, partitionNum: String) + extends DataReader(spark, configs) { + override def read(): DataFrame = { + val localPath = configs.localConfigEntry.filePath + val data = spark.read.json(localPath) + val partition = partitionNum.toInt + + val weight = configs.localConfigEntry.weight + val src = configs.localConfigEntry.srcId + val dst = configs.localConfigEntry.dstId + if (configs.dataSourceSinkEntry.hasWeight && weight != null && !weight.trim.isEmpty) { + data.select(src, dst, weight) + } else { + data.select(src, dst) + } + if (partition != 0) { + data.repartition(partition) + } + data + } +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/utils/NebulaUtil.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/utils/NebulaUtil.scala new file mode 100644 index 0000000..98d5723 --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/utils/NebulaUtil.scala @@ -0,0 +1,53 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.utils + +import org.apache.spark.graphx.{Edge, Graph} +import org.apache.spark.rdd.RDD +import org.apache.spark.sql.{Dataset, Encoder, Row} +import org.slf4j.LoggerFactory + +object NebulaUtil { + private val LOG = LoggerFactory.getLogger(this.getClass) + + /** + * construct original graph + * + * @param hasWeight if the graph has no weight, then edge's weight is default 1.0 + * @return Graph + */ + def loadInitGraph(dataSet: Dataset[Row], hasWeight: Boolean): Graph[None.type, Double] = { + implicit val encoder: Encoder[Edge[Double]] = org.apache.spark.sql.Encoders.kryo[Edge[Double]] + val edges: RDD[Edge[Double]] = dataSet + .map(row => { + if (hasWeight) { + Edge(row.get(0).toString.toLong, row.get(1).toString.toLong, row.get(2).toString.toDouble) + } else { + Edge(row.get(0).toString.toLong, row.get(1).toString.toLong, 1.0) + } + })(encoder) + .rdd + + Graph.fromEdges(edges, None) + } + + /** + * Assembly algorithm's result file path + * + * @param path algorithm configuration + * @param algorithmName + * + * @return validate result path + */ + def getResultPath(path: String, algorithmName: String): String = { + var resultFilePath = path + if (!resultFilePath.endsWith("/")) { + resultFilePath = resultFilePath + "/" + } + resultFilePath + algorithmName + } +} diff --git a/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/writer/AlgoWriter.scala b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/writer/AlgoWriter.scala new file mode 100644 index 0000000..b22f635 --- /dev/null +++ b/nebula-algorithm/src/main/scala/com/vesoft/nebula/algorithm/writer/AlgoWriter.scala @@ -0,0 +1,58 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.writer + +import com.vesoft.nebula.connector.connector.NebulaDataFrameWriter +import com.vesoft.nebula.connector.{NebulaConnectionConfig, WriteNebulaVertexConfig} +import com.vesoft.nebula.algorithm.config.Configs +import org.apache.spark.sql.DataFrame + +abstract class AlgoWriter(data: DataFrame, configs: Configs) { + def write(): Unit +} + +class NebulaWriter(data: DataFrame, configs: Configs) extends AlgoWriter(data, configs) { + override def write(): Unit = { + val graphAddress = configs.nebulaConfig.writeConfigEntry.graphAddress + val metaAddress = configs.nebulaConfig.writeConfigEntry.metaAddress + val space = configs.nebulaConfig.writeConfigEntry.space + val tag = configs.nebulaConfig.writeConfigEntry.tag + val user = configs.nebulaConfig.writeConfigEntry.user + val passwd = configs.nebulaConfig.writeConfigEntry.pswd + + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress(metaAddress) + .withGraphAddress(graphAddress) + .withConenctionRetry(2) + .build() + val nebulaWriteVertexConfig: WriteNebulaVertexConfig = WriteNebulaVertexConfig + .builder() + .withSpace(space) + .withTag(tag) + .withVidField("_id") + .withVidAsProp(false) + .withBatch(1000) + .build() + data.write.nebula(config, nebulaWriteVertexConfig).writeVertices() + } +} + +class CsvWriter(data: DataFrame, configs: Configs) extends AlgoWriter(data, configs) { + override def write(): Unit = { + val resultPath = configs.localConfigEntry.resultPath + data.repartition(1).write.option("header", true).csv(resultPath) + } +} + +class TextWriter(data: DataFrame, configs: Configs) extends AlgoWriter(data, configs) { + override def write(): Unit = { + val resultPath = configs.localConfigEntry.resultPath + data.repartition(1).write.option("header", true).text(resultPath) + } +} diff --git a/nebula-algorithm/src/test/resources/application.conf b/nebula-algorithm/src/test/resources/application.conf new file mode 100644 index 0000000..a17fb11 --- /dev/null +++ b/nebula-algorithm/src/test/resources/application.conf @@ -0,0 +1,126 @@ +{ + # Spark relation config + spark: { + app: { + name: LPA + # spark.app.partitionNum + partitionNum:100 + } + master:local + } + + data: { + # data source. optional of nebula,csv,json,parquet + source: csv + # data sink, means the algorithm result will be write into this sink. optional of nebula,csv,txt + sink: nebula + # if your algorithm needs weight + hasWeight: false + } + + # Nebula Graph relation config + nebula: { + # algo's data source from Nebula + read: { + # Nebula metad server address, multiple addresses are split by English comma + metaAddress: "127.0.0.1:9559" + # Nebula space + space: nb + # Nebula edge types, multiple labels means that data from multiple edges will union together + labels: ["serve"] + # Nebula edge property name for each edge type, this property will be as weight col for algorithm. + # Make sure the weightCols are corresponding to labels. + weightCols: ["start_year"] + } + + # algo result sink into Nebula + write:{ + # Nebula graphd server address, multiple addresses are split by English comma + graphAddress: "127.0.0.1:9669" + # Nebula metad server address, multiple addresses are split by English comma + metaAddress: "127.0.0.1:9559,127.0.0.1:9560" + user:root + pswd:nebula + # Nebula space name + space:nb + # Nebula tag name, the algorithm result will be write into this tag + tag:pagerank + } + } + + local: { + # algo's data source from Nebula + read:{ + filePath: "hdfs://127.0.0.1:9000/edge/work_for.csv" + # srcId column + srcId:"_c0" + # dstId column + dstId:"_c1" + # weight column + #weight: "col3" + # if csv file has header + header: false + # csv file's delimiter + delimiter:"," + } + + # algo result sink into local file + write:{ + resultPath:/tmp/ + } + } + + + algorithm: { + # the algorithm that you are going to execute,pick one from [pagerank, louvain, connectedcomponent, + # labelpropagation, shortestpaths, degreestatic, kcore, stronglyconnectedcomponent, trianglecount, + # betweenness] + executeAlgo: pagerank + + # pagerank parameter + pagerank: { + maxIter: 10 + resetProb: 0.15 # default 0.15 + } + + # louvain parameter + louvain: { + maxIter: 20 + internalIter: 10 + tol: 0.5 + } + + # connected component parameter TODO not implemented yet. + connectedcomponent: { + maxIter: 20 + } + + # LabelPropagation + labelpropagation: { + maxIter: 20 + } + + # ShortestPaths + shortestpaths: { + # several vertices to compute the shortest path to all vertices. + landmarks: "1" + } + + # vertex degree static + degreestatic: {} + + # kcore + kcore:{ + maxIter:10 + degree:1 + } + + # trianglecount + trianglecount:{} + + # betweenness centrality + betweenness:{ + maxIter:5 + } + } +} diff --git a/nebula-algorithm/src/test/resources/edge.csv b/nebula-algorithm/src/test/resources/edge.csv new file mode 100644 index 0000000..ce93855 --- /dev/null +++ b/nebula-algorithm/src/test/resources/edge.csv @@ -0,0 +1,17 @@ +src,dst,weight +1,1,5.0 +1,2,1.0 +1,3,5.0 +1,4,1.0 +2,1,5.0 +2,2,1.0 +2,3,5.0 +2,4,1.0 +3,1,1.0 +3,2,5.0 +3,3,1.0 +3,4,5.0 +4,1,1.0 +4,2,5.0 +4,3,1.0 +4,4,5.0 \ No newline at end of file diff --git a/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/config/ConfigSuite.scala b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/config/ConfigSuite.scala new file mode 100644 index 0000000..f8f485c --- /dev/null +++ b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/config/ConfigSuite.scala @@ -0,0 +1,133 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.config + +import com.vesoft.nebula.algorithm.config.Configs.Argument +import org.junit.Test + +import scala.collection.mutable.ListBuffer + +class ConfigSuite { + + var configs: Configs = _ + + @Test + def getConfigsSuite(): Unit = { + val args: ListBuffer[String] = new ListBuffer[String] + args.append("-p") + args.append("src/test/resources/application.conf") + try { + val options = Configs.parser(args.toArray, "TestProgram") + val p: Argument = options match { + case Some(config) => config + case _ => + assert(false) + sys.exit(-1) + } + configs = Configs.parse(p.config) + } catch { + case e: Exception => { + e.printStackTrace() + assert(false) + } + } + + } + + @Test + def getSparkConfigSuite(): Unit = { + if (configs == null) { + getConfigsSuite() + } + val sparkConfig = configs.sparkConfig + assert(sparkConfig.map.size == 3) + + val spark = SparkConfig.getSpark(configs) + assert(spark.partitionNum.toInt == 100) + } + + @Test + def getSourceSinkConfigSuite(): Unit = { + if (configs == null) { + getConfigsSuite() + } + val dataSourceSinkEntry = configs.dataSourceSinkEntry + assert(dataSourceSinkEntry.source.equals("csv")) + assert(dataSourceSinkEntry.sink.equals("nebula")) + assert(!dataSourceSinkEntry.hasWeight) + } + @Test + def getNebulaConfigSuite(): Unit = { + if (configs == null) { + getConfigsSuite() + } + val nebulaConfigEntry = configs.nebulaConfig + val writeConfig = nebulaConfigEntry.writeConfigEntry + assert(writeConfig.graphAddress.equals("127.0.0.1:9669")) + assert(writeConfig.metaAddress.equals("127.0.0.1:9559,127.0.0.1:9560")) + assert(writeConfig.space.equals("nb")) + assert(writeConfig.tag.equals("pagerank")) + assert(writeConfig.user.equals("root")) + assert(writeConfig.pswd.equals("nebula")) + + val readConfig = nebulaConfigEntry.readConfigEntry + assert(readConfig.address.equals("127.0.0.1:9559")) + assert(readConfig.space.equals("nb")) + assert(readConfig.labels.size == 1) + assert(readConfig.weightCols.size == 1) + } + + @Test + def getLocalConfigSuite(): Unit = { + if (configs == null) { + getConfigsSuite() + } + val localConfigEntry = configs.localConfigEntry + assert(localConfigEntry.filePath.startsWith("hdfs://")) + assert(localConfigEntry.srcId.equals("_c0")) + assert(localConfigEntry.dstId.equals("_c1")) + assert(localConfigEntry.weight == null) + assert(!localConfigEntry.header) + assert(localConfigEntry.delimiter.equals(",")) + assert(localConfigEntry.resultPath.equals("/tmp/")) + } + + @Test + def getAlgoConfigSuite(): Unit = { + if (configs == null) { + getConfigsSuite() + } + val algoConfig = configs.algorithmConfig + val algoName = AlgoConfig.getAlgoName(configs) + assert(algoName.equals("pagerank")) + + val prConfig = PRConfig.getPRConfig(configs) + assert(prConfig.maxIter == 10) + assert(prConfig.resetProb < 0.150000001) + + val louvainConfig = LouvainConfig.getLouvainConfig(configs) + assert(louvainConfig.maxIter == 20) + assert(louvainConfig.internalIter == 10) + assert(louvainConfig.tol < 0.5000001) + + val ccConfig = CcConfig.getCcConfig(configs) + assert(ccConfig.maxIter == 20) + + val lpaConfig = LPAConfig.getLPAConfig(configs) + assert(lpaConfig.maxIter == 20) + + val shortestPathConfig = ShortestPathConfig.getShortestPathConfig(configs) + assert(shortestPathConfig.landmarks.size == 1) + + val kcoreConfig = KCoreConfig.getKCoreConfig(configs) + assert(kcoreConfig.maxIter == 10) + assert(kcoreConfig.degree == 1) + + val betweennessConfig = BetweennessConfig.getBetweennessConfig(configs) + assert(betweennessConfig.maxIter == 5) + } +} diff --git a/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/data/MockNebulaData.scala b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/data/MockNebulaData.scala new file mode 100644 index 0000000..a71f04a --- /dev/null +++ b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/data/MockNebulaData.scala @@ -0,0 +1,9 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.data + +object MockNebulaData {} diff --git a/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/BetweennessAlgoSuite.scala b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/BetweennessAlgoSuite.scala new file mode 100644 index 0000000..210c24c --- /dev/null +++ b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/BetweennessAlgoSuite.scala @@ -0,0 +1,22 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.config.BetweennessConfig +import org.apache.spark.sql.SparkSession +import org.junit.Test + +class BetweennessAlgoSuite { + @Test + def betweennessAlgoSuite(): Unit = { + val spark = SparkSession.builder().master("local").getOrCreate() + val data = spark.read.option("header", true).csv("src/test/resources/edge.csv") + val betweennessConfig = new BetweennessConfig(5) + val result = BetweennessCentralityAlgo.apply(spark, data, betweennessConfig, false) + assert(result.count() == 4) + } +} diff --git a/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/CcAlgoSuite.scala b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/CcAlgoSuite.scala new file mode 100644 index 0000000..c513537 --- /dev/null +++ b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/CcAlgoSuite.scala @@ -0,0 +1,22 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.config.CcConfig +import org.apache.spark.sql.SparkSession +import org.junit.Test + +class CcAlgoSuite { + @Test + def ccAlgoSuite(): Unit = { + val spark = SparkSession.builder().master("local").getOrCreate() + val data = spark.read.option("header", true).csv("src/test/resources/edge.csv") + val ccAlgoConfig = new CcConfig(5) + val result = ConnectedComponentsAlgo.apply(spark, data, ccAlgoConfig, false) + assert(result.count() == 4) + } +} diff --git a/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/DegreeStaticAlgoSuite.scala b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/DegreeStaticAlgoSuite.scala new file mode 100644 index 0000000..4f68ff0 --- /dev/null +++ b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/DegreeStaticAlgoSuite.scala @@ -0,0 +1,25 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import org.apache.spark.sql.SparkSession +import org.junit.Test + +class DegreeStaticAlgoSuite { + @Test + def degreeStaticAlgoSuite(): Unit = { + val spark = SparkSession.builder().master("local").getOrCreate() + val data = spark.read.option("header", true).csv("src/test/resources/edge.csv") + val result = DegreeStaticAlgo.apply(spark, data) + assert(result.count() == 4) + result.foreach(row => { + assert(row.get(1).toString.toInt == 8) + assert(row.get(2).toString.toInt == 4) + assert(row.get(3).toString.toInt == 4) + }) + } +} diff --git a/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/KCoreAlgoSuite.scala b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/KCoreAlgoSuite.scala new file mode 100644 index 0000000..f70056a --- /dev/null +++ b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/KCoreAlgoSuite.scala @@ -0,0 +1,22 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.config.KCoreConfig +import org.apache.spark.sql.SparkSession +import org.junit.Test + +class KCoreAlgoSuite { + @Test + def kcoreSuite(): Unit = { + val spark = SparkSession.builder().master("local").getOrCreate() + val data = spark.read.option("header", true).csv("src/test/resources/edge.csv") + val kcoreConfig = new KCoreConfig(10, 3) + val kcoreResult = KCoreAlgo.apply(spark, data, kcoreConfig) + assert(kcoreResult.count() == 4) + } +} diff --git a/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/LabelPropagationAlgoSuite.scala b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/LabelPropagationAlgoSuite.scala new file mode 100644 index 0000000..7d226c5 --- /dev/null +++ b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/LabelPropagationAlgoSuite.scala @@ -0,0 +1,25 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.config.LPAConfig +import org.apache.spark.sql.SparkSession +import org.junit.Test + +class LabelPropagationAlgoSuite { + @Test + def lpaAlgoSuite(): Unit = { + val spark = SparkSession.builder().master("local").getOrCreate() + val data = spark.read.option("header", true).csv("src/test/resources/edge.csv") + val lpaConfig = new LPAConfig(5) + val result = LabelPropagationAlgo.apply(spark, data, lpaConfig, false) + assert(result.count() == 4) + result.foreach(row => { + assert(row.get(1).toString.toInt == 1) + }) + } +} diff --git a/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/LouvainAlgoSuite.scala b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/LouvainAlgoSuite.scala new file mode 100644 index 0000000..06aa3ed --- /dev/null +++ b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/LouvainAlgoSuite.scala @@ -0,0 +1,22 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.config.{ConfigSuite, Configs, LouvainConfig, SparkConfig} +import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession} +import org.junit.Test + +class LouvainAlgoSuite { + @Test + def louvainSuite(): Unit = { + val spark = SparkSession.builder().master("local").getOrCreate() + val data = spark.read.option("header", true).csv("src/test/resources/edge.csv") + val louvainConfig = new LouvainConfig(5, 2, 1.0) + val louvainResult = LouvainAlgo.apply(spark, data, louvainConfig, false) + assert(louvainResult.count() == 4) + } +} diff --git a/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/PageRankAlgoSuite.scala b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/PageRankAlgoSuite.scala new file mode 100644 index 0000000..f402931 --- /dev/null +++ b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/PageRankAlgoSuite.scala @@ -0,0 +1,22 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.config.{Configs, PRConfig, SparkConfig} +import org.apache.spark.sql.{DataFrame, SparkSession} +import org.junit.Test + +class PageRankAlgoSuite { + @Test + def pageRankSuite(): Unit = { + val spark = SparkSession.builder().master("local").getOrCreate() + val data = spark.read.option("header", true).csv("src/test/resources/edge.csv") + val prConfig = new PRConfig(5, 1.0) + val louvainResult = PageRankAlgo.apply(spark, data, prConfig, false) + assert(louvainResult.count() == 4) + } +} diff --git a/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/SCCAlgoSuite.scala b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/SCCAlgoSuite.scala new file mode 100644 index 0000000..65ea743 --- /dev/null +++ b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/SCCAlgoSuite.scala @@ -0,0 +1,22 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.config.CcConfig +import org.apache.spark.sql.SparkSession +import org.junit.Test + +class SCCAlgoSuite { + @Test + def sccAlgoSuite(): Unit = { + val spark = SparkSession.builder().master("local").getOrCreate() + val data = spark.read.option("header", true).csv("src/test/resources/edge.csv") + val sccConfig = new CcConfig(5) + val sccResult = StronglyConnectedComponentsAlgo.apply(spark, data, sccConfig, true) + assert(sccResult.count() == 4) + } +} diff --git a/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/ShortestPathAlgoSuite.scala b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/ShortestPathAlgoSuite.scala new file mode 100644 index 0000000..d980d4b --- /dev/null +++ b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/ShortestPathAlgoSuite.scala @@ -0,0 +1,22 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import com.vesoft.nebula.algorithm.config.ShortestPathConfig +import org.apache.spark.sql.SparkSession +import org.junit.Test + +class ShortestPathAlgoSuite { + @Test + def shortestPathAlgoSuite(): Unit = { + val spark = SparkSession.builder().master("local").getOrCreate() + val data = spark.read.option("header", true).csv("src/test/resources/edge.csv") + val shortestPathConfig = new ShortestPathConfig(Seq(1, 2)) + val result = ShortestPathAlgo.apply(spark, data, shortestPathConfig, false) + assert(result.count() == 4) + } +} diff --git a/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/TrangleCountSuite.scala b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/TrangleCountSuite.scala new file mode 100644 index 0000000..95e9fc6 --- /dev/null +++ b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib/TrangleCountSuite.scala @@ -0,0 +1,24 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.lib + +import org.apache.spark.sql.SparkSession +import org.junit.Test + +class TrangleCountSuite { + @Test + def trangleCountSuite(): Unit = { + val spark = SparkSession.builder().master("local").getOrCreate() + val data = spark.read.option("header", true).csv("src/test/resources/edge.csv") + val trangleCountResult = TriangleCountAlgo.apply(spark, data) + assert(trangleCountResult.count() == 4) + assert(trangleCountResult.first().get(1) == 3) + trangleCountResult.foreach(row => { + assert(row.get(1) == 3) + }) + } +} diff --git a/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/utils/NebulaUtilSuite.scala b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/utils/NebulaUtilSuite.scala new file mode 100644 index 0000000..ac87eed --- /dev/null +++ b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/utils/NebulaUtilSuite.scala @@ -0,0 +1,44 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package com.vesoft.nebula.algorithm.utils + +import org.junit.Test + +class NebulaUtilSuite { + + @Test + def validateWithWeight: Unit = { + val hostPorts: String = "127.0.0.1:45500" + val nameSpace: String = "nb" + val labels: List[String] = List("serve", "follow") + val hasWeight: Boolean = true + val weightCols: List[String] = List("start_year", "degree") + } + + @Test + def validateWithoutWeight: Unit = { + val hostPorts: String = "127.0.0.1:45500" + val nameSpace: String = "nb" + val labels: List[String] = List("serve") + val hasWeight: Boolean = false + val weightCols: List[String] = List() + } + + @Test + def getResultPathWithEnding: Unit = { + val path: String = "/tmp/" + val algorithmName: String = "aaa" + assert(NebulaUtil.getResultPath(path, algorithmName).equals("/tmp/aaa")) + } + + @Test + def getResultPathWithoutEnding: Unit = { + val path: String = "/tmp" + val algorithmName: String = "aaa" + assert(NebulaUtil.getResultPath(path, algorithmName).equals("/tmp/aaa")) + } +} diff --git a/pom.xml b/pom.xml index cdd9f83..1142c84 100644 --- a/pom.xml +++ b/pom.xml @@ -47,6 +47,7 @@ nebula-exchange nebula-spark-connector + nebula-algorithm example From b8eaafc535a21ec63176822ace92b180206d17bb Mon Sep 17 00:00:00 2001 From: cooper-lzy <78672629+cooper-lzy@users.noreply.github.com> Date: Thu, 6 May 2021 13:18:00 +0800 Subject: [PATCH 105/213] Update ex-ug-import-from-mysql.md --- .../CN/use-exchange/ex-ug-import-from-mysql.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-mysql.md b/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-mysql.md index 0ea4925..264e8a5 100644 --- a/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-mysql.md +++ b/nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-mysql.md @@ -13,25 +13,25 @@ mysql> desc player; +----------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+-------------+------+-----+---------+-------+ -| playerid | varchar(20) | YES | | NULL | | +| playerid | varchar(30) | YES | | NULL | | | age | int | YES | | NULL | | -| name | varchar(20) | YES | | NULL | | +| name | varchar(30) | YES | | NULL | | +----------+-------------+------+-----+---------+-------+ mysql> desc team; +--------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------+-------------+------+-----+---------+-------+ -| teamid | varchar(20) | YES | | NULL | | -| name | varchar(20) | YES | | NULL | | +| teamid | varchar(30) | YES | | NULL | | +| name | varchar(30) | YES | | NULL | | +--------+-------------+------+-----+---------+-------+ mysql> desc follow; +------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+-------+ -| src_player | varchar(20) | YES | | NULL | | -| dst_player | varchar(20) | YES | | NULL | | +| src_player | varchar(30) | YES | | NULL | | +| dst_player | varchar(30) | YES | | NULL | | | degree | int | YES | | NULL | | +------------+-------------+------+-----+---------+-------+ @@ -39,8 +39,8 @@ mysql> desc serve; +------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+-------+ -| playerid | varchar(20) | YES | | NULL | | -| teamid | varchar(20) | YES | | NULL | | +| playerid | varchar(30) | YES | | NULL | | +| teamid | varchar(30) | YES | | NULL | | | start_year | int | YES | | NULL | | | end_year | int | YES | | NULL | | +------------+-------------+------+-----+---------+-------+ @@ -345,4 +345,4 @@ GO FROM "player100" OVER follow; ### 步骤 5:(如有)在Nebula Graph中重建索引 -导入数据后,您可以在Nebula Graph中重新创建并重建索引。详情请参见[索引介绍](https://docs.nebula-graph.com.cn/2.0/3.ngql-guide/14.native-index-statements/)。 \ No newline at end of file +导入数据后,您可以在Nebula Graph中重新创建并重建索引。详情请参见[索引介绍](https://docs.nebula-graph.com.cn/2.0/3.ngql-guide/14.native-index-statements/)。 From bf771f83b94eae828e48ab9ebdf424d47f7dc148 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 6 May 2021 18:41:36 +0800 Subject: [PATCH 106/213] update metad port --- .../com/vesoft/nebula/algorithm/utils/NebulaUtilSuite.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/utils/NebulaUtilSuite.scala b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/utils/NebulaUtilSuite.scala index ac87eed..fc39ff5 100644 --- a/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/utils/NebulaUtilSuite.scala +++ b/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/utils/NebulaUtilSuite.scala @@ -12,7 +12,7 @@ class NebulaUtilSuite { @Test def validateWithWeight: Unit = { - val hostPorts: String = "127.0.0.1:45500" + val hostPorts: String = "127.0.0.1:9559" val nameSpace: String = "nb" val labels: List[String] = List("serve", "follow") val hasWeight: Boolean = true @@ -21,7 +21,7 @@ class NebulaUtilSuite { @Test def validateWithoutWeight: Unit = { - val hostPorts: String = "127.0.0.1:45500" + val hostPorts: String = "127.0.0.1:9559" val nameSpace: String = "nb" val labels: List[String] = List("serve") val hasWeight: Boolean = false From bf762e636cec81dd8d459f064c056e7b221585af Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 7 May 2021 11:55:06 +0800 Subject: [PATCH 107/213] fix datetime & escape for label and property name --- .../vesoft/nebula/connector/Template.scala | 2 +- .../com/vesoft/nebula/connector/package.scala | 7 +++--- .../connector/writer/NebulaExecutor.scala | 22 ++++++++++++++++++- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala index 1ef7f7d..ba8c28d 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala @@ -8,7 +8,7 @@ package com.vesoft.nebula.connector object NebulaTemplate { - private[connector] val BATCH_INSERT_TEMPLATE = "INSERT %s %s(%s) VALUES %s" + private[connector] val BATCH_INSERT_TEMPLATE = "INSERT %s `%s`(%s) VALUES %s" private[connector] val VERTEX_VALUE_TEMPLATE = "%s: (%s)" private[connector] val VERTEX_VALUE_TEMPLATE_WITH_POLICY = "%s(%s): (%s)" private[connector] val ENDPOINT_TEMPLATE = "%s(\"%s\")" diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala index 8974836..119cca7 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala @@ -6,9 +6,10 @@ package com.vesoft.nebula.connector +import com.vesoft.nebula.connector.writer.NebulaExecutor import org.apache.commons.codec.digest.MurmurHash2 import org.apache.spark.rdd.RDD -import org.apache.spark.sql.types.{LongType, StringType} +import org.apache.spark.sql.types.LongType import org.apache.spark.sql.{ DataFrame, DataFrameReader, @@ -47,7 +48,7 @@ package object connector { values: List[NebulaVertex], policy: Option[KeyPolicy.Value]) { - def propertyNames: String = propNames.mkString(",") + def propertyNames: String = NebulaExecutor.escapePropName(propNames).mkString(",") override def toString: String = { s"Vertices: " + @@ -72,7 +73,7 @@ package object connector { values: List[NebulaEdge], sourcePolicy: Option[KeyPolicy.Value], targetPolicy: Option[KeyPolicy.Value]) { - def propertyNames: String = propNames.mkString(",") + def propertyNames: String = NebulaExecutor.escapePropName(propNames).mkString(",") def getSourcePolicy = sourcePolicy def getTargetPolicy = targetPolicy diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala index 935eb50..04eb6d1 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala @@ -26,6 +26,8 @@ import com.vesoft.nebula.meta.PropertyType import org.apache.spark.sql.catalyst.InternalRow import org.apache.spark.sql.types.StructType +import scala.collection.mutable.ListBuffer + object NebulaExecutor { /** @@ -138,7 +140,7 @@ object NebulaExecutor { case PropertyType.STRING | PropertyType.FIXED_STRING => NebulaUtils.escapeUtil(propValue.toString).mkString("\"", "", "\"") case PropertyType.DATE => "date(\"" + propValue + "\")" - case PropertyType.DATETIME => "datatime(\"" + propValue + "\")" + case PropertyType.DATETIME => "datetime(\"" + propValue + "\")" case PropertyType.TIME => "time(\"" + propValue + "\")" case PropertyType.TIMESTAMP => { if (NebulaUtils.isNumic(propValue.toString)) { @@ -262,4 +264,22 @@ object NebulaExecutor { BATCH_INSERT_TEMPLATE.format(DataTypeEnum.EDGE.toString, edgeName, edges.propertyNames, values) } + /** + * escape nebula property name, add `` for each property. + * + * @param nebulaFields nebula property name list + * @return escaped nebula property name list + */ + def escapePropName(nebulaFields: List[String]): List[String] = { + val propNames: ListBuffer[String] = new ListBuffer[String] + for (key <- nebulaFields) { + val sb = new StringBuilder() + sb.append("`") + sb.append(key) + sb.append("`") + propNames.append(sb.toString()) + } + propNames.toList + } + } From 3f214ac3e27b80c61185e0bf545ee4c200bd3a40 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 20 Apr 2021 17:55:31 +0800 Subject: [PATCH 108/213] add ut for exchange --- .../src/test/resources/application.conf | 453 ++++++++++++++++++ .../src/test/resources/docker-compose.yaml | 338 +++++++++++++ .../vesoft/nebula/exchange/MockConfigs.scala | 58 --- .../nebula/exchange/MockGraphData.scala | 203 -------- .../nebula/exchange/MockQueryProcessor.scala | 61 --- .../nebula/exchange/MockQueryServer.java | 118 ----- .../nebula/exchange/NebulaGraphMock.scala | 138 ++++++ .../nebula/exchange/config/ConfigsSuite.scala | 240 ++++++++++ .../exchange/processor/ProcessorSuite.scala | 131 +++++ .../exchange/utils/NebulaUtilsSuite.scala | 165 +++++++ 10 files changed, 1465 insertions(+), 440 deletions(-) create mode 100644 nebula-exchange/src/test/resources/application.conf create mode 100644 nebula-exchange/src/test/resources/docker-compose.yaml delete mode 100644 nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockConfigs.scala delete mode 100644 nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockGraphData.scala delete mode 100644 nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockQueryProcessor.scala delete mode 100644 nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockQueryServer.java create mode 100644 nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala create mode 100644 nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala create mode 100644 nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/processor/ProcessorSuite.scala create mode 100644 nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala diff --git a/nebula-exchange/src/test/resources/application.conf b/nebula-exchange/src/test/resources/application.conf new file mode 100644 index 0000000..2964967 --- /dev/null +++ b/nebula-exchange/src/test/resources/application.conf @@ -0,0 +1,453 @@ +{ + # Spark relation config + spark: { + app: { + name: Nebula Exchange 2.0 + } + + master:local + + driver: { + cores: 1 + maxResultSize: 1G + } + + executor: { + memory:1G + } + + cores:{ + max: 16 + } + } + + # if the hive is hive-on-spark with derby mode, you can ignore this hive configure + # get the config values from file $HIVE_HOME/conf/hive-site.xml or hive-default.xml + + hive: { + warehouse: "hdfs://NAMENODE_IP:9000/apps/svr/hive-xxx/warehouse/" + connectionURL: "jdbc:mysql://your_ip:3306/hive_spark?characterEncoding=UTF-8" + connectionDriverName: "com.mysql.jdbc.Driver" + connectionUserName: "user" + connectionPassword: "password" + } + + # Nebula Graph relation config + nebula: { + address:{ + graph:["127.0.0.1:9669", "127.0.0.1:9670", "127.0.0.1:9671"] + meta:["127.0.0.1:9559", "127.0.0.1:9560", "127.0.0.1:9561"] + } + user: root + pswd: nebula + space: test + + # parameters for SST import, not required + path:{ + local:"/tmp" + remote:"/sst" + hdfs.namenode: "hdfs://name_node:9000" + } + + # nebula client connection parameters + connection { + timeout: 3000 + retry: 3 + } + + # nebula client execution parameters + execution { + retry: 3 + } + + error: { + # max number of failures, if the number of failures is bigger than max, then exit the application. + max: 32 + # failed import job will be recorded in output path + output: /tmp/errors + } + + # use google's RateLimiter to limit the requests send to NebulaGraph + rate: { + # the stable throughput of RateLimiter + limit: 1024 + # Acquires a permit from RateLimiter, unit: MILLISECONDS + # if it can't be obtained within the specified timeout, then give up the request. + timeout: 1000 + } + } + + # Processing tags + # There are tag config examples for different dataSources. + tags: [ + + # HDFS parquet + # Import mode is client, just change type.sink to sst if you want to use sst import mode. + { + name: tag0 + type: { + source: parquet + sink: client + } + path: path0 + fields: [parquet-field-0, parquet-field-1, parquet-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: { + field:parquet-field-0 + #policy:hash + } + batch: 256 + partition: 32 + } + + # HDFS csv + # Import mode is sst, just change type.sink to client if you want to use client import mode. + { + name: tag1 + type: { + source: csv + sink: sst + } + path: path1 + # if your csv file has no header, then use _c0,_c1,_c2,.. to indicate fields + fields: [csv-field-0, csv-field-1, csv-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: { + field:csv-field-0 + } + separator: "|" + header: true + batch: 256 + partition: 32 + } + + # HDFS json + { + name: tag2 + type: { + source: json + sink: client + } + path: path3 + fields: [json-field-0, json-field-1, json-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: { + field: json-field-0 + #policy: hash + } + batch: 256 + partition: 32 + } + + # Hive + { + name: tag3 + type: { + source: hive + sink: client + } + exec: "select hive-field0, hive-field1, hive-field2 from database.table" + fields: [hive-field-0, hive-field-1, hive-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: { + field: hive-field-0 + # policy: "hash" + } + batch: 256 + partition: 32 + } + + # neo4j + { + name: tag4 + type: { + source: neo4j + sink: client + } + server: "bolt://127.0.0.1:7687" + user: neo4j + password: neo4j + exec: "match (n:label) return n.neo4j-field-0 as neo4j-field-0, n.neo4j-field-1 as neo4j-field-1 order by (n.neo4j-field-0)" + fields: [neo4j-field-0, neo4j-field-1] + nebula.fields: [nebula-field-0, nebula-field-1] + vertex: { + field:neo4j-field-0 + # policy:hash + } + partition: 10 + batch: 1000 + check_point_path: /tmp/test + } + + # HBase + # if fields or vertex contains rowkey, please configure it as "rowkey". + { + name: tag5 + type: { + source: hbase + sink: client + } + host:127.0.0.1 + port:2181 + table:hbase-table + columnFamily:hbase-table-cloumnfamily + fields: [hbase-column-0, hbase-column-1] + nebula.fields: [nebula-field-0, nebula-field-1] + vertex: { + field:rowkey + } + partition: 10 + batch: 1000 + } + + # Pulsar + { + name: tag6 + type: { + source: pulsar + sink: client + } + service: "pulsar://localhost:6650" + admin: "http://localhost:8081" + options: { + # choose one of "topic", "topics", "topicsPattern" + topics: "topic1,topic2" + } + fields: [pulsar-field-0, pulsar-field-1, pulsar-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: { + field:pulsar-field-0 + } + partition: 10 + batch: 1000 + interval.seconds: 10 + } + + # KAFKA + { + name: tag7 + type: { + source: kafka + sink: client + } + service: "kafka.service.address" + topic: "topic-name" + fields: [kafka-field-0, kafka-field-1, kafka-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: { + field: kafka-field-0 + } + partition: 10 + batch: 10 + interval.seconds: 10 + } + + # MySql + { + name: tag8 + type: { + source: mysql + sink: client + } + user:root + host: "127.0.0.1" + port: "3306" + database: database + table:table + user:root + password:nebula + sentence: "select mysql-field0, mysql-field1, mysql-field2 from database.table" + fields: [mysql-field-0, mysql-field-1, mysql-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: { + field: mysql-field-0 + # policy: "hash" + } + batch: 256 + partition: 32 + } + ] + + # Processing edges + # There are edge config examples for different dataSources. + edges: [ + # HDFS parquet + # Import mode is client, just change type.sink to sst if you want to use sst import mode. + { + name: edge0 + type: { + source: parquet + sink: client + } + path: path0 + fields: [parquet-field-0, parquet-field-1, parquet-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: { + field:parquet-field-0 + #policy:hash + } + target: { + field:parquet-field-1 + #policy:hash + } + batch: 256 + partition: 32 + } + + # HDFS csv + { + name: edge1 + type: { + source: csv + sink: client + } + path: path1 + fields: [csv-field-0, csv-field-1, csv-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: { + field: csv-field-0 + #policy: hash + } + target: { + field: csv-field-1 + } + ranking: csv-field-2 + separator: "," + header: true + batch: 256 + partition: 32 + } + + # HDFS json + { + name: edge2 + type: { + source: json + sink: client + } + path: path2 + fields: [json-field-0, json-field-1, json-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: { + field: json-field-0 + #policy: hash + } + target: { + field: json-field-1 + } + ranking: json-field-2 + batch: 256 + partition: 32 + } + + # Hive + { + name: edge3 + type: { + source: hive + sink: client + } + exec: "select hive-field0, hive-field1, hive-field2 from database.table" + fields: [ hive-field-0, hive-field-1, hive-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: hive-field-0 + target: hive-field-1 + batch: 256 + partition: 32 + } + + # Neo4j + { + name: edge4 + type: { + source: neo4j + sink: client + } + server: "bolt://127.0.0.1:7687" + user: neo4j + password: neo4j + exec: "match (a:vertex_label)-[r:edge_label]->(b:vertex_label) return a.neo4j-source-field, b.neo4j-target-field, r.neo4j-field-0 as neo4j-field-0, r.neo4j-field-1 as neo4j-field-1 order by id(r)" + fields: [neo4j-field-0, neo4j-field-1] + nebula.fields: [nebula-field-0, nebula-field-1] + source: { + field: a.neo4j-source-field + } + target: { + field: b.neo4j-target-field + } + partition: 10 + batch: 1000 + check_point_path: /tmp/test + } + + # HBase + { + name: edge5 + type: { + source: hbase + sink: client + } + host:127.0.0.1 + port:2181 + table:hbase-table + columnFamily:hbase-table-cloumnfamily + fields: [hbase-column-0, hbase-column-1] + nebula.fields:[nebula-field-0, nebula-field-1] + source: { + field: hbase-column-k + } + target: { + field: hbase-column-h + } + partition: 10 + batch: 1000 + } + + + # Pulsar + { + name: edge6 + type: { + source: pulsar + sink: client + } + service: "pulsar://localhost:6650" + admin: "http://localhost:8081" + options: { + # choose one of "topic", "topics", "topicsPattern" + topic: "topic1" + } + fields: [pulsar-field-0, pulsar-field-1, pulsar-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: { + field: pulsar-field-0 + #policy: hash + } + target: { + field: pulsar-field-1 + } + ranking: pulsar-field-2 + partition: 10 + batch: 10 + interval.seconds: 10 + } + + # KAFKA + { + name: edge7 + type: { + source: kafka + sink: client + } + service: "kafka.service.address" + topic: "topic-name" + fields: [kafka-field-0, kafka-field-1, kafka-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + source: kafka-field-0 + target: kafka-field-1 + partition: 10 + batch: 1000 + interval.seconds: 10 + } + ] +} diff --git a/nebula-exchange/src/test/resources/docker-compose.yaml b/nebula-exchange/src/test/resources/docker-compose.yaml new file mode 100644 index 0000000..1f112e0 --- /dev/null +++ b/nebula-exchange/src/test/resources/docker-compose.yaml @@ -0,0 +1,338 @@ +version: '3.4' +services: + metad0: + image: vesoft/nebula-metad:v2-nightly + environment: + USER: root + TZ: "${TZ}" + command: + - --meta_server_addrs=172.28.1.1:9559,172.28.1.2:9559,172.28.1.3:9559 + - --local_ip=172.28.1.1 + - --ws_ip=172.28.1.1 + - --port=9559 + - --data_path=/data/meta + - --log_dir=/logs + - --v=0 + - --minloglevel=0 + - --heartbeat_interval_secs=2 + healthcheck: + test: ["CMD", "curl", "-f", "http://172.28.1.1:11000/status"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + ports: + - "9559:9559" + - 11000 + - 11002 + volumes: + - ./data/meta0:/data/meta:Z + - ./logs/meta0:/logs:Z + networks: + nebula-net: + ipv4_address: 172.28.1.1 + restart: on-failure + cap_add: + - SYS_PTRACE + + metad1: + image: vesoft/nebula-metad:v2-nightly + environment: + USER: root + TZ: "${TZ}" + command: + - --meta_server_addrs=172.28.1.1:9559,172.28.1.2:9559,172.28.1.3:9559 + - --local_ip=172.28.1.2 + - --ws_ip=172.28.1.2 + - --port=9559 + - --data_path=/data/meta + - --log_dir=/logs + - --v=0 + - --minloglevel=0 + - --heartbeat_interval_secs=2 + healthcheck: + test: ["CMD", "curl", "-f", "http://172.28.1.2:11000/status"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + ports: + - "9560:9559" + - 11000 + - 11002 + volumes: + - ./data/meta1:/data/meta:Z + - ./logs/meta1:/logs:Z + networks: + nebula-net: + ipv4_address: 172.28.1.2 + restart: on-failure + cap_add: + - SYS_PTRACE + + metad2: + image: vesoft/nebula-metad:v2-nightly + environment: + USER: root + TZ: "${TZ}" + command: + - --meta_server_addrs=172.28.1.1:9559,172.28.1.2:9559,172.28.1.3:9559 + - --local_ip=172.28.1.3 + - --ws_ip=172.28.1.3 + - --port=9559 + - --data_path=/data/meta + - --log_dir=/logs + - --v=0 + - --minloglevel=0 + - --heartbeat_interval_secs=2 + healthcheck: + test: ["CMD", "curl", "-f", "http://172.28.1.3:11000/status"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + ports: + - "9561:9559" + - 11000 + - 11002 + volumes: + - ./data/meta2:/data/meta:Z + - ./logs/meta2:/logs:Z + networks: + nebula-net: + ipv4_address: 172.28.1.3 + restart: on-failure + cap_add: + - SYS_PTRACE + + storaged0: + image: vesoft/nebula-storaged:v2-nightly + environment: + USER: root + TZ: "${TZ}" + command: + - --meta_server_addrs=172.28.1.1:9559,172.28.1.2:9559,172.28.1.3:9559 + - --local_ip=172.28.2.1 + - --ws_ip=172.28.2.1 + - --port=9779 + - --data_path=/data/storage + - --log_dir=/logs + - --v=0 + - --minloglevel=0 + - --heartbeat_interval_secs=2 + depends_on: + - metad0 + - metad1 + - metad2 + healthcheck: + test: ["CMD", "curl", "-f", "http://172.28.2.1:12000/status"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + ports: + - "9779:9779" + - 12000 + - 12002 + volumes: + - ./data/storage0:/data/storage:Z + - ./logs/storage0:/logs:Z + networks: + nebula-net: + ipv4_address: 172.28.2.1 + restart: on-failure + cap_add: + - SYS_PTRACE + + storaged1: + image: vesoft/nebula-storaged:v2-nightly + environment: + USER: root + TZ: "${TZ}" + command: + - --meta_server_addrs=172.28.1.1:9559,172.28.1.2:9559,172.28.1.3:9559 + - --local_ip=172.28.2.2 + - --ws_ip=172.28.2.2 + - --port=9779 + - --data_path=/data/storage + - --log_dir=/logs + - --v=0 + - --minloglevel=0 + - --heartbeat_interval_secs=2 + depends_on: + - metad0 + - metad1 + - metad2 + healthcheck: + test: ["CMD", "curl", "-f", "http://172.28.2.2:12000/status"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + ports: + - "9780:9779" + - 12000 + - 12002 + volumes: + - ./data/storage1:/data/storage:Z + - ./logs/storage1:/logs:Z + networks: + nebula-net: + ipv4_address: 172.28.2.2 + restart: on-failure + cap_add: + - SYS_PTRACE + + storaged2: + image: vesoft/nebula-storaged:v2-nightly + environment: + USER: root + TZ: "${TZ}" + command: + - --meta_server_addrs=172.28.1.1:9559,172.28.1.2:9559,172.28.1.3:9559 + - --local_ip=172.28.2.3 + - --ws_ip=172.28.2.3 + - --port=9779 + - --data_path=/data/storage + - --log_dir=/logs + - --v=0 + - --minloglevel=0 + - --heartbeat_interval_secs=2 + depends_on: + - metad0 + - metad1 + - metad2 + healthcheck: + test: ["CMD", "curl", "-f", "http://172.28.2.3:12000/status"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + ports: + - "9781:9779" + - 12000 + - 12002 + volumes: + - ./data/storage2:/data/storage:Z + - ./logs/storage2:/logs:Z + networks: + nebula-net: + ipv4_address: 172.28.2.3 + restart: on-failure + cap_add: + - SYS_PTRACE + + graphd0: + image: vesoft/nebula-graphd:v2-nightly + environment: + USER: root + TZ: "${TZ}" + command: + - --meta_server_addrs=172.28.1.1:9559,172.28.1.2:9559,172.28.1.3:9559 + - --port=9669 + - --ws_ip=172.28.3.1 + - --log_dir=/logs + - --v=0 + - --minloglevel=0 + - --heartbeat_interval_secs=2 + depends_on: + - metad0 + - metad1 + - metad2 + healthcheck: + test: ["CMD", "curl", "-f", "http://172.28.3.1:13000/status"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + ports: + - "9669:9669" + - 13000 + - 13002 + volumes: + - ./logs/graph0:/logs:Z + networks: + nebula-net: + ipv4_address: 172.28.3.1 + restart: on-failure + cap_add: + - SYS_PTRACE + + graphd1: + image: vesoft/nebula-graphd:v2-nightly + environment: + USER: root + TZ: "${TZ}" + command: + - --meta_server_addrs=172.28.1.1:9559,172.28.1.2:9559,172.28.1.3:9559 + - --port=9669 + - --ws_ip=172.28.3.2 + - --log_dir=/logs + - --v=0 + - --minloglevel=0 + - --heartbeat_interval_secs=2 + depends_on: + - metad0 + - metad1 + - metad2 + healthcheck: + test: ["CMD", "curl", "-f", "http://172.28.3.2:13000/status"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + ports: + - "9670:9669" + - 13000 + - 13002 + volumes: + - ./logs/graph1:/logs:Z + networks: + nebula-net: + ipv4_address: 172.28.3.2 + restart: on-failure + cap_add: + - SYS_PTRACE + + graphd2: + image: vesoft/nebula-graphd:v2-nightly + environment: + USER: root + TZ: "${TZ}" + command: + - --meta_server_addrs=172.28.1.1:9559,172.28.1.2:9559,172.28.1.3:9559 + - --port=9669 + - --ws_ip=172.28.3.3 + - --log_dir=/logs + - --v=0 + - --minloglevel=0 + - --heartbeat_interval_secs=2 + depends_on: + - metad0 + - metad1 + - metad2 + healthcheck: + test: ["CMD", "curl", "-f", "http://172.28.3.3:13000/status"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 20s + ports: + - "9671:9669" + - 13000 + - 13002 + volumes: + - ./logs/graph2:/logs:Z + networks: + nebula-net: + ipv4_address: 172.28.3.3 + restart: on-failure + cap_add: + - SYS_PTRACE + +networks: + nebula-net: + ipam: + driver: default + config: + - subnet: 172.28.0.0/16 \ No newline at end of file diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockConfigs.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockConfigs.scala deleted file mode 100644 index d5e789d..0000000 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockConfigs.scala +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 2020 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -package com.vesoft.nebula.exchange - -import com.vesoft.nebula.exchange.config.{ - Configs, - ConnectionConfigEntry, - DataBaseConfigEntry, - ErrorConfigEntry, - ExecutionConfigEntry, - RateConfigEntry, - SparkConfigEntry, - UserConfigEntry -} - -import scala.util.Random - -object MockConfigs { - - val port: Int = 9000 + Random.nextInt(1000) - val metaPort: Int = 9000 + Random.nextInt(1000) - - val dataBaseConfig: DataBaseConfigEntry = - DataBaseConfigEntry(List("127.0.0.1:" + port), "test", List("127.0.0.1" + metaPort)) - - val userConfig: UserConfigEntry = UserConfigEntry("user", "password") - - val connectionConfig: ConnectionConfigEntry = ConnectionConfigEntry(1000, 1) - - val executionConfig: ExecutionConfigEntry = ExecutionConfigEntry(1000, 1, 1) - - val errorConfig: ErrorConfigEntry = ErrorConfigEntry("/tmp/", 100) - - val rateConfig: RateConfigEntry = RateConfigEntry(100, 100) - - val sparkConfigEntry: SparkConfigEntry = SparkConfigEntry(Map[String, String]()) - - val tagsConfig = List(new MockGraphDataVertex().tagConfig) - - val edgesConfig = List(new MockGraphDataEdge().edgeConfig) - - val configs: Configs = Configs( - dataBaseConfig, - userConfig, - connectionConfig, - executionConfig, - errorConfig, - rateConfig, - sparkConfigEntry, - tagsConfig, - edgesConfig - ) - -} diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockGraphData.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockGraphData.scala deleted file mode 100644 index 2f58bde..0000000 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockGraphData.scala +++ /dev/null @@ -1,203 +0,0 @@ -/* Copyright (c) 2020 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -package com.vesoft.nebula.exchange - -import com.typesafe.config.impl.ConfigImpl.fromAnyRef -import com.vesoft.nebula.exchange.config._ -import org.apache.spark.sql.{DataFrame, SparkSession} - -object Spark { - private val master = "local[1]" - private val appName = "exchange_testing" - val sparkSession: SparkSession = - new SparkSession.Builder().appName(appName).master(master).getOrCreate() - sparkSession.sparkContext.setLogLevel("warn") -} - -object MockGraphData { - - import Spark.sparkSession.implicits._ - - private val numberVertex = 5 - private val numberEdgeDegree = 1 - - val policyList = List(Some(KeyPolicy.HASH), Some(KeyPolicy.UUID), None) - val dataSourceConfig: FileBaseSourceConfigEntry = - FileBaseSourceConfigEntry(SourceCategory.TEXT, "") - val dataSinkConfig: NebulaSinkConfigEntry = NebulaSinkConfigEntry(SinkCategory.CLIENT, List("")) - - private def genRow(id: Long) = (id, id.toString, id + 0.01, id % 2 == 0) - - val vertexTypeName = "tagA" - - val edgeTypeName = "edgeAA" - - val propertyFieldName = List("idInt", "idString", "tDouble", "tBoolean") - - val vertexFieldName: List[String] = propertyFieldName - - val edgeFieldName: List[String] = List("from.idInt", "to.idInt") ::: vertexFieldName - - val vertexIdFieldName = "idInt" - - val edgeRankFieldName = "idInt" - - val edgeFromFieldName = "from.idInt" - - val edgeToFieldName = "to.idInt" - - val vertexData: Seq[(Long, String, Double, Boolean)] = - Seq(for (ids <- Range(0, numberVertex)) yield genRow(ids)).flatMap(_.toList) - - val vertexDataIdString: Seq[(String, String, Double, Boolean)] = - vertexData.map(x => (x._1.toString, x._2, x._3, x._4)) - - val edgeData: Seq[(Long, Long, Long, String, Double, Boolean)] = { - val fromVertexId = Range(0, numberVertex).map(_.toLong).toList - var toVertexId = Range(0, numberVertex).map(_.toLong).toList - var id = numberVertex - for (_ <- Range(0, numberEdgeDegree)) yield { - toVertexId = toVertexId.last :: toVertexId.init - for (ids <- Range(0, numberVertex)) yield { - val property = genRow(id) - id += 1 - (fromVertexId(ids), toVertexId(ids), property._1, property._2, property._3, property._4) - } - } - }.flatMap(_.toList).toList - - private val edgeDataIdString00: Seq[(Long, Long, Long, String, Double, Boolean)] = edgeData - private val edgeDataIdString01: Seq[(Long, String, Long, String, Double, Boolean)] = - edgeData.map(x => (x._1, x._2.toString, x._3, x._4, x._5, x._6)) - private val edgeDataIdString10: Seq[(String, Long, Long, String, Double, Boolean)] = - edgeData.map(x => (x._1.toString, x._2, x._3, x._4, x._5, x._6)) - private val edgeDataIdString11: Seq[(String, String, Long, String, Double, Boolean)] = - edgeData.map(x => (x._1.toString, x._2.toString, x._3, x._4, x._5, x._6)) - - def vertexDataFrame: DataFrame = vertexData.toDF(vertexFieldName: _*) - - def vertexDataFrame(vertex: Option[KeyPolicy.Value]): DataFrame = - if (vertex.isEmpty) vertexDataFrame else vertexDataIdString.toDF(vertexFieldName: _*) - - def edgeDataFrame: DataFrame = edgeData.toDF(edgeFieldName: _*) - - def edgeDataFrame(source: Option[KeyPolicy.Value], target: Option[KeyPolicy.Value]): DataFrame = { - { - if (source.isEmpty) { - if (target.isEmpty) edgeDataIdString00.toDF() - else edgeDataIdString01.toDF() - } else { - if (target.isEmpty) edgeDataIdString10.toDF() - else edgeDataIdString11.toDF() - } - }.toDF(edgeFieldName: _*) - } - - private def getVertexIDTemplateFromKeyPolicy(keyPolicy: Option[KeyPolicy.Value]) = - keyPolicy match { - case Some(KeyPolicy.HASH) => "hash(\"%d\")" - case Some(KeyPolicy.UUID) => "uuid(\"%d\")" - case _ => "%d" - } - - def createInsertVertexSentence(vertexPolicy: Option[KeyPolicy.Value]): String = { - val vertexIdTemplate = getVertexIDTemplateFromKeyPolicy(vertexPolicy) - val s = if (vertexPolicy.isEmpty) "" else "\"" - - s"INSERT VERTEX ${vertexTypeName}(idInt,idString,tDouble,tBoolean) VALUES " + - s"${vertexIdTemplate.format(0)}: (${s}0${s}, ${'"'}0${'"'}, 0.01, true), " + - s"${vertexIdTemplate.format(1)}: (${s}1${s}, ${'"'}1${'"'}, 1.01, false), " + - s"${vertexIdTemplate.format(2)}: (${s}2${s}, ${'"'}2${'"'}, 2.01, true), " + - s"${vertexIdTemplate.format(3)}: (${s}3${s}, ${'"'}3${'"'}, 3.01, false), " + - s"${vertexIdTemplate.format(4)}: (${s}4${s}, ${'"'}4${'"'}, 4.01, true)" - } - - def createInsertEdgeSentence(fromVertexPolicy: Option[KeyPolicy.Value], - toVertexPolicy: Option[KeyPolicy.Value], - hasRank: Boolean): String = { - val from = getVertexIDTemplateFromKeyPolicy(fromVertexPolicy) - val to = getVertexIDTemplateFromKeyPolicy(toVertexPolicy) - val rankList = for (i <- Range(5, 10)) yield if (hasRank) s"@${i}" else "" - - s"INSERT EDGE ${edgeTypeName}(idInt,idString,tDouble,tBoolean) VALUES " + - s"${from.format(0)}->${to.format(4)}${rankList(0)}: (5, ${'"'}5${'"'}, 5.01, false), " + - s"${from.format(1)}->${to.format(0)}${rankList(1)}: (6, ${'"'}6${'"'}, 6.01, true), " + - s"${from.format(2)}->${to.format(1)}${rankList(2)}: (7, ${'"'}7${'"'}, 7.01, false), " + - s"${from.format(3)}->${to.format(2)}${rankList(3)}: (8, ${'"'}8${'"'}, 8.01, true), " + - s"${from.format(4)}->${to.format(3)}${rankList(4)}: (9, ${'"'}9${'"'}, 9.01, false)" - } -} - -class MockGraphDataVertex(vertexPolicy: Option[KeyPolicy.Value] = None) { - - val vertexDataFrame: DataFrame = MockGraphData.vertexDataFrame(vertexPolicy) - val tagConfig: TagConfigEntry = { - val fields = MockGraphData.propertyFieldName - .map(property => { - (property, fromAnyRef(property, "")) - }) - .toMap - - // TODO fields - TagConfigEntry( - MockGraphData.vertexTypeName, - MockGraphData.dataSourceConfig, - MockGraphData.dataSinkConfig, - Nil, - Nil, - MockGraphData.vertexIdFieldName, - vertexPolicy, - MockGraphData.vertexData.size, - 1, - None - ) - } - - val insertVertexSentence: String = MockGraphData.createInsertVertexSentence(vertexPolicy) - -} - -class MockGraphDataEdge(edgeSourcePolicy: Option[KeyPolicy.Value] = None, - edgeTargetPolicy: Option[KeyPolicy.Value] = None, - rank: Boolean = false) { - - val edgeDataFrame: DataFrame = - MockGraphData.edgeDataFrame(edgeSourcePolicy, edgeTargetPolicy) - - val edgeConfig: EdgeConfigEntry = { - val fields = MockGraphData.propertyFieldName - .map(property => { - (property, fromAnyRef(property, "")) - }) - .toMap - val rankingField = if (rank) Some(MockGraphData.edgeRankFieldName) else None - - // TODO fields - EdgeConfigEntry( - MockGraphData.edgeTypeName, - MockGraphData.dataSourceConfig, - MockGraphData.dataSinkConfig, - Nil, - Nil, - MockGraphData.edgeFromFieldName, - edgeSourcePolicy, - rankingField, - MockGraphData.edgeToFieldName, - edgeTargetPolicy, - isGeo = false, - None, - None, - MockGraphData.edgeData.size, - 1, - None - ) - } - - val insertEdgeSentence: String = - MockGraphData.createInsertEdgeSentence(edgeSourcePolicy, edgeTargetPolicy, rank) - -} diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockQueryProcessor.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockQueryProcessor.scala deleted file mode 100644 index 50f4b29..0000000 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockQueryProcessor.scala +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (c) 2020 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -package com.vesoft.nebula.exchange - -import com.vesoft.nebula.graph.{AuthResponse, ErrorCode, ExecutionResponse, GraphService} -import org.apache.log4j.Logger - -class MockQueryProcessor extends GraphService.Iface { - private[this] val LOG = Logger.getLogger(this.getClass) - - var queryStatement: Array[Byte] = null - var countDownLatchFailOfInsert: Int = -1 - var countDownLatchFailOfSentence: Int = -1 - - def resetLatch(): Unit = { - resetLatchInsert() - resetLatchSentence() - } - - def resetLatchInsert(): Unit = countDownLatchFailOfInsert = -1 - def resetLatchSentence(): Unit = countDownLatchFailOfSentence = -1 - - override def authenticate(username: Array[Byte], password: Array[Byte]): AuthResponse = { - LOG.info(s"Get login user: ${username}, password: ${password}") - if (MockConfigs.userConfig.user == username && MockConfigs.userConfig.password == password) - new AuthResponse(ErrorCode.SUCCEEDED, "SUCCEEDED".getBytes(), 1) - else - new AuthResponse(ErrorCode.E_BAD_USERNAME_PASSWORD, "BAD USERNAME OR PASSWORD".getBytes(), 1) - } - override def signout(sessionId: Long): Unit = {} - override def execute(sessionId: Long, stmt: Array[Byte]): ExecutionResponse = { - queryStatement = stmt - if (queryStatement.contains("INSERT")) { - if (countDownLatchFailOfInsert == 0) { - LOG.info(s"mock server got statement: ${queryStatement}, return error") - new ExecutionResponse(ErrorCode.E_SYNTAX_ERROR, 1) - } else { - if (countDownLatchFailOfInsert > 0) - countDownLatchFailOfInsert -= 1 - LOG.info(s"mock server got statement: ${queryStatement}, return success") - new ExecutionResponse(ErrorCode.SUCCEEDED, 1); - } - } else { - if (countDownLatchFailOfSentence == 0) { - LOG.info(s"mock server got statement: ${queryStatement}, return error") - new ExecutionResponse(ErrorCode.E_SYNTAX_ERROR, 1) - } else { - if (countDownLatchFailOfSentence > 0) - countDownLatchFailOfSentence -= 1 - LOG.info(s"mock server got statement: ${queryStatement}, return success") - new ExecutionResponse(ErrorCode.SUCCEEDED, 1); - } - } - } - - override def executeJson(sessionId: Long, stmt: Array[Byte]): Array[Byte] = ??? -} diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockQueryServer.java b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockQueryServer.java deleted file mode 100644 index bc3305b..0000000 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/MockQueryServer.java +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright (c) 2020 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -package com.vesoft.nebula.exchange; - -import com.facebook.thrift.TProcessor; -import com.facebook.thrift.TProcessorFactory; -import com.facebook.thrift.protocol.TProtocol; -import com.facebook.thrift.server.TRpcConnectionContext; -import com.facebook.thrift.server.TServer; -import com.facebook.thrift.transport.TFramedTransport; -import com.facebook.thrift.transport.TServerSocket; -import com.facebook.thrift.transport.TTransport; -import com.facebook.thrift.transport.TTransportException; -import com.vesoft.nebula.graph.GraphService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -public class MockQueryServer extends Thread { - private static final Logger LOGGER = LoggerFactory.getLogger(MockQueryServer.class); - private final TServer server; - - public MockQueryServer(GraphService.Iface mockProcessor, final int port) { - TProcessor processor = new GraphService.Processor(mockProcessor); - TProcessorFactory factory = new TProcessorFactory(processor); - TServerSocket serverSocket = null; - - try { - serverSocket = new TServerSocket(port); - } catch (TTransportException e) { - e.printStackTrace(); - } - - server = new TServer(factory, serverSocket, new TFramedTransport.Factory(10000000)) { - public void serve() { - LOGGER.info("TServer start " + port); - try { - serverTransport_.listen(); - } catch (TTransportException ttx) { - LOGGER.error("Error occurred during listening.", ttx); - return; - } - - TTransport client = null; - TProcessor processor; - TTransport inputTransport = null; - TTransport outputTransport = null; - TProtocol inputProtocol; - TProtocol outputProtocol; - while (true) { - try { - client = serverTransport_.accept(); - if (client != null) { - processor = processorFactory_.getProcessor(client); - - inputTransport = inputTransportFactory_.getTransport(client); - inputProtocol = inputProtocolFactory_.getProtocol(inputTransport); - outputTransport = outputTransportFactory_.getTransport(client); - outputProtocol = outputProtocolFactory_.getProtocol(outputTransport); - - TRpcConnectionContext serverCtx = new TRpcConnectionContext(client, - inputProtocol, outputProtocol); - try { - while (processor.process(inputProtocol, outputProtocol, serverCtx)) - ; - } catch (TTransportException e) { - } - } - } catch (Exception x) { - LOGGER.error("Error occurred during processing of message.", x); - } finally { - if (client != null) { - client.close(); - } - - if (inputTransport != null) { - inputTransport.close(); - } - - if (outputTransport != null) { - outputTransport.close(); - } - } - } - } - }; - } - - public void run() { - startServer(); - } - - public void startServer() { - server.serve(); - synchronized (server) { - server.notify(); - } - } - - public void waitUntilStarted() { - synchronized (server) { - try { - server.wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } - - public void stopServer() { - server.stop(); - this.stop(); - } -} diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala new file mode 100644 index 0000000..fc072c2 --- /dev/null +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala @@ -0,0 +1,138 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package scala.com.vesoft.nebula.exchange + +import com.vesoft.nebula.client.graph.NebulaPoolConfig +import com.vesoft.nebula.client.graph.data.HostAddress +import com.vesoft.nebula.client.graph.net.NebulaPool + +import scala.collection.JavaConverters._ +import scala.collection.mutable.ListBuffer + +class NebulaGraphMock { + + @transient val nebulaPoolConfig = new NebulaPoolConfig + @transient val pool: NebulaPool = new NebulaPool + val address = new ListBuffer[HostAddress]() + address.append(new HostAddress("127.0.0.1", 9669)) + + val randAddr = scala.util.Random.shuffle(address) + pool.init(randAddr.asJava, nebulaPoolConfig) + + def mockStringIdGraph(): Unit = { + val session = pool.getSession("root", "nebula", true) + + val createSpace = "CREATE SPACE IF NOT EXISTS testSST1(partition_num=10);" + + "USE testSST1;" + "CREATE TAG IF NOT EXISTS person(col1 string, col2 fixed_string(8), col3 int8, col4 int16, col5 int32, col6 int64, col7 date, col8 datetime, col9 timestamp, col10 bool, col11 double, col12 float, col13 time);" + + "CREATE EDGE IF NOT EXISTS friend(col1 string, col2 fixed_string(8), col3 int8, col4 int16, col5 int32, col6 int64, col7 date, col8 datetime, col9 timestamp, col10 bool, col11 double, col12 float, col13 time);"; + val createResp = session.execute(createSpace) + if (!createResp.isSucceeded) { + close() + sys.exit(-1) + } + + Thread.sleep(3000) + val insertTag = + "INSERT VERTEX person(col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13) VALUES " + + " \"1\":(\"person1\", \"person1\", 11, 200, 1000, 188888, date(\"2021-01-01\"), datetime(\"2021-01-01T12:00:00\"),timestamp(\"2021-01-01T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"2\":(\"person2\", \"person2\", 12, 300, 2000, 288888, date(\"2021-01-02\"), datetime(\"2021-01-02T12:00:00\"),timestamp(\"2021-01-02T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " \"3\":(\"person3\", \"person3\", 13, 400, 3000, 388888, date(\"2021-01-03\"), datetime(\"2021-01-03T12:00:00\"),timestamp(\"2021-01-03T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " \"4\":(\"person4\", \"person4\", 14, 500, 4000, 488888, date(\"2021-01-04\"), datetime(\"2021-01-04T12:00:00\"),timestamp(\"2021-01-04T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"5\":(\"person5\", \"person5\", 15, 600, 5000, 588888, date(\"2021-01-05\"), datetime(\"2021-01-05T12:00:00\"),timestamp(\"2021-01-05T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"6\":(\"person6\", \"person6\", 16, 700, 6000, 688888, date(\"2021-01-06\"), datetime(\"2021-01-06T12:00:00\"),timestamp(\"2021-01-06T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " \"7\":(\"person7\", \"person7\", 17, 800, 7000, 788888, date(\"2021-01-07\"), datetime(\"2021-01-07T12:00:00\"),timestamp(\"2021-01-07T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"8\":(\"person8\", \"person8\", 18, 900, 8000, 888888, date(\"2021-01-08\"), datetime(\"2021-01-08T12:00:00\"),timestamp(\"2021-01-08T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"9\":(\"person9\", \"person9\", 19, 1000, 9000, 988888, date(\"2021-01-09\"), datetime(\"2021-01-09T12:00:00\"),timestamp(\"2021-01-09T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " \"10\":(\"person10\", \"person10\", 20, 1100, 10000, 1088888, date(\"2021-01-10\"), datetime(\"2021-01-10T12:00:00\"),timestamp(\"2021-01-10T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"11\":(\"person11\", \"person11\", 21, 1200, 11000, 1188888, date(\"2021-01-11\"), datetime(\"2021-01-11T12:00:00\"),timestamp(\"2021-01-11T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " \"12\":(\"person12\", \"person11\", 22, 1300, 12000, 1288888, date(\"2021-01-12\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"-1\":(\"person21\", \"person21\", 23, 1400, 13000, 1388888, date(\"2021-01-13\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"-1\":(\"person22\", \"person22\", 24, 1500, 14000, 1488888, date(\"2021-01-14\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))" + val insertTagResp = session.execute(insertTag) + if (!insertTagResp.isSucceeded) { + close() + sys.exit(-1) + } + + val insertEdge = "INSERT EDGE friend(col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13) VALUES " + + " \"1\" -> \"2\":(\"friend1\", \"friend2\", 11, 200, 1000, 188888, date(\"2021-01-01\"), datetime(\"2021-01-01T12:00:00\"),timestamp(\"2021-01-01T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"2\" -> \"3\":(\"friend2\", \"friend3\", 12, 300, 2000, 288888, date(\"2021-01-02\"), datetime(\"2021-01-02T12:00:00\"),timestamp(\"2021-01-02T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " \"3\" -> \"4\":(\"friend3\", \"friend4\", 13, 400, 3000, 388888, date(\"2021-01-03\"), datetime(\"2021-01-03T12:00:00\"),timestamp(\"2021-01-03T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " \"4\" -> \"5\":(\"friend4\", \"friend4\", 14, 500, 4000, 488888, date(\"2021-01-04\"), datetime(\"2021-01-04T12:00:00\"),timestamp(\"2021-01-04T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"5\" -> \"6\":(\"friend5\", \"friend5\", 15, 600, 5000, 588888, date(\"2021-01-05\"), datetime(\"2021-01-05T12:00:00\"),timestamp(\"2021-01-05T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"6\" -> \"7\":(\"friend6\", \"friend6\", 16, 700, 6000, 688888, date(\"2021-01-06\"), datetime(\"2021-01-06T12:00:00\"),timestamp(\"2021-01-06T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " \"7\" -> \"8\":(\"friend7\", \"friend7\", 17, 800, 7000, 788888, date(\"2021-01-07\"), datetime(\"2021-01-07T12:00:00\"),timestamp(\"2021-01-07T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"8\" -> \"9\":(\"friend8\", \"friend8\", 18, 900, 8000, 888888, date(\"2021-01-08\"), datetime(\"2021-01-08T12:00:00\"),timestamp(\"2021-01-08T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"9\" -> \"10\":(\"friend9\", \"friend9\", 19, 1000, 9000, 988888, date(\"2021-01-09\"), datetime(\"2021-01-09T12:00:00\"),timestamp(\"2021-01-09T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " \"10\" -> \"11\":(\"friend10\", \"friend10\", 20, 1100, 10000, 1088888, date(\"2021-01-10\"), datetime(\"2021-01-10T12:00:00\"),timestamp(\"2021-01-10T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"11\" -> \"12\":(\"friend11\", \"friend11\", 21, 1200, 11000, 1188888, date(\"2021-01-11\"), datetime(\"2021-01-11T12:00:00\"),timestamp(\"2021-01-11T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " \"12\" -> \"1\":(\"friend12\", \"friend11\", 22, 1300, 12000, 1288888, date(\"2021-01-12\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"-1\" -> \"11\":(\"friend13\", \"friend12\", 22, 1300, 12000, 1288888, date(\"2021-01-12\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"-2\" -> \"-1\":(\"friend14\", \"friend13\", 22, 1300, 12000, 1288888, date(\"2021-01-12\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))" + val insertEdgeResp = session.execute(insertEdge) + if (!insertEdgeResp.isSucceeded) { + close() + sys.exit(-1) + } + } + + def mockIntIdGraph(): Unit = { + val session = pool.getSession("root", "nebula", true) + + val createSpace = "CREATE SPACE IF NOT EXISTS testSST2(partition_num=10, vid_type=int64);" + + "USE testSST2;" + "CREATE TAG IF NOT EXISTS person(col1 string, col2 fixed_string(8), col3 int8, col4 int16, col5 int32, col6 int64, col7 date, col8 datetime, col9 timestamp, col10 bool, col11 double, col12 float, col13 time);" + + "CREATE EDGE IF NOT EXISTS friend(col1 string, col2 fixed_string(8), col3 int8, col4 int16, col5 int32, col6 int64, col7 date, col8 datetime, col9 timestamp, col10 bool, col11 double, col12 float, col13 time);"; + val createResp = session.execute(createSpace) + if (!createResp.isSucceeded) { + close() + sys.exit(-1) + } + + val insertTag = + "INSERT VERTEX person(col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13) VALUES " + + " 1:(\"person1\", \"person1\", 11, 200, 1000, 188888, date(\"2021-01-01\"), datetime(\"2021-01-01T12:00:00\"),timestamp(\"2021-01-01T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " 2:(\"person2\", \"person2\", 12, 300, 2000, 288888, date(\"2021-01-02\"), datetime(\"2021-01-02T12:00:00\"),timestamp(\"2021-01-02T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " 3:(\"person3\", \"person3\", 13, 400, 3000, 388888, date(\"2021-01-03\"), datetime(\"2021-01-03T12:00:00\"),timestamp(\"2021-01-03T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " 4:(\"person4\", \"person4\", 14, 500, 4000, 488888, date(\"2021-01-04\"), datetime(\"2021-01-04T12:00:00\"),timestamp(\"2021-01-04T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " 5:(\"person5\", \"person5\", 15, 600, 5000, 588888, date(\"2021-01-05\"), datetime(\"2021-01-05T12:00:00\"),timestamp(\"2021-01-05T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " 6:(\"person6\", \"person6\", 16, 700, 6000, 688888, date(\"2021-01-06\"), datetime(\"2021-01-06T12:00:00\"),timestamp(\"2021-01-06T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " 7:(\"person7\", \"person7\", 17, 800, 7000, 788888, date(\"2021-01-07\"), datetime(\"2021-01-07T12:00:00\"),timestamp(\"2021-01-07T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " 8:(\"person8\", \"person8\", 18, 900, 8000, 888888, date(\"2021-01-08\"), datetime(\"2021-01-08T12:00:00\"),timestamp(\"2021-01-08T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " 9:(\"person9\", \"person9\", 19, 1000, 9000, 988888, date(\"2021-01-09\"), datetime(\"2021-01-09T12:00:00\"),timestamp(\"2021-01-09T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " 10:(\"person10\", \"person10\", 20, 1100, 10000, 1088888, date(\"2021-01-10\"), datetime(\"2021-01-10T12:00:00\"),timestamp(\"2021-01-10T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " 11:(\"person11\", \"person11\", 21, 1200, 11000, 1188888, date(\"2021-01-11\"), datetime(\"2021-01-11T12:00:00\"),timestamp(\"2021-01-11T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " 12:(\"person12\", \"person11\", 22, 1300, 12000, 1288888, date(\"2021-01-12\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))" + val insertTagResp = session.execute(insertTag) + if (!insertTagResp.isSucceeded) { + close() + sys.exit(-1) + } + + val insertEdge = "INSERT EDGE friend(col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13) VALUES " + + " 1 -> 2:(\"friend1\", \"friend2\", 11, 200, 1000, 188888, date(\"2021-01-01\"), datetime(\"2021-01-01T12:00:00\"),timestamp(\"2021-01-01T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " 2 -> 3:(\"friend2\", \"friend3\", 12, 300, 2000, 288888, date(\"2021-01-02\"), datetime(\"2021-01-02T12:00:00\"),timestamp(\"2021-01-02T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " 3 -> 4:(\"friend3\", \"friend4\", 13, 400, 3000, 388888, date(\"2021-01-03\"), datetime(\"2021-01-03T12:00:00\"),timestamp(\"2021-01-03T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " 4 -> 5:(\"friend4\", \"friend4\", 14, 500, 4000, 488888, date(\"2021-01-04\"), datetime(\"2021-01-04T12:00:00\"),timestamp(\"2021-01-04T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " 5 -> 6:(\"friend5\", \"friend5\", 15, 600, 5000, 588888, date(\"2021-01-05\"), datetime(\"2021-01-05T12:00:00\"),timestamp(\"2021-01-05T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " 6 -> 7:(\"friend6\", \"friend6\", 16, 700, 6000, 688888, date(\"2021-01-06\"), datetime(\"2021-01-06T12:00:00\"),timestamp(\"2021-01-06T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " 7 -> 8:(\"friend7\", \"friend7\", 17, 800, 7000, 788888, date(\"2021-01-07\"), datetime(\"2021-01-07T12:00:00\"),timestamp(\"2021-01-07T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " 8 -> 9:(\"friend8\", \"friend8\", 18, 900, 8000, 888888, date(\"2021-01-08\"), datetime(\"2021-01-08T12:00:00\"),timestamp(\"2021-01-08T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " 9 -> 10:(\"friend9\", \"friend9\", 19, 1000, 9000, 988888, date(\"2021-01-09\"), datetime(\"2021-01-09T12:00:00\"),timestamp(\"2021-01-09T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " 10 -> 11:(\"friend10\", \"friend10\", 20, 1100, 10000, 1088888, date(\"2021-01-10\"), datetime(\"2021-01-10T12:00:00\"),timestamp(\"2021-01-10T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " 11 -> 12:(\"friend11\", \"friend11\", 21, 1200, 11000, 1188888, date(\"2021-01-11\"), datetime(\"2021-01-11T12:00:00\"),timestamp(\"2021-01-11T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + + " 12 -> 1:(\"friend12\", \"friend11\", 22, 1300, 12000, 1288888, date(\"2021-01-12\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))" + val insertEdgeResp = session.execute(insertEdge) + if (!insertEdgeResp.isSucceeded) { + close() + sys.exit(-1) + } + } + + def close(): Unit = { + pool.close() + } +} diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala new file mode 100644 index 0000000..6fe0595 --- /dev/null +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala @@ -0,0 +1,240 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package scala.com.vesoft.nebula.exchange.config + +import java.io.File + +import com.vesoft.nebula.exchange.config.{ + Configs, + FileBaseSourceConfigEntry, + FileDataSourceConfigEntry, + HBaseSourceConfigEntry, + HiveSourceConfigEntry, + MySQLSourceConfigEntry, + Neo4JSourceConfigEntry, + SinkCategory, + SourceCategory +} +import com.vesoft.nebula.exchange.{Argument, KeyPolicy} +import org.junit.Test + +class ConfigsSuite { + @Test + def configsSuite(): Unit = { + val args = List("-c", "src/test/resources/application.conf", "-h", "-d") + val options = Configs.parser(args.toArray, "test") + val c: Argument = options match { + case Some(config) => config + case _ => + assert(false) + sys.exit(-1) + } + assert(c.hive) + assert(c.directly) + + val configs = Configs.parse(new File(c.config)) + val dataBaseConfigEntry = configs.databaseConfig + val userConfig = configs.userConfig + val connectionConfig = configs.connectionConfig + val executionConfig = configs.executionConfig + val errorConfig = configs.errorConfig + val rateConfig = configs.rateConfig + val tagsConfig = configs.tagsConfig + val edgesConfig = configs.edgesConfig + val hiveConfigEntry = configs.hiveConfigEntry + + assert(dataBaseConfigEntry.graphAddress.size == 3) + assert(dataBaseConfigEntry.metaAddresses.size == 3) + assert(dataBaseConfigEntry.space.equals("test")) + + assert(userConfig.user.equals("root")) + assert(userConfig.password.equals("nebula")) + + assert(connectionConfig.retry == 3) + assert(connectionConfig.timeout == 3000) + + assert(executionConfig.retry == 3) + assert(executionConfig.interval == 3000) + assert(executionConfig.timeout == 3000) + + assert(errorConfig.errorMaxSize == 32) + assert(errorConfig.errorPath.equals("/tmp/errors")) + + assert(rateConfig.limit == 1024) + assert(rateConfig.timeout == 1000) + + if (hiveConfigEntry.get != null) { + assert(hiveConfigEntry.get.connectionDriverName.equals("com.mysql.jdbc.Driver")) + assert(hiveConfigEntry.get.connectionPassWord.equals("password")) + assert( + hiveConfigEntry.get.connectionURL + .equals("jdbc:mysql://your_ip:3306/hive_spark?characterEncoding=UTF-8")) + assert(hiveConfigEntry.get.connectionUserName.equals("user")) + assert( + hiveConfigEntry.get.warehouse + .equals("hdfs://NAMENODE_IP:9000/apps/svr/hive-xxx/warehouse/")) + } + + for (tagConfig <- tagsConfig) { + val source = tagConfig.dataSourceConfigEntry + val sink = tagConfig.dataSinkConfigEntry + assert(sink.category == SinkCategory.CLIENT || sink.category == SinkCategory.SST) + + val label = tagConfig.name + val batch = tagConfig.batch + val partition = tagConfig.partition + + val vertexField = tagConfig.vertexField + val policy = tagConfig.vertexPolicy + if (policy.isDefined) { + assert(policy.get == KeyPolicy.UUID || policy.get == KeyPolicy.HASH) + } + + val nebulaFields = tagConfig.nebulaFields + val fields = tagConfig.fields + assert(nebulaFields.size == fields.size) + + source.category match { + case SourceCategory.CSV => { + val csv = tagConfig.dataSourceConfigEntry.asInstanceOf[FileBaseSourceConfigEntry] + assert(label.equals("tag1")) + assert(csv.header.get) + assert(csv.separator.get.equals("|")) + assert(csv.path.equals("path1")) + } + case SourceCategory.JSON => { + val json = tagConfig.dataSourceConfigEntry.asInstanceOf[FileDataSourceConfigEntry] + assert(label.equals("tag2")) + assert(json.path.equals("path3")) + } + case SourceCategory.PARQUET => { + val parquet = tagConfig.dataSourceConfigEntry.asInstanceOf[FileDataSourceConfigEntry] + assert(label.equals("tag0")) + assert(parquet.path.equals("path0")) + } + case SourceCategory.HIVE => { + val hive = tagConfig.dataSourceConfigEntry.asInstanceOf[HiveSourceConfigEntry] + assert(label.equals("tag3")) + assert( + hive.sentence.equals( + "select hive-field0, hive-field1, hive-field2 from database.table")) + } + case SourceCategory.NEO4J => { + val neo4j = tagConfig.dataSourceConfigEntry.asInstanceOf[Neo4JSourceConfigEntry] + assert(label.equals("tag4")) + assert(!neo4j.database.isDefined) + assert(neo4j.server.equals("bolt://127.0.0.1:7687")) + assert(neo4j.user.equals("neo4j")) + assert(neo4j.password.equals("neo4j")) + assert(neo4j.sentence.equals( + "match (n:label) return n.neo4j-field-0 as neo4j-field-0, n.neo4j-field-1 as neo4j-field-1 order by (n.neo4j-field-0)")) + } + case SourceCategory.HBASE => { + val hbase = tagConfig.dataSourceConfigEntry.asInstanceOf[HBaseSourceConfigEntry] + assert(label.equals("tag5")) + assert(hbase.columnFamily.equals("hbase-table-cloumnfamily")) + assert(hbase.host.equals("127.0.0.1")) + assert(hbase.port.equals("2181")) + } + case SourceCategory.MYSQL => { + val mysql = tagConfig.dataSourceConfigEntry.asInstanceOf[MySQLSourceConfigEntry] + assert(label.equals("tag8")) + assert(mysql.database.equals("database")) + assert(mysql.host.equals("127.0.0.1")) + assert(mysql.port == 3306) + assert(mysql.user.equals("root")) + assert(mysql.password.equals("nebula")) + assert(mysql.database.equals("database")) + assert(mysql.table.equals("table")) + } + case _ => {} + } + } + + for (edgeConfig <- edgesConfig) { + val source = edgeConfig.dataSourceConfigEntry + val sink = edgeConfig.dataSinkConfigEntry + assert(sink.category == SinkCategory.CLIENT || sink.category == SinkCategory.SST) + + val label = edgeConfig.name + val batch = edgeConfig.batch + val partition = edgeConfig.partition + + val sourceField = edgeConfig.sourceField + val targetField = edgeConfig.targetField + val sourcePolicy = edgeConfig.sourcePolicy + val targetPolicy = edgeConfig.targetPolicy + if (sourcePolicy.isDefined) { + assert(sourcePolicy.get == KeyPolicy.UUID || sourcePolicy.get == KeyPolicy.HASH) + } + if (targetPolicy.isDefined) { + assert(targetPolicy.get == KeyPolicy.UUID || targetPolicy.get == KeyPolicy.HASH) + } + + val nebulaFields = edgeConfig.nebulaFields + val fields = edgeConfig.fields + assert(nebulaFields.size == fields.size) + + source.category match { + case SourceCategory.CSV => { + val csv = edgeConfig.dataSourceConfigEntry.asInstanceOf[FileBaseSourceConfigEntry] + assert(label.equals("edge1")) + assert(csv.header.get) + assert(csv.separator.get.equals(",")) + assert(csv.path.equals("path1")) + assert(batch == 256) + assert(partition == 32) + } + case SourceCategory.JSON => { + val json = edgeConfig.dataSourceConfigEntry.asInstanceOf[FileDataSourceConfigEntry] + assert(label.equals("edge2")) + assert(json.path.equals("path2")) + assert(batch == 256) + assert(partition == 32) + } + case SourceCategory.PARQUET => { + val parquet = edgeConfig.dataSourceConfigEntry.asInstanceOf[FileDataSourceConfigEntry] + assert(label.equals("edge0")) + assert(parquet.path.equals("path0")) + assert(batch == 256) + assert(partition == 32) + } + case SourceCategory.HIVE => { + val hive = edgeConfig.dataSourceConfigEntry.asInstanceOf[HiveSourceConfigEntry] + assert(label.equals("edge3")) + assert( + hive.sentence.equals( + "select hive-field0, hive-field1, hive-field2 from database.table")) + assert(batch == 256) + assert(partition == 32) + } + case SourceCategory.NEO4J => { + val neo4j = edgeConfig.dataSourceConfigEntry.asInstanceOf[Neo4JSourceConfigEntry] + assert(label.equals("edge4")) + assert(!neo4j.database.isDefined) + assert(neo4j.server.equals("bolt://127.0.0.1:7687")) + assert(neo4j.user.equals("neo4j")) + assert(neo4j.password.equals("neo4j")) + assert(neo4j.sentence.equals( + "match (a:vertex_label)-[r:edge_label]->(b:vertex_label) return a.neo4j-source-field, b.neo4j-target-field, r.neo4j-field-0 as neo4j-field-0, r.neo4j-field-1 as neo4j-field-1 order by id(r)")) + assert(batch == 1000) + assert(partition == 10) + } + case SourceCategory.HBASE => { + val hbase = edgeConfig.dataSourceConfigEntry.asInstanceOf[HBaseSourceConfigEntry] + assert(label.equals("edge5")) + assert(hbase.columnFamily.equals("hbase-table-cloumnfamily")) + assert(hbase.host.equals("127.0.0.1")) + assert(hbase.port.equals("2181")) + assert(batch == 1000) + assert(partition == 10) + } + case _ => {} + } + } + } +} diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/processor/ProcessorSuite.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/processor/ProcessorSuite.scala new file mode 100644 index 0000000..924bd85 --- /dev/null +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/processor/ProcessorSuite.scala @@ -0,0 +1,131 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package scala.com.vesoft.nebula.exchange.processor + +import com.vesoft.nebula.exchange.processor.Processor +import com.vesoft.nebula.{Date, DateTime, NullType, Time, Value} +import com.vesoft.nebula.meta.PropertyType +import org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema +import org.apache.spark.sql.types.{ + BooleanType, + DoubleType, + IntegerType, + LongType, + ShortType, + StringType, + StructField, + StructType +} +import org.junit.Test + +class ProcessorSuite extends Processor { + val values = List("Bob", + "fixedBob", + 12, + 200, + 1000, + 100000, + "2021-01-01", + "2021-01-01T12:00:00", + "12:00:00", + "2021-01-01T12:00:00", + true, + 12.01, + 22.12, + null) + val schema: StructType = StructType( + List( + StructField("col1", StringType, nullable = true), + StructField("col2", StringType, nullable = true), + StructField("col3", ShortType, nullable = true), + StructField("col4", ShortType, nullable = true), + StructField("col5", IntegerType, nullable = true), + StructField("col6", LongType, nullable = true), + StructField("col7", StringType, nullable = true), + StructField("col8", StringType, nullable = true), + StructField("col9", StringType, nullable = true), + StructField("col10", StringType, nullable = true), + StructField("col11", BooleanType, nullable = true), + StructField("col12", DoubleType, nullable = true), + StructField("col13", DoubleType, nullable = true), + StructField("col14", StringType, nullable = true) + )) + val row = new GenericRowWithSchema(values.toArray, schema) + val map = Map( + "col1" -> PropertyType.STRING, + "col2" -> PropertyType.FIXED_STRING, + "col3" -> PropertyType.INT8, + "col4" -> PropertyType.INT16, + "col5" -> PropertyType.INT32, + "col6" -> PropertyType.INT64, + "col7" -> PropertyType.DATE, + "col8" -> PropertyType.DATETIME, + "col9" -> PropertyType.TIME, + "col10" -> PropertyType.TIMESTAMP, + "col11" -> PropertyType.BOOL, + "col12" -> PropertyType.DOUBLE, + "col13" -> PropertyType.FLOAT, + "col14" -> PropertyType.STRING + ) + + @Test + def extraValueForClientSuite(): Unit = { + assert(extraValueForClient(row, "col1", map).toString.equals("\"Bob\"")) + assert(extraValueForClient(row, "col2", map).toString.equals("\"fixedBob\"")) + assert(extraValueForClient(row, "col3", map).toString.toInt == 12) + assert(extraValueForClient(row, "col4", map).toString.toInt == 200) + assert(extraValueForClient(row, "col5", map).toString.toInt == 1000) + assert(extraValueForClient(row, "col6", map).toString.toLong == 100000) + assert(extraValueForClient(row, "col7", map).toString.equals("date(\"2021-01-01\")")) + assert( + extraValueForClient(row, "col8", map).toString.equals("datetime(\"2021-01-01T12:00:00\")")) + assert(extraValueForClient(row, "col9", map).toString.equals("time(\"12:00:00\")")) + assert( + extraValueForClient(row, "col10", map).toString.equals("timestamp(\"2021-01-01T12:00:00\")")) + assert(extraValueForClient(row, "col11", map).toString.toBoolean) + assert(extraValueForClient(row, "col12", map).toString.toDouble > 12.00) + assert(extraValueForClient(row, "col13", map).toString.toDouble > 22.10) + assert(extraValueForClient(row, "col14", map) == null) + } + + @Test + def extraValueForSSTSuite(): Unit = { + assert(extraValueForSST(row, "col1", map).toString.equals("Bob")) + assert(extraValueForSST(row, "col2", map).toString.equals("fixedBob")) + assert(extraValueForSST(row, "col3", map).toString.toInt == 12) + assert(extraValueForSST(row, "col4", map).toString.toInt == 200) + assert(extraValueForSST(row, "col5", map).toString.toInt == 1000) + assert(extraValueForSST(row, "col6", map).toString.toLong == 100000) + val date = new Date(2021, 1, 1) + assert(extraValueForSST(row, "col7", map).equals(date)) + val datetime = new DateTime(2021, 1, 1, 12, 0, 0, 0) + assert(extraValueForSST(row, "col8", map).equals(datetime)) + + val time = new Time(12, 0, 0, 0) + assert(extraValueForSST(row, "col9", map).equals(time)) + + try { + extraValueForSST(row, "col10", map).toString + } catch { + case e: Exception => assert(true) + } + + assert(extraValueForSST(row, "col11", map).toString.toBoolean) + assert(extraValueForSST(row, "col12", map).toString.toDouble > 12.0) + assert(extraValueForSST(row, "col13", map).toString.toFloat > 22.10) + + val nullValue = new Value() + nullValue.setNVal(NullType.__NULL__) + assert(extraValueForSST(row, "col14", map).equals(nullValue)) + } + + /** + * process dataframe to vertices or edges + */ + override def process(): Unit = ??? + +} diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala new file mode 100644 index 0000000..ff866de --- /dev/null +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala @@ -0,0 +1,165 @@ +/* Copyright (c) 2020 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License, + * attached with Common Clause Condition 1.0, found in the LICENSES directory. + */ + +package scala.com.vesoft.nebula.exchange.utils + +import com.google.common.net.HostAndPort +import com.vesoft.nebula.client.graph.NebulaPoolConfig +import com.vesoft.nebula.client.graph.data.HostAddress +import com.vesoft.nebula.client.graph.net.NebulaPool +import com.vesoft.nebula.client.storage.StorageClient +import com.vesoft.nebula.exchange.config.TagConfigEntry +import com.vesoft.nebula.exchange.utils.NebulaUtils +import com.vesoft.nebula.exchange.{KeyPolicy, MetaProvider, VidType} +import com.vesoft.nebula.meta.PropertyType +import org.junit.{After, Before, Test} + +import scala.collection.JavaConverters._ +import scala.collection.mutable.ListBuffer +import scala.com.vesoft.nebula.exchange.NebulaGraphMock + +class NebulaUtilsSuite { + @transient val nebulaPoolConfig = new NebulaPoolConfig + @transient val pool: NebulaPool = new NebulaPool + val address = new ListBuffer[HostAddress]() + address.append(new HostAddress("127.0.0.1", 9669)) + + val randAddr = scala.util.Random.shuffle(address) + pool.init(randAddr.asJava, nebulaPoolConfig) + + @Before + def setUp(): Unit = { + val mockData = new NebulaGraphMock + mockData.mockStringIdGraph() + mockData.mockIntIdGraph() + mockData.close() + } + + @After + def tearDown(): Unit = {} + + @Test + def getDataSourceFieldType(): Unit = { + val nebulaFields = List("col1", + "col2", + "col3", + "col4", + "col5", + "col6", + "col7", + "col8", + "col9", + "col10", + "col11", + "col12") + val sourceFields = List("col1", + "col2", + "col3", + "col4", + "col5", + "col6", + "col7", + "col8", + "col9", + "col10", + "col11", + "col12") + val label = "person" + val sourceConfig = new TagConfigEntry(label, + null, + null, + sourceFields, + nebulaFields, + null, + Some(KeyPolicy.UUID), + 1, + 1, + Some("")) + + val space = "testSST1" + val address = new ListBuffer[HostAndPort]() + address.append(HostAndPort.fromParts("127.0.0.1", 9559)) + val metaProvider = new MetaProvider(address.toList) + + val map: Map[String, Int] = + NebulaUtils.getDataSourceFieldType(sourceConfig, space, metaProvider) + assert(map("col1") == PropertyType.STRING) + assert(map("col2") == PropertyType.FIXED_STRING) + assert(map("col3") == PropertyType.INT8) + assert(map("col4") == PropertyType.INT16) + assert(map("col5") == PropertyType.INT32) + assert(map("col6") == PropertyType.INT64) + assert(map("col7") == PropertyType.DATE) + assert(map("col8") == PropertyType.DATETIME) + assert(map("col9") == PropertyType.TIMESTAMP) + assert(map("col10") == PropertyType.BOOL) + assert(map("col11") == PropertyType.DOUBLE) + assert(map("col12") == PropertyType.FLOAT) + } + + @Test + def getPartitionId(): Unit = { + val storageClient = new StorageClient("127.0.0.1", 9559) + storageClient.connect() + for (i <- 1 to 12) { + val vid = i + "" + val partitionId = NebulaUtils.getPartitionId(vid, 10, VidType.STRING) + val scanResultIter = storageClient.scanVertex("testSST1", partitionId, "person") + var containVertex = false + while (scanResultIter.hasNext) { + val scanResult = scanResultIter.next() + val map = scanResult.getVidVertices + for (value <- map.keySet().asScala) { + if (value.asString().equals(vid)) { + containVertex = true + } + } + } + assert(containVertex) + } + + for (i <- 1 to 12) { + val vid = i + "" + val partitionId = NebulaUtils.getPartitionId(vid, 10, VidType.INT) + val scanResultIter = storageClient.scanVertex("testSST2", partitionId, "person") + var containVertex = false + while (scanResultIter.hasNext) { + val scanResult = scanResultIter.next() + val map = scanResult.getVidVertices + for (value <- map.keySet().asScala) { + if (value.asLong() == vid.toLong) { + containVertex = true + } + } + } + assert(containVertex) + } + } + + @Test + def isNumeric(): Unit = { + assert(NebulaUtils.isNumic("123456")) + assert(NebulaUtils.isNumic("0123456")) + assert(NebulaUtils.isNumic("-123456")) + assert(NebulaUtils.isNumic("000")) + assert(!NebulaUtils.isNumic("aaa")) + assert(!NebulaUtils.isNumic("0123aaa")) + assert(!NebulaUtils.isNumic("123a8")) + + } + + @Test + def escapePropName(): Unit = { + val fields = new ListBuffer[String] + fields.append("col1") + fields.append("col2") + fields.append("col3") + val escapeName = NebulaUtils.escapePropName(fields.toList); + assert("`col1`".equals(escapeName(0))) + assert("`col2`".equals(escapeName(1))) + assert("`col3`".equals(escapeName(2))) + } +} From 9042b074666d7f2c29585575bbdb2a015b1af6bd Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 20 Apr 2021 17:56:00 +0800 Subject: [PATCH 109/213] add workflow --- .github/workflows/maven.yml | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .github/workflows/maven.yml diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000..0b6d23f --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,46 @@ +# This workflow will build a Java project with Maven +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: Java CI with Maven + +on: + push: + branches: [ master ] + pull_request: + branches: + - master + - 'v[0-9]+.*' + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + + - name: Cache the Maven packages to speed up build + uses: actions/cache@v2 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-maven- + + - name: Install nebula-graph + run: | + mkdir tmp + pushd tmp + git clone https://github.com/vesoft-inc/nebula-docker-compose.git + pushd nebula-docker-compose/ + cp ../../nebula-exchange/src/test/resources/docker-compose.yaml . + docker-compose up -d + sleep 10 + popd + popd + + - name: Build with Maven + run: mvn -B package From 7566f65b545c08a10024327fc91043be06e9b2a4 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 20 Apr 2021 17:56:09 +0800 Subject: [PATCH 110/213] fix get partitionId for unsignedLong & update configs --- .../nebula/exchange/config/Configs.scala | 4 +-- .../exchange/processor/EdgeProcessor.scala | 1 - .../nebula/exchange/processor/Processor.scala | 9 ++---- .../nebula/exchange/utils/NebulaUtils.scala | 32 +++++++++++++------ 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala index 01d1f9c..bf0d074 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala @@ -593,8 +593,8 @@ object Configs { val fields: ListBuffer[String] = new ListBuffer[String] fields.append(config.getStringList("fields").asScala: _*) - if (config.hasPath("vertex")) { - fields.append(config.getString("vertex")) + if (config.hasPath("vertex.field")) { + fields.append(config.getString("vertex.field")) } if (config.hasPath("source.field")) { fields.append(config.getString("source.field")) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index e230ee6..f71e180 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -162,7 +162,6 @@ class EdgeProcessor(data: DataFrame, val codec = new NebulaCodecImpl() import java.nio.ByteBuffer - val order = ByteOrder.nativeOrder val srcBytes = if (vidType == VidType.INT) { ByteBuffer .allocate(8) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala index 08f98be..d75f5f8 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/Processor.scala @@ -39,10 +39,7 @@ trait Processor extends Serializable { * DataTime type: add datetime() function for attribute value. * eg: convert attribute value 2020-01-01T22:30:40 to datetime("2020-01-01T22:30:40") */ - def extraValueForClient(row: Row, - field: String, - fieldTypeMap: Map[String, Int], - toBytes: Boolean = false): Any = { + def extraValueForClient(row: Row, field: String, fieldTypeMap: Map[String, Int]): Any = { val index = row.schema.fieldIndex(field) if (row.isNullAt(index)) return null @@ -54,10 +51,10 @@ trait Processor extends Serializable { value = "" } val result = NebulaUtils.escapeUtil(value).mkString("\"", "", "\"") - if (toBytes) result.getBytes else result + result } case PropertyType.DATE => "date(\"" + row.get(index) + "\")" - case PropertyType.DATETIME => "datatime(\"" + row.get(index) + "\")" + case PropertyType.DATETIME => "datetime(\"" + row.get(index) + "\")" case PropertyType.TIME => "time(\"" + row.get(index) + "\")" case PropertyType.TIMESTAMP => { val value = row.get(index).toString diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala index edf6747..c86ef61 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala @@ -47,7 +47,11 @@ object NebulaUtils { } def isNumic(str: String): Boolean = { - for (char <- str.toCharArray) { + val newStr: String = if (str.startsWith("-")) { + str.substring(1) + } else { str } + + for (char <- newStr.toCharArray) { if (!Character.isDigit(char)) return false } true @@ -80,16 +84,26 @@ object NebulaUtils { } def getPartitionId(id: String, partitionSize: Int, vidType: VidType.Value): Int = { - val hashValue: Int = if (vidType == VidType.INT) { - val value = java.lang.Long.parseUnsignedLong(id) - (Math.floorMod(value, partitionSize) + 1).toInt + val hashValue: Long = if (vidType == VidType.STRING) { + MurmurHash2.hash64(id.getBytes, id.length, 0xc70f6907) } else { - val hash = MurmurHash2.hash64(id.getBytes, id.length, 0xc70f6907) - val value = UnsignedLong.fromLongBits(hash) - val partSize = UnsignedLong.fromLongBits(partitionSize) - value.mod(partSize).intValue + 1 + id.toLong } - hashValue + val unsignedValue = UnsignedLong.fromLongBits(hashValue) + val partSize = UnsignedLong.fromLongBits(partitionSize) + unsignedValue.mod(partSize).intValue + 1 + } + + def escapePropName(nebulaFields: List[String]): List[String] = { + val propNames: ListBuffer[String] = new ListBuffer[String] + for (key <- nebulaFields) { + val sb = new StringBuilder() + sb.append("`") + sb.append(key) + sb.append("`") + propNames.append(sb.toString()) + } + propNames.toList } def escapePropName(nebulaFields: List[String]): List[String] = { From c69ef213893aeaea5f6128fab13cd6a3643c6a81 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 20 Apr 2021 18:05:25 +0800 Subject: [PATCH 111/213] clean duplicate method --- .../vesoft/nebula/exchange/utils/NebulaUtils.scala | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala index c86ef61..0ed3dd3 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/NebulaUtils.scala @@ -105,16 +105,4 @@ object NebulaUtils { } propNames.toList } - - def escapePropName(nebulaFields: List[String]): List[String] = { - val propNames: ListBuffer[String] = new ListBuffer[String] - for (key <- nebulaFields) { - val sb = new StringBuilder() - sb.append("`") - sb.append(key) - sb.append("`") - propNames.append(sb.toString()) - } - propNames.toList - } } From be1c14af2438180c231657cf189ce04725dab153 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 28 Apr 2021 12:42:35 +0800 Subject: [PATCH 112/213] update copyright --- .../test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala | 2 +- .../scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala | 2 +- .../com/vesoft/nebula/exchange/processor/ProcessorSuite.scala | 2 +- .../com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala index fc072c2..cc3da31 100644 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala @@ -1,4 +1,4 @@ -/* Copyright (c) 2020 vesoft inc. All rights reserved. +/* Copyright (c) 2021 vesoft inc. All rights reserved. * * This source code is licensed under Apache 2.0 License, * attached with Common Clause Condition 1.0, found in the LICENSES directory. diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala index 6fe0595..eb65f13 100644 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala @@ -1,4 +1,4 @@ -/* Copyright (c) 2020 vesoft inc. All rights reserved. +/* Copyright (c) 2021 vesoft inc. All rights reserved. * * This source code is licensed under Apache 2.0 License, * attached with Common Clause Condition 1.0, found in the LICENSES directory. diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/processor/ProcessorSuite.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/processor/ProcessorSuite.scala index 924bd85..b67e56a 100644 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/processor/ProcessorSuite.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/processor/ProcessorSuite.scala @@ -1,4 +1,4 @@ -/* Copyright (c) 2020 vesoft inc. All rights reserved. +/* Copyright (c) 2021 vesoft inc. All rights reserved. * * This source code is licensed under Apache 2.0 License, * attached with Common Clause Condition 1.0, found in the LICENSES directory. diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala index ff866de..e1c3ef1 100644 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala @@ -1,4 +1,4 @@ -/* Copyright (c) 2020 vesoft inc. All rights reserved. +/* Copyright (c) 2021 vesoft inc. All rights reserved. * * This source code is licensed under Apache 2.0 License, * attached with Common Clause Condition 1.0, found in the LICENSES directory. From 31c332cc326ea3e0dfb355d7d990be174d05a518 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Sat, 8 May 2021 15:38:17 +0800 Subject: [PATCH 113/213] modify space name & add test data to cover all partition --- .../vesoft/nebula/exchange/NebulaGraphMock.scala | 14 ++++++++------ .../nebula/exchange/utils/NebulaUtilsSuite.scala | 14 +++++++------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala index cc3da31..d53acb7 100644 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala @@ -26,8 +26,8 @@ class NebulaGraphMock { def mockStringIdGraph(): Unit = { val session = pool.getSession("root", "nebula", true) - val createSpace = "CREATE SPACE IF NOT EXISTS testSST1(partition_num=10);" + - "USE testSST1;" + "CREATE TAG IF NOT EXISTS person(col1 string, col2 fixed_string(8), col3 int8, col4 int16, col5 int32, col6 int64, col7 date, col8 datetime, col9 timestamp, col10 bool, col11 double, col12 float, col13 time);" + + val createSpace = "CREATE SPACE IF NOT EXISTS test_string(partition_num=10);" + + "USE test_string;" + "CREATE TAG IF NOT EXISTS person(col1 string, col2 fixed_string(8), col3 int8, col4 int16, col5 int32, col6 int64, col7 date, col8 datetime, col9 timestamp, col10 bool, col11 double, col12 float, col13 time);" + "CREATE EDGE IF NOT EXISTS friend(col1 string, col2 fixed_string(8), col3 int8, col4 int16, col5 int32, col6 int64, col7 date, col8 datetime, col9 timestamp, col10 bool, col11 double, col12 float, col13 time);"; val createResp = session.execute(createSpace) if (!createResp.isSucceeded) { @@ -50,8 +50,10 @@ class NebulaGraphMock { " \"10\":(\"person10\", \"person10\", 20, 1100, 10000, 1088888, date(\"2021-01-10\"), datetime(\"2021-01-10T12:00:00\"),timestamp(\"2021-01-10T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + " \"11\":(\"person11\", \"person11\", 21, 1200, 11000, 1188888, date(\"2021-01-11\"), datetime(\"2021-01-11T12:00:00\"),timestamp(\"2021-01-11T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + " \"12\":(\"person12\", \"person11\", 22, 1300, 12000, 1288888, date(\"2021-01-12\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + - " \"-1\":(\"person21\", \"person21\", 23, 1400, 13000, 1388888, date(\"2021-01-13\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + - " \"-1\":(\"person22\", \"person22\", 24, 1500, 14000, 1488888, date(\"2021-01-14\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))" + " \"-1\":(\"person00\", \"person00\", 23, 1400, 13000, 1388888, date(\"2021-01-13\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"-2\":(\"person01\", \"person01\", 24, 1500, 14000, 1488888, date(\"2021-01-14\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"19\":(\"person19\", \"person22\", 25, 1500, 14000, 1488888, date(\"2021-01-14\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " \"22\":(\"person22\", \"person22\", 26, 1500, 14000, 1488888, date(\"2021-01-14\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))" val insertTagResp = session.execute(insertTag) if (!insertTagResp.isSucceeded) { close() @@ -83,8 +85,8 @@ class NebulaGraphMock { def mockIntIdGraph(): Unit = { val session = pool.getSession("root", "nebula", true) - val createSpace = "CREATE SPACE IF NOT EXISTS testSST2(partition_num=10, vid_type=int64);" + - "USE testSST2;" + "CREATE TAG IF NOT EXISTS person(col1 string, col2 fixed_string(8), col3 int8, col4 int16, col5 int32, col6 int64, col7 date, col8 datetime, col9 timestamp, col10 bool, col11 double, col12 float, col13 time);" + + val createSpace = "CREATE SPACE IF NOT EXISTS test_int(partition_num=10, vid_type=int64);" + + "USE test_int;" + "CREATE TAG IF NOT EXISTS person(col1 string, col2 fixed_string(8), col3 int8, col4 int16, col5 int32, col6 int64, col7 date, col8 datetime, col9 timestamp, col10 bool, col11 double, col12 float, col13 time);" + "CREATE EDGE IF NOT EXISTS friend(col1 string, col2 fixed_string(8), col3 int8, col4 int16, col5 int32, col6 int64, col7 date, col8 datetime, col9 timestamp, col10 bool, col11 double, col12 float, col13 time);"; val createResp = session.execute(createSpace) if (!createResp.isSucceeded) { diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala index e1c3ef1..70cc7d9 100644 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala @@ -79,7 +79,7 @@ class NebulaUtilsSuite { 1, Some("")) - val space = "testSST1" + val space = "test_string" val address = new ListBuffer[HostAndPort]() address.append(HostAndPort.fromParts("127.0.0.1", 9559)) val metaProvider = new MetaProvider(address.toList) @@ -105,14 +105,14 @@ class NebulaUtilsSuite { val storageClient = new StorageClient("127.0.0.1", 9559) storageClient.connect() for (i <- 1 to 12) { - val vid = i + "" + val vid = Integer.toString(i) val partitionId = NebulaUtils.getPartitionId(vid, 10, VidType.STRING) - val scanResultIter = storageClient.scanVertex("testSST1", partitionId, "person") + val scanResultIter = storageClient.scanVertex("test_string", partitionId, "person") var containVertex = false while (scanResultIter.hasNext) { val scanResult = scanResultIter.next() val map = scanResult.getVidVertices - for (value <- map.keySet().asScala) { + for (value <- map.keySet().asScala if !containVertex) { if (value.asString().equals(vid)) { containVertex = true } @@ -122,14 +122,14 @@ class NebulaUtilsSuite { } for (i <- 1 to 12) { - val vid = i + "" + val vid = Integer.toString(i) val partitionId = NebulaUtils.getPartitionId(vid, 10, VidType.INT) - val scanResultIter = storageClient.scanVertex("testSST2", partitionId, "person") + val scanResultIter = storageClient.scanVertex("test_int", partitionId, "person") var containVertex = false while (scanResultIter.hasNext) { val scanResult = scanResultIter.next() val map = scanResult.getVidVertices - for (value <- map.keySet().asScala) { + for (value <- map.keySet().asScala if !containVertex) { if (value.asLong() == vid.toLong) { containVertex = true } From 3448dd3e3464ba9fd2fbcb13983dbfd97601e072 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 7 May 2021 11:03:10 +0800 Subject: [PATCH 114/213] support empty vid for string vid_type --- .../exchange/processor/EdgeProcessor.scala | 16 +++++++++++++--- .../exchange/processor/VerticesProcessor.scala | 15 +++++++++++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index f71e180..4bba5f9 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -19,6 +19,7 @@ import com.vesoft.nebula.exchange.config.{ SinkCategory, StreamingDataSourceConfigEntry } +import com.vesoft.nebula.exchange.utils.NebulaUtils.DEFAULT_EMPTY_VALUE import com.vesoft.nebula.exchange.utils.{HDFSUtils, NebulaUtils} import com.vesoft.nebula.exchange.{ Edge, @@ -115,9 +116,16 @@ class EdgeProcessor(data: DataFrame, .mapPartitions { iter => iter.map { row => val srcIndex: Int = row.schema.fieldIndex(edgeConfig.sourceField) + assert(srcIndex >= 0 && !row.isNullAt(srcIndex), + s"edge source vertex must exist and cannot be null, your row data is $row") var srcId: String = row.get(srcIndex).toString + if (srcId.equals(DEFAULT_EMPTY_VALUE)) { srcId = "" } + val dstIndex: Int = row.schema.fieldIndex(edgeConfig.targetField) + assert(dstIndex >= 0 && !row.isNullAt(dstIndex), + s"edge target vertex must exist and cannot be null, your row data is $row") var dstId: String = row.get(dstIndex).toString + if (dstId.equals(DEFAULT_EMPTY_VALUE)) { dstId = "" } if (edgeConfig.sourcePolicy.isDefined) { edgeConfig.sourcePolicy.get match { @@ -259,9 +267,10 @@ class EdgeProcessor(data: DataFrame, .map { row => var sourceField = if (!edgeConfig.isGeo) { val sourceIndex = row.schema.fieldIndex(edgeConfig.sourceField) - assert(sourceIndex >= 0 && row.get(sourceIndex) != null, + assert(sourceIndex >= 0 && !row.isNullAt(sourceIndex), s"source vertexId must exist and cannot be null, your row data is $row") - row.get(sourceIndex).toString + val value = row.get(sourceIndex).toString + if (value.equals(DEFAULT_EMPTY_VALUE)) "" else value } else { val lat = row.getDouble(row.schema.fieldIndex(edgeConfig.latitude.get)) val lng = row.getDouble(row.schema.fieldIndex(edgeConfig.longitude.get)) @@ -282,9 +291,10 @@ class EdgeProcessor(data: DataFrame, } val targetIndex = row.schema.fieldIndex(edgeConfig.targetField) - assert(targetIndex >= 0 && row.get(targetIndex) != null, + assert(targetIndex >= 0 && !row.isNullAt(targetIndex), s"target vertexId must exist and cannot be null, your row data is $row") var targetField = row.get(targetIndex).toString + if (targetField.equals(DEFAULT_EMPTY_VALUE)) targetField = "" if (edgeConfig.targetPolicy.isEmpty) { // process string type vid if (isVidStringType) { diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index a921954..cb7b686 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -10,7 +10,7 @@ import java.nio.file.{Files, Paths} import java.nio.{ByteBuffer, ByteOrder} import com.vesoft.nebula.client.graph.data.HostAddress -import com.vesoft.nebula.encoder.{NebulaCodecImpl} +import com.vesoft.nebula.encoder.NebulaCodecImpl import com.vesoft.nebula.exchange.{ ErrorHandler, GraphProvider, @@ -27,6 +27,7 @@ import com.vesoft.nebula.exchange.config.{ StreamingDataSourceConfigEntry, TagConfigEntry } +import com.vesoft.nebula.exchange.utils.NebulaUtils.DEFAULT_EMPTY_VALUE import com.vesoft.nebula.exchange.utils.{HDFSUtils, NebulaUtils} import com.vesoft.nebula.exchange.writer.{NebulaGraphClientWriter, NebulaSSTWriter} import org.apache.commons.codec.digest.MurmurHash2 @@ -122,8 +123,13 @@ class VerticesProcessor(data: DataFrame, data .mapPartitions { iter => iter.map { row => - val index: Int = row.schema.fieldIndex(tagConfig.vertexField) + val index: Int = row.schema.fieldIndex(tagConfig.vertexField) + assert(index >= 0 && !row.isNullAt(index), + s"vertexId must exist and cannot be null, your row data is $row") var vertexId: String = row.get(index).toString + if (vertexId.equals(DEFAULT_EMPTY_VALUE)) { + vertexId = "" + } if (tagConfig.vertexPolicy.isDefined) { tagConfig.vertexPolicy.get match { case KeyPolicy.HASH => @@ -225,9 +231,10 @@ class VerticesProcessor(data: DataFrame, .map { row => val vertexID = { val index = row.schema.fieldIndex(tagConfig.vertexField) - assert(index >= 0 && row.get(index) != null, + assert(index >= 0 && !row.isNullAt(index), s"vertexId must exist and cannot be null, your row data is $row") - val value = row.get(index).toString + var value = row.get(index).toString + if (value.equals(DEFAULT_EMPTY_VALUE)) { value = "" } if (tagConfig.vertexPolicy.isEmpty) { // process string type vid if (isVidStringType) { From ef1d3b9972c3d287a3aedcd73fc957138911426f Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Sat, 8 May 2021 18:04:14 +0800 Subject: [PATCH 115/213] comment out workflow temporarily --- .github/workflows/maven.yml | 92 ++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 0b6d23f..a10e886 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -1,46 +1,46 @@ -# This workflow will build a Java project with Maven -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven - -name: Java CI with Maven - -on: - push: - branches: [ master ] - pull_request: - branches: - - master - - 'v[0-9]+.*' - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - - name: Cache the Maven packages to speed up build - uses: actions/cache@v2 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: ${{ runner.os }}-maven- - - - name: Install nebula-graph - run: | - mkdir tmp - pushd tmp - git clone https://github.com/vesoft-inc/nebula-docker-compose.git - pushd nebula-docker-compose/ - cp ../../nebula-exchange/src/test/resources/docker-compose.yaml . - docker-compose up -d - sleep 10 - popd - popd - - - name: Build with Maven - run: mvn -B package +## This workflow will build a Java project with Maven +## For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven +# +#name: Java CI with Maven +# +#on: +# push: +# branches: [ master ] +# pull_request: +# branches: +# - master +# - 'v[0-9]+.*' +# +#jobs: +# build: +# +# runs-on: ubuntu-latest +# +# steps: +# - uses: actions/checkout@v2 +# - name: Set up JDK 1.8 +# uses: actions/setup-java@v1 +# with: +# java-version: 1.8 +# +# - name: Cache the Maven packages to speed up build +# uses: actions/cache@v2 +# with: +# path: ~/.m2/repository +# key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} +# restore-keys: ${{ runner.os }}-maven- +# +# - name: Install nebula-graph +# run: | +# mkdir tmp +# pushd tmp +# git clone https://github.com/vesoft-inc/nebula-docker-compose.git +# pushd nebula-docker-compose/ +# cp ../../nebula-exchange/src/test/resources/docker-compose.yaml . +# docker-compose up -d +# sleep 10 +# popd +# popd +# +# - name: Build with Maven +# run: mvn -B package From 870a64e14b24f69b2096a672b896b35b55ff9476 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 10 May 2021 11:53:03 +0800 Subject: [PATCH 116/213] add deploy plugins --- nebula-algorithm/pom.xml | 147 ++++++++++++++++++++++++++++++++++----- 1 file changed, 131 insertions(+), 16 deletions(-) diff --git a/nebula-algorithm/pom.xml b/nebula-algorithm/pom.xml index 42e6b70..c5e8bd5 100644 --- a/nebula-algorithm/pom.xml +++ b/nebula-algorithm/pom.xml @@ -72,7 +72,137 @@ src/main/scala - + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + + default-deploy + deploy + + + + + org.scala-tools + maven-scala-plugin + 2.15.2 + + 2.11.12 + + -target:jvm-1.8 + + + -Xss4096K + + + + + scala-compile + + compile + + + + com/vesoft/tools/** + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + scala-test-compile + + testCompile + + + + com/vesoft/tools/** + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.0 + + + attach-sources + + jar + + + + + + net.alchim31.maven + scala-maven-plugin + + + Scaladoc + + doc + + prepare-package + + + -nobootcp + -no-link-warnings + + + + + attach-javadocs + + doc-jar + + + + -nobootcp + -no-link-warnings + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + com.facebook.thrift:com.facebook.thrift.* + + + + attach-javadocs + package + + jar + + + UTF-8 + UTF-8 + + -source 8 + -Xdoclint:none + + + + + + org.apache.maven.plugins @@ -140,21 +270,6 @@ - - - net.alchim31.maven - scala-maven-plugin - 3.2.2 - - - - compile - testCompile - - - - - org.scalatest From cc291fbaf81cbffc1ce3b295cdf039fc4cbe81c8 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 10 May 2021 19:31:35 +0800 Subject: [PATCH 117/213] add more way to get nebula-algorithm --- nebula-algorithm/README.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/nebula-algorithm/README.md b/nebula-algorithm/README.md index 05ac2b6..ef711ab 100644 --- a/nebula-algorithm/README.md +++ b/nebula-algorithm/README.md @@ -18,14 +18,17 @@ nebula-algorithm 是一款基于 [GraphX](https://spark.apache.org/graphx/) 的 使用 `nebula-algorithm`,可以通过提交 `Spark` 任务的形式使用完整的算法工具对 `Nebula Graph` 数据库中的数据执行图计算,也可以通过编程形式调用`lib`库下的算法针对DataFrame执行图计算。 -## 编译 Nebula-Algorithm +## 如何获取 + 1. 编译打包 Nebula-Algorithm + ``` + $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git + $ cd nebula-algorithm + $ mvn clean package -Dgpg.skip -Dmaven.javadoc.skip=true -Dmaven.test.skip=true + ``` + 编译完成后,在 `nebula-algorithm/target` 目录下会生成 `nebula-algorithm-2.0.0.jar` 。 -``` -$ git clone https://github.com/vesoft-inc/nebula-spark-utils.git -$ cd nebula-algorithm -$ mvn clean package -Dgpg.skip -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -``` -编译完成后,在 `nebula-algorithm/target` 目录下会生成 `nebula-algorithm-2.0.0.jar` 。 + 2. 在 Maven 远程仓库下载 + https://repo1.maven.org/maven2/com/vesoft/nebula-algorithm/2.0.0/ # 使用 Nebula-Algorithm From 78ab71513e7494dc07ecfdfa18143f86095096d9 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 11 May 2021 10:24:26 +0800 Subject: [PATCH 118/213] modify port to nebula default port --- .../connector/NebulaSparkReaderExample.scala | 18 +++++++++--------- .../connector/NebulaSparkWriterExample.scala | 10 +++++----- nebula-spark-connector/README.md | 8 ++++---- nebula-spark-connector/README_CN.md | 8 ++++---- .../nebula/connector/NebulaConfigSuite.scala | 6 +++++- 5 files changed, 27 insertions(+), 23 deletions(-) diff --git a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala index 39c2989..a11ae2b 100644 --- a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala +++ b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala @@ -43,12 +43,12 @@ object NebulaSparkReaderExample { val config = NebulaConnectionConfig .builder() - .withMetaAddress("127.0.0.1:45500") + .withMetaAddress("127.0.0.1:9559") .withConenctionRetry(2) .build() val nebulaReadVertexConfig: ReadNebulaConfig = ReadNebulaConfig .builder() - .withSpace("exchange") + .withSpace("test") .withLabel("person") .withNoColumn(false) .withReturnCols(List("birthday")) @@ -67,13 +67,13 @@ object NebulaSparkReaderExample { val config = NebulaConnectionConfig .builder() - .withMetaAddress("127.0.0.1:45500") + .withMetaAddress("127.0.0.1:9559") .withTimeout(6000) .withConenctionRetry(2) .build() val nebulaReadEdgeConfig: ReadNebulaConfig = ReadNebulaConfig .builder() - .withSpace("exchange") + .withSpace("test") .withLabel("knows") .withNoColumn(false) .withReturnCols(List("degree")) @@ -91,13 +91,13 @@ object NebulaSparkReaderExample { val config = NebulaConnectionConfig .builder() - .withMetaAddress("127.0.0.1:45500") + .withMetaAddress("127.0.0.1:9559") .withTimeout(6000) .withConenctionRetry(2) .build() val nebulaReadVertexConfig: ReadNebulaConfig = ReadNebulaConfig .builder() - .withSpace("exchange") + .withSpace("test") .withLabel("person") .withNoColumn(false) .withReturnCols(List("birthday")) @@ -115,14 +115,14 @@ object NebulaSparkReaderExample { val config = NebulaConnectionConfig .builder() - .withMetaAddress("127.0.0.1:45500") + .withMetaAddress("127.0.0.1:9559") .withTimeout(6000) .withConenctionRetry(2) .build() val nebulaReadEdgeConfig: ReadNebulaConfig = ReadNebulaConfig .builder() - .withSpace("exchange") - .withLabel("knows1") + .withSpace("test") + .withLabel("knows") .withNoColumn(false) .withReturnCols(List("timep")) .withLimit(10) diff --git a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala index 1a43509..c3dc75f 100644 --- a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala +++ b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala @@ -34,7 +34,7 @@ object NebulaSparkWriterExample { .getOrCreate() writeVertex(spark) - // writeEdge(spark) + writeEdge(spark) spark.close() sys.exit() @@ -48,8 +48,8 @@ object NebulaSparkWriterExample { val config = NebulaConnectionConfig .builder() - .withMetaAddress("127.0.0.1:45500") - .withGraphAddress("127.0.0.1:3699") + .withMetaAddress("127.0.0.1:9559") + .withGraphAddress("127.0.0.1:9669") .withConenctionRetry(2) .build() val nebulaWriteVertexConfig: WriteNebulaVertexConfig = WriteNebulaVertexConfig @@ -72,8 +72,8 @@ object NebulaSparkWriterExample { val config = NebulaConnectionConfig .builder() - .withMetaAddress("127.0.0.1:45509") - .withGraphAddress("127.0.0.1:3799") + .withMetaAddress("127.0.0.1:9559") + .withGraphAddress("127.0.0.1:9669") .build val nebulaWriteEdgeConfig: WriteNebulaEdgeConfig = WriteNebulaEdgeConfig .builder() diff --git a/nebula-spark-connector/README.md b/nebula-spark-connector/README.md index bc65623..47b8380 100644 --- a/nebula-spark-connector/README.md +++ b/nebula-spark-connector/README.md @@ -30,8 +30,8 @@ Nebula Spark Connector 2.0 only supports Nebula Graph 2.x. If you are using Nebu ``` val config = NebulaConnectionConfig .builder() - .withMetaAddress("127.0.0.1:45500") - .withGraphAddress("127.0.0.1:3699") + .withMetaAddress("127.0.0.1:9559") + .withGraphAddress("127.0.0.1:9669") .build() val nebulaWriteVertexConfig: WriteNebulaVertexConfig = WriteNebulaVertexConfig .builder() @@ -47,7 +47,7 @@ Nebula Spark Connector 2.0 only supports Nebula Graph 2.x. If you are using Nebu ``` val config = NebulaConnectionConfig .builder() - .withMetaAddress("127.0.0.1:45500") + .withMetaAddress("127.0.0.1:9559") .withConenctionRetry(2) .build() val nebulaReadVertexConfig: ReadNebulaConfig = ReadNebulaConfig @@ -66,7 +66,7 @@ Nebula Spark Connector 2.0 only supports Nebula Graph 2.x. If you are using Nebu ``` val config = NebulaConnectionConfig .builder() - .withMetaAddress("127.0.0.1:45500") + .withMetaAddress("127.0.0.1:9559") .build() val nebulaReadVertexConfig = ReadNebulaConfig .builder() diff --git a/nebula-spark-connector/README_CN.md b/nebula-spark-connector/README_CN.md index 00ef4ec..f5382d2 100644 --- a/nebula-spark-connector/README_CN.md +++ b/nebula-spark-connector/README_CN.md @@ -30,8 +30,8 @@ Nebula Spark Connector 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Ne ``` val config = NebulaConnectionConfig .builder() - .withMetaAddress("127.0.0.1:45500") - .withGraphAddress("127.0.0.1:3699") + .withMetaAddress("127.0.0.1:9559") + .withGraphAddress("127.0.0.1:9669") .build() val nebulaWriteVertexConfig = WriteNebulaVertexConfig .builder() @@ -47,7 +47,7 @@ Nebula Spark Connector 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Ne ``` val config = NebulaConnectionConfig .builder() - .withMetaAddress("127.0.0.1:45500") + .withMetaAddress("127.0.0.1:9559") .withConenctionRetry(2) .build() val nebulaReadVertexConfig = ReadNebulaConfig @@ -66,7 +66,7 @@ Nebula Spark Connector 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Ne ``` val config = NebulaConnectionConfig .builder() - .withMetaAddress("127.0.0.1:45500") + .withMetaAddress("127.0.0.1:9559") .withConenctionRetry(2) .build() val nebulaReadVertexConfig = ReadNebulaConfig diff --git a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/NebulaConfigSuite.scala b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/NebulaConfigSuite.scala index 0e6ea06..aef5840 100644 --- a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/NebulaConfigSuite.scala +++ b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/NebulaConfigSuite.scala @@ -25,7 +25,11 @@ class NebulaConfigSuite extends AnyFunSuite with BeforeAndAfterAll { } try { - NebulaConnectionConfig.builder().withMetaAddress("127.0.0.1:45500").withTimeout(1).build() + NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:9559") + .withTimeout(1) + .build() assert(true) } catch { case _: Throwable => assert(false) From 0738ed31c9a51a531d1b691c99b3aa10cf1f8f26 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 11 May 2021 11:28:40 +0800 Subject: [PATCH 119/213] add timeout config for client --- nebula-exchange/src/main/resources/application.conf | 9 ++------- .../scala/com/vesoft/nebula/exchange/GraphProvider.scala | 6 +++++- .../scala/com/vesoft/nebula/exchange/MetaProvider.scala | 4 +++- .../com/vesoft/nebula/exchange/config/Configs.scala | 4 ++-- .../vesoft/nebula/exchange/processor/EdgeProcessor.scala | 9 +++++---- .../nebula/exchange/processor/ReloadProcessor.scala | 5 +++-- .../nebula/exchange/processor/VerticesProcessor.scala | 9 +++++---- .../vesoft/nebula/exchange/writer/ServerBaseWriter.scala | 4 ---- .../vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala | 2 +- 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/nebula-exchange/src/main/resources/application.conf b/nebula-exchange/src/main/resources/application.conf index aa52ae6..a64d625 100644 --- a/nebula-exchange/src/main/resources/application.conf +++ b/nebula-exchange/src/main/resources/application.conf @@ -52,13 +52,8 @@ # nebula client connection parameters connection { - timeout: 3000 - retry: 3 - } - - # nebula client execution parameters - execution { - retry: 3 + # socket connect & execute timeout, unit: millisecond + timeout: 30000 } error: { diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala index 5570f94..84b8307 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala @@ -19,7 +19,9 @@ import scala.collection.mutable.ListBuffer /** * GraphProvider for Nebula Graph Service */ -class GraphProvider(addresses: List[HostAndPort]) extends AutoCloseable with Serializable { +class GraphProvider(addresses: List[HostAndPort], timeout: Int) + extends AutoCloseable + with Serializable { private[this] lazy val LOG = Logger.getLogger(this.getClass) @transient val nebulaPoolConfig = new NebulaPoolConfig @@ -29,6 +31,8 @@ class GraphProvider(addresses: List[HostAndPort]) extends AutoCloseable with Ser address.append(new HostAddress(addr.getHostText, addr.getPort)) } val randAddr = scala.util.Random.shuffle(address) + + nebulaPoolConfig.setTimeout(timeout) pool.init(randAddr.asJava, nebulaPoolConfig) def getGraphClient(userConfigEntry: UserConfigEntry): Session = { diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala index f483b00..9a2b757 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/MetaProvider.scala @@ -20,7 +20,9 @@ import scala.collection.mutable.ListBuffer /** * MetaProvider provide nebula graph meta query operations. */ -class MetaProvider(addresses: List[HostAndPort]) extends AutoCloseable with Serializable { +class MetaProvider(addresses: List[HostAndPort], timeout: Int, retry: Int) + extends AutoCloseable + with Serializable { private[this] lazy val LOG = Logger.getLogger(this.getClass) val address: ListBuffer[HostAddress] = new ListBuffer[HostAddress] diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala index bf0d074..59ef44f 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala @@ -186,10 +186,10 @@ case class Configs(databaseConfig: DataBaseConfigEntry, object Configs { private[this] val LOG = Logger.getLogger(this.getClass) - private[this] val DEFAULT_CONNECTION_TIMEOUT = 3000 + private[this] val DEFAULT_CONNECTION_TIMEOUT = Integer.MAX_VALUE private[this] val DEFAULT_CONNECTION_RETRY = 3 private[this] val DEFAULT_EXECUTION_RETRY = 3 - private[this] val DEFAULT_EXECUTION_TIMEOUT = 3000 + private[this] val DEFAULT_EXECUTION_TIMEOUT = Integer.MAX_VALUE private[this] val DEFAULT_EXECUTION_INTERVAL = 3000 private[this] val DEFAULT_ERROR_OUTPUT_PATH = "/tmp/nebula.writer.errors/" private[this] val DEFAULT_ERROR_MAX_BATCH_SIZE = Int.MaxValue diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index 4bba5f9..91a98bf 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -57,11 +57,10 @@ class EdgeProcessor(data: DataFrame, private[this] val DEFAULT_MAX_CELL_LEVEL = 18 private def processEachPartition(iterator: Iterator[Edge]): Unit = { - val graphProvider = new GraphProvider(config.databaseConfig.getGraphAddress) + val graphProvider = + new GraphProvider(config.databaseConfig.getGraphAddress, config.connectionConfig.timeout) val writer = new NebulaGraphClientWriter(config.databaseConfig, config.userConfig, - config.connectionConfig, - config.executionConfig.retry, config.rateConfig, edgeConfig, graphProvider) @@ -98,7 +97,9 @@ class EdgeProcessor(data: DataFrame, val address = config.databaseConfig.getMetaAddress val space = config.databaseConfig.space - val metaProvider = new MetaProvider(address) + val timeout = config.connectionConfig.timeout + val retry = config.connectionConfig.retry + val metaProvider = new MetaProvider(address, timeout, retry) val fieldTypeMap = NebulaUtils.getDataSourceFieldType(edgeConfig, space, metaProvider) val isVidStringType = metaProvider.getVidType(space) == VidType.STRING val partitionNum = metaProvider.getPartNumber(space) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala index 073bf66..2bc353b 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala @@ -25,8 +25,9 @@ class ReloadProcessor(data: DataFrame, } private def processEachPartition(iterator: Iterator[Row]): Unit = { - val graphProvider = new GraphProvider(config.databaseConfig.getGraphAddress) - val session = graphProvider.getGraphClient(config.userConfig) + val graphProvider = + new GraphProvider(config.databaseConfig.getGraphAddress, config.connectionConfig.timeout) + val session = graphProvider.getGraphClient(config.userConfig) if (session == null) { throw new IllegalArgumentException("connect to graph failed.") } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index cb7b686..f6568ab 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -63,12 +63,11 @@ class VerticesProcessor(data: DataFrame, private[this] lazy val LOG = Logger.getLogger(this.getClass) private def processEachPartition(iterator: Iterator[Vertex]): Unit = { - val graphProvider = new GraphProvider(config.databaseConfig.getGraphAddress) + val graphProvider = + new GraphProvider(config.databaseConfig.getGraphAddress, config.connectionConfig.timeout) val writer = new NebulaGraphClientWriter(config.databaseConfig, config.userConfig, - config.connectionConfig, - config.executionConfig.retry, config.rateConfig, tagConfig, graphProvider) @@ -106,7 +105,9 @@ class VerticesProcessor(data: DataFrame, val address = config.databaseConfig.getMetaAddress val space = config.databaseConfig.space - val metaProvider = new MetaProvider(address) + val timeout = config.connectionConfig.timeout + val retry = config.connectionConfig.retry + val metaProvider = new MetaProvider(address, timeout, retry) val fieldTypeMap = NebulaUtils.getDataSourceFieldType(tagConfig, space, metaProvider) val isVidStringType = metaProvider.getVidType(space) == VidType.STRING val partitionNum = metaProvider.getPartNumber(space) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala index 9911486..186b6cc 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala @@ -118,8 +118,6 @@ abstract class ServerBaseWriter extends Writer { */ class NebulaGraphClientWriter(dataBaseConfigEntry: DataBaseConfigEntry, userConfigEntry: UserConfigEntry, - connectionConfigEntry: ConnectionConfigEntry, - executionRetry: Int, rateConfig: RateConfigEntry, config: SchemaConfigEntry, graphProvider: GraphProvider) @@ -131,8 +129,6 @@ class NebulaGraphClientWriter(dataBaseConfigEntry: DataBaseConfigEntry, && dataBaseConfigEntry.getMetaAddress.nonEmpty && dataBaseConfigEntry.space.trim.nonEmpty) require(userConfigEntry.user.trim.nonEmpty && userConfigEntry.password.trim.nonEmpty) - require(connectionConfigEntry.timeout > 0 && connectionConfigEntry.retry > 0) - require(executionRetry > 0) val session = graphProvider.getGraphClient(userConfigEntry) val rateLimiter = RateLimiter.create(rateConfig.limit) diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala index 70cc7d9..d6cc7a6 100644 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala @@ -82,7 +82,7 @@ class NebulaUtilsSuite { val space = "test_string" val address = new ListBuffer[HostAndPort]() address.append(HostAndPort.fromParts("127.0.0.1", 9559)) - val metaProvider = new MetaProvider(address.toList) + val metaProvider = new MetaProvider(address.toList, 6000, 1) val map: Map[String, Int] = NebulaUtils.getDataSourceFieldType(sourceConfig, space, metaProvider) From 42d8317a88b7c32d3fa9548374669b2afe01b5ee Mon Sep 17 00:00:00 2001 From: cooper-lzy <78672629+cooper-lzy@users.noreply.github.com> Date: Mon, 17 May 2021 16:18:03 +0800 Subject: [PATCH 120/213] Update application.conf --- nebula-algorithm/src/main/resources/application.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nebula-algorithm/src/main/resources/application.conf b/nebula-algorithm/src/main/resources/application.conf index 1b1e17a..48102b8 100644 --- a/nebula-algorithm/src/main/resources/application.conf +++ b/nebula-algorithm/src/main/resources/application.conf @@ -90,7 +90,7 @@ tol: 0.5 } - # connected component parameter TODO not implemented yet. + # connected component parameter. connectedcomponent: { maxIter: 20 } From c0e9d4c077270c25a26c045545925026dd52a26a Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 17 May 2021 16:20:52 +0800 Subject: [PATCH 121/213] update description for algorihtms' example configuration --- .../src/main/resources/application.conf | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/nebula-algorithm/src/main/resources/application.conf b/nebula-algorithm/src/main/resources/application.conf index 1b1e17a..d8eb43c 100644 --- a/nebula-algorithm/src/main/resources/application.conf +++ b/nebula-algorithm/src/main/resources/application.conf @@ -77,48 +77,48 @@ # betweenness] executeAlgo: pagerank - # pagerank parameter + # PageRank parameter pagerank: { maxIter: 10 resetProb: 0.15 # default 0.15 } - # louvain parameter + # Louvain parameter louvain: { maxIter: 20 internalIter: 10 tol: 0.5 } - # connected component parameter TODO not implemented yet. + # ConnectedComponent parameter connectedcomponent: { maxIter: 20 } - # LabelPropagation + # LabelPropagation parameter labelpropagation: { maxIter: 20 } - # ShortestPaths + # ShortestPaths parameter shortestpaths: { # several vertices to compute the shortest path to all vertices. landmarks: "1" } - # vertex degree static + # Vertex degree statistics parameter degreestatic: {} - # kcore + # KCore parameter kcore:{ maxIter:10 degree:1 } - # trianglecount + # Trianglecount parameter trianglecount:{} - # betweenness centrality + # Betweenness centrality parameter betweenness:{ maxIter:5 } From fe9f4dec59a6cd27da7c7bbbe11fa975ea7939b6 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 17 May 2021 16:56:41 +0800 Subject: [PATCH 122/213] modify conf file name & update link --- nebula-algorithm/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nebula-algorithm/README.md b/nebula-algorithm/README.md index ef711ab..01332b1 100644 --- a/nebula-algorithm/README.md +++ b/nebula-algorithm/README.md @@ -38,12 +38,12 @@ nebula-algorithm 是一款基于 [GraphX](https://spark.apache.org/graphx/) 的 * 设置配置文件 - 关于配置项的具体说明参考[示例配置](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/nebula-spark-utils/nebula-algorithm/src/main/resources/application.conf) + 关于配置项的具体说明参考[示例配置](https://github.com/vesoft-inc/nebula-spark-utils/blob/master/nebula-algorithm/src/main/resources/application.conf) * 提交算法任务 ``` - ${SPARK_HOME}/bin/spark-submit --master --class com.vesoft.nebula.algorithm.Main nebula-algorithm-2.0.0.jar -p property_file + ${SPARK_HOME}/bin/spark-submit --master --class com.vesoft.nebula.algorithm.Main nebula-algorithm-2.0.0.jar -p application.conf ``` * 使用方法2:调用 nebula-algorithm 算法接口 @@ -62,7 +62,7 @@ nebula-algorithm 是一款基于 [GraphX](https://spark.apache.org/graphx/) 的 val louvainResult = PageRankAlgo.apply(spark, data, prConfig, false) ``` - 其他算法的调用方法见[测试示例](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/nebula-spark-utils/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib) 。 + 其他算法的调用方法见[测试示例](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib) 。 *注:执行算法的DataFrame默认第一列是源点,第二列是目标点,第三列是边权重。* From 3b8a0a237cd210083ad5f67beffe2ea55efb05fc Mon Sep 17 00:00:00 2001 From: wey-gu <1651790+wey-gu@users.noreply.github.com> Date: Mon, 17 May 2021 18:35:19 +0800 Subject: [PATCH 123/213] doc: Algorithm README in en --- nebula-algorithm/README-CN.md | 75 +++++++++++++++++++++++++++ nebula-algorithm/README.md | 98 +++++++++++++++++++---------------- 2 files changed, 128 insertions(+), 45 deletions(-) create mode 100644 nebula-algorithm/README-CN.md diff --git a/nebula-algorithm/README-CN.md b/nebula-algorithm/README-CN.md new file mode 100644 index 0000000..01332b1 --- /dev/null +++ b/nebula-algorithm/README-CN.md @@ -0,0 +1,75 @@ +# 欢迎使用 nebula-algorithm + +nebula-algorithm 是一款基于 [GraphX](https://spark.apache.org/graphx/) 的 Spark 应用程序,提供了以下图计算算法: + + + | 算法名 |中文说明|应用场景| + |:------------------------:|:-----------:|:----:| + | PageRank | 页面排序 | 网页排序、重点节点挖掘| + | Louvain | 社区发现 | 社团挖掘、层次化聚类| + | KCore | K核 |社区发现、金融风控| + | LabelPropagation | 标签传播 |资讯传播、广告推荐、社区发现| + | ConnectedComponent | 联通分量 |社区发现、孤岛发现| + |StronglyConnectedComponent| 强联通分量 |社区发现| + | ShortestPath | 最短路径 |路径规划、网络规划| + | TriangleCount | 三角形计数 |网络结构分析| + | BetweennessCentrality | 介数中心性 |关键节点挖掘,节点影响力计算| + | DegreeStatic | 度统计 |图结构分析| + +使用 `nebula-algorithm`,可以通过提交 `Spark` 任务的形式使用完整的算法工具对 `Nebula Graph` 数据库中的数据执行图计算,也可以通过编程形式调用`lib`库下的算法针对DataFrame执行图计算。 + +## 如何获取 + 1. 编译打包 Nebula-Algorithm + ``` + $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git + $ cd nebula-algorithm + $ mvn clean package -Dgpg.skip -Dmaven.javadoc.skip=true -Dmaven.test.skip=true + ``` + 编译完成后,在 `nebula-algorithm/target` 目录下会生成 `nebula-algorithm-2.0.0.jar` 。 + + 2. 在 Maven 远程仓库下载 + https://repo1.maven.org/maven2/com/vesoft/nebula-algorithm/2.0.0/ + +# 使用 Nebula-Algorithm + + 使用限制:Nebula-Algorithm 未自动对字符串id进行编码,因此执行图算法时,边的源点和目标点必须是整数(Nebula Space 的 vid_type可以是String类型,但数据必须是整数)。 + +* 使用方法1:直接提交 nebula-algorithm 算法包 + + * 设置配置文件 + + 关于配置项的具体说明参考[示例配置](https://github.com/vesoft-inc/nebula-spark-utils/blob/master/nebula-algorithm/src/main/resources/application.conf) + + * 提交算法任务 + + ``` + ${SPARK_HOME}/bin/spark-submit --master --class com.vesoft.nebula.algorithm.Main nebula-algorithm-2.0.0.jar -p application.conf + ``` +* 使用方法2:调用 nebula-algorithm 算法接口 + + 在`nebula-algorithm`的`lib`库中提供了10中常用图计算算法,可通过编程调用的形式调用算法。 + * 在pom.xml中添加依赖 + ``` + + com.vesoft + nebula-algorithm + 2.0.0 + + ``` + * 定义算法参数调用算法(以`PageRank`为例) + ``` + val prConfig = new PRConfig(5, 1.0) + val louvainResult = PageRankAlgo.apply(spark, data, prConfig, false) + ``` + + 其他算法的调用方法见[测试示例](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib) 。 + + *注:执行算法的DataFrame默认第一列是源点,第二列是目标点,第三列是边权重。* + +## 贡献 + +nebula-algorithm 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: + +- 前往 [Nebula Graph 论坛](https://discuss.nebula-graph.com.cn/ "点击前往“Nebula Graph 论坛") 上参与 Issue 讨论,如答疑、提供想法或者报告无法解决的问题 +- 撰写或改进文档 +- 提交优化代码 diff --git a/nebula-algorithm/README.md b/nebula-algorithm/README.md index 01332b1..5bbd4f2 100644 --- a/nebula-algorithm/README.md +++ b/nebula-algorithm/README.md @@ -1,54 +1,62 @@ -# 欢迎使用 nebula-algorithm - -nebula-algorithm 是一款基于 [GraphX](https://spark.apache.org/graphx/) 的 Spark 应用程序,提供了以下图计算算法: - - - | 算法名 |中文说明|应用场景| - |:------------------------:|:-----------:|:----:| - | PageRank | 页面排序 | 网页排序、重点节点挖掘| - | Louvain | 社区发现 | 社团挖掘、层次化聚类| - | KCore | K核 |社区发现、金融风控| - | LabelPropagation | 标签传播 |资讯传播、广告推荐、社区发现| - | ConnectedComponent | 联通分量 |社区发现、孤岛发现| - |StronglyConnectedComponent| 强联通分量 |社区发现| - | ShortestPath | 最短路径 |路径规划、网络规划| - | TriangleCount | 三角形计数 |网络结构分析| - | BetweennessCentrality | 介数中心性 |关键节点挖掘,节点影响力计算| - | DegreeStatic | 度统计 |图结构分析| - -使用 `nebula-algorithm`,可以通过提交 `Spark` 任务的形式使用完整的算法工具对 `Nebula Graph` 数据库中的数据执行图计算,也可以通过编程形式调用`lib`库下的算法针对DataFrame执行图计算。 - -## 如何获取 - 1. 编译打包 Nebula-Algorithm +# Welcome to Nebula-Algorithm + +

                                          + +nebula-algorithm is a Spark Application based on [GraphX](https://spark.apache.org/graphx/) with below Algorithm provided for now: + + +| Name |Use Case| +|:------------------------:|:---------------:| +| PageRank | 网页排序、重点节点挖掘| +| Louvain | 社团挖掘、层次化聚类| +| KCore |社区发现、金融风控| +| LabelPropagation |资讯传播、广告推荐、社区发现| +| ConnectedComponent |社区发现、孤岛发现| +|StronglyConnectedComponent|社区发现| +| ShortestPath |路径规划、网络规划| +| TriangleCount |网络结构分析| +| BetweennessCentrality |关键节点挖掘,节点影响力计算| + +You could either leverage comprehensive Nebula-Algorithm tooling in way to submit its `Spark Application` or invoke its `lib` in a programming way to apply Graph Compute towards the `DataFrame`. + +## Get Nebula-Algorithm + 1. Build Nebula-Algorithm ``` $ git clone https://github.com/vesoft-inc/nebula-spark-utils.git $ cd nebula-algorithm $ mvn clean package -Dgpg.skip -Dmaven.javadoc.skip=true -Dmaven.test.skip=true ``` - 编译完成后,在 `nebula-algorithm/target` 目录下会生成 `nebula-algorithm-2.0.0.jar` 。 + After the above buiding process the target file `nebula-algorithm-2.0.0.jar` will be placed under `nebula-algorithm/target` . - 2. 在 Maven 远程仓库下载 - https://repo1.maven.org/maven2/com/vesoft/nebula-algorithm/2.0.0/ + 2. Download from Maven repo + + Alternatively, it could be downlaoded from below Maven repo: + + https://repo1.maven.org/maven2/com/vesoft/nebula-algorithm/2.0.0/ -# 使用 Nebula-Algorithm +## Use Nebula-Algorithm - 使用限制:Nebula-Algorithm 未自动对字符串id进行编码,因此执行图算法时,边的源点和目标点必须是整数(Nebula Space 的 vid_type可以是String类型,但数据必须是整数)。 - -* 使用方法1:直接提交 nebula-algorithm 算法包 +Limitation: Due to Nebula-Algorithm will not encode string id, thus during the algorithm execution, the source and target of edges must be in Type Int (The `vid_type` in Nebula Space could be String, while data must be in Type Int). + +* Option 1: Submit nebula-algorithm package - * 设置配置文件 + * Configuration - 关于配置项的具体说明参考[示例配置](https://github.com/vesoft-inc/nebula-spark-utils/blob/master/nebula-algorithm/src/main/resources/application.conf) + Refer to [configuration example](https://github.com/vesoft-inc/nebula-spark-utils/blob/master/nebula-algorithm/src/main/resources/application.conf) - * 提交算法任务 + * Submit Spark Applicaiton ``` ${SPARK_HOME}/bin/spark-submit --master --class com.vesoft.nebula.algorithm.Main nebula-algorithm-2.0.0.jar -p application.conf ``` -* 使用方法2:调用 nebula-algorithm 算法接口 + +* Option2: Call nebula-algorithm interface - 在`nebula-algorithm`的`lib`库中提供了10中常用图计算算法,可通过编程调用的形式调用算法。 - * 在pom.xml中添加依赖 + Now there are 10 algorithms provided in `lib` from `nebula-algorithm`, which could be invoked in a programming fashion as below: + + * Add depedencies from `pom.xml` ``` com.vesoft @@ -56,20 +64,20 @@ nebula-algorithm 是一款基于 [GraphX](https://spark.apache.org/graphx/) 的 2.0.0 ``` - * 定义算法参数调用算法(以`PageRank`为例) + * Pass arguments of the algorithm, below is an example for `PageRank`. ``` val prConfig = new PRConfig(5, 1.0) val louvainResult = PageRankAlgo.apply(spark, data, prConfig, false) ``` - - 其他算法的调用方法见[测试示例](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib) 。 - - *注:执行算法的DataFrame默认第一列是源点,第二列是目标点,第三列是边权重。* + + For other algorithms, please refer to [test cases](https://github.com/vesoft-inc/nebula-spark-utils/tree/master/nebula-algorithm/src/test/scala/com/vesoft/nebula/algorithm/lib). + + *Note: The first column of DataFrame in the application are the source vertices, the second are the target vertices and the third are edges' weight.* -## 贡献 +## Contribute -nebula-algorithm 是一个完全开源的项目,欢迎开源爱好者通过以下方式参与: +nebula-algorithm is an Open-Source project, you are more than welcomed to contribute in below ways: -- 前往 [Nebula Graph 论坛](https://discuss.nebula-graph.com.cn/ "点击前往“Nebula Graph 论坛") 上参与 Issue 讨论,如答疑、提供想法或者报告无法解决的问题 -- 撰写或改进文档 -- 提交优化代码 +- Discuss in the community via [the forum](https://discuss.nebula-graph.io/) or raise issues here. +- Compose or improve our documents. +- Pull Request to help improve the code itself here. \ No newline at end of file From 038a3e18ec19dab8e6242d2347323f5b26dda74f Mon Sep 17 00:00:00 2001 From: wey-gu <1651790+wey-gu@users.noreply.github.com> Date: Tue, 18 May 2021 09:44:49 +0800 Subject: [PATCH 124/213] Added parts from Anqi Co-authored-by: Anqi <16240361+Nicole00@users.noreply.github.com> --- nebula-algorithm/README.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/nebula-algorithm/README.md b/nebula-algorithm/README.md index 5bbd4f2..4bd7558 100644 --- a/nebula-algorithm/README.md +++ b/nebula-algorithm/README.md @@ -9,17 +9,19 @@ nebula-algorithm is a Spark Application based on [GraphX](https://spark.apache.o | Name |Use Case| |:------------------------:|:---------------:| -| PageRank | 网页排序、重点节点挖掘| -| Louvain | 社团挖掘、层次化聚类| -| KCore |社区发现、金融风控| -| LabelPropagation |资讯传播、广告推荐、社区发现| -| ConnectedComponent |社区发现、孤岛发现| -|StronglyConnectedComponent|社区发现| -| ShortestPath |路径规划、网络规划| -| TriangleCount |网络结构分析| -| BetweennessCentrality |关键节点挖掘,节点影响力计算| - -You could either leverage comprehensive Nebula-Algorithm tooling in way to submit its `Spark Application` or invoke its `lib` in a programming way to apply Graph Compute towards the `DataFrame`. +| PageRank | page ranking, important node digging| +| Louvain | community digging, hierarchical clustering| +| KCore | community detection, financial risk control| +| LabelPropagation | community detection, consultation propagation, advertising recommendation| +| ConnectedComponent | community detection, isolated island detection| +|StronglyConnectedComponent| community detection| +| ShortestPath | path plan, network plan| +| TriangleCount | network structure analysis| +| BetweennessCentrality | important node digging, node influence calculation| +| DegreeStatic | graph structure analysis| + + +You could submit the entire spark application or invoke algorithms in `lib` library to apply graph algorithms for DataFrame. ## Get Nebula-Algorithm 1. Build Nebula-Algorithm From 5f1ebbfdc27f263adc69e5d35226511880e80499 Mon Sep 17 00:00:00 2001 From: cooper-lzy <78672629+cooper-lzy@users.noreply.github.com> Date: Tue, 18 May 2021 10:04:49 +0800 Subject: [PATCH 125/213] Delete nebula-exchange/doc-2.0 directory --- .../CN/about-exchange/ex-ug-limitations.md | 39 -- .../doc-2.0/CN/about-exchange/ex-ug-terms.md | 9 - .../about-exchange/ex-ug-what-is-exchange.md | 61 --- nebula-exchange/doc-2.0/CN/ex-ug-FAQ.md | 95 ----- nebula-exchange/doc-2.0/CN/ex-ug-compile.md | 85 ---- nebula-exchange/doc-2.0/CN/ex-ug-toc.md | 25 -- nebula-exchange/doc-2.0/CN/figs/ex-ug-001.png | Bin 151025 -> 0 bytes nebula-exchange/doc-2.0/CN/figs/ex-ug-002.png | Bin 60193 -> 0 bytes .../.ex-ug-paras-nebulagraph.md | 16 - .../parameter-reference/.ex-ug-paras-neo4j.md | 36 -- .../parameter-reference/.ex-ug-paras-spark.md | 10 - .../ex-ug-para-import-command.md | 19 - .../CN/parameter-reference/ex-ug-parameter.md | 168 -------- .../CN/use-exchange/.ex-ug-import-from-sst.md | 98 ----- .../CN/use-exchange/.ex-ug-import-steps.md | 55 --- .../CN/use-exchange/ex-ug-import-from-csv.md | 392 ----------------- .../use-exchange/ex-ug-import-from-hbase.md | 337 --------------- .../CN/use-exchange/ex-ug-import-from-hive.md | 360 ---------------- .../CN/use-exchange/ex-ug-import-from-json.md | 396 ------------------ .../use-exchange/ex-ug-import-from-kafka.md | 293 ------------- .../use-exchange/ex-ug-import-from-mysql.md | 348 --------------- .../use-exchange/ex-ug-import-from-neo4j.md | 313 -------------- .../CN/use-exchange/ex-ug-import-from-orc.md | 364 ---------------- .../use-exchange/ex-ug-import-from-parquet.md | 364 ---------------- .../use-exchange/ex-ug-import-from-pulsar.md | 307 -------------- .../EN/about-exchange/ex-ug-limitations.md | 32 -- .../doc-2.0/EN/about-exchange/ex-ug-terms.md | 9 - .../about-exchange/ex-ug-what-is-exchange.md | 59 --- nebula-exchange/doc-2.0/EN/ex-ug-compile.md | 47 --- nebula-exchange/doc-2.0/EN/ex-ug-faq.md | 123 ------ nebula-exchange/doc-2.0/EN/ex-ug-toc.md | 25 -- nebula-exchange/doc-2.0/EN/figs/ex-ug-001.png | Bin 151025 -> 0 bytes nebula-exchange/doc-2.0/EN/figs/ex-ug-002.png | Bin 60193 -> 0 bytes .../ex-ug-para-import-command.md | 17 - .../ex-ug-paras-nebulagraph.md | 16 - .../parameter-reference/ex-ug-paras-spark.md | 10 - .../EN/use-exchange/ex-ug-import-from-csv.md | 312 -------------- .../EN/use-exchange/ex-ug-import-hive.md | 374 ----------------- .../EN/use-exchange/ex-ug-import-json.md | 288 ------------- .../EN/use-exchange/ex-ug-import-steps.md | 45 -- 40 files changed, 5547 deletions(-) delete mode 100644 nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-limitations.md delete mode 100644 nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-terms.md delete mode 100644 nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-what-is-exchange.md delete mode 100644 nebula-exchange/doc-2.0/CN/ex-ug-FAQ.md delete mode 100644 nebula-exchange/doc-2.0/CN/ex-ug-compile.md delete mode 100644 nebula-exchange/doc-2.0/CN/ex-ug-toc.md delete mode 100644 nebula-exchange/doc-2.0/CN/figs/ex-ug-001.png delete mode 100644 nebula-exchange/doc-2.0/CN/figs/ex-ug-002.png delete mode 100644 nebula-exchange/doc-2.0/CN/parameter-reference/.ex-ug-paras-nebulagraph.md delete mode 100644 nebula-exchange/doc-2.0/CN/parameter-reference/.ex-ug-paras-neo4j.md delete mode 100644 nebula-exchange/doc-2.0/CN/parameter-reference/.ex-ug-paras-spark.md delete mode 100644 nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-para-import-command.md delete mode 100644 nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-parameter.md delete mode 100644 nebula-exchange/doc-2.0/CN/use-exchange/.ex-ug-import-from-sst.md delete mode 100644 nebula-exchange/doc-2.0/CN/use-exchange/.ex-ug-import-steps.md delete mode 100644 nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-csv.md delete mode 100644 nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-hbase.md delete mode 100644 nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-hive.md delete mode 100644 nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-json.md delete mode 100644 nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-kafka.md delete mode 100644 nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-mysql.md delete mode 100644 nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-neo4j.md delete mode 100644 nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-orc.md delete mode 100644 nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-parquet.md delete mode 100644 nebula-exchange/doc-2.0/CN/use-exchange/ex-ug-import-from-pulsar.md delete mode 100644 nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-limitations.md delete mode 100644 nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-terms.md delete mode 100644 nebula-exchange/doc-2.0/EN/about-exchange/ex-ug-what-is-exchange.md delete mode 100644 nebula-exchange/doc-2.0/EN/ex-ug-compile.md delete mode 100644 nebula-exchange/doc-2.0/EN/ex-ug-faq.md delete mode 100644 nebula-exchange/doc-2.0/EN/ex-ug-toc.md delete mode 100644 nebula-exchange/doc-2.0/EN/figs/ex-ug-001.png delete mode 100644 nebula-exchange/doc-2.0/EN/figs/ex-ug-002.png delete mode 100644 nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-para-import-command.md delete mode 100644 nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-nebulagraph.md delete mode 100644 nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-spark.md delete mode 100644 nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-from-csv.md delete mode 100644 nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-hive.md delete mode 100644 nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-json.md delete mode 100644 nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-steps.md diff --git a/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-limitations.md b/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-limitations.md deleted file mode 100644 index c2272fb..0000000 --- a/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-limitations.md +++ /dev/null @@ -1,39 +0,0 @@ -# 使用限制 - -本文描述Exchange 2.0的一些使用限制。 - -## Nebula Graph版本 - -Exchange client版本(即JAR包版本)和Nebula Graph的版本对应关系如下。 -|Exchange client版本|Nebula Graph版本| -|:---|:---| -|2.0.0|2.0.0| -|2.0.0|2.0.1| - -JAR包有两种获取方式:[自行编译](../ex-ug-compile.md)或者从maven仓库下载。 - -如果您正在使用Nebula Graph 1.x,请使用[Nebula Exchange 1.x](https://github.com/vesoft-inc/nebula-java/tree/v1.0/tools "Click to go to GitHub")。 - -## 使用环境 - -Exchange 2.0 支持以下操作系统: - -- CentOS 7 -- macOS - -> **说明**:仅Linux系统支持导入SST文件。 - -## 软件依赖 - -为保证Exchange正常工作,请确认您的机器上已经安装如下软件: - -- Apache Spark:2.3.0及以上版本 - -- Java:1.8 - -- Scala:2.10.7、2.11.12或2.12.10 - -在以下使用场景,还需要部署Hadoop Distributed File System (HDFS): - -- 迁移HDFS的数据 -- 生成SST文件 diff --git a/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-terms.md b/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-terms.md deleted file mode 100644 index f61eac7..0000000 --- a/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-terms.md +++ /dev/null @@ -1,9 +0,0 @@ -# 名词解释 - -本文描述使用Exchange时可能需要了解的名词和解释。 - -- Nebula Exchange:在本手册中简称为Exchange或Exchange 2.x,是一款基于Apache Spark™的Spark应用,用于批量数据迁移。它支持将多种不同来源和格式的数据文件转换为Nebula Graph能识别的点和边数据,再并发导入Nebula Graph。 - -- Aparch Spark™:是专为大规模数据处理而设计的快速通用的计算引擎,是Apache软件基金会的一个开源项目。 - -- Driver Program:在本手册中简称为Driver,是运行应用的main函数并且新建SparkContext实例的程序。 diff --git a/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-what-is-exchange.md b/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-what-is-exchange.md deleted file mode 100644 index 44872a8..0000000 --- a/nebula-exchange/doc-2.0/CN/about-exchange/ex-ug-what-is-exchange.md +++ /dev/null @@ -1,61 +0,0 @@ -# 什么是Nebula Exchange - -[Nebula Exchange](https://github.com/vesoft-inc/nebula-spark-utils/tree/v2.0.0/nebula-exchange)(简称Exchange)是一款Apache Spark™应用,用于在分布式环境中将集群中的数据批量迁移到Nebula Graph中,能支持多种不同格式的批式数据和流式数据的迁移。 - -Exchange由Reader、Processor和Writer三部分组成。Reader读取不同来源的数据返回DataFrame后,Processor遍历DataFrame的每一行,根据配置文件中`fields`的映射关系,按列名获取对应的值。在遍历指定批处理的行数后,Writer会将获取的数据一次性写入到Nebula Graph中。下图描述了Exchange完成数据转换和迁移的过程。 - -![Nebula Graph® Exchange 由 Reader、Processor、Writer 组成,可以完成多种不同格式和来源的数据向 Nebula Graph 的迁移](../figs/ex-ug-001.png "Nebula Graph® Exchange 转数据转换和迁移的过程") - -## 适用场景 - -Exchange适用于以下场景: - -- 需要将来自Kafka、Pulsar平台的流式数据,如日志文件、网购数据、游戏内玩家活动、社交网站信息、金融交易大厅或地理空间服务,以及来自数据中心内所连接设备或仪器的遥测数据等转化为属性图的点或边数据,并导入Nebula Graph数据库。 - -- 需要从关系型数据库(如MySQL)或者分布式文件系统(如HDFS)中读取批式数据,如某个时间段内的数据,将它们转化为属性图的点或边数据,并导入 Nebula Graph数据库。 - -- 需要将大批量数据生成Nebula Graph能识别的SST文件,再导入Nebula Graph数据库。 - -## 产品优点 - -Exchange具有以下优点: - -- 适应性强:支持将多种不同格式或不同来源的数据导入Nebula Graph数据库,便于迁移数据。 - -- 支持导入SST:支持将不同来源的数据转换为SST文件,用于数据导入。 - - > **说明**:仅Linux系统支持导入SST文件。 - -- 支持断点续传:导入数据时支持断点续传,有助于您节省时间,提高数据导入效率。 - - > **说明**:目前仅迁移Neo4j数据时支持断点续传。 - -- 异步操作:会在源数据中生成一条插入语句,发送给Graph服务,最后再执行插入操作。 - -- 灵活性强:支持同时导入多个标签和边类型,不同标签和边类型可以是不同的数据来源或格式。 - -- 统计功能:使用Apache Spark™中的累加器统计插入操作的成功和失败次数。 - -- 易于使用:采用HOCON(Human-Optimized Config Object Notation)配置文件格式,具有面向对象风格,便于理解和操作。 - -## 数据格式和来源 - -Exchange 2.0支持将以下格式或来源的数据转换为Nebula Graph能识别的点和边数据: - -- 存储在HDFS的数据,包括: - - [Apache Parquet](../use-exchange/ex-ug-import-from-parquet.md) - - [Apache ORC](../use-exchange/ex-ug-import-from-orc.md) - - [JSON](../use-exchange/ex-ug-import-from-json.md) - - [CSV](../use-exchange/ex-ug-import-from-csv.md) - -- [Apache HBase™](../use-exchange/ex-ug-import-from-hbase.md) - -- 数据仓库:[Hive](../use-exchange/ex-ug-import-from-hive.md) - -- 图数据库:[Neo4j](../use-exchange/ex-ug-import-from-neo4j.md)(Client版本2.4.5-M1) - -- 关系型数据库:[MySQL](../use-exchange/ex-ug-import-from-mysql.md) - -- 流处理软件平台:[Apache Kafka®](../use-exchange/ex-ug-import-from-kafka.md) - -- 发布/订阅消息平台:[Apache Pulsar 2.4.5](../use-exchange/ex-ug-import-from-pulsar.md) \ No newline at end of file diff --git a/nebula-exchange/doc-2.0/CN/ex-ug-FAQ.md b/nebula-exchange/doc-2.0/CN/ex-ug-FAQ.md deleted file mode 100644 index 297d064..0000000 --- a/nebula-exchange/doc-2.0/CN/ex-ug-FAQ.md +++ /dev/null @@ -1,95 +0,0 @@ -# 常见问题FAQ - -## 编译问题 - -### 部分非central仓库的包下载失败,报错`Could not resolve dependencies for project xxx` - -请检查Maven安装目录下`libexec/conf/settings.xml`文件的`mirror`部分: - -```text - - alimaven - central - aliyun maven - http://maven.aliyun.com/nexus/content/repositories/central/ - -``` - -检查`mirrorOf`的值是否配置为`*`,如果为`*`,请修改为`central`或`*,!SparkPackagesRepo,!bintray-streamnative-maven`。 - -**原因**:Exchange的`pom.xml`中有两个依赖包不在Maven的central仓库中,`pom.xml`配置了这两个依赖所在的仓库地址。如果您的maven中配置的镜像地址对应的`mirrorOf`值为`*`,那么所有依赖都会在central仓库下载,导致下载失败。 - -## 执行问题 - -### 报错`method name xxx not found` - -一般是端口配置错误,需检查Meta服务、Graph服务、Storage服务的端口配置。 - -### 报NoSuchMethod、MethodNotFound错误(`Exception in thread "main" java.lang.NoSuchMethodError`等) - -绝大多数是因为JAR包冲突和版本冲突导致的报错,请检查报错服务的版本,与Exchange中使用的版本进行对比,检查是否一致,尤其是Spark版本、Scala版本、Hive版本。 - -### Exchange导入Hive数据时报错`Exception in thread "main" org.apache.spark.sql.AnalysisException: Table or view not found` - -检查提交exchange任务的命令中是否遗漏参数`-h`,检查table和database是否正确,在spark-sql中执行用户配置的exec语句,验证exec语句的正确性。 - -### 运行时报错`com.facebook.thrift.protocol.TProtocolException: Expected protocol id xxx` - -请检查Nebula Graph服务端口配置是否正确。 - -- 如果是源码、RPM或DEB安装,请配置各个服务的配置文件中`--port`对应的端口号。 - -- 如果是docker安装,请配置docker映射出来的端口号,查看方式如下: - - 在`nebula-docker-compose`目录下执行`docker-compose ps`,例如: - - ```bash - $ docker-compose ps - Name Command State Ports - --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - nebula-docker-compose_graphd_1 /usr/local/nebula/bin/nebu ... Up (healthy) 0.0.0.0:33205->19669/tcp, 0.0.0.0:33204->19670/tcp, 0.0.0.0:9669->9669/tcp - nebula-docker-compose_metad0_1 ./bin/nebula-metad --flagf ... Up (healthy) 0.0.0.0:33165->19559/tcp, 0.0.0.0:33162->19560/tcp, 0.0.0.0:33167->9559/tcp, 9560/tcp - nebula-docker-compose_metad1_1 ./bin/nebula-metad --flagf ... Up (healthy) 0.0.0.0:33166->19559/tcp, 0.0.0.0:33163->19560/tcp, 0.0.0.0:33168->9559/tcp, 9560/tcp - nebula-docker-compose_metad2_1 ./bin/nebula-metad --flagf ... Up (healthy) 0.0.0.0:33161->19559/tcp, 0.0.0.0:33160->19560/tcp, 0.0.0.0:33164->9559/tcp, 9560/tcp - nebula-docker-compose_storaged0_1 ./bin/nebula-storaged --fl ... Up (healthy) 0.0.0.0:33180->19779/tcp, 0.0.0.0:33178->19780/tcp, 9777/tcp, 9778/tcp, 0.0.0.0:33183->9779/tcp, 9780/tcp - nebula-docker-compose_storaged1_1 ./bin/nebula-storaged --fl ... Up (healthy) 0.0.0.0:33175->19779/tcp, 0.0.0.0:33172->19780/tcp, 9777/tcp, 9778/tcp, 0.0.0.0:33177->9779/tcp, 9780/tcp - nebula-docker-compose_storaged2_1 ./bin/nebula-storaged --fl ... Up (healthy) 0.0.0.0:33184->19779/tcp, 0.0.0.0:33181->19780/tcp, 9777/tcp, 9778/tcp, 0.0.0.0:33185->9779/tcp, 9780/tcp - ``` - - 查看`Ports`列,查找docker映射的端口号,例如: - - - Graph服务可用的端口号是9669。 - - - Meta服务可用的端口号有33167、33168、33164。 - - - Storage服务可用的端口号有33183、33177、33185。 - -## 配置问题 - -### 哪些配置项影响导入性能? - -- batch:每次发送给Nebula Graph服务的nGQL语句中包含的数据条数。 - -- partition:Spark数据的分区数,表示数据导入的并发数。 - -- nebula.rate:向Nebula Graph发送请求前先去令牌桶获取令牌。 - - - limit:表示令牌桶的大小。 - - - timeout:表示获取令牌的超时时间。 - -根据机器性能可适当调整这四项参数的值。如果在导入过程中,Storage服务的leader变更,可以适当调小这四项参数的值,降低导入速度。 - -## 其他问题 - -### Exchange支持哪些版本的Nebula Graph? - -请参见Exchange的[使用限制](about-exchange/ex-ug-limitations.md)。 - -### Exchange与Spark Writer有什么关系? - -Exchange是在Spark Writer基础上开发的Spark应用程序,二者均适用于在分布式环境中将集群的数据批量迁移到Nebula Graph中,但是后期的维护工作将集中在 Exchange上。与Spark Writer相比,Exchange有以下改进: - -- 支持更丰富的数据源,如MySQL、Neo4j、Hive、HBase、Kafka、Pulsar等。 - -- 修复了Spark Writer的部分问题。例如Spark读取HDFS里的数据时,默认读取到的源数据均为String类型,可能与Nebula Graph定义的Schema不同,所以Exchange增加了数据类型的自动匹配和类型转换,当Nebula Graph定义的Schema中数据类型为非String类型(如double)时,Exchange会将String类型的源数据转换为对应的类型(如double)。 \ No newline at end of file diff --git a/nebula-exchange/doc-2.0/CN/ex-ug-compile.md b/nebula-exchange/doc-2.0/CN/ex-ug-compile.md deleted file mode 100644 index 2fed4cb..0000000 --- a/nebula-exchange/doc-2.0/CN/ex-ug-compile.md +++ /dev/null @@ -1,85 +0,0 @@ -# 编译Exchange - -本文介绍如何编译Nebula Exchange。您也可以直接[下载](https://repo1.maven.org/maven2/com/vesoft/nebula-exchange/2.0.0/)编译完成的`.jar`文件。 - -## 前提条件 - -安装[Maven](https://maven.apache.org/download.cgi)。 - -## 编译流程 - -1. 克隆仓库`nebula-java`。 - - ```bash - git clone -b v2.0.0-ga https://github.com/vesoft-inc/nebula-java.git - ``` - -2. 切换到目录`nebula-java`。 - - ```bash - cd nebula-java - ``` - -3. 安装Nebula Java Client 2.0.0。 - - ```bash - mvn clean install -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true - ``` - - >**说明**:安装后在本地Maven仓库会生成`.jar`文件,例如`com/vesoft/client/2.0.0/client-2.0.0.jar`。 - -4. 返回根目录克隆仓库`nebula-spark-utils`。 - - ```bash - cd ~ && git clone -b v2.0.0 https://github.com/vesoft-inc/nebula-spark-utils.git - ``` - -5. 切换到目录`nebula-exchange`。 - - ```bash - cd nebula-spark-utils/nebula-exchange - ``` - -6. 打包Nebula Exchange 2.0.0。 - - ```bash - mvn clean package -Dmaven.test.skip=true -Dgpg.skip -Dmaven.javadoc.skip=true - ``` - - >**说明**:如果报错`Could not resolve dependencies for project xxx`,请修改Maven安装目录下`libexec/conf/settings.xml`文件的`mirror`部分: - > - >```text - > - >alimaven - >central - >aliyun maven - >http://maven.aliyun.com/nexus/content/repositories/central/ - > - >``` - -编译成功后,您可以在当前目录里查看到类似如下目录结构。 - -```text -. -├── README-CN.md -├── README.md -├── pom.xml -├── src -│   ├── main -│   └── test -└── target - ├── classes - ├── classes.timestamp - ├── maven-archiver - ├── nebula-exchange-2.x.y-javadoc.jar - ├── nebula-exchange-2.x.y-sources.jar - ├── nebula-exchange-2.x.y.jar - ├── original-nebula-exchange-2.x.y.jar - └── site -``` - -在`target`目录下,您可以找到`exchange-2.x.y.jar`文件。 - -> **说明**:`.jar`文件版本号会因Nebula Java Client的发布版本而变化。您可以在[Releases页面](https://github.com/vesoft-inc/nebula-java/releases)查看最新版本。 - -迁移数据时,您可以参考配置文件[`target/classes/application.conf`](https://github.com/vesoft-inc/nebula-spark-utils/blob/master/nebula-exchange/src/main/resources/application.conf)。 diff --git a/nebula-exchange/doc-2.0/CN/ex-ug-toc.md b/nebula-exchange/doc-2.0/CN/ex-ug-toc.md deleted file mode 100644 index 38d7b75..0000000 --- a/nebula-exchange/doc-2.0/CN/ex-ug-toc.md +++ /dev/null @@ -1,25 +0,0 @@ -# Nebula Exchange 用户手册 - -- 认识 Nebula Exchange - - [什么是 Nebula Exchange](about-exchange/ex-ug-what-is-exchange.md) - - [使用限制](about-exchange/ex-ug-limitations.md) - - [名词解释](about-exchange/ex-ug-terms.md) -- [编译 Exchange](ex-ug-compile.md) -- 操作指南 - - [导入Apache Parquet数据](use-exchange/ex-ug-import-from-parquet.md) - - [导入Apache ORC数据](use-exchange/ex-ug-import-from-orc.md) - - [导入JSON数据](use-exchange/ex-ug-import-from-json.md) - - [导入CSV数据](use-exchange/ex-ug-import-from-csv.md) - - [导入Neo4j数据](use-exchange/ex-ug-import-from-neo4j.md) - - [导入Apache HBase™数据](use-exchange/ex-ug-import-from-hbase.md) - - [导入Hive数据](use-exchange/ex-ug-import-from-hive.md) - - [导入MySQL数据](use-exchange/ex-ug-import-from-mysql.md) - - [导入Kafka数据](use-exchange/ex-ug-import-from-kafka.md) - - [导入Pulsar数据](use-exchange/ex-ug-import-from-pulsar.md) - - 导入SST文件(TODO:doc) -- 参数说明 - - [配置说明](parameter-reference/ex-ug-parameter.md) - - [导入命令参数](parameter-reference/ex-ug-para-import-command.md) -- [常见问题](ex-ug-faq.md) -- 错误信息(TODO:doc) - diff --git a/nebula-exchange/doc-2.0/CN/figs/ex-ug-001.png b/nebula-exchange/doc-2.0/CN/figs/ex-ug-001.png deleted file mode 100644 index 0e57d6f37d403a85e59ae6b842c289fbaa8ff791..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151025 zcmeFZg;!nA(k6@?2=4Cg65I&{cXxMpcbDLLa0z~Z;O-$%fQFeKsszLtcfgMj|meJBWs zC>sdC|9VCdeE$0b1RsCj`JZR#LdgI1H27X2)PFq<$SZ{YuWQKDzpu@vsqukN@XpdY zZV(W-7=I5)tAaUjw?!ai#6{J;A>pdmt$bgL^UeTS+R99bd;Wx_3zZ1eKQ=?jzDO)w+?!g~-v%5rpR8r1 zt)rE_ZWm%cua<`JO{E&5jSi>gywyOY#m+rh_~syx=ut=a-}DBOm8#COaH;vc(1m4pgl${UMTd{!2YrTWJXKw?~(LSf}~J#9Ch{x{!Y1fb(T zz|{fD{WoKl4=zf@CH42r14sw|L%WHEkSKqpm~fT(r%$E(V&RqDZ+63`Yf>TLlm6c( z5{O>-E6vDUhvlC>g@E^FgN#u$^uJp1_-A>2X9W-MCYEX9pA`VfN+U8m7KeANqh;dAUJFnQ%lMIkJJ$Dn38?H3kJGHY6E_c>eNM219z18sz23S zGQA3SPPkP}`14OHzy`vDi?ng1SZLkm7CDA7?)5~UU-jd#XOAgnHHN_WOsT@wsZkp3 z&(SP*n{IulA68o2xc^=b%G&^Ev#|H65-0rv7bVKJQMMp^?^K&q`Sm696FvK|HL|h3 z0D1nFkE~H*b9KVlr>f2zX>swX{_NEBVpNbXBW8u(P-{cG9+RU|3A>8N&a#z6NYcq+ z0t5TX$jMD+pj|p6N%qHDv{7=V+DzIku_)Vf`M-aDn@VK%ixm`nlE_z#UmcSwJj@0s z+mYq4j&Zi;Ea^8bl^9w1^vU?8)N@C{;w56r2u-n0&VY-m>Kw-9xsKU6>Ibha?_hT{cw7Mobnt!hsI!%D!rIG%lfUx$i4^hhKkHmXT(k305$Hgc| zlBf>^oLe{Q!(fc^dYwsfJ`;vx##6YND@AoB5o#E3^BzCn>H+_#%DVh{ z@LkjJ4r9)q*}>K^v3>o|h%W%?KE%IPa3E}oB~>H@Gx%QhXp5R`5f>=cGq=7)(>k#G zi@>i=-DBG&n|Mo{0RgmK%)>)-Y!$Glo17do>gLUs{2%5ammJcKBRxRxk>N2%@TReL z>K-!&ZWx)+obF4#IK##aoNimM+HjS6(|1ZaBKnWbzoCKZjR{uY&wfGhVPVpO#A=&B zi`bZ8xx#~uBM3mM?->t3$Pp>GNMLwyZ&(kck&az-9v+KFxuKlN{9SwZN$= zrW&x-quT^qVC>7i(WO+8Sqg~QvYH8MIzEG%sQddW&rhI)Hd#sIxlYV($T2zV21nV2 zIlY1y9l7rM>we}~7U+6*j4fRgIzgfdG@}opJQlJa?fan7K{B_{=x1Z3qR9UBcZ0&V z6c-;}9GU0YahD&t88cIRv|^*HFq;r(KbatJ$fsX!`m0bj+%pb~( ztcwFWVUp!A=nnsi;}-h+VXBA<`HaQay^%@k8@yfCW(1@ZI**761>*ssC^Ey;_SxAM zEd(qO-hR?e$g%1OX-F>Gg8*PlUKA}pF4KHE4I)~`^J&ilGt%7(S=+g?Bt6gNhK{lJ z?M63f#KT$aKNbit6i_2Y*x9WtmxqI-;0L!(Wm0pL-zP8p4p>t4687CRr?4=h|+<;>-5wFkpSwBgt?74${2q+fjzg{;W;V3r}g|Iu0 z54Y@HI6OxJqzkn%3V*3Hp%M}*KuLu4y~PsmeB|$d=HaY;`7PIm?KY-n-{5G0HY)Q< zMwEV!Yok9-j!daqstZSw4vI*oCea~0S`zxv*fPOfaQdH~%2Zw-=weVEXPo*I1Se}j<`&5tX%m8Z6*45vWm79SK^STD7SP7c`%wZor)3fuSSd)ff5`v$wjP2Z))!EFl$JJt z2K!aQy|Rfe6{>WMCdvfHgKXF`ykdCN|JsnukZ+KY4m$n~bP}0KxwdIq% z7f;V@Z z!%Xq$xb$`|SZ4fI?(4~buGqf8SmN3pl5Nq>-ZTZd@0(uDwg?0BAkW$3IV?>DjWF~! zyEEse@0)!~GC`Z4(WLh}lVud*`FLIuZ_eyQz~A7w6q=I(CPAPHH+gZZW?$YH)fF zlu=N~7*A)EzPDX0@gE+CV~83(mSD2jb_qQDf@wJr9)0EPACym+gY;CG8y)LLn3`Xi z!=D+;RC*K}sB)whdWD>T};2&^~k>C~!w)nw-26Sh56|TYgeV?v`vZwFAc{^Xd z$wat!X~iyC?_Xq7g@1*w8Hj0%zn!8^l#c@Wf6Lq3zD#6I^nyn!kq&mMi+s(0vS83b z0U}K)lFt$MT}gwo_RKQS0#-}OQ2m5B*jzH15mrDBRvVBQB&TEoNX0z{QzY%I!APoKc>zIyjr zRs7doxa-HqjBBTEn#C%OA8xm9<5$Q@Y_)OeMnNxw(Wt4PGRd&VGX%>l^mG(Ymt;sJp;&wTmU!|8OGP%U{ zHAW_1^3?B0rh(N_NQc4ODrF;4Piqg}`1*XPosXOnZUlhe^+`WHL&FgEk5!5==P>k9 zb@;`b<8P3uIL5iWO%(*@nql`-gI}tb>-=^(JnDTl#O1NhaXx?-b+Df0B z2OJpEDMR_Ms~5KE;KO4DK-q3I-748ciR^3@H&3-o>-S!Dz(rWhGpDnc1hns08wE}a z1Q%^dv?Kvys6$AP{xA?bb;>Ykg~Z}9c}?--v%%w@uISfxpbq6g$>oPGuPmIN($1F! zG9cnIbBCtt+6z5M)7k|1$iXKv&~~;sVKl?(wFW{X`LUNs)&400n)UaK`gr}Ym7DU^ zKJ}Q+_3_Dwl)5|WyU~AO`{63>?%t&D^+O{C7)70$2n=93QgI9rT=P76$es${TCqQ6 zS{(arKmIAzQ`_S7Mt^m`{nKCbl#36!Jgsz4h;*zj1gUxNnN`Q7>`C)1&3|*3BTn1c zpOe`~_FOVyI?61Zb@NmLY$>+Vglq*v0(5ZT_z@wL{gf=kRNQz}HOmGyC1+B5=-#Xr zv75HHTs6C?f09xZ4l7U-df9X#h&vq+!vOh7dk_gvP`<2>>paek<#-zpx5=Dp?2vhl zih=!e(RiN+BeYArBG*i$!1^`ihl8u+V%5e&81FQs`4J@SYy%?%1o*XWRKp5N=n$TU zgJa(xQig~4-hxk+*l}Vg=UcR+3B(zy$)zRs&v?~gZNMn&PK z7%@M!D2)i1G%B^kI?Y7%B{($2DfSDM~wE6YjfRNN<02 z#%?TqTPx9BWZ2zHY?H({-W`*Byp^x`gxP=FV!uMJ!7wZ>B2B*#@&$kDqfJ}|EbdaO zz(vQ0`+efUamW_#UbM7IF&+iD%#?4ezWUWZGwIY*kc{{we=z(2f(fKya>j8_A8fX6 zgj>(9=5e-+iH;0L5WY3I?1^vWd)PkPMp)ivJncmtZ0}G;1|jLA1VD$X2(SJco6=gV z9n+{~R(?2JwSS<;g$`MQ^imT-b)|9p6Jx*Dr8Azv%q+Sy%eyi2iBv9nh)qGtAb%{E z7XPPJECA+%tPiu10`pXc_mK|n-`QhM8;tk$#FwYSvB*B*FNob6 ztc#29lSvcg!X7#6>)ecfkgwn+sI2|h4a4zSl7o_n>+41&_6Q3ASVCchke=CtY>mtA zDzcc8A@LwiGUv_KvmC?%!O#=$C1628K1_}@3IYQcmvz23m;P}*;N|!<1h3Iy4F&)9 z_gX{X9u214Xo&VFjY{>De&`oDY&fg=FFG z{1n^8D!vat(TF5_e`ik`)y)ja{`NmHj}}_mHZuRy_37ZAXH-mEI$7qjn;M(Jtalw_ zH8VGjO6}8|cu)TIH;|mc5GQPE#}|)d_kwlTTjX*NKEI${EJ|LRtNW_e=7?=|>`=%d zSVoX^NC$s$7uS2W#94{R3PgQ>h_8L%A9mLvX`QZpR?KW z`fB}VSc+&?XDeBxp{%3dkL+v-)rUHA9^dATPp3b#H^v$*@9KkdpiN?A0WUY8@j#47yqLAnN;`XoV3jcJTpOKJHD zJwkUgZz-8+(b@*6vBWiHmwiPF&{wCIX}Vqam-Aw}t?la@v=Ibe6evI^r}4|%cg`ab znyJL`bOzb?O`-i#m12dD4=wQJb~=K-89%0GIk);TfU>%HHY_Jx zwEPq`Txl`LLf%FCN|E2AFxnWwF=0LJj1Q=o*7AeS&Q&s8)M>en2X)+s61!$BpRa*M z;=9Kf!)2yH6)Pd8(jr!Wd>ht^@vH^HjFjGefmAfR$u$Y9O39W}zZHKA3MhMCtU6f6 zOek03oVjlIi5_ow1v6>4;dvdeI6=FU3HdMBHQ3%0=)dDj+QVI;rV$Hx%4}JE7(;an zbiFJdNQ%+UdMc6@Ju9(?KhW;)oF~&gNLMAFyz}v_o6O}REJ}`HUu8!6Wgs9QZd@$d zKdk-vz%XVh;MKc&OkT^#$=0OIp>ef><0{~8%!=K9h|#)Omk0E)jU~+~JYTm{ z`@O@1P&rJkt5M9G-}kOUP{6q2HMH=A@42e)ZlF%(=5eb^K1W?09tDNl;?B?UN@gtw z!R;lC`zu*k6{rE6 zWDlb92=MU0G151sp0^7rwel7l?#*8Q-wJ$j+j|Tbd{;^^oXkP^rmpwH&rlJQD|SRk zr-HdCqF47kBROuOYb8giBTWQfARhQrzhVzEa&v3uU#uwM^kJ)g`=IfpdhN2+^TrOI zmxrr!Z})9_Hp~e-YSAz)p69-9XY(dmrK37#k;pzK;qq@=R)>wvLK$FZ1x5q{sKlco zpJH;4aWF6=zvpPRSc$o{&1mNTOSL}{xVP{LxTL5LMnLxoL(aT%o;8sXX}~*k3?LH4 z<7r!F=Ht3oZ^#3TE~U`AliWR7RM$MOXmz)(Hc&}^nOeMACDAa=u)OxDd6p4DiKln9tVeKmO1iZ2oSSnPAHC3D@9=C#M z3l#DIRr%6pdCk5*bY*y51gA|?$V07zn$NMvwSo^Y0N9Bo&$jVqhCioJDbbBG$iBXK z(_r&?p07|Iur+Rqp>9$t313&7ZFEj+$AMzc*i#bGg|Nc0Mj?+|`?lBxYbdPXI+-BLzR#6clE z_bf`eSy935{Y#p!E2tNJt7-bA;b*Ov7bV2k#+$wMtvIq$56<>G(`UyeTz0Dmcb~hR zsE^-oIYvd9L*wMiq&n3LLE2xTm_}&6I(?G4G*rrFZ_b@I=CS~=FTCd=YNTb#acsUYo3)rK3Kyq`1*Ref0$Fl6QEju63c28oOA2z z^Vp4Q!i8rSc#+N7u5B4`|LOU;+-d*M%SEVnw&}y{?{BX6{Av?iLckFZw+h-HAWU%fV;De|7ZQN9sDxDMRhp5rlZ>ThCH&02b)qoQ5_DvC zYT9QN&Fa&e(=xTf(^h`S5!k8-OgXM)tGEkEJR@-_ofkb~jv?DP+oZw4`^+U0v1N4# z1XLP}9;gm+(UoKwt=5i1yv&pjPhadMK!qAOMe4Qr8)Sujb8rPtJ;##m57|{n6I5;3 zfouk13FaFypkZaLwj6_ibFMlD*_4U~i@JahZe8kVtId8&E&Pi2qA+RQFArnFaMFB6 z9m2>SIv{3!45xlJO*vK}){alN)nl^Z+K!>tGh6BE%Hkz`94+U4ca%Tgqv zv1XO@?{L)J%a|@^pv(1sMN!HiR?Zu*uKZ)rJG_%PwTjN1vsXf2uyO znq)jIv2p~~Qp0^(P|{RNmMbp&e2f5wv_mMw$>yU;P~8L9wNqc6R^2HhD^4{Z%rg$0 z#Z;3&GmD}0D;$#==OpTOHEi4d^7U1Ke>3z+V=J@g+g2fzH1Jo61y_a9G#pi# zyuDGkB=#Ou*@df(jZY_oZ;L1lE4B}T!9rh~jPK#GANEOT-(((HMMWFfwX-AtWzRFJ zgYRLzrC8IsBiTed94*-CdCt8Xd$GJd@EeY(1}d>i!TK~>rLK>o|DgUOJ+kx#L!;y1U$#thE!MUY#Jva?Yzbrmby;{ zetYDWH+aaS8|#~~fTGLjF++hJup`66S*J&3gf%0waPpddXq;UJYuwKFuT#6=j>4I)_wfNz!66u;Hq1hnb%;`7K^pk9w}J? ze#%J7?aLY(HHEsSm(H&?Q&+jQE+|L*DoV&&T5#6$R0$I5iW>^`{TMDRqyO_dAy3^d z4}I7i9?$)^Jh}rk&fL({);#Ppr+Ttrfg?0Hc&`nY9Dm_AyOp5r;I8Y3PK-#86}2+^ zwVsW(vSTv8zQPRG6In}3*5;|`Fb&xy4in@qBuFWk3?h1nQ%)s=-WG?oFY8QSsYc7J z9?^{?_eQ(p@gy1JV{>)KDkQ#8$K=VF5D3r%L?^kt?^po&Qx7na?Mj8R-GE1Ji4VD&;!tnrVZDDm;VSg2OnD|u`D;aL9S?Ji+(>AqFH{}IY~$*M~% z&u+Oo#cS(bd4ZpvoLnV^i~z)2aXt%iwe5&i`2W?JhFld1mGp= z6Pzh9yQFcAJZ*hl3drx6y|C~g*54Y(l@k02hR652NAraqKSSjOxdC=XZ-~OxhxVLk zgOTE*7-0B~Q*x=ud$4l5u9}Q9Vlg430bcH1Iz2Ccq$nF+*@8mUtMO8cKlF?giNjDd zV|5(Wti?y~wI@%hm+iV*SLo)Ow_}!yMN3Z)XVYK`BTTK#5MhvfrO@&ur;hS8sg@Ny zoj84K0?o%YCm|rPIcwRjl{GI^>Oe0EdmQN9UFSIU;$o*Orb9tPQwa)A!ttW`w+DQB z(QE$`X%{z<7Q;X=Kc0Oq9~NLo=JAcSwFKugzgnJEHkTRDU*P3KW8#Rf?M7w9LL{Ni zo3DrYMeXf67^i=nedNC_sP7ur(Te1N>smTE)AKydJTrF#`bHMa3LRY!;C4@#p1S*; zFoibu-38uJZv<$YDYO*3+hnGgNmsP8cN|pURyXPasms1c;sKuaR&b9HT8|i zJ%B#!%g3Idr`OJXk+szF-jClgM&nbnS9%!lA{!v7wy6PvP9M5TCeCQ!y=g-PdYzx- zl9)uFfU){&Gz0Om zB>rZ*L1ydb`s{Yd3saMw9UX%~G9PaJXm#%xQDdvKv#I(1r@4cPQhssl_z*LUn`RVj zEcNddhTjM@tq5Z2-j2Fi8S^>cR$&VUesPSu1)Vhy%R8EU{4v63Jo0B zl!itr1rzbRQ%Uu@vdUX!s%13yXG+L3n^=8!gP5o$7&gI!)f7 zEG`8dtwlV|{Cgi9<)llt&J8)rD6uvHYo`4>?=#8Q3QA`e!lwaeAB%;Llv5ShnH^c6 zmz`beiT$Zge#>Tz06&jOy^%Ln<`{Qi->(}Jo#%3&^0=e7c8HoFdS1^zaG{$LHTGT+ zsa#WE4konn%fjcaPVGJVqn}G~)Cuak0-^|KShc!74t>^Zvj(jN%;;o`*%~SjPLfm% z*iGR4$aNXLBU%iyi#ao_&>mIqn$Nj>Q7zCz@AY_O{D%8*yP?Vxu`=1>`v<|Cf z6Fl*o(^xt>@|A*+)%4i^I-@+0ul#>6yrDyqY}t{`=qjNsR1JHj|hYnj&ID z{u63}Q26cjaN7N-#S|*ZwO93ko6gDIeYU#u$0e?-0OeWR#{_0)tCxxD<=GGmg%mk- z$u#TLu4YcVrJ=R}5cNFA8yLEI2*hOl-iH1eE9d=1@Y(#tsvJGnbpe8NG=bl0io-!Y zM0yQQ(a*~%OuBw(QPLnje%6!GCTH2{CsmLM4qqdQeM0EL-&j{v-r%lA@}mRx)s)wq z<`C`BL_YDF{EP!~SHK*iquIFR{Fx4i#eH_r)f5dE8mIrOH=N|`?BV)qu<$EvEX%o@ zxH`Uek%4i-;*>$>!KFpCSxG=-VR`>~bMFZS2uEf1psG+XgSR+6mxjJ~qw}GVp!rpG zSwIkXF=5*cqq;oseNV{?p5bSn+-pf)-N#uS46bi_ttvDDS2gf$K}0UShtoN53oK~H$`O@kc83!bTGNdk7izYDown@W{wxr zGUeJ^vC(~JNWKIomk`n+n3zdU+*#K<19^b-E2~iCUw!6j>O3py^;#S=j*Wh#JtN}C z0Q6@Phy@a~`9>!pItZ#Y9lM@=tw~rIiL}VMqZy`A@EEYSFUo493BvXE@N6p8I)UQk zPmNO#ix)B6>^mDWmO0=FX2n$XN+x_3qOriH&3}MxyrvP4&dH!r9esoP9R&~<*dS#z zJ57)y1MQ(FV|Ebd?^E5yX%Dfh)$cmez+TTiLv1N`y0Is7yb)9g|L_g6*3THW<)bz= zOd%>m52&ti0NB%jh?oy^;9UzeKzmX*UTO5Ib-!HPYGQ-bH1eC3#CB+6GU#FdtuQ&o zJ##m~AQ6_+%YUdqAFJ~#t+ZoJ=iGX39|N=nkxK6ayWHscnka|;om0At3(>%F*rt=V z`w@ulBmCPu8+}?`8$SYn`z{xc%RgE$!mQ{zev{}ifzx(Dq)0Xc2s!-#r0slUJC*AG z-H{gcQZxcNkAGcVxY6C=C5G?ZC{}mHp}=5#f)rAqRA3@rb$uz%d6C}V-yhkn+XK?b z%Gcts3`BhFhU1vn$O6``JqJ$=8jz$pDhZjbR$t`wzWw=N*?Plvln1-A%&QEs2RzsY;C!d2qpfOg50-x$}xOtA9M=2!3yB4WB{Aas#i%M0bM@P4?7#wC-4;p5>7 zy8du9Mu}Fr+G1m|u7OI#Yra}~5w#i=kITKiVnxN9A#$jR{uhhG5)O$hots4Zk#BUJ zS^m}Cz(}XIksmh@aRmy4t{q^Hh{I&9%+KJfu;J^m5S{hc-2tF`TYoL?HVU3>2GE}C zA_2-pJus;IE}k3pLivBxfcZw`h0wahXjZ0$)dO*`np4am>J-Bt47{0zyV}_RHt`Sl z4B-{QO)j^ZNYxY4dHl^(upC~`qCaOv+i02r{J#5mOrrks_GOemtqxAOGRZIN)Z^$` zky)x4Ew&v?i_)y-_)$feejjalj1W}JO5hFzfFc26{=BaH(Kdd3+RxTxCwp}bvf>4t z$NXwItC9WYFUW2HI54k=GHL+-7D^jPYOkvjPm;{jZKAcpU|0zH;!N03PSBvcB1q>K5 z>%3j|f>U6c^lCJ+1mquEmQHI&)d<5%t{W0Y^FKlXT{Tbf89`)4MOiU=1Uz(9fc~vp zX$CaVef%lXcQeK#+wSAon3$A7UPWO#LTtRRW4CyAS7%`#3__NZYhV2XT#)*hgjuF? z_3T{El!jY(5;raizYF+3)uG3wh3PKoK;`Gp zGdlkv7Ql(klwDMDNOa?HAvkVqFYB1Y-x% z{&8HePXE4#{THj61arQ~9=pDP=19Z{ja=7@l^2~{MEV=?<){P6Xh-13s)Li}rVpm` zy{9}o+TqgQbh%1x4`eZ-Z#VdX7r+0-68eSSr?sK<0&Ov_Xyg?~t1WPRAYkUokt3DV zQMByd5)Fu<47oq$=1m|HT5m#=pp|E%e7IDGzpalqFIjD8>K@4$TI_4r z7Ol^B|HcpDY)~(efAOXeglN=<_>}X|F8^{Sr*;iIt0IJyDfz4Q}@u?BWc{tLEmKq7NF*AJe#WG^r%HB&= zLS?(bz`xZEf`x!agL_XIiT}YAU@Py8>WO!6oSNlJ85e|+r=lm}cP!SS^ zV66*wAtfQuMC+N{=imDZK?+de3o=PS#HOU9joP#sB{j*rMM%hxww>q4*kFkDgUpGo zAO2F%zN0H^v0CL)Fjh3(Gj)IGT6`f0_txD2^HJ(uXwAn`ENGqxOdtOF6;Sxo41;b3upsRwz2SZQqEsEveI|)*93Ehlqs;L^B4x< zM_QnO0z{F^JB>woLhlb0Ab_gV56ASQ38WbjvG1Sb$^x9rC&ZZ=Y+WIt&g|l7Iy2?pvDu^kMSi)8_%e^VsAhgwR_*;oI8fCsN=#VF&xtk0!4jN6X~UpXEmA|Met#CM zYs;4%F5d`zN~Rw>!XHqRmwbm}3IOHyijmYN98Z129zIg8F9m0HsFcs((qf`NiVkx{ zKj?IF;&g7}OvBps-Bf&+wkmYq(=UGOQ>egJiVIb{7Ob=9g3qN6=|Bg$8t8QTH*RUU z`xjzf_8}JSiNzA}1T73a{LsM}{Q-`gZpf6)#mmLRLo@wlLMyI@#G#%g`V!dsekq7H z2*CF;QGXO_7`l#0?A6cRxjB&@zFz>zGFZ|ugydOd{H6VYnLc#@L^~a0ksKChZ1`AUHautcVwU#-#T*o#s(b6|d3$da)H z(qMe&f#U5}_h$G4x}}if(w7us>X+H$HBjRgBM=u28K?W2$MWSvO2B_smC${Jdel@* zHaTUB$YWdyE44ftPB2l+UW?Q|Z3DA#c)g&g=hyeveVmmr=z0MD=DdQiP~TA0gJXZ^ zVY4xRfT2Z%|C=xScT0*FSxjywD;u3pYi!xY|?`K90CB7>A^@Tnz=nbM~XncourMQQsh-~ZXR7XV~} z8ziYf2SUGK!Jp4OQqT5`|LRmVJXThwqSeNY+F241NOQ~&Et62vm=1s)c!8V8h=x|# zbzPwuWsx{4o(c`~BwcO&F#kFtYie2)9uXmPTp>-5Z2%k4pHX6QsOql!1Be9?!h%Tb z;NrQ^Vp%SBC3dXKjDCW-$BPXSs44m%q5>kX9LP)wW?^(T*)PgcZE*e2nnIqwYeWyz z$KxO~KS;fDyV@4T7dmtRTcu8$Ea>}+=(6KEIRcs5iw!DX-k<)5q^y+28MrPCKfkHf z25Lu&e`w2{>qdg<{6EWSj>I80p}Os8WNR1u;Z#CQ@>V}SeIL%t;MG;KvCIilwD_Bd zhosyE@*;sipp=x9P_4?LQQ9^mc=#_VX}L@So);;&M!q^D2|i-(Yi^3pcN<+cvFqMu zQtjP)-C+3m#EpevnpkCY$w6R$>>|Koa73Z3`x+j;EXejeE#Wv2m-&wz$?1|@0*L@k zJA;D{&Q#p4V&N^6)L!sM8#{PK`kCyD$~0J;^#5DY_He(#)(%xjP@RbJSOxZX8tKE< zz_!VpR{4f0Pw+P`78c#(hFiwd%gbOYivbF$FhwkoDVybDjU?e8s4eJbCF@r$u{%^xd&BN0bpRqT8IVq zzqM|q3i&;L){f06_j|~&nJ+73U3p7>wY7&Xj^)_nPPKy)QqO*QOl$tg(lv;l1fYFo>lE$;gx) zyPx^noA-XWzT^=fTssdErI^Ynr4lJNvDUBruO$w3fXx93 z2O)1CsQLKdeSu;WlyYN*{bJM<6i}bD3l>0XdXl|@NQ-=@v9YnK8)!uh)Y`H(IqYAh zD}Gs~w5Tlm(acYg*;lcCnkG8(bEv&I+BMbmt>Jii!MCg0tFPC2vD5j<0;#DZl}POM zpz}Dv*xsUbF)ru-HP-iL((V(h{`(BnD9lHj%1itSkeNIN3@xi5?oW$p&}!7QHGD(Qi$o!`0J;U{ zGCJtChNJ9ZnJ(B`kB`ppKl%g_)JrKLVprHMRg-t43xMn+ZceQ*4aD!Z(3RhoG<@5G72Y`&M?9|A(pfJr&Dn=AgJMNqZRj_ zUrVb>SHf5DtxbJ+P8Srqz!6Zug9MKD6iK|V47KG&iNs_T6_dXX8l^#hK#>iDy)RWN zu&P^<%0GXvCK5lZjwLjrdfaj=N5XqeArf{Kuhgn#D30tU3*5fx1r?01xA%^J;mzPf zd9Yt>h`2lZ)0We^WP$;p-S{(Fa2V6^*%ko_E{SBLAjwhzy?6Q~cx;E%sB=Af5UpC$ zGrJPTiXE7W3G)tKSpTk(>*K@puC{IHsv}p1ViR0=&UT&-Fj_7kp6=S}KfHE-%Z)us zpxV{|$hQ4T8?7Iz_V}S^$db;e#SS^@b-9B0$jf{7xr7fgxnj#r%p7$IG*iN{bF6Cg z{<+WRY|N0|^A7II7Z90%*Lg^3Y5_n5Z??qI&j!sFMbx_=rNQHr+sAP`*0PN6hZdy# zw-kSW`v&tdqnjbMoc$m5ta8V5Dn1Ad$#u33Vn`DrIULsnZ2oEMz7xo*t(pq;A1Iu8 zEqD9^``qX@EDR2U7t5!{KS=BrkEtC@)LOOwPDTk~8eHhLxy1qJX?g{nFAZFmg<8#C z8(+_#RcR1hLiU2t^)UHh-5bK7V*Ba!OzFs0 z2dP6hZvPgu$;{dQLD0v>Q?gTZd49mKW~qz65YlxQ5o)K>f9x$_zO53(<06>LUCKZt zf?{lKks|h*Dt4gT^}Y^{WWae>4yvTV(G#Rc2KXGlxspQ|+{}DD9+u{!`j_#$TFbGE z4L`D;r-6<`b|0_x)0;P*`BL2K6m@Hr9rMjsm}n3dUFxQvobRLWDjcP*a_cB*^5aN+ zI^(LbreHLyEwcp-L+|0q!_8Ql*FjEg`4}@8I2n(LAY47W4C17Sy(rLQFao74)EZ4k zD>AgbHrux&5!|G#djwhGvp>P;JRN;@DWMkQ4b{`&uMSgp{;bt`tu`OrzAJ!vNAgKa-*mGB(k4pA3h?Tc3?3E;Cfd6T^aB>L z+4o{W>=ttXdOey|I1Pq;a0o1D)!6mmmNA^5w|$Q1@I}#gXcgETh~15YDDZ#QYrf|} zL`LFfjN{NQM@Dr%zCDKOK!FVsBr8syxNJHChm^imuz>Rw+UA!>I=bUf+4iKD>Iuv5-rQv60P@1JX zRqfR4HKO3^6!74*fKX+VDrbI@_PAePlPH@rq4zyBLN0C_8ylOtwwqgDmYhTbrj7a` z=t0NKq>SV8o9=CG{pM<`U&iFKNsYJ^K*MlDi!c*OJ@HnyAop=(KRRl6#k##zme zW&`wllyB_%1gW}w8@iA+N!(rkcP;eOG(cC`rZ+rvmeW9nYnV?z^-(QGB7U|U4N%s{t`EHH<;Lq z7fZV_fdG!G9Bg5@Ean6-pz7_8YBtJdfXvx4Na1YmLptz4a9u(=;^}gF&~lB`7PrY; z&^$?V&nW5XE=$mR2(;vks*0S!t~$92k4WlV>V979Xl9${Zyn~U7N;$n_225soo_(G zgP+L(7ycWPYrkJe5%&v%miQ+y%DFNQeauc87F2ZDONG}@klc7Mr8;na~7GGa2NY*E4D z0Od(&@reM)F_hNE>7KOGpf_f}hYPVnduS$GT3@oH_E3FubJ~!-K z^`t7b&a$G9>#7zIs!=c_^!bSx|?rH5a!k2T+a)*!3*H4bjDK^EniBO*AZZyU(r z0l9*gO-mx^X+EkAyiINE->}G^G5^P|1x8Q=AO&Z-dsQpr*7sR|C-Fc}dlP&5Ai=1* z^LtgU&m+QnfBTh|oMOoo##!ewJ-}s;tR&R{g?f8@+tSqjK(J z&RP;V>-TJ~cf8oLL}CABZMGf8>9bPDU=OrQdIFckkse_Z$RBSOgw>Ji>NirsZVL2u z3t*bSnXHtuo5G);A25=93LZ(}2>8MoryV>Z`99S(rYt#8W1lK!+~HZPeyt4XY_Sfy zU~#86u3WS3Vs=uDzW)=w7{vALfOmmrL@Fe?q|5Su6^;MFgk0BKMpjCv`xGSO%%^K? zj=AX*Qhc2@;lTK=wz8fD=!y=0jNe=wfQ1^bGTU_5TjO+Gn1SQ+^EwAAp%+o_HV@h}U$xRahP`P6R0ynj-1n%o!K^(2OOM zH>2s?2EE#y%V@;F4M&zG)z3)r4oekzKLzAmA_Q1_;!_yVrlk^JkxpDsCxlaify zYr}!kXHo7n)DB|Oua+TI=~M8T=lee4EW{kQplfj`7OT4?d+J)1hO#fV z%W6~=qh&lrWXfOmzJINj6f7?+6dBaEx}4`emiHib>W2TkDp4_h|0BUm3gse0EDF`^ zv#^mnOaNa5gy#u2FizjvwbiPl3tP>_wuSy%qJgaB)=%&j`@iet!1xmb!2OptBd3_= zNC#=m%kvWgtoi3zPz4cHOYwKi@9Z-4Hwr>gu%=}B@T64n%_XeOS9~#9OTPES!C5mv z{8)T!N&ZdWVss%Cip;hc(vBL#?hclESW`qm9yrz*XPLAur*FOP2Id_$kc5U(zdQ)+ z5gadpS=P=m!pBn$oYpNCU()<+YI-QNz0diZ!CYT?)d|p>-$Q0#rY9cQ*Pt}Qht}fv z7#zII$6fe1v3jx;+2niwslj{a^B%XgrpVp%{o^O|(`!d>R{Na@l5Wk%}e zDOtHt#vGcfpB)xCU@vp%`5Ea?<*A{FNa4=Q^@0-hpYZv3m5G?B(+w@7puK!@WgoCx zyRtY6fq#FZO~g4lQeJ%}tE8AD{PtnIak`gmZ!@c+=Zn=$XiDc8r5v#X+RzM@5bA^& zCNt))YN4!S>k7yJDOzW!-`d@ZbR)?mTxJG(iHZK;FxHs>ih6bKSX@8%?t*6qjsRuy zV@6UE9XP_^67A8@pIyc@AO&WQYs6D0z^-dPGJ8B`hiJ>gUteRW^>m%Bv??7=y=?$G zHS_ga9a1mR1&%xHYCqeTSX)83R2STgakibkF>5tBP^X(RWV*V)@N5Q3ts1Q?O>VaY ztf6G}8Yizw*z;IU~dFc9Z`iqMN*`a(!cd7- zU7#9g0n~-GL6FF;n9$?qxxDOrL3uuJ{S=3Hk73!?S>#~%1*D8Juwt0?I9h-f0X3On zHM-^)Spn;YukF4VHB;6c>UZL5_U7F)Ek_xx50BzaH2$&x$g7A%brbG%$q&#oGZ*y@-fGRr@z&-1XZT8`j0QLfx7gn4 zDiHp}1K+x-g)QD)4d$dGgkUi9gFNQHiYbbY@EhBrmn?BH@OJatX6h>!XQStG_JXU2 zqDfo7-_=_6r%$kaG8y4-{vTw$V|-m<*Y(@jX=7WBZ6}Rw8#`)jHfn6!YHZtf(%81K zgR^_zzjMy>yzjUDAv?*!wbqQjJW-okDB&kTrb)!XNXN6X1Vs$;ltf?_jkY%#| zd;=h-8t$~Cq_%sy9G%-wrgJc3s?oUmuzE#J>uL?vPf6F}qTpkrqW?byP} zk>mwZtNU_B;g%CB+NE8 z<0l3hE+{gKrx6rUS-$VAd-~#a_gC{O|5%pQR^vgd*_7gN43NJfMLQr%DZt*1mTRa_ z&TffwYxHKX_Llw!4=we)b(Jk6K~*c}`QjgHwafM^+ZG7Iq^-lr6g~U*`IMx@&qab& zDPTEoOH5MIk&8@5L!IuKs&yM1YL!c7mc&FzY!m0*q_#d%u{<1HdG0r2i zP?A|24QvjuM71XIHx|p?50j5(Ykj(0qd*af(TR2?K*cC=`OOwZqT21NcN6#=Kj{d) zJ1nZlGa5Xi(`8(QA}noW-XzV;TtjSSZmtMK4OsAnm2I0M!c?MpMkL}9!lc)t3=0d} z{WYUjZA+l?6=SSc(uU;gNFi&t69YojKh9^9Q6WZ>N6a&&y7=M9cP zm(?DM!XqpH(5EOjd~y0F0WD&e+s*A8mzZHd5+oR+sFuk8Ok=XGsO?&X zLy<7yv#cojlSC_ZXPzSU-Ix)lSIVu&_rM5_9n=bHH9Rv86s$s7e;2GN4SCd${wq7q zjAxMPw8Y!8N4@4{B$pJ5bI_+4O;G<~Ci5+u@boRWc44)_gLZ5UjJ8g;3|nPN(~A99 zV=_u+MOIIxM0E+`QRP}w|DYXbdNK)f4Yu_vXiBeFoxO}8pQXVi4QGs_JtAV{jd^hO zf@X1GFZI6~u7B{WVP7^hHpe?&h$IoVqIu6*Zk3*`9{KHw2X#(xtPmWPp-zpVaNwNM zto7+q`5p^4T??UL)7;L8{a}gwujm^sC*4u8K`V&-aFj~bf!ZK^v4mw$T7{JCHJvk; z?s{sOr*V3%hqGDbP7**`>qWs?#ru@0m$lBuSK}EEshSy<6WP;cq-j?#z)8s`f^Gj2 z)Ohp{fY*6y$5)c}Q(yPApZzCp4D0lSdb_33<0eSaUZG8epqXdh11iOg{7#vD45Ib_ zOl<+t9ZbHd?SeuAn+H_B*doNSEzv{*S?d$724NShAmro7zvtBj4__jh&{i9ytxZAT ztNhU4mDE3Tp_&}0KWJ3YKXan(*LGt79(MuiL0(Af#xv*fdW`BRSK$1j0r)M7CoQU= zBZ;RwTktc_cP?(FYY<`hKNN-iuVCw5oODT)IJ_i0dC*)Yu#q|1M+#56I=L9c$XQlX?t^wD)jhvC_c`Xrg zBQVk|t;GbF_zmQ!lpgUn<&+liN6cXBKX;)#nQ&nbxC!|`v_)bAxMQbHi=cyR$*xD( zu$$+JX3&$*;~OXt2nM@~(w|hKha|M?QWj?>g9fI*DWxqTI7sGyy{|^Fz-f5I`c_BD zR(AXqhxS;vKnlvfFeuW8(69xB$>DiX7F`tZ4 z*UAqngVDl&8aP#kUJoR;WXCW6dLC3R4e$>X)O5$b*5*Hhd0@{wv=b|Y56dZ_Bk7Uq zQ4WfL_^RJNxbwX>3Q8`QORpbl^7jLX=SpSzgW^lb0L?LhlueBh3K}hK--8T;S=lJf z#Qq{wGbaiX7+KV!2_Nffumd@L3*Jl?S??QP>wNpgf1;wnxwHE#7fFv6#JFHex#<;( zr9oG1q}7{`AJXeYIMS|g{4?~LjVH#*f8B`To{8vX*UdH6!~w+xQGrFB6h7@N(Q^fa zY1~X4d4Za^b&%zLEDK>d9;E(%+a_DAB;H-EsRMi7yQwK+!fiL&GkOP;>+tM7GJctKK=Z#+}9JrJegDc7lNcK?9lp zjybmX$Z~vNgU|oAX3&8q3qr))+*-f8xX_n|Mqj4Lz?rkwZ!tHC*P+Bpyi2CwrNP0j zzGbOKPo0#M(8 zUKZGR)n=y{`)W;+H>vHa?5N(gM1Wmd%s%D)Gowk#s~Q-RcL8=BDD_wH@<(Q2VKL90 zFfsnihoNB++OZcdwxyo7xP@lvb6_4XH5+f&P*O@)Dx0&4+H+J!;g2y3KB~X>m_?>l zWQ5iE&XRwVy~(!&{SBm~I$UMO;!Fjnehbxh{=S*-cHMvmiJ`0YCk)LL{-`pD z^DCe6z&Dt;WVX+ct1b@Gk);dXB8@9Rlwl#>a=D7cP&5wQyxdW#AH6QxD?hL1d6z3$ zxbAvOZ6rQBx|s+qerI?4m>1uWj5#jfiH+M{haVaglUa5d)!ZIcsNBKoBr zIK{g^TV;PS)3xGbcF5_p-#$~sA_P~mECkiZi>Ga~K=UjKMWL*Ng-O9L+d%M45%;&Vx{`htDD%DP_ z!wW^a@Ok+BwC&nB5~_b~qseZnx6Zd*<|ko z*#C{}8_bT+gmr-!5f}PXV%XIZ43W3uACOafy}j=-p$7+z%X2@p-PzAo+bG|Q5}dP&b_+$VfZ>GUmYEpJU)dS7robu z!roSFO`j7PKC*UlzSq1S1%7aiFMniZ+BqGzpQ`Inw14GF?J7r#J_M#WWwgx-5KS(} zC$cxGFw3kJO96?tbNFc<$JDG%XLpNk-@gh*KtG)?x3{y|C~nzYRr=ZEs$DlYv*fFw zuz=6s=|YuI$`LcL#DU5J`}I`ki`SEiEkAaZ#GKN>1orfRi4S1Ld zNcZ~TVUQhRLPlCNzyI>DpP{$NNqeEWJtjd;B?*n9XAwJ>QbcL*VK=kQgvG>Q5q$q4 z&fSftN~c6Z17&NhK6Vf17_Q*jlJ7x@p&AQ_x*>4SpENAo@{l=)kjMDv0=kMq*NJ$q*Mmv1k834Zo1T;4l`$D|!z zPXc7gPDtAn5fi~p7ZLcJ&>J&|59f;T|}0|V%~ zMHOL?@NvI>W1KA3Q$@l!Mh?U0%XJ|iX-=u72+fC&|gEWcl9^k zZe-?|Mp$cGG`7vIG-B|b+4MUZ7b!8K;0!O0kQILie(+8 zl|gzOv+jMW<;JpsSL4xTu`XGYnSoB7Aa^c2&rK*}GL!lLU;kV?f?HYY!YqZeTQA)^ zqMmm(e^cxSn|9C?fW|O_hV)MyfrIlW3Rz?D8obg2Ec%e_E$~I9+r?kf-_H`M8Sxg!P+{mW;(nt5I4l zjcJEK??7HXyQ);Lys6`96L`tzV{&kIn-7g-wmb0kcA~pN3a#}#P|D-5x$VtyHU)4? z*X`5pn$I}BpXRsGxE$8SmjL*vY+k2%y_L;=aocifJ|1WFICS%@N%-#vpNeuovd2~0 zR=vcu%?s#HEo79W{EmrzxjP!wFz}^-fI-6i%vIhU5i)dyshHdT(~NVIZM9T(5ha-?p|uoYLoWHp&gRc8Nhzq`QSw#z%tgKK!?NdYnlkpQcx^*yQ|8y}Y&Y6i9-}ym zcIlXQ&T910KVTA!5VDo6cXSd&R`1g0)N|hnp8HbGphuY8^93Z#7q?v- zH8tTF_|aE)vkU7Ju&bswTm0TWq!5hmtyR52s*hMJQG%ihmtVqBahGXi;ZwV1tzDP* z>B_PCd>gA@{b}5^<7qKI@)#EaH5sq zpZ)$n2e6P7wqA!E825ybCqiswE@$anSL9z$KVW;0K6S%Eb@MVcbu2wOk;$6N)hSWHpzRD>fv$a z84*Nr6X|+4PxhJt`TkWBioHoi4X|OYODf!TUskgFXn0wXe#`k%CMH;d(`Uh-Nt!N} zA8mmgXR;H_1b*=|s8e`!ynMvKlzAAf?D8zcoLwNR5j0853m>+1JW|!{A!AZ{j56ygTn1 zAz{QwJEWSp9&jYMP!z!zW?7*|%9 zxo9k(wHPF4;~L+kg+UzNkOVQk*=VL6=Ca{c3lOoGHaV6=pCZ!^ z^}c2O+UoG`Ngd3k$@3D9JjU-~g$EKxe^!t`0Dqh+70k&{J%EYFydCU|q*ptv>M~bc@R56vz1A^6P zX^KG{2wIXXQ%27~fcFtzE@<9nMD$T|&NWo_6cOgkQ#^I*=|sk8zp_{uqqYuJ`YvZ& zLT7kc;z}yqDA^vUhH(lVEbgep*}AE8*jrp)TJIP(9#8MMtC<# zqe=Ao9aG(bir%HWdxz%wLBk-ew+4c9+{nntam(ikPXns+!x@iYqU-6hy=C?>A)DW8 zR2q?|`_-|{a+xefAUxyYkSb{s<6msiSl_A;lqvx_p~f;^A<^N4KYL$^a;u|RD?aO> zZxkHO!hZmbDvJYB!obhoYDZ>Q$ThUHAS-<8`Yd zCpUdRv|O>$n#E)g+GulO6+3Q9p!6|pQd<_8z9PpssOmbz^|+6ds0YDVoLfxlX}DPP z(yPdwDW11wC52k^=9d=+gzRImRtF@`?6&KF7YcmTBBINAoO6#&!S?HV;7Vb=9rhwN z955H7bgNO$aJihHV^P!})|Uzc;$-^x`w8&F4ql*u!+Q=| ziX`!yQw>r&qWd8gm`)5soLs3ZrTatIfzTcE&O^&Nyu~sV!Cth#dUKr;3anq29(ZQX zR|?wC*P5phPo2HahCG(5^lq2uib8SN!N3v%U7S`BIrF=GfcfW$D$Uwr7OM>>{AdO= z&3H!iPOG0ER75^(g9Bx^HuFx?{Ina}f9%gHo6{V3Z=9d)209gKOP{E^81Fux``3HU zkh+d~7HuX3$rXhlEACct6SWqt5V0D2W}SGTF$F1Gp@XalDt8m~6?S%Z#0O@7Qtftp z?1T_aJfLAt?TS1VGlw!;UrZN$8{q;clBbEqSsyn~5 z)hhil7JGyt%m%JeieJ-M0V9yQ^=(m`&849Q%uDy4n=K9nd^gW~EM{X8#ph8O9AoDz z^^;$;D`OV=B%xU7K?xgn=9BToav9PIG8rRvW`1cOrJ5BYvD(@cLf*>d$QyveNE~y= zB=t(2J+Bc;(U7h$Bwl5$zKuC%C~orfWQ)qQnBW`NDf;oC#gFT-wp&&K8i3kBQoY-T z1(_vkduhH^UbK+=_YvpT6IJWAt2c={&slHQ2`O8P@w+|nExM#XtyOooiBbJL>)7(+ z+`{n8DN_$R!8tk9p7}|uUSaXLXzc+}r4)su1~M}^`B0&d=QbuM)q5Fx|;CN#M{~!3Wiy=fIL;x;M91CMOdd8C&Z_nR&}^ zTU(a`p=x2q9xJUW*tszj;;p%V>fW_p_I)P=%kqYNlINP0n}fP^NDYStbJ4jQJ@_>t zvh77+{|CDuur(Z;?$m8T9g>)c+c8M1IvL~r^&#auB479Oo0G}tJ+H0z{2c54%TYG# zS~+_V^6mZahx`bJc%2(lb(q9@^QnQJD}d7;&(BphlipbH<@V++Uj#Eidd8{e!>LS3 z2v3@|34Zp-AA7TnXYJ>ERqaqs&iN8QqoBgqhclTYhOZfTIt1QVtF0;msaz5Y+QDQXNUgn7O!I;qk7 z@#y-vG*O;3mO+dGFWVKW#Iw6)zNd#-%fMvwD0-uStEieLnr>(BZTWq~`9r|qBJ`kq zGo_Tvwt-GO?J5aKfR_NV70Kf|jeYF9WKyG2b0@tpliN;c(0@*|i%FxBt09y+m!SK3 zq@hgc{T`dQ#@cI07tY>6rB3p{q@B;c2l=&9AAB&d@5KSWFip!!qs>AngRJvZ3T5MQ5>1wl+ERY}ecH1y*_uVDd#N=GwT z`bpUlF9xLwhnuhyGY+*Do9e+O!J6}{D1DDWVq`M|TKc#OWhoaGBL zNqRy+WQ)Iox1RnfFS8c0w%o*uQA$HX1{9F^M9b3<}g3xbf0Am80iN|=yJC^>e}=d{9OLV}6T z@ez=C&$}k3s#g#$52eka)p)Bsbh{r!MRCw>BoWz>Fwa*}2{4+S}!<@V?%cVBuVvD3LxZ6J8jP41yNRFu+`SnhQnE5Au9EcS_a{Xfd(lsm1^~r>5$O~z^!!3>oP5}nC8NsGt zwspj7PmO6W$)n`TB}MfrcjkMLB=RYLo&cO7(rK_DS!=SJcRqi5=GF z^#M^ifpV?!3i8ogwc;}}*~MFU4=IX9Kw`2NM4~f-`!-ExUf>844)dHXKCmxRtHmR&@kB@X;Hh(V(dDf+Wzn>dP+`vb_NeY0qxaA;Or{T&$ zS;jF`#4r9lBy*+>VcdGYEy{Mu*9x7*Z^>@1P>NwLZ8!}kEA5UI2~9Wsq~TZVH+J&U zpTgkBqf|MnlZf)38GYn{FAWXHywP)4k85UxY~Q(d^k6=1@V4!uwDD!f!`P)5#t~Dd zhNuThpr-(O^d#cs^K|oC$!oon8hANkY$lF^!#vC0xRBv!U{;Vf8{+~^=&Q0%Tc5ww z0lbn_mnG(eR~y9lWr+7To%X-|q#|S%Ad`=3ruE!5TmbC;S1-7lkolBklTs@%lBimJ zdx#?TYn9Eyw5QB2bp{aHYK;9~aVIUb9zWiJ`(G^>;v!F%Dl_If|zRFx5-%GO=CP0O}u)*#J z{Q|_xW5>?g1b;O`o@!AOQ^h1RgYbvPIHucV7CP+Vr{RI_o|Yw-#)HRcnRM}AU14f! zxNlmzt0L53@p|eCV-@dYz;C$h-;VD}wwMzYq^&ofOzaK3S{#bo-yyzV4n{bTNZoFQ zY-S6il4ojNP5+jY8^R@|7Xi0ljo=q|vF29lWRD)~Uvi~INq_&@cSHhL2%m?ct96Iq zg*f>vsj4MF)#8URLXT|By5g=NHp+^<$?EZnH?LlRzkYO_K(5OujEgk#a}qSSq>gtU!xf7@u~;2r`F_3? z=`JP`>Y?@<#NT(YDJ2WCofr|B5#BcsI7GJBFgltDnzf7Eba}xPa}!Ob=Amh!>PG&S zat!yl;l5pWn(ig>#QNck6yKbOH0V1q;vy>}l9`U~eL2Iqz?F&+|EnH9b^cRD-3YHV z%U{~+UH(_1E7nrfD&fCJ3z9!5h?ACjz$@p;-C4HbRf-HnCchMf&vc#j_4S!@PF!*H znm!h1yp~cE0x5td%M5zcr^DwF)!iR$w5tSLk6K$kT0j+=)YiAiap+ipQ`5zQ8;=INV&9?-T{XYOu8BsTD$Oo~w&<+OB?Q?6V0riTflWUEl6So(l`qkdDG-FVcRn zdVQ}DOg&fY2}(noZ${Azr)_%6MjkHKJ+YaoiE9vZ&ML|ARF)z+^F}tN#^-BKCEIX1 zjA1uwdi;w57t{BScqMO4!)w$jWlljw)rzbURE&ez5mP(CAV^kF*p6ZCy z|E~eQ&%uNx5-vv~d%4EhN9YJFdv$%Z+jOb1X@VCWbG%1>R;poxQ0)-pi ztjKvI=JB@E)AB`5gfp4l7msJB{Kug7SktCc(-)~f0b%#^3W5-mmF`Atot@VR5-_`X z+Y6~L9pFF1uddf%kiS^(wz42A>F@3CB_ggt$VGnwyFXQk6f@7~7?Gr?;sJ;}_UC_@ zpLQR3&wS9yF{G}YEp(N52lO-r<%^@RA*D&d`3=E&Va)5!oq#hMm~XccR#>%FY<>lb zWZ{KqVZ>ubnzD+=oXq7l-5}z4Q;f@uKYMxWy!o8hTb+;3IH){F=P040cpxCsJS};q zB1Sv>$TL~XauP60ybW>J#;Or&!f->I9xq1?4K^*-!zx9^S0fSS4GHlFQcAj3iiL2b zal5?t9c;TbWnh7i6O!w%UY%(fYubDj&tx7({90?aJ0FEyt6GY$)Rc1oRnyen*~C#a z52Jeik*rr~-PIM*m*JdfFjE^Fe996Mrr@$FZFn{V5A0POEei0%e2&-?wg^xdzJJ11 zw{yIVAT1iD>_p-^X-!2INNeEHEb7Lw;qX6wwx_b=OF@~Z8%dXx&N?PuhE!lO!7t~ChHL{NI#qOy_3^bbT$ zeWWEHDQ<#~;)jW`zlPv|Ijwyy_9NCY+!U{@WS+4gtsSboIQWSYWQg8C)NJkR{4D76 z>Kx)^94ltm`H~z286pYF^DFXce`N9PbElZ+YBkro$CBXoxGj7GbIPVQnlf1o?8-^* z&q=Vd*lrcS_(lc|rXZXvF`XScz@rmJ`6{X%Wl@VRo>~7&`HsZ^i6b^Sq}T5HhmsiR z>`K|l*UW%vdP`f9>mz2w&Gz0nVn%BaVcI15(^?SN)t%G*s9>G*LZ=Veu@NHRzOdI# zk`?|GpE}3?1#Fr;>x&KS8@B_R-7|M>uV4Voub+Q3?O`>S*OD<~WH)j?pftp#Mn|y< z$RRtYZ330rGIW)5r``BzRKHitw{W+R!~K{m6Apy7VrX_gLB;vl4m_O?eqv=jX}TX)U=T1gY3LXP z2k@Fg^LaHj_7wfceqlb|JR>x(<-4X2Yyl|eAw*p8S>g3l=STM>q8BAk*XtxF-t6FY zOyGyKq45$?4DdHKvgj@$FDBo<_rhLpR;f3p$NzEe@BQw8{@8B4fvL*iAH&Mfbp4UT zVivynxe%$WjP22aAVn%(K3=`xPc7h68TZ3DEi(Cp;Zi&L^2*XLc3oWh8+Z#pOPqWu z?$VaGj3Sbp8t6rW3Km0=MaRZXO>>YLxTt!UMh~8fdv?yX7Fc9SrBl|&SVc7Db68+X z+7s%8=-dNFP8HU8wlG9~iTUiIT~waswmGX1R&oog)&*Z)dw2L=QHTOlq#IUrMPa3; zXzq6#Mp%wW4@eTza}!dRS07KrDw3oRvo*g@PjXuGmy#F{5N}h%&S*X7%q$gbvBOU)mJvuQhbu$j{$h(dGX6Gd{Ae97 zPacGzoLar;cDh(yt)%8F5U}sS=tlBt~VJ6*9 zIB*EH-oLp!F%FtX*AxGCz0MuVIa<6uwqLIv*wx#R#+nZwG>^Z ztskbSJQ%wln_3Ds)8vOH&PN>AY(d*wG{IWqQi`#V6cUxZMXS=9QQtF`*~gm)L*L0{ z^X3u&m#QL*$88CYIIO75u7hMc#s`^FV4gxifH1BUKS32avqV1Yk2cyuY`y_ya;wK3 zrN>KAm?t6G&qa|?b8A!^;gM67GvR_0qx?}PeUBFkkBdeP_6nY?R2KBNjX>xV>T|dM zwomDej`89K-!s<_)FewakIdWz-9*rbpLQZM5`GXKnI=LqPM^&cMaYJPWwk>%^5FX+ z?W0qL%ZmOKeZ=!E!NKdV3|S62DZew|wBYE3xF9{8X7d)WF^H!l^=HSS^q@=V8*#Mj zd`NEawK$iPy;JyRZ`f~Vb z(N%%aSf)SBTEyb5Qj0v1VX5_$A(xb;Jy?125~R`N+;VD~7!` zDdUvlZo%K$_C+x;1Z@Qg3qltQx{jai3pC4y-7D|~*a13NRF1?VgSkOmHPJvVXye7LB z5mI%)poOvVf1MaOm^_^&^3Wve<+xm``SvgWHZ99~-fH;JR7*RB`B75#RIa!RmG{gKo598@`l7WaEYzM%JF$o)GnT5;`p_4{Rqia>vR8iKq+0F!w)fX9kHUbPD!Or*+T ziR`IF%U^Zb)DaBUompScoSU_5ykqN)1r{4J6W0Au6|({&>w-|wS0tl1MNHdDJFK&m zT&l@-acb@yMyw|yth1P_~AkVi}eGWbVxaz}lrCv#S+C;*@ zywJ1f@mh0CcDd!Yb80!IcdOEwztR>oB0e$arhQ;Bi7lfs@i^AzFstAa7TeiAT;FI- zV|pQ)heGK+)Dkm6{kPSaKr+>xMs{Uy*lU*9d!v17nYy#;b%{?olROX8u%zf5wm>{~ zD|AY)6J#XlAKAB$k38j9^;es-SIDgoORU=H0>^ji`i$Lg;W7|?tHVyv{W%Ei!hfgL z0>OapZ?(gO%cs}vN!h&5SyMsnCNhDaxSMu-)8j)@HKNa2c)rv_(Jl=et5+OHn&c~JtsbAHhv#g7C%Bx<+^X%EhBn1uFQoAyu^p?!o+z0dbzP;5(*zI z13GVy8>ogaC=S>Ri@04r2qi^J4iS9ygaCEiGtM<`EMytK&kMJX%&L^~st)+_1g~#q zM_3+TDY?pp*1b*Va2utg|2k3COL9Doh!j*Eb74L7lo(O&7Gy!x)cB?W!UEE6x#Msl;+os#M_OB&Y#8q2UBzZd+{l zU(No4_WC);8dS|4AluF>M9aK1f+B{Zeb$Xu=r0iyN(8w@r#%FxRp!E6^|+Rj(G%=O-QBKE4LcBUCc3&16ze#)bp05zr7Xia361mrHH( z&Tsafjv@Q>((89%@1*IBJ55I!HPLKT9aF~ezoz~{bNlUqtKrV4R(h~M;|%VQtUYFl zV-KwSm3Y! z@6h=O{U@@Yn5OG+=0^7z|5ys;k!^D%(cjm>H+w%?iPM&zInfO5n z+MBGpaQ<*IgZ-X)v{VCyAqi0lHWU5n3rVB%iE`MlO71mjCmtTcpJ0yRkZQ8dk#yP( zuyNI!%27m&&jGDFuXx+T2ZSq4E*Y2QUbA8heWO+?7ut=BpW`PgCH%>S4$sN<4I`j_ zijfI%qV3#}y`{n1+&JAn;ktQ{GC7$e-Sz)E25Ba6trC2F@%b`H1A3Ll_<&!48g>e( zO7Kz`xz*CN{ZOFEvyZ3i=@EEtbFLr z43nck+@^{Z<<0JPsrv$^t%?{`(UqR7Wd=9BgNa2{0vXl(6(7Zm$O;6?eA^Y{0 zF*s}W;N!`>goSeRakH3}$g-c1ACld=J>rs*Y1>5B%B7Y|m5bMO*D|+fLopTV;x5?C6a?P?AH}oP}Qo=TG&J0d`P^rbG59 zPpuqW=yBYaqvJ5R=O5TF%Jj&BGevD-#SZ`LpZ>QN;-i1DH#;uQr!KeVG8rI(bCYbR z9l8)_>U&y(B0Ic+WB>kt7drzam^lANvt6~# zYJ-$$;2pst4gz^3;h+hvdX*xYV;A6Az-q1qE*sz)21@D!wO%?A`(%}9q?O5x2Kv*W zwOM{15F>i1gmETbGNJpunZz0wJ2w%Mo?yE6e1MW=-k z+;ou-=I^Zb`U%ByMM|O;G<#bo^Ce~nV@c`JE`WQ@E}68gL;4J}t<6r)3LZ?K)dt&w zqig;N9t(H3{pHiTaoxBIWI~?rXE?3|CfPzASAQwR*NuJ4)vM#tV3|aaPC&`I9rKJ! zZ(PaGpzWK2yS{o$nJOM3%OEm3Nt|!|7)Bf zZ)|fj-Tismc-`yK(IgDAgYnp`w+JKS^OZg?4?UNwm5<-!iw~G(lsZhltu|OfG=oRq ztbp`)Q-~pk$hJ|T?-MawX~*m#7R!D}y~8 zaj!MoC1ka`TD~8z)q^A<&*-Ej@9d~A4r>tt?JKACEfOBp=F0%Qf@zMXSGsk6i=1Fr zZav%@1x+7U+E=>wc=I(t3jKVr$RlgC#F@UT2Cd8fh>=#kxm=TvE7I$EZGpstc3n)f z{o~5>v-=C$)1O7aTBBX{o@JBe)1{sjMh~zZ97wlnI=Tfrg%%79eIm5U)8|RghjO`0MS{mL zVCO)0;2Dl`i@fmJx9x7~Lz>5-cAE<};RM#Rca*kyNG{zF{4BJz4LqR-r1fjVC4Uwij;Eqp?PR>`t8SlI>O;947R}o3C_>Ve8K9etmi9LA9%s?A5P1hl} z+-cvREh|V-9ZF1Ir@e`a{1GYbucl&thEHFwAd-@dmlt=G_(cw0O*^cF)%yvM z(1j_V{s;vo`lS0b`F(;e&EAQ`@=Hm0`iz%)Hhl!LZ7Ir;Z1lQncM?5 zx6bQ9_vcdE?RN8VJ+Is4f&j1kwIM}T>efzw$N>aj$X~|B>41*fSGq72=nsecmFOyg zjKoB`oPufbA3ul%A6H6reUgQJD+FXTur5~J>>pO3j_b(-B~xc(Xr-u@{9jt0RzQ?X z`|CN){mS$@kWP{+yT9w*fRF6yYOA_s)9({PnkR07yXI3ihhpVNJ|ok&4?7YWOvdD3 z1S}ecjdnMUxv-bPeq%$9S2`)W#}(#jekykBg#{;fMopjO2q1wXjG*8!>BF?(J2@VQ z&5YMUH1DM%=sR)Gj#u@%_N9s>s&_z`0lp3YYkf<&xd_np9MoGzygbo_Yb1Lz|#eRCt1I?9LMQj9RUpdp7%4oI|tacw z_AuW5zJ9}OH)(3$JNrh?E`B$sAudgRS_9!Cq&Z`exaaAYTk-sE9C0hr$($$6Go{=> zC#B%n5caTBEvxPuYQ2(ktKb)nFQV$6ZZdX^&cO(zRRH|#oM(V>Ag;czkb{aW@oq4)*oP@4$0K1<1E)0BXddI?>hrDC5Yj|=`)AEG&lQvoH1OQKnd5L1K=9;tC}3@5DkCb`WIrQdP4B$-Va}`j^n{Xl za&EE;aPYIvIe4EG7=JW&x~i`|wqpQ0Tm{qy`e06D(F)?_@LqyGX@?7NX8K@8V!p0{ zojWgqX|CkY0(|^41VS=>l3hT*l^^hX-hb{#t=`8hBJuj(l9talR~Y_Tf!+ znf6Ne+MyDfS1`T1arWA?qZ**x5{@*S)QO zf1?}iM_8(K&01x7>)p{d_$YRruQBS^?QR`&n%?%h=lq-j%yxgim6zu%gy*;ZS`_zP zsx~kn#Qx|>6UNSVM}J~l{G*o84zrO(jij<+-;bn;0yp2FD>ork(c#FWp9!3{;L&Pq z5QwN(4_4tArss&cC<_h@8(jo-px<#|L5b)3?_V9k?}x4 z{CKwJEr~glnOb`xm$Gp~d{T*b44^4FT;o+zEsP((<4C6bcDmm0cav3ZAu2>mo@e(v z9Nu$HSG~gyMUyHTB^bML{C{Zr=CH8d|L@G@TFbV%jAgr)ZQItet!3A$W!tuG+x47% zzQ1RGw(Huiu5+LJyx%V_5Cua(48riGN)>X<1pfU~te-dF7@M*Hn!sA_6Ccj?$0xO` zw(58&WpD|KcknrTT->oi;JvtBLzM5+tApUgKz{kL-oTBu1|iqL(@ z+Rgip%Lo_|8=G<-gUdUwbo$$a-#yw;m zbJ^bZW~FAb$WmiNGn#MIvh?`gXKV#H+Pt?$or|6{z00QB&ovz-8S|!L67L6TJTuin z!|?L^wV|R(3!kO~;Gb_(^K13YslUKz2W7gp>r_jfIH~J^d41Sy=HH6@O6c-gHj`@z zy|~kseah*Jo4`0(T3uQy2m~qr=_YRy*_TvdXSZG`7~&qAa(2O^shPiaWA~j01uu(i zQz5~&xK{3N@C?MmWFRsZ!dRLi6yC~3A(_jW?U%pzHax*W{la|`fO>F=+lrx_ERv3- z#{JCf45L%h^x>6jPncLvIQSj*pC1Gg6i$s7rvK4E3Kntj^bpQtyK^YHa2#LAJ@ zmz1k5C#+d?@W`FEUtKTvrI$ms`@U4vnQM{WAMVY#C)WTCQiundF7yR=YSVZ}vrg36 z{WH)!wO+4QWd_pwF=^O#XvA05TxQvoLOQdgNa9e_8CA5Gz)c_k%$tmiN~fruLzxsg z{YO|TsRpWFD6O=;vQt2C3UBbM+gLm)DimT*2+do|^*3_CKk$u;oHvJc*)gw1TjRsj z!Iz&Pv6x=;@#6YEZv{_=oosx19%h`Sj06jdsL8!IlojA=`)QD;{cp52D}7u7mQoba zJOfF-zK`sn&=Y4=Q_S+#UwkP1ds>u!LLa1PXOy&ex3Iulqun@~6z~7x3HQuklt=_= zWZw@u4Q>cqTGx;`@BI@GTXflO}1Q|Uht|Cf@NwbVC=t7 zx$@2+LllaDS4OU~Mu4wMU|2caHRJBvLP2l7=|88A--2J!B(U#db`+1F(P+ZMNYeo;a%IgT(iV%uxO1Vg_?h=cI9UDjYS# zs~ak_NJ-@kP68?g4CW-J|6sg5{<9l;uWy`VYY!ZR_7o^hgIN{!&`||q0md`?J|LUx z6fNqA#>9WuV(bIZFG<=TecJx|OP8k#a<#jT{T`or~v)gv-a_=*=8h07o)Ca9NV0SeG zM?(@vnD#ZWF!JEz_^!jpIvi>_Wc~(mlo#&TuaN7TXVpcM*|+LPvgj>_I>gyR&5!Dp z%tJ2x$jLs0&*xKH1=Wml$WQ)UbE|+0`cHq-(%4M&o_muPEiOfp4 z!NGF>)BOm82%98aY3xM&MsleJArp$I<0`TOu)*I~$czO_+xi)onY`L0RGT1sv7oRN zAsvOB0SG3}xOyR~!pdKSc=r8Lm#zOle)ZW02T=&Gu3PPczEw>`}fF z&vfL8Yd3W}`c@@7aD*4S-<4la2_coq6)QhEd6?e`z`8ufDbv<72Pca_cTB*rQ^w0QFKK%#-^;1K!?l8wqh1b;K7$S7fEavKq1qrqu>($LG-D zKbdwZf4I_50P*WLtpan7ulS?EVZ0?@2UtQJCXUO{uyEcPrrW9#pM}Ru$4z{PMY{A6 zPmgL$mQ)?86H3zr2|HojLIxY&8ft^GJ1yp^pLZe{i~!P+l$m*i&3>cBx!mh!n8M*? zt`w}?T~V?&(#dj*7wtA+;wmQkJ)m8RzmzYi_Ije>n6g0Z=k7mYe0!L?OTMb z@K$zCbe0SUhVTbD(xj+g!7eio-=Osm@ibg76;Bs&`bMKL(5i{xwjnLHn-_%rW1)Fb*SCGmFA5D(E`wINN(-w4 z26+L2?Qs!#K6?S|vD~mD2MJ6IHlsnwNVl!G;>2r$&3qIQti#O%PtLk4eDlEja=2uz>&}0`_Fi=i~Ql*fQE-EFb2*4We&&srG^{DLd0* z`1a-$AD8bGlhHaUKx0&n;BQ9cE-#bAjeMBQy>iD?j-N)~{@t9C6kyq$Kl-)|&g$|} zB)*k(ZwP)def{7)=~H8XeabI-DIbm8z5{J9XB!uDKs(N%GkTbeNoLr19H!MD|hl1YM(Px!%ka zO6}((@yEMvc#BadGF&qC)_sY!bUg6dwt~I@4KRM=Y_762|LA#r9(^a))c+yE&j&o6 zW+FS}@XVZx;M+C3Ns>iJOHF%%!vdeJu2#Jw@K45?R=nuB@K(j5H|8(_Y%etLmvL0s zK4N7ntH^j+W7Jxy6OCUmjeXGG)hI%3Nz*xYL3CLRB=-_9zJKcGo8M^=4(y%MbKQswCO9;6v-5@ z&{A5Rb8OP_G9h+11*0j|E%>1aBLu0N*gaIbjLD@5rPsnrt?yHjEQ(h!9NE2hNQPdg z7(6ZHgKflJ66Mt~NPh>LIa!BpJ#5sa#H>AR%~IWF5wSi2VP80cf1)zhLTB-s=V6os z!(X)C-k$JE>LR^=SG*m{m9$K8Pk+IX<72mg`Q6d9B&kdepAZn&bz0VY!RxuVH=N*b zKd&}QX2*UJ2#Ud$=ksAlY1-Zr*M&+^Yu99my0MI zBIrw~daF(4Q-O$-=$pRzbQ9lKKOPsl@-06mP7F>ktw@XIitH!IqK79TRCIywkigOC4+6&jc0I5-ed4qa6Dbgi&%?!C6^?P1k+rq$I}jU_LiDK(URt|u7Yc^CA>Dvv)O z$i5(pUjcCcV@}LRsINc}M1tX9^l;7YpfR8rFT<-hnL^!%XYiys+@dUo*i*=lVEgTCB&}s+ZLV|2=Jx^*zlN;WCBSk(@ zI>96tEA^-7L{5;J=qg!*eEh0Vn=C&&-XAoJ6RhI8x&+A7Y}&3xn`<7UUa}CoT>(ok zkg1UaPe!MuAGS%J2TBhV!;0Lo6q6BsY6WVe0o5y<+QDite2n)zK|6cENP2IkA2pYzv zgoBvbMuN&nYskj2Ixn_cqjh@AvG6*|#G!NiE05CEYPde2ZE#CN@vvp2&00K)4(J2| z1&)RO>2ceb&`?pgX=hOO{fs1`pmFeNaY^UF!kjK+J@;=X`CRLRI?@9I1C9H`F&suK z8!6-N_Kqlkuzz*H>P7}YiHQWAp9&q%2b#?nFQ-~2t||2$(q&!KPZT+04*SmE4xHa@ zE-92YGpT{V(Zrm?aYww{zYL&+lW*_u^(&?FlWdCY$iHrA9}SIn^W4N~cE=6#n2Dba!sFX9Zz~`q~YB8PVyAy{4a?-1_O5B#Ow* zUAPQLAHg8N-u8#p_#8#6M`I~+JS1CO&NUz)Gl>6vrSe3(+L9u$?Hg|t6%_?C`&%+S z6WmU`4Q-zfd^d*xpEKhxxsFz|)jPM5D1wA<*;ZM1+Nh zfLa6Nm%HQm)Ktpvn_hKm_Jeq7s;?ZFgq)Z-Xs7nkz3YUI-YT<_#RL>S-+|vxyx?m? z+EQ{`!Fu zDZ%*IRALs>i66e-dHJ~KI^J&JLnW*n($|(>;e@!1q2rg;j9{ja2*0D% z**8}#mIYE%r6ncj#MxkL;;_T|^-s1D91yLUjS`Es7qm_@!f}>2V`ZCnj8HS9{OkpM z*~y>RdnI_iVOCJLBRQZNs;{WbfbR+}jNSEd*R~QW%;1vN7)v}07y#_Im>utKe+A=g zoWi}vg*f}+Yqd6am8|52oL4z<1QL3?V?OEv25MEkLe#Q)DAP@vc!Zn|%trG(1Q!r1h7 zlpj-XVK~48ZvFBFi}_67TC8v+Y3q<$`DCt&458`N;lm`=3 z2-oeRp5`Jw!?W0~%Fm$-#>!tEe9jzx>)B!#=gXw!J8dRchL#jE*py9I|3DYHZxGpH zYW()t22R-@Dym_!5`VI4YU|a81OZ^gJXZT+s$ZWZ*7H1bO=xGavy_?{p|Z%&?4 zZ$^$K!M6Pfnm}qR9Uq(0c+Gvn)aa+6bDJuqvP12`H#vx^_Kd1Q^b!gTD&{+v3G~Nd zC=QdAyrf+Olk@PgU-ptxw@FUXs7D9-MjR-~vdxKIa zaN7g^Dq<=M=34fuyS2ERu}jm( zWr(}wUtW*uBH$-7&K9bm$LQ1#Q(Q|)pRdy_3hedlFu?rIlk7zOo>F9|$>H?`-V?PG z7UMR-Zzh}SkEtpuI-pJ-Kw9L5ypKHU_NTUPG$bm+X#E9&8Rz&tAfW%NqPkW0PlZw~ zsTm~eV{W}Jznp`yv^o(`Cg1;CYY63FyZ}Z9@sklq;oK~KeNK>_isnc|rFA6kHMUfA zN0vkEv`*fD&$%b1qK_OIQ9_f>%M1*1g^*?JDnJy^l%qPkIn% zPtX4MDXX1PcZnjMqF@Mo(#PH_ncBja%ZywUW$dnEPv?+u1{mg=Y zfrg(_lQm>+QqYlq7>mgmqx~#Q0m^@>o2?MP-k9uOlnO_i9T(Qe>eHR_QA-N!7O(ne z9dYtzOhd&)Mu>`0>AW5s{t~-7&eBXCpOQiz9qSk^e6P1ROKAcTr&hhaOc>H0%py!; z!d`ro=tc0%gm=emhlOr8Goonz1x48+&LJ@V(}3)xnKMc{n4c+2?UObR_si=?byL~g zx}e*4A7cc4s|@029T@v3_-aytPzV#>F%vcbH2MnUzrFlngeGA#cHQ%Vs?X`y`wNaz z@I+x$A_7E64{dB9nXH?c>f_*L1nJG5LRe(DC~K$qa=UBJ*+!K0q)wP%A0I)i6CB7vQ#TFBz@xXBCr!0YXB z?{Xv>s_4AtZ2HczL`5bZ*+c+9gKC{(Y9-HME0SW zh6q-V0d_4Z`@2i#$WCGsqT8<;$jZJuOS-^Z(PK6Ce@8P5CN{58e;TY|JPqb;P2*MQ zP9(%`1fhW0YmERr;ZtNj3A)Ut7ghJ7r@4&b>x@?}=k}>3k6#u%6Fm=em!yN_in~SN zvazP3v3kzWjk|S6P%Y7znn|AsK5p6=Z&m#O+nR}#?gx&HB}*74SiS>GKF+B*t+iYrtNL{TbjNwxRd6dtcULn};d z(H_cdipT_*q@gm<*umbQ2D>{(!#iX%m73q@zr0va+s>dBph&Q)0J}k6lE*m+Dle7j4UXov%38nw(>^8CwDgUQXvT{US40Py9oM;CU6(P89%$ zu2=`448v-33ZGBm&B-$57K+2_QJ z#lIE3nt*dgIy*>?Fa@eO6_a>q>@>DS2t0LQx@H#akQ~4=;K8m{@jA=(iRY0Qn{YZ@ z`|Hg^PdST$N!1MCQL7hgP5iDXa53IV533LR-R0+ zT~_2h*YL8RqPrLPxVgB{5#X3Yr&;7KCMIUdIa?%?AW-#U94Ka`Ma!BoA)Nlp9|^)T zI6d7ESdT!4s3`WFH|E!iv{G7P|{MynV9WLtDwL}_O@v_e&bgv00HPI8K4_u8&Pnm{=5c+f2ZVKa- z(0t82N{E^;9o#n3Z-0g;eKa;}GBlL7pT0oDitsB0x-opg=Sh7;#!F)Ov9fvP{rxHe z{20R$-Y>=RXBFj>YVY;z|J{l<5VBjm2G5~2mhvHM7Dg#DQx4SF>w9Y_2GJ=-5Np%b%2R)D4h(e5*_08Co$mY=*vc8+v{LULM_c7|3vTDM5|D0^muqvgac=OG z>Z@32Ahri2{{;y+IwCho1>NBoG>LEKGfiQ@_D5xYw;hSJKTIKJiPwfg6eSEVk@|qQ zGCG|vw(tK+5bL_>sa7PNMhx_@Bt|fF{2XZKKrHgly&39_8JfW3Cc{5~1x{fS5J@Lx zbLO4@MZ_o$ZBT9qu zU`PX5X@xn`Kj&GbV9i1-gbGhNCGx52JNT(C>R0{P+oX2WwiR%7`t9!?r@MMzGI@>f z+jZ#E$}TC%M~RcgEUsZYi(#juK5EiM*MpY%SWRsd$m>~d;_Xr0ugs?{L)&nIF`je6 zWP+}@FdyS6Ahjc)eE4ARC|*}isTTkk;)s>v4ECCpFvb)BCud$B@>fg^c9%;xo|3i# z0HaD1PYCcol%}8K(P%ZPOs^^|EG`Yh8ejT&J|qZ>ib3<`4-J5Shy71G9nvExJ$*PE z014j*9R&0>byfyV0eGhI=)rgo4DtSG%HY`(6IvE!Q0NrK(lG9b_M7I=nrb0nSGYy3uC2EM2h* zZ-U{NknN=>(zg2z@&?%CN3>lx$(%%eHvhbmA~*v9h&dKIC>i%aJ*a@5pPQ%q=-cyc zlG8}KuHf5&7EmP`B?+=JgBs-A_Lpo$Q5s@wr$3@J)M>8Sy6cd~iu&qU8An)|Ay$0u zmqlRKe)BfBw@B$v4f(gf9lIc+lZsM}eLp3%KR9_)4W$y^*-l0WQ&{7H?K#c^Q@cO` zy>$8@27|byJZ{{7B=+hznf+3Zy>4)@dTsid#oZVhv@e(J<;iNA#+5$ z#6q~o3bzi*V%*eg<@-ldI@0|7BnZrer&cv9viTr4cg+F%Lzr`V~`r=F1CJDWd?$(;akV4_dsLUs_Cc;vcpt50z( zYreUzs{Zqw1#!dOIXcj|vOkid)Tv6kBT!<712ny!Fi*DTf8r??#s}h#0#EbZ$6(K} zt9P556u?ZA>7Vfc+stw@qrdyUzOs3;V*((aR_m)T|Dshs)rR<5y#*CjBH1^y@`s_$ zEw|j^_CBR=2(8v_*#7xF#<=AN7A|hkDJtzg3K%C(MF*?(ig-G^Ij!LSQ3)oTl3hbp zkjeq>IKzJ%DG&zBQQCRYa*Fq%Z}70^o*fq}=nW4b^o}H5oaV9hizrcD(_Ro2@#bVG6>UQ^6~!*7rn2)Td}OBdhT-oFlL0?TG*S_%T5XISRQm# zrn!&YS!+0NMnG95^{A9_oUCaR_b*Aukbm-ZIkythfP#ldOM;y1=mH4H{#Ec3%juDD ze(U9%Pm%+wg@CrlaAB?Iq79bYq5y2LF4>5h<6&8ygT>FR`!{Hxjh=D;-k7!lks#(Vf!sqh@QZ>%aAWvdB<)tW)44#Rko4+R13Ylyf7F(Oj3>H z;ut!fh*6#Q8{k*rtZens%$gvH9X3=53#xi1>6gm%%RwBd=T=8YlLeKybf_$t^>23$ zw(#_`(|)gB?@}1AK4jhOPQu&i7Fs$D0J^ve)UCPjeRvkH~fUxXekc5DIV03a+P_ zwY`N?Nt1QenFQ3;o)6uhzfyD=y=vxr0?ZSbqq2(GvmspE>_Xf{-MSznr5YuS;7mV6 z7_wP389c1C$Yun;v-to>GvMaPguT_mL)kN182IH9!*@eT37U~U#LNHS&ZfQE>D!qZ zKu{1W%2ObWAr4tz7!w(u*c*yC3KZzheX;FkfZqcitqQ*!%a&CpxhFIduClHiI25AY zJV`49>DmRpQ{z|$znmx_3&-;z;CA_w&q6Hz>fT(KlEbNWqlucd|M~9ymS_zhJngN)5Del$Y0-V1V*=ojrTL~I zHx~|xYNRAx2ptD zoR$>%@{nOWKZ#Z!c0}rRQ!xB5@i)rmaZ3nEa+A;dZf!sYyL=#VUi9UU1yCvxFF;zi z;d#mHjzb;-jf59OAj9u&bLKen9!|qNpK>_ETBVRLs#v4gFFi;dqB{5X%^y)Xbgo=e zuD(v(!tOVUYG((RSWI|iJfAn7^UlYpM*U1JmU#@e&X_4cBr2kzJi$5o%@mFA??{E_ zx;!lg6eXdOKWS?0)lKsC&T2N{VYdy)MoYBKT%uRA#$ls)7D(N2Eq|#jnk|-<(()qq zitOL@DBN1n$Npt$5~t9XoIC|oo(T&VoblUt<}*b12nQdMfTHGZ-m%j@P#c?fstZjNjA)1P7Jz>+b?uO+PK9x|)V*`f_=* zw13o1{)f|KGJqY_cy|24aDTZa4u)@X2_Bq7w-aG8hEAxBi{UN!us!1wuhntF2%OEIKTW^adau$i!-1Uu z&PP-nOr-NJx2U$E5Kh*-w!|a5#ppbKN-l$am$N5W^-lY`mtQ+@=H9|81?-q6}EqV*dF=-W~V%-!gB;t$jyIcO7n0V#qvZ zndj!E0&sNcRjQlSz$_O>HTxZD2nhyb#TPe zZ;8;}5j=)XBJ&y)#nN7xcx-oR;*S^AyhZx>t2h?2CZ7Z_>f@f;u;nJ<_~>(#PYdTb zf0>zGLsGJxU%0v)N# zP%?NFrHmZ`LNYd)3j!9QccTHKrUAgd0!tjgBWSuJMb4#7SB#g z(t_kmpj}=A?O?oCBKuve^Gp! zq|3dwH#E6%X$Eb+SS`gyo6)@pFCGOGj5ODYIR-!AHNmI1NhN^4+C%@okV0B$`|Ss+ zAdtG|TLRp1BiZe*Yz_uM4i{_IPNK9T0(qvbxzP2j_EUzrYSm97UwYlDY0`2b-WG}3 zq8SLE!IRM7?n5c}dskI@2tHCmr&zm+Z`S}RF@WXEqg@gU# z9tN3DDx$0-B&~lhbbS1G;PXWDLBW#$mdwV3D#^uv=V3tTXiy}HrgG`Punfn%DlW+8 zqh~jR@_JO$xDjj>qSQN7=^(-hRmWjAVD1Y1GjA&e*rc|Z_8Zl1DceC6JIqIR5E+{ z$P&r;j|~+?w4{btqTBOsOP!WkiH0j`jA>6hoZaIv;$xOahi;NaML?W^s9!qi*($qk zQ%>FP#>9;k<-tkX&geHVCi^f(8dtNEoLlx#qE_hI`>iHBj za!yuo&9^~Y@m>%+(VHMYR43A7#jQ>%0S#T3(!VzAsAyuXTsU$+DECRtM9))!c1kuuKtLS9vDT-TDVOGL)|FG> zWyxjpsC(QU5rIQ}k+&gkb;7J=;Khhu5WEwv(jdgB_M_5;7yvfE1;kdU-vg8 z``ha*`TNZ07L9Zw~*c?YH$&XmF-E?t+iPC8GF0uH|Rmhx%rg{%Zl|RHyRqFZzn_ zE&ix=CTV9m?>r~?rHgSv%Jr6^TTg_0arDr9KC%Yvba8h<9M_1Yg!7&o;5XL4;w8c< zZoos~XJAD9A#O_H3_?vZHyGPNJ`=pokYWDl6ShSYHOqJjl}iMQ@gskx-`mO7o~1ga z#LFH_*k4T|lYXe2O6F6T27IGo7(DbQr}*ksP>?XbDhFl}(!4TSOQLEN_&VFg3)1un zx0ZtZc+rKor@3lburZYauY4=HYWtyu3?_*?^Bosx!gQ7lrFnW zFLpUfwp|ZwFjh;2x@)7aac=3`0{RXu7*g_4PqfhPw$6Yh8rJTmDc}>~OeNh6B>IZ} zkEM}dE$rE57vbmJp%j?*|I5-DFwS`>sbTz8*qw7f2}rNuwycE9LsY+|9oqcb-OY0> zH7d@BqW5Y4K;$c2x2p;ohgiN?LXU@BukbEhNH!9!?P)|Iee1I0$jzF6L^3iHl*hml zUWhNFI6_=hG2}iy)t3uyuhV%JbbL&3UYz3-k47Ok;{CWzF&8~@`7TaO@%MfnRk<^` z?_8bXG*p{*AG;A zqk=S)J{sLLPKsn@N6ardd3Vmc&PBnXF>rV1EYd6v7`oqviX9@Du|Gi_uJS2VPD@dK zk>d=tw6lngKGb}d7>)TzbV{uz!`*ar?Hwb_=SeC{2i6W~n{nHZT!YJRo!C6;%)771dm#&$CvyB&I@2C~FZw1pK)V&E3Z z=OIrxP_Nu$|D2IXt0+ijydy?(U)EayY&=%z^ScO`#rJpzx|SWqr9`uc<-dre%C!Xp z!Xwu?8)!KWNd*>O)RD2lJQoF^Se(cITD=d-^lh`CtIqzDspU+vSvPs;Z z(87y)VQ;TuoG-ntsIAWoNh`ve@8FUk6e zKa+m>9!RZi-0vWCieMsm>9hqq$n(EICR{q~tmk zL0H~Gb#3oO#Fp;TdqyjZigXb`F30*NvJSH;ZMW93tJ{1OZ8|R=6%OBT- zU0+SP?4resg{dt+fi2t7j&?5|Hxua^=DR`4EwJa`XWOY;>c~^{AX2rVtx3+*- zfKJ^iT8uc~C8I-Aks+xxMUasHKbORz!ubl@_GdB;>s1CA0=%xYBD^GVe%>BH_bXVJ z@p?WC?Z)t{%B$zFcuN=@NyB9qrg$r^jM;)as+3x~f%*!pKJ|S==Hm@#P;o4vlV0HXN|s=US}My?EY9 z#XcT^7}v5A_YBO;HsICT!g08oy(V;T7|LxcoB&x7*Nz( zKR7w0W+Ou7h)&*1fL8X5;83(8Op2FhpF}8gt;w%+^GUIsK}?swJibPM8dO~K9SY#S zs_CjJ27fd`Tw^o5E$$=idJH$DSqlRTOHY9Bm>EiNhKlU>Rt0|y1rJF?6HBy0Fkiz? zcez>|7*x`Mcr?D5ZlCJ774oe>IPY;oZeuw0)~;L>;M;-IDk*h)nqB2S$0*ipo}S%EOnMC!)2;yxvPJ+DD$#(C`B6sn!~kIFGxK*SvJ(KiE>|`AOLxv%XC$ zZ(tgGK67sryJ)ygZIXIPyd+k;sZN(p7yFrGe;vEB62`~Pr*zk8iaDq|vDe|=8a3~+ z%rQj7^kXY`m?^f^HD9P$b~n}s=GQM^+5TN=SP`akiwaV)(j*~Bj$f9%e#gV^3=_-1 zS7R zRsu(Ekz0Ko^?vHWSI$yX^+g@e$}b(Re+s$@z{1)>@x8>q(*7iLMQYLf21>_WGcvA0 zP*fj%?YXdfG3fU8BgmcSeoiS`iG@Qzfa+V@H!2+nvl|QTO$|0nxJH^5=U(2VTt0S1 zWUA02XImis@+0p?L-Qpto!7IW;={ENLhD&tM-FIWT7e(*O(#;oNfs|hTJX2>AI3lM zOlsAod*v4`(OG-^sK+T^)?DvKBWnVcZi*E;E5ZP_HUt9k+;oCRcl`j#ZM`asYEXxx z(UiTp9ywBrapKfw-rvtqb2eq}^GCc|)XvBGfu}|sGqP(n8ZvLG%~2ik6DLFyf_Z_n zj!xu&ZAUy0BGdERf!BOB7BQPm3qeOb*#6dCO}w2M^bKa1PP4$scN^%+%0uPd<1JG( zh2r2;Wqx8%wi79bK85C|dH2*aa$;|4F9Eu*mp4iBkR{Q7$lv-1lQMLZ%BCu?DKc`} z6j5EO;25N8ZYN=IGnz($*{i0k zOU~#`U^iRf!(5s>9Bb0Z`*f#d7zRrY`#TA5XMV0yn^jySD8mBK?bX`6Df48x#G}AyiC-)1G%3zDsXU8$OFrJez4gPxv&~W4+`N5ah`Nq; z;4h!u_c-n?HC}FUGRtkMsiH!`=KA(siEV`D^k^(x1ibcHK0dXj{gi)^#pb!mhG1($ zzvPMw)Rj$!NgY%hMkYq7zzcKyp?p${=9651p>$q3@s z?BQlI-r{}Q>wJ#36&B6JrJQh zDhg#EiorJfA~X{9MD$r^6DNfXqyllM$0&+_gwYt_cQJaPsN2s0%4sgvTTicUbveYc zSxlqvE;n^eym_SZwxEF`BzA{IZC7(Q57|GyPan`}{JtHTT+WhZ{(qZ+B8Gn%aT>f; zjN{M$Dp~%78=U(bw}(QYDjv(U_&Fg1e?TE=2>V0A5isUVy(c%r5s)z;&@qrP1mmJ1 zAu%w7J&;HXVmC&8C)Qe1GGgH*2#3E|U9@x8DNS6AO=Lcg#K-JU@_#D3SbG@wwI3g3 zB&soyZ~bn4$(a9<(x5I+mFon3TLgM2{q0n{!>ZY8?Jr71J=k$DeKPPWd_qGT+9L3uA~+9csQW~{4|y5m*@j6Jy34CGil)# zX&*}Hpt~PeJg@Qk;+gTXA#@FSi|CITsOWz&MDnj;mF-`R3&j^t;bh<W?t#{HtI zMql-AvU9y-k-%2)pwfFXvIhZ0Z@o5*b&Qf%!QtdO^s&E#Mg0_PEa~T3bTx-|rJgxv zRX#*#ayH;6?F{)PC2z?2e0(d9&}TzFP{m?teh9baf97a82h|ih6c*#h4Z{L|K?v&Y ziNt_KgXcJmvX%GY4_&mY9t9*!2q`8#=!>JahJ07?X1%VaL(RNzBBqyE>9c-Ej|K(H zeOOVy@2pUg4=YRrQC7hN51@NPnN+gyM-@$z*Q^gt5s}27_QBr81@A3bPLLvc4ie#D z8SqWc2>z>VXiQ)S7bfgEK9!$gB9f{;byzkH7HPBTro zaq)~3jP+ASxjDGdiMb1ae$IC`U?)|AGTz|BO47Xb{4rbi=xTaR(Q{~bp6MapQemrJ zi$T&hrDf6P0=LHLfTQp%6`#R$Sof6lkRcm+$8QS`o5_5<1nvB=;7LRT(8+qZg60$& z-zA3F@}m=IR4!@)1@1H-$KO=<5HbwM#-t*g%L5H9#Zr>YOI~`T-yG27s}owCf&lMrLMUDAs`z}Y)5_S92y`zw2}=e@9e`{#+j^`B3H<$Zpv9GT z{dT$2k(Ik{<&E+LOr{a{(b(I{F{kZ9&jZ6f|1nFB>y?6u)_2P>r@5zDu86nqr+s9B zPh~G(IDbtv4CYlY1(+D*XfMj?gx=`%Yf66{6(xB7Q4r%+^5NW#bvb>_q$RM8@f6JDO@A*&Kn!MuwfC-9EyP!0`HeI6WR_BEw*lp@B5+J7k2Bkf8h|v zyH(Kl<%IfVy(CsTB@XQI#_J;)SI=DuUE$f?C|-1}$ttyzhR*F` zy(P6-O`D7*C#~%KFp5M#S1RJ0PCHOOi=Q%9AZCnX+g=O;_EMu^=X8U&V#kbpA+s`? zGZAeCG;-tpe6Oaye^hqKv*TcWa8EI`JR*@_V5F~h>`+Fcu1BSi{te_Bq$sKkn#s94 zU6s-Gx?nSz-Zv=Sv)Ss@z+up)IjIe0If>yh-rDe}_q?}k13ANEpD_7-c(0tS(l(g& z7^IV6l{vQgX=+xiMe7~0r|>{#)vlrM@D+?xQ)XA@^zG3Zaw4=syoU{1fktA7Hix8a zw{~f&Q!?~6l818kgC}ky{$lWhSZO`JNIZeD2E(S2$4q*sDvss{tltEQlHA$`7-Lg| zYWgb(UfB7HLpE#o#rC8O_8!9OaoWJo$a-=+6G~M?!(F#*O`|TjEv4^4fzEFukWB zvvABfmW~{$M8X4~^M(NEs+Q1U>Jx2yu2nOEPxD^u0JYK+dElB%Ft|^+EM68;uXNo) z3B@xwQ(6PDB3k`o+JiB4X}x??3YZw=o&S7cytvA7e3@t|>~opVYvxe!XyJKV;zM}! z|7htip4XOrG9W=nWAk*+BlLZKaB6Kip*MK!uCkvFwbbzy*CgAZzhBT}08vd#R&o{8 zLVfTUl(Vikih{H$1NJs*zgri+lX2BLEa?xj7U6r|Wrb3DOvg&E#hyUE2-E3r_^^^t zz2=a7&9*0w3w+vWG(OC$2dk)v+W#EiGOJFdLiH<*+URI$m+l`HfGq0;ay{LMa>9e1 z1VYo^I)zAE?2iZl3xA&+UP^8pDI`VE?su*~1YFd8?s-fmzfVV{RJx-H9-T=_vZdFJ zI`*uD-mt)DpV$Yz&_G`F$5+aWWSz%R+q6R?_u%gTw&!{pcQ0KYG>k`7$PBAkHcEop zeyFu{I}PwV__OhvNA8UCj(`DBRI_m3-``ud3)Z9|@wBNgBwCFYqZ=lUB0?7DC;jNE z3GHgmay;0C#VQl`vPt5-7SkZx&xyMm2%R~mE(_t@u5+y>j;rsKfPjfo!H6H($|ei9 zuN2gB1Z)!JMQl8wqm8>WlK7tK#>vWCTIY>Sq{MaGgQ5RW4Nw86M$?VqY+S#eQ#u+} zKv8Y72Ws`cO9_M>qfQsAO%Sg@^>@Hd_n38T)l#~HWzZ;*`l(#;UnvGloU1wQuDYNu zbiWDQcxOeK+6*Fj+=jLHk9ggqW@7WchfcqX?_j_-S@18jPXoutIZl!VW>87MB|cX4c;< z=ji&%v4^xC{$Wmi!Jp6>@x15bVC75M?vXtRhH48o%W@&6up~#%_{_-qt(wHSXk|98 zH7FJeS~Y-GW31>5FWO%`7azS8L_0La{bz1BCppc9 zuASsx&j(0QV9ZcMvGmu?v$pC@e1iv+~Wb=naH~NS7Od*zMA6a;p-; z7c^Wh=cC`BL6qo_>I1#E%Sd~r?JdU)1+lDp?_>@?9!Y=pOq+ zf(e#aJAJkDtfGW@uteC{lmzUyz4Et^IQIfF;zx|KPPQRYk9fEqGy`yeERZX5@j1^m zAw0NrN^5&7-B`KvpRL#qi%drY1+_;&760=ACYR$=7&D=q1=XkLM`=y0Y$lTux(iT7 z7MAL3N=+Py?|^tc`jb^k-1O%+jZV=A|3<6Xn|_z(>#Y>Ko}hQaFuwT_FBDx(kx=B} z=>kxCqU|u+%+d_<_vj2`{gWBZ-6ZY$ix<7Vx zfY}+t+(`qUC3)n?ECykxcj1tqfP^Ol!+h;dV4hv&Lm>= zMGt?_46Y+!H?^iV?t+3ptER8v595fS;JmHYK!&Md-&tgL%tz31#yhF!BJVeARLQGo zmZZrB^A)dx1EKzgG#ySkbf#*e)@8Z zpD>!rjQ6Z79{Vi_r#;PNBU3_Z$nzgzmF&tTD5u`}N`?2IKdJnYxleYJnP&Gn_|x%7 zOZ)SR=cA&KQ6XT44>>lOLEZnwnTUp(-(7aG<64BI^m=D7zvPgq5WQ=McL&S5vxsPw zvU7=T4}t4?4AIeWSN1xP#s4X%d$=_Td@;K%4#A3snrt>6p(ed;%mO3mVfLr&1a9|G z|AKA|X;16D48VSrQ_`3r?&+eUNVg}0Qh&#NBhkjuaExX2kruw^)?|TFX4U=Ha$Y7- ze9KHJxvJbOXxh-;M>4+;Jg}tXL01ibim~g?&oC$F+p|SU9T}X($|;?czCVU&)z(y0Z*R%0zv|F1LSK_dRvLP$ zRAZ<%uD+>IvYpgS&YiCgo$3(vn1l>^f95q>Z=*gy6$qLO)gzo-a2Tm&#Y0PEBhf$z?f`;gfvIW69@P3!LGPc#MYC?S77PT&spt?O_;DB}#O&OMU+& zf=#}cRDBHA>j^Mhu`3+9)%!}j=`$VG-_e$L+A*sL5=eY$YxMSDVGln)yvjfoIrOP= zXFY+Epy-h~{~23!k~lGwBjgUAT3H%o+3-n&4y) zCRyZS33+-RbGgIznAFN)$>>nZk>&n$->qcx5;rOx)Ltv|E*{~`{jk-5(Q$%lqVgSm zZtnXTj&uPmt{{F}LFUViOH?8~VE+$8h${He!y<Y zXwiaA6pEmpH5#SU_N!u>4Ygrg8fo|aLx*LZ=XW?$Q`0d}FKK9KQOtBIvuv~kq*rTl z9A;_QA~YEt&>;%&#cPEtzCM^1c-2m8CMjfIs@D0+5#1q$&IvFvw~IJHQJvY?#YjT5 z(jBqCtVW1Q1(vS>0IS5>K zc|?dZ&na}c{UYyv$_ViICjq=#W!T}4too|!b5`A}K?4CJiUd!FPDs;BnhAV(nhdY0(lAL5PDD?uR@8KYy8R7F>!izcECyMabX0c` z!hT$old75Q^|9J-Cdt3r%ht;03Kji!E{Imq+nn3&S{o2D1s7{~tQQGTw7EJWBnY1# z(h6f;xX>2li)@rJfRuv3yQBr`9gW-&cD~!&U2jHZbn#IA{e~5=jNdaofMG!w(Lt;B z{-{jBsEwkm`d+^a-P8V`KSn^841tUypu&%bZPLxevC+OsF;FG!|Df!F? z4MD5UtK|${=dDdYNOOYQ;=+YvNSbwJ&)w=N5`AnFM}E%eu1E%90$E08CMkAMBp9+x zSZbK?hI<65t__1iR8p7_Xy=3Ay7AYazF42@;ls#%>nvO$w1Sf7sI^r;;2c49gJqjB zDXgraPH<9HImCn3VQ=#qAHLgz>IGs!QV@>ipcp_i#?RnPYa@2wl6zJnf>H4mryx#z zaF1i}@2YeW6A%B?0rKrp30b;B6M0^cxPU+OHTyS14*x%vC}X95fSV}}efyp)O+pEN zPCZA={W{ml#0JGh2fGa+Lc#jO!7LnUd@92_{Ktz|bI3*4+azaf%1r#2kYLD#2Wvu` zym34jZ)+i4A-eKc7t&2V)zb)%FVAt!8xVV3a2P6a2mVmNF7Ra|rMFn}7h$T-Fr2j= z-C)T-M2w`w7`d%(s$U2VFioeNRG7jMQXww7szpoNaxX!2!(y2dgT}aoHdES6jGEF; zIM|hVOJ<`oLQkUv<@fvr`e?)X2Fs^SJ7IiIL8;XPKvw+Mtu-=N#S!_$J5e3JE!SK&pks8h9Y zo^EW^yP{eiJt3a~!0yPRG7wb!&Q-Az!m1k$8O9^CZ)LA`?W!a^MyzW(A0XEl!)4jFD!w zD$2`C{kYc7zvh{K4h&9bb4od1?@;*L{>p$@$NcedO-Bz;nZPUF<#Dk@;;Y!4Bl$N8 z2g%`DXc;MCtIMmR5D*~A2@TV4D*}(pBWzL%1`9c1$`=WfVA%M@1h#_3oSvymsQ zB<$ST>1C}_5=G$y*8K#`T=he?Eg&V5s5m6K=LS#^av7qCIP&qZ z<9~;ib~%1ZFavUbT<6juhgI#&x|M}E;zwbP9`n3b(-Q3xTDH8YGyiv-zN6bar zTE#W<0T`FOg1$g4u%5%!;^amzJAzE-H?pw~zrd{gtO#SStDcOa#ZRA_P8IHa)S=!C zT1ph!Yf%^)>~ebsAvsd)Gzv0~Nnt+;y}r2pMGLgy!03cVr-Ig&a|VkMSDAT<6hTc| zsj^>dTwbGP(|T-tLFSBOzo1t1ol(T}Aa=#QLeKri`7x%h+G5h)m;s5r-#;hS5@M3V z)^1n8EO`8Q3T<;>R$n>J6>XAPw$D>Vo&y(IG;1d%Y)E=En#NSZ6}g=g@0D<&6VnXCl}IK0JJdHLHvK<*wEjBWtp zbhMA39w44WTv^aEX0E66bK3TJ!mQXz!RZg=gd5|bz z9*R}da^lc&OJAU}K6|Zp2M3b;n%=~86vT(}w@pPfmqgwK2~$i;nl(?05dXbVI--AX zRFxaayD0qaZGPHvCfk+dynxllk~TzH02sgiyqt4N7){>uv3AA`GETu;Z%zd<&9WI#oPo%NiTPQ3jq1%kLEalvKZm2i#D?yl?Tgl@~l!v(P<}8 z{)J5LD5JaV*foh^&o%ct6^4W-kX8Z-9Z1G2&zj|jxE4O$Sguu;5%N2$mojkZ?|_Aa zDb;#T;!{Qo8}+g#`F_4X%79q=2hYbjiSk4|V|F}Oh9Wy$<@-JzM_ON4Op&%~*l*6A zrfDlN@?hs>bVl4F6g~bH7N?a{B1u@pT zKvrU1)~k0t?c6n;({7?-cnFNb^OrBD?ksu5o;k|zQfovMli3>KAv|uUb>R1}rlnEE zk~a+B0Mo;ULQhCI!MdaSZY!=GDtj#qiMa&CKnsh@QOHv<%bUC@ecnOC1dJcWP|Z8( zrI3isu*yK`Mc7EI%NU&`fWg!%USb!GlbWrd!3B))&SN5R z+UdAmH;3yXS-P+MFZ1g!3M0t-m`qh%xHmYt10L;Ms+z${MXuA(9np>_)#eDmr(v zbXgS2E@@xM5L0|>on2yCwjaQY}N_~8Q^Fr}ehT|4CW zW=Nb=63Hf4vF1WP$^~vcF?0|Rzm}O~GvWjNz%)j7u^r^3L}L)9 zkOL|#XukduTYUdnHRY8JL5tdt7aJ(+cO}$zT3%6J&70K#x}Nr9X#a2=nBw7R3ZXmw zo3JnVl%bh|P&(#2{+Y?iRSV;##7p@ePDnk+{mDAjKsu)k4%?I^8&aIe_}PJZk+PK8 zr)IvelK40vLaCa9hnZHbK6vM1x@1XM7@U}7*X>`P{@XjC1gbMgU_uR`;O^ea`xIw^ zA?+m%)N4RVGTkfOg0%EVES60`J@U(~F7hOxEHU?rNRSqTbjyi68e&~Keul`G2HC|e zjhCygcnIypu<`w!t=Jlb$26wyJfDqwA;P>=1T{mGd!HD4UX=SO28tko1?)C!01+6} zAw&wjMT@JrKFc|d{kktV;}bQbi|@H8{`DKz7$gF|ollTPR^F<8*l!{nn-6FW482rAsiyxw<^QL^|n6i)mH|+`pD}C{lf~tqv)vo|L zEs7Occwhq36seeY2K$flBJf%_SMvuQrqXw;(ew&Ri{;q3Ee{3ql5SmVX!Bc950^-u zvciN70+-st{rn|Z*F1Bclfl5$!6qpQE=U6DJKMvh(kgBYUo8rWtxmPK*Dab8QgeA< z2-K(o5_By!4lWeC=rShvzstAWE8IMJI1@48yAizgSjuy_os9J0dPLsZLyzTW0MmB~ zMY3{K$evxtqjl&~nf&_Ky@lNFgecCYJr^-YY<*ovmz`?h|Y5ZP$=BROvay=bA^Y!bK)YOQAh7x1rV?>U( zyPv@8KlAC4B_*lGys_JO-$zAobV2AI(>!xv;y<_MWh8G%N80uG2)$mGsEl8wfARF^e34p&vM z7$eZJRtyV9Bm1752y0$Ic}71m2qBq{?4AB-(uh}J4VDkwYN=&r>Pz2S z$964ZB355c0~m&b2iG8n^Vlyl)cOr2xpss14jhc}+P9zl~e5~~z zRY)NQok7{ooaLg=z%9r_O__bQ6y_0Pmdkd}D7Ofxid^F(g?GvWH)`edH_>}O95;l| zB~`vuRey`#B#X@dS<)2G*oUqoge0Nc+gpxfe>N(}1yF*hJ6sc`|M z7=t}KSE@u|A_1>-9MX1sRNm>Hg)S-I_1X8Da@*I}SAVq5hQr22K}6Xg$$!1(su-Yo zbB(cz2ss1fvc{WJTy-^k*8&N|f^2D2A97KMxC@zb8*$Gjtw40_Z;?2R%3IGXAOF-f z*-Uh(3w}p<-@Nc#c1}3MA11UVM(7X{u|j}KV-QIFg0_?2jXCT=uofyc+>w^RwTO0J zt8xj~)OH>`PwGud??3cqjK;Iy(*0J&(edPV{3sE5%LLtRY8V2C{qt%s7gjn!R=n1w zF%d?jxVQGf$??2PqUgj(hKy)PjA@Hn9SmBRN8@H*#h~`prw$rige{Y5-k_5Qpqz~B zvCV6u&ExU-BiZi?IaccZ?C+6oTJYfSI2A>7=@%==n+a@z6`6dcYlzZ8EI|kv>*>XT z(%9>C)LU@q@r=R~o3SCY6+r1=uDsHO?vF^z@@2MA38_>#N%p*U^v52G&|TLLPC%V` zX!sT-0UyHtI1Sy?aARO8(Jd4V&)Y;M z_bt)>;_j#+2kt9xAu0ORz4lSqTyi)IM2Q~oIlQfpnBVC?*=-@J)i(yVRD+Zrg=|8% zm>S470{Sax4~$r@9(5!Jp>_GWwrBE;p*T~EQU#<_fCRJt_1<2niBI$s`klVe*6}_y z=csixv)_NZg$6L4Uk34Wh{el$nIiSFETJVthEn2QBa8Eqeqs8l$EwK9WPUerb2&ed zSAB#K^x3tL88_cwOItGn%^gla!rJAqwvdvXc!c2$HfFbnI{>M}rQ9h8L(5UHyJl>n47R znhA!ziqTM>0+-l^73BdIFqnt}x}1U+qPeCC@~yZqV?e?B6LL7}{buFKC`)4`u~6O= zu|UbLKqk_J@Z&a^`&|tx&Q?XwBTP6cQetsk^xfT*%Qs==qX>2zgsgqk1i7WYcKKls zc^q@K@H}(AXx2AYfOO?FHs3Tmo(;pVsTYoU=hGFXEW>np(!!^8njDxR4<@|h1=KeK zpUCFzu#Pl^0>X3DEWJNN#+5byn((0K6W~bE`$+C;m87ZCv>Mvy)x0{7h}9;dJfukp z*!fj=Rn3k=OtVXijxn}zc-)_)OTpvUE#Wggy+<$z&{4Fzl2f+(BNr#wPn-F-);?4d zD&da-T(?O(RCETzs@b&Rwb>2c7&Lj1+er4D!z{@aTzYww$vQU~!4j;u^3LcO29q^& zl!wUs?|C))b6_?KvExu?bon>@X-0f^n?&j(x)1rG3_aIoMKa5~oin=6PM~|qotsJm zTKU#!@PnadZ-=ohLR7MdXMf+s5LV4EglXITVyT(vc}0?)Jw$Cql!<)sL#o*6kOd$y zT(hyHa{9Rj28-6Wy$p!s4dYTeVe!v(&(lfGFxYUS%P}W=3;LSch(6@P(D? zI>!KIbegenj@ymyDB09yQjS1Yf=1O_YZkOCD#;RXw-u z`8|ITMclu92_%O|N>G2H1^%+G7gQe{4-3$#gDKCp z5c7pMh8e@?COF^WQi>N*&n*MXKh5MAcDh6^Zb1>_lSvRYu=iKGd?SZw($0;?%XgE8 zp`h;}5KZe!wGbI5ty6EyH(}~>p((QwCw5H>J-`)FuVY|W*IrxAfTymIjc%va{%ymY zpI$@XX}H#Z<*vl5j;r;}+J>kr!baeGZRjbc)VH*>?;(zjvosy`{1>x-GbEft5mIuD z4~@vGMe5)bxgDlDJq#0xkts|$c90J(T4&!CciE}1IO69bo(aPY zTPL<8dt--WsoVWz$kY|STWSAIEtEAmEK>XCO=6VyPF#4(cJb+&AV%V8&CxKJ8zp4~ zkc^{14o>W~hg&1rk92Xh+5|Al;=Xuq+lLP{vEa4?o%s$1xguY~z_=|b%s7QajFh2a z{=w0@6w2VCR+A+%(S1J*_}30~ln}mlH#OMXB@rVN3hnN`6l_{kVczAlP`r#;6z5jeLv)d10|)0WY28n;+DSo0 zRDbnM%Q^X?DfKu>>_k~r8?l6Lc(#UFuxJH*K5de|VE!2jVO0ke89&yK6z?{3y{D>NeO)BKN} zj(xg|BC4v#dIZGf<+dWkt`_`O3=i&~%B4!mhjou@K)2Q$suF#N(|d|P z$|dTf8oksMO3=HXt`2MAce+heKoQQPy(;R&isxhFn&L7vb|e_UNIN=Lp|b2bwXEr!5BJ*{};-yZ~xtlCd_{aBs4{i8qjYdE12C}TXG8D0#Nkl5{5z9>$gbD2=kb|8RQ=ud0=3fAyo2T~v+B%NgOPv)WE`xrq9O~a6 zF^D@|?G*dP{T{C!1${0EJwEH-Oh8$h3AUr%GD(r0`$VFhbsw}14968%E zpv@I0|F}`rQSb45RmI?yDbwA2D4VX0sEJ|zMiahaXd+K+|0g*yy7CUb@m5r&i#<>} zXrY*>^9_FSESFeoD>roJhFrB}KDlLj$tKD9j19sCHQ<*Vw*z#<{s>9)XgjhNNSW)M z`STrhaB{NHR_)Q&?85dtHLqP4m)26H1_fw(Fx2x+r{1;uko zi~6sVDr>!I&v`jS{PPbzFxd)9E>TV@#CMhzko z#%zj?<5ud3osuaWX?S`Tfa<_5mE!a(*iz|M#gf@@aU05sCYo zjsw%WbNk_vRuM?_H0A9M_h0^eAXO|l-qlD?ciawQ0dT)W-RMiurafOyCZ5cbEMUg0 z-9~9@-hhB|jfDgZj6VyVSKve@q-w&F-p)t?hE_FX1Re zbR+?^D#c+G7XyVO;VN7g1FfrAlI_Krbf2aR^@MHyF7(F`?6^+;3O}r|c+>>Orrd%N zRz>MAfc>}jBtSzxUf$rXvmd`bfE$~cGLjlkjYeFTV!IW0HSItBt;DvPNO>QL_(R-6 z$Gmi;rKNR(WLnfH6wS~|XA2V(DnUOKDM&Vj#sbXimx z${SIg&Z=63tZ9D$4(*@M2mGb3>ZTJ|Jf>cJfqySbUE1QEZ-yF_v$Hc0*F_Oi?Qn3- zB&4LIeiW)yK^7+9ixO}TE5(1)vALgUA$MOKYAl~#ORky5e^QiAnKlygCGJ!>wGo5F zeJ?{VwSikOpOd<|F}XwL7)KR&{{|YQQVUvgV(cu1FIjs?%IEVYlgnoPGI#q>Z#aZt z(qVN&q<(JRUxu@Fk&tn4St?bMFgyFbh-@dMC5tLcTI5gvUh8P>*pOl4#)E-1;5V7v z$D}ikmX8Pn(jB*>DnD_x;>exj$+$rT*d({t?XIE(T6?YOnsED|Ggu?Soe)WfbyK=l zfDA)r;7d7vq<`6TadO3Uxp;r`%0Zo4WL7~27UyDOSXdbTx~q=EzdPj&$|5I&&4;F= zl_SI{C#V8sj~iT4?e~8ykw)I)y-fKjtyrGB1_kQ9LwyH2xl zdiCF)uJ;G0M?{pBRfyOtq@e7@aoWf!p+*dVI0bDFiDk>0Y+ZZhaJc zQe^{z4=K zUtBNrRf5=dfgQHqU#fOl4-gpRN$Ox`RT7wc=Vn9Dc5dg!F%jp5&F*8z1@&JbAGOX0 zzJX>;72Hzi8t7}|Q>Ne*>oCV=eqj|Esg4+R()hc+^5pql^(Q72h+h~udsEJmgx)m^d@^&$VeB@R?YH+-~V2eN#e^QuV?C%#- zp5CvLT5LDD>slH@Q}nVMtyiUA(kLC>`MQFvH`}3gh0cNA9j+IL<+hvOmOtxmQJ?RZ z_40J}Bj0Wh#=mw*j>HhrU$6VFQu!Icrn^i?tb0EEp{>$v`9W{|k7eAucH>=>H8^{M-t0rNS?(FJXyd-p|)9kkXa!!?o^ufi=J&w$=MN?f}O_z;fn&aCJ ztY6;fF-!#2u zt6;XzUs^HFGN?6`tiU{m4-3e-F=WJeU{|~juH7eeOF9Nym)yWQ^l={JH{t-Na_(k# zf@Fa^`^b0~S}NLu8@(cxB}%Aj=V-__r2sLSi@u%GUhF0a`Ki84{pF@1 zrBb7rlOszgOFoFEQ0Mw?RZ^*s%TL{uyE|4B=U<6?Gc)$?f9zXi#U)FvS88>&wY9OX zXUkN~#JIn#ib_ZXr9F#xjXD|BsR@6@b*H+4i36&Aj=~W#XNg`$2%=@51D+ z2sc;9ABBnNet%}juod=?JGYjX72@T^dEtxfmMfLW_W=RIBEm&%lGH}bO;*bctF^ve z(()K(Vz)RUk|kMwZ)81hH<1z44g(JwiSmHXkJT=%p+w+mNIO9xCi3(9(|jyxRZOY7 zyeSMazA;(W&5fhU?U9`0(eE$V3iTFHl3#YHT zKPi~TU)4i21(UsHOAEnZbH>`yI6rUi?h-i6dT8CYomxO*v}MtQ32X9(mRp@3d&Z%1 zJyGs$CdPV)T$P1)A=B%UkSj)KyTpt=h0oYAb3LcL5P*#8M}E!kgqc|f@wm9@UCW0P z1uUkL)7gAqQ$ppd{^7@PP?nS@KrrS4y&T;Hdv+z)i?yoJDB?{ab-{}%DpXO}!o&p3 zeR=@wC6+raw)G8J7UT)wx27z0R1b8fBCg=jSAuJQUu;*5a=N-{-b)s-KGX1PM%JtZSt{J)TCn~-kRDbbrMP{>+{V2V(F7ZyDaGwDbLwa!apI_|#)V>$6^p|d;<=_uO8?s! z0WM=9NfgPp82f7pWyJ41dYa<8K56JejBr$9B2sMR3Ui~ax`#pu zaD^D6`GR!c^%B&J&*b!?+><76CYLKXljE*Q+krlcb_>Vao3i&xE*yHjFZkERZw~b9 zKXb$AE8LS~0KX`SPY{}jaOebz#Fwm@ znxdT(nd~h36j?M-F{5Gp5Y7jEQYM}$j-dC>1D5?IbJ>qt)FgWTPYb||`buNudS;UG zOTbx>m^l03m69U{krO(ceI_buELsMVx`o1&s97Z#VidHv$Ox7P?-j|joh%}n0(R>I z`DrC%S0{RH3vJw&058hlv|or?-U@h*u_P3RBM^~{2$Yvn-DJMDxMn^opI*)MiPZaT z`)bsAhlt&Tn-Z_6MGH1y%AWNik0Qd!*Y@1z!1PRf8m^7^eRC)3@aMgwY=Q;%s?;DB z%RzPt9E(P{)4+s)9{U z`8n|_^f9E7o~+l4n|R$n`O<=dx+J`5?vm1L5L!RR<%tHTm(}WCe)lMeLXC6uw8vMQ zJ=$W36Ue4X+A}X!TI@SrKk?=IkytEZa8qbI?z`O$X4)W^ziqPGMimzKU(f~;t?ir{)gKRT$E4NDcD|dAF|AwY z<8@>ZY(%67VGf#<$Y+Dyb76w!6;32y!H)#lIxQY$m3q=zf`SVA`@&K;tlJ*Dy{<6b zcRNt<1M=Z&OOVP@Rb}x)KTwLtd;_2Bv@;9Uh~zb{B(0dsY0R7MIC7v-vIuofG{X0F zaP?N|2I6GPIET*^UEt8{kgl*>P>rgUOPvxrG2UQ-7lFp~F;JcC=0OuFpp?q*k5bJmvz-*4I@v%xrStt9u;P4^1Q9E~cO079@?Qg> zN;KCsQNGgz;8}`cM#RJek5pQMayAc01PXfd`T4cA`{fAF;>^Ka-$Oz!DA5E6(HR`h zGjU21h3s*CHS9Ixlq4k%2~_1>97~ec$b&i}kzDT7P;tS+opiF%Z23kjjm~?quA^kg z>xM5Gk&MNecd~Rpo{+y-4K3A>03lVe#n+LFWy6iyuLv70XaQHt!4`b+G8Qdr8;kW! zG&mmsj5mkVF5I~u6J0LhBQdH6YU*-VACdJ!BQJins2C%%s~3b@XN4JCfPaN$;2e3a zzVun#Qd|3HhvYUm#*h18fMNXh=L7r4B3auG%q#PNKB95jH2P}JE_H`}=5N>dL0)Pp z3EtPb=L_v7Wj#D^P61d;*J;`{?wi?axRz+mGAx0r$&{< zBX_O72WZL4%RPCgV6{HG`u4UNPUqy@BxKV{5Uui0Et(75RdH-5U<-XcsP4GzhcPeh zyqo(JBDqG=O$wE(+=gcVX*$8vF(hsFXdXV{kh(n&k?VL&cHI_}kYY!zf#)wJ|3|R_ zz4mVdzpDnuc^sLI_I^=%%!rRCBPPy{`@yjokg$1s^gFci;PCTzykbP8Kt*OtZTr#@LWC8) z>WQJDVbXyLraKogt9z~U1s;4qytOUuptgetwpVqp{M*I6N!%lP#h(chiHh;lnnUs2 zgqO;;&IYNndaqBZG{F-~UyO<4fVz#vMR+z)l$(G7m*du9ZxL1#1)=J#icoiV55n>D z%N9^mWP;O0K#t=Q?pm73pmt8114SL`2ieM(0|<6@c2HeTz-DPZwo?_`ow_dZ&*G|uNN?w#qkiF6z)gq@iPD3-1#V6!V}utoCRw#20|S&W0yq`YVx8wPN*!l zI=SGCsYiKF(l@yZ?>M3bCnW?E<=H-oPjUW-4});$e6(EF`4+40WIf+!F%Oi<-@mb> zgRT-qv2d$~h{W@r6%)-dl=P}kP#4d&tB}lg@&(u+QVAef0mMX@Ut_!8(s@}OYMoCO zet)}nZd(K{m#|axx((}n5;w#RfnrLEnx2O$KD%{kSP8$+3yq7SVJ>{>+8f|c^CC7B z>j_ZpZ=-F={~8tMP|||_i7!?#dK43>jEsfVA{|V;;|LFN>>loWXmXs%&`B{h7*G-A zX-dj9jrwS%OBStg)wF$zh?V9(;h5{$85v*4#>VD~JxZxE=@9be^=RRY2Ucf3C}vYS zpR}1lN|IwBFPB3Q@RR(L4A}%Enmbo4M^GfMxqw-4X!tJn?_kf-XA0*{{34y9L8tyd zwDBHpWqozx9d(1Trsu&k1bEOIcQId7h?$j+IO|@3HH#Wi`679eCIk{k*++w>m-C=NkUWDsj2)W=%s{E2*wA!^7U`)7YXq9 zKh}&3C@5es6l1O;@G*&kd|yz`YdmPmO1^ez)B3zTpnGY(GUq&xmlaI?TVLt7f4is11$cnn4x(y=|i~(m{x@w;dA~^~yEdPOi zU=Za@bQdf|Won4)6)$QjVhes9PX}8V4+F%yz{nQuAj5mCxqpc0}R-zq2EQ{!U!+ZJh6#|C{`J*|ALyt!z4U>vXVHax}3%Esx`-cFdf31_c6P z#d~M_bdUH2G^{s70MoR&^$j%+&$JR?q?tcK=->OxW8zD|y()p^w^%%WVZc{$z+vs^ zA>)ebe(f@LH5dfYBBanTaoFHSJya+mEs16%mL!!vqh)j&1b4B=ofaT7Q{bI$SuIy% z3kdifUImutpO6*-bLlv((N6!h>9l>}7Wn4E*K3!w>cqq%C-bw8H|frt#cuWY@~@o- ztZayP^7rE7o2tN5><*@NOokmISK*S;?eu}lA4NmBLvbz*)p{D&;yic%_nv?}5K~iA z(rYIxbw-xdZH)*AM@N#Hn!k(K($*c1h}*))QeZ7`;$z7)w^<0CWF{}c?HO3 z_q>N*voTI8ky_|*QN_R^o6K}-4Cr?VQ25sj5e9o_XQLOfb|l+0PNlN7wUu6bh+tP6 zZM2v-UgW4SzCD^u$V{rt)Wn-p_?abCzORJLSSl2^0TS9{_FS+(S@}S4kl=R(R8%hO zrj~}ctAlb#Z?Iq%c@|Azo9(;l;StvthTKG^uuU$Hz^9kzUy|rv66vphwZj8pp;4^G z;ZP6~%2cS-!xD}3caM8MVNu5dLu3{hzE4;$HI{8Su5%`? zuvb^rfpddKKSxcB?Jwr$&(T4_7&)a}&v6w|3~+is_} zZQGpMw#~GCa)1BN?^V{yo2(=!Cl~hKpAN3=u~?Ch{I!vn-DQ;c>doqJ$Xj7wXA?Dt zEyMzgC{X(&Q3Ujt?4yjv@Q1ALe}aKs=cK{p=dSmygoVEl-F_GW-i1F8IQi^$;uvyV zpe6NOt3X!M6|C5v&f)1X%x%M1e{0ZE=)YqGTB=}yd(@cZlHY=GOZsJ;cu!n1jJ)i( zl>~2=q>?HMMdU^Mk8qgcu(hKVKaR&A!_tEj)?% zC(sIaT7UuMabsm2%m5kicr(&0VqBFI;Sx0;+Fn{;pe7!vyeawzW)5SKjQ5Svdk6zt z1Lt0C|8>5$0nte@9VLenAM)h`pDx$5qRJ-m%ieaX&XFr^dC~+U!}}RCwIhme?NRIr&%P#Kg*r zfmYrul|Z^H0&fLMB{jH%gQKx^Qm;#kw8{=~h3SWTR2HMOI|1lHr9jYiJLdae*mtvOlB1_JhgdP$Wb~~VMMg+ z_fF!ybX;T}ZT72jIZBel3OC0sU~LTUu%of9w~%eYtH^ zg@&?n!s(`&8WAp7m*;bcA^fnfHR&({{>P&-8KB0og69(JzxB${FsXD&JKBnGq9LsL zB(e!pkc!r2F@FLjw*W{OaDMX0Nw#3tU@D9 zRO3mRp(Hhx%{xc8mHT{6w~b?#{8V4Y#Z~0;rnJSjU0G!_m^tIfe%vpK@A@Y!V{^+N z(kWOfhX+hK^iUCGH|AFX@_D%l-5;7tCD+8kb|1AN(}oJpxEb%CMCox$6qZpOzJ$|Z zj{xzvyQ{REXRxZi{+lNKCqknp0|bmMF3O*bMf#g?K#tfN7#NiD%O!&>^5cQ?q^cPG z3>dz=KHF~l(KP+xw67RStPuBPwp0r_pq;mvpCU<)!Fv)6U2YrRzBPU!(4breM7bn$(eOo#J4@b{gc4`ufBjQoc@9zGucYZcZnX4z~qi8 z&;m;=P3WfAX{-pOU+*Xt3q}p&Uy4ML544KMfHX|t*+6K|NK|XDX z5@ibs=?)5CfzOZ%8~L7PJiU~sQlh}|KGm`SkXD{pCmd$4>Q~cnP8|)Cau(WeDPYj3&_{hR%JB%zsqT&T5W zd0awRujY(eujV3Gs>Ju1IL@|5hcy(1RIOODmBf?`{qW!bDxX0m#iw0Yy;_(0GtTd9 zqpS;wU`27G%d7Sr!U(ET53~*h`H67-wI%r5dUg656h&B2r`%-9R^m^0VlMu3$&r6& zz}|)IdgkVh>UA8R?VkZbUnt856>;&(tg0`lvSf`9`ZyoDXFJ^^9phijh_82d$)|R; z2Kn)Bfe%3n!l>tl#EKZ@bm+hS@8SCTI##rq?Y}3S5lEK$_=RhIymx=<8uFLx?bzD? zLkI;WIAEL0Ax3w)C$I+9^ypIy_`J*GcsDAU^*w=6|3k>#vQUYm$3H#&O>6QEse+Id zJsA{HW{%F5U7&gsmyRYg*$0^%8VKRDG^3scU5dk#`J5d}{K;#maEf%P=i0gGrm+1^ z!9!xgxR}!Nano?I>3bpwa;6md`}=dakDK!LSik_~zS3lSd_E39>+Y0~_h-aygO&}C z$cRImdrn1>=x9u)hdhegLr?j^KE3r&`hd<)Eo3;}Uc4uh=RWetABADwLXTeR;&oir za8JKQ3`FXrLydk3{0Y;xu3c&!K0#QO1^$VKeQ2zP(1Bxe>w@pz{)aa)SzLK;KMS(^&yiI!6elv9O; z8ZFA7{E)dQ-TV7zf&2BMzX(+pk$oI!hd=y*X18})XH<6G^%}A+F!nF-{ns=wHi;6> z>e0S<=et+`ApBf~Icp+h6ve20-uR0ar}-FHV2ytkQmI(lJg@O`ngZj>wwnkG|H@5u z9%jYl197K?AnQ4jU7`^SScgoqiY!`ALKY=-la-kc--_m8eml-vB`*YBHybPWiLhrK z+)^$m13^pgLF;KV5}7QL=g%g+OHA$MnS-`=^KbX9;%8`V|Hs?|bFp~}DG*$m6~D|9 zgOHF`$7h4)oW~~QqlD%KEImVJ?8}YAHtc>CbsO(<2dFL>Ip z>NQ4#yh5iv98wx>772LMKeHxwHd=Oa4T~Ijj9=iA$HVeet1>boO~t#iOrC;61kq4S z9Q6*aokUhsPnk;`b*boQ)HgL`Sk?RIUc@SjYbw4&@t!&jyIsZ%Yzxa$5UCVqS!D+C z6-9Iq7uvGekxy9mt`@4+jmh?F&*RStb_ZwA%lr|Go{pFc2iXn-cm;a7%_S2yc#P6` z4RV*qbRSkN9_D*EfTlfH4P0++bX9jJ<$Hd4Aa-b~UiX6QXj1XCc~O;Yz&AT7T+e|q zWy|y=ELhep*3K@mOi{l%UD)GS2`*-t_D0=fJ~l&@;Ot3p@-C-y>wS<*Vkzg>eG2Kq zUkZGZA>>oq?g6)1#Md6r#AI3UagAdo9HfJg+T z$G)vnPgm=#u`_Pp1H^0l0Xq-_WSI-_A0_Ib;wfm!=xN=t$g_rI#k-e5C6qrHfHhg& z1qwrlT%uFRL_f_%uNCu~8SKW2{{m7v7+}WJkf_HyA6ERgaR&z8LHvc=3lB~ zZFvuGLqS1`2MNvu=hsoBAS}82>Cu32l>8C?FVf*DY$O8-NE{~G2EkuGx|nG4(+SbI zt)h5|{q-ZHB>W2`P`p26htCE1K+4VCmAEt3Etj^r?T;v=N4@}Q-67b=KPwa+jz^y3 zSDM-$A(fi95|`kW2|D#4JwOqS><@m|ZGI@$pHf0=;~L?8WLfp53ESZC&LN|(&<{HO2T=XtbM;=dYHh1X4UNjN zBzi?7Y8nXJ(V;O!$!gn`$-X zE4*#~vtp3Exu6ej7A`3q5KWUcJxn{w+H<88GBBc;$pA__N+q;u{kd8`YXV4r?v|v^ z?OPAsfpA~zdM?d+1DRFQ1$S|fUc8Xclv2?~hl~%WAT?_Zi>;Ux&XwPtbtXc=a*)e) zx;>Q+Ub$&>6rK0Fzyil_&G$@iX(vqASp{n0M0moF3bReYYSEUfpHs3M}xuPk?xB!YSP5NMIeT)xrGz&E)Ek1$v`R(a@V(O|LEra z47o#5Dtc<-HRm=NnLNSM^WOw9kVv@PBsil>g&`a~TjeuLYGmhz9nqf%@-Ecg1kiK# z!(~exL)WbjkAmS1k`WF8f#&~a*2Uumpl{;j6H2rL+%ebJ*Aa^a*JMYg^{B|XCDm)R z7&|^+HOlt>m4)O*C{RRXaMs;KJ%7B(-%b6!9ugv&>$|MM&gf;s+kfn;y;5b4UJM3_ zK~bT8vz!Kj?_Bq|$~rhi7#D5sd^&?rnhqb21=E~y9`1lDEBiXQpnkB|2Ut?&ka0o@ zNkBS=q}OC(N#vA{fdMDlj?Q`yU~po%riABnTU7d6Etcfc`O*N@{9MCpvupJn>MmE*8== z=Wy(M?r`A_YI;?iY~+95&8BYWx>1bWNH|%@Y8fcrLa`chd-RmDM}i{Q+!&pOy%lB3 zffX)bQ%^Zw-d!La--wu+pe#mW!a*phFL+xc&XXx8V!YA#XJTa5frJUi+ohH9K2ji% zW$UUXijc=U&4o!+KpDr&R7ULm6DYs~nto#AuDHxOIU>8iF=)zf zEenH^4JsCdrVj^|w=WU;H473+6>(o_wJ;U9-e}Yv59#?DL>5i$x+RQCau;Vf8EM%7VZw!TVmk zI_C;jzGk+Q;{WO1Z{vTE1Sh!>4F;nQ#PL1`j^pN+!epRPC`4GYY;*CeZ36s0o<3gC zEDw^X@@nVRul$-aV1=^z+hxE73-sssgwm~uR38ybk68lW_-$;sih2a}cHwRe!}NCPa&p`aKOB!;1a z;7WBGpGbivZPmzUgZuMp8S3@ENq{f(_ld@-bP5iuy+@Z9|4nUWXgSXXL>0Qq2~TyB zQSJb*9;zyk&$Wi9Xo_*#E5yazY1z)E^}PTRPCGjwO23&Ik2HI~Gn$?it`EY7BwH#q z?J?LDiQr|B8(sJhL0k@Oc)m9&uQ;fVEmuR70b&C|^5qB$KzPXv2B8dX3-4`1$(h-z ze`K$|o_3_$cfeUL_)$Qx8R9Q>|9;3&+-tDyt-{?tbM2eS4l_c} zx-0{##6FqjC8xSlS^U`4;pY1XE4zVv5Rh$wp-BA!iz;e*GSrlIO4s;m9Qn?) z9dv&r=O(iHRF+RtGK$iCzV;Q<@3$bvCP!79X)Ruo{1dnR{5&{*AF!SNt3Vx!n|&$A zC#9GE#XsJoH0s~CN_;9@Ui}s;nad0HLiH6#K)38p%FNRK;&`#qlplz@-8s%HdpdZM zhF3Qg;9>ncVc|Ydp8LM_r}pP6w9B1NyQ`(NQ>G-~bMhvk(o4Xtl<8QKEiB{M;6sy$ zD6h!)nw(NHD((nGw9}VThCt|>nv(y^WksPl=_NKzGd$6S=!+4G=^H_n85f|N_FfzK zmv8Q`b@9&^MzElH`Pu?E%+V6PI3JIJzP?>pG^N>zc~HOgj8@uKnE0xXt()t)+3s3l zr5G7YB0!-i_>`u7VrK^$zojFQAfPg>mAPEDjZrrSHD`iaBwaWN^So#sAMFD%nbKmb z+ENAn3@X;1CvF!##WMJ6ql+Z2QGdM*BhaA6nKFbyOdnlAO_PfSBlF^(nsvWYX{c<{ zP=&0g1cr{)S$nQbuJOz%AW-Y7eCBWI!d%|yK=HgQp)an$vPpvVKEpsL@<>xt{z&T9 z4PsaphkHV6M~5^H_YF>$3+aMwmh6ng|uG*nj8G} zW{2Q0o#Z}R^YeNG>zM}tvijE!n}#BBXSn806{7)qfZU@5g_~YTa!H_oxrmq|>sdb~ zVP=onmgA$LnL5og0lr6F^(nV7!Ybo{FPX1j`jxnJ(u*emhzaEdB6j-`w_7CLT8N@MV3`lhX0X)xNg zu)Kf_W$dVX6J(#Q;W9HdHkFvV{jRN>MZ9B3qZO~<3|SP>!okcezgn0lQ>hhJ5G6Nj z&gqoH3`s?d4ApwsYhKhbGUl)!kBV+e0uB9o)}?-h$m%SHfVytPd!YpW3Thq6;AvkRR3SM3VD>P>q}v@0*}b&W#q3Qk@YMtZw0BQmdoR+E1&p}|c| zF!-cr;2NZ37EL`@P*C7%TUFC{Z4W56&?U0Rw2(1iE-aarnwM{vZD-teOW^6 z*^IvcDB~8Gmoq-1YopEh*jy7XS?dfn8QD<=7Iq9Zr|!QYDCGG$dN?k4?)5fBLoX z1#Buo4b54=SjAn+3`eRLur4#eV-N)BhW=^Zy3yI&+j-RWoIUt`L=%RKMXH~&zeuA- z|G$W|!^<+MMZOo3VTkdep~C=uw&@$C73}Br)m7+3IUO(MZ@^4mD~YrG`6VVO2Pyt! z@xT(ZCYj}CezZ}>8K_o%2IY7T5G9YAYMiHHd3<@>E3|G}8eKsW=M_&@r{xceYgCUG z@Eq3fPd=~4BUcg!9c@8ANDr-mpp04QBP1fFbQ7)WAvNjvZE99lvDoCC7b1O_AphbA z!c1Z`6!cqIVnc2~`Ks#Ov^E-qKFa0?~tsLu| z>YZvWPEi>s`N9UEuF#BuO49}*q;;~KvTQ#6>Uw<>PkA@6L|S{FNLg1`$6>4gSh{-k z;aWpspm{YEvPrfRLn4Im7{QjTrtR_f&w8_big&kME)P;T+x0|<+xX;U5@=o^oxyE= za7#D!Z>j(Hw4qbL<&Yjw()I_vx3vmn2ns+ewVy#L%<%bm#nozk zQOV;+f~Tdl%OAJ58y@k%vOv5 zfPRjra0lv!ovu!eseCi?{?F}f^s`&%GEgaqZxz+;GF1DGQW3CoTGE(FZrBMX13#Wu zmBHqIB7h51;$xq*oKeV(A*c%Jy;kJoRuHkAi%g_2%Zfo8yw3Q3-VcLN<(;Cu(f#l5 z_?3E)k!!vjvf^B#Kt^5;QNYli_ZRn)d<{j8?0rHH)QLmPJ^GQbi%au3`*=9!&%0Sl zRFiCzUn|&-xhE%_Akuh=m?L8zav-AuKRN1j4GzE)bkwzAP}{ZnozIj`3sq2fBPAkJ z8MgAJ_a!+DXUTH4&235!;mbi^mL!+QIs53}jSV8fv?ttes`h>xbta)6r64&8RVWH^ zLcvH3{auJXyN%&?gke;G!Zd6KpJ~}o9Qm0cxpV@vs z0;%yV@mEN;I+BvG92b{3h(Tz+~*9 zh{uMvxUTzd4yCCaQv^P0upNPOHB_G)45@!FC=)BRir%Ax7`ZB8lsKaeqXO6BSQvm3 zI^9%MVZ;|mKpDoTYi|kv);aWz!Esgpy41yRJmSs*)`^))oG<1PSjFx8!`J((RXIDC@*VwsVQb*nHb5wlSIrWL3DdQ1N+^<4Tg^WS)E^^=i-P5Ns~Ibr+D?M;BqsxCL4^Kt$Myb_f1 zN%q#?7+NSV^E?msFCvCD#)Jij#&TF&IanqC~)t4Md2#v$)t&5DYQ8~a}@M&YUdb9lMT(lZ~WY)B)^Zv%CXW+%{HqtA{>zKu@!^MR*Hakmq4~k9m#z9 zC9#Ktwh+A>*6T0)<_j{R6+4VMMoTIPr)_r$eF)lj08=nTObqo2x@Jrf@PnSt9g3iKCd>TMtGl4xqRrZ{M!aM0W1L{HaPwSu~E*Ud)W)KcUv0kGmd&!X12(ncQC! zDL>op4xy4o91g-XK{u43lpmW5u}-H2`v>sei9p0hunXq)JPe(3l(~a&Dn}&eXgXcC z>GvXqr26VxxO-}v?C;Gr=SJ^$m$Dw0tThNYcD9H4pq!l>D;W^?fUMe6c;gH2MJBCP zMZe8KLcQNTuHP_7*i1~VTs^O(R%Wfmmo%APFQnb&oMCyPN{5HvZU-!x?x&a!=Z#vW z8@r_}6aNv?jcy&HZcev%Z5oOE{z!BxS_cy*3D#=4w6CG*p*SHy($Qp=Y$~f>areiY za+z|G#n2sgqsQX!a=nV?QF|&ddRA7}vyHX}O;PI36xWZV_vYuBu2uyXdU))LGMH%L zFS-wtZED)bGzM@r2uTWXKlv7$jl$##o&?aQ{8gxsio~Q3R`l^~DgS8dFW!c!>00Bd zDaj=(kgb_JMW$i#s~l=h4PtVF-E57&zR|u=={vIF7DaQj`usY^%daCj2dByJd9@0a zDov{OfRYy3pU zjqXGOZksg09r*ilKOP^a%Qumma(4i@zbKoMeSyO-nRo%gKNyfTWIsG^FZi;Ae8DAg zVs{n~Ag;4?RSWIN>s`T~>z{<}79K#8oPGD`;yG&BL4jci5%&mN=${I$z{BZem1fKj zG4DQ$<>U%qM2#la@k5XbU{lv$8p}TvQ?Ov~$~#{IZ+^Npy^6i*@A~)&rE(?yCuH1f zizNsuk%V7uC*SjjL1LjoBNk+mroD0?(e^2Xdokv=+KTGDJ5Jr&$p3}-Hzu6BV{fta zXW)|UY*5Wp_qn{U-is_#;0k}Z-aX!|7@YjuLE@dVa7Typ#R@v(5}EhVZ12^ds%~ou z7CWu?tM_XQkm%`P|D1A3vQM;6wOLLJ!QYd_6{@+pe}{@JC8Oe8hY~SRp`c0k2Skcd zZuytH_Zx`q1NCjK{#T^mcck1bAxHIbBxHDOMw;x*I^%&I!j@l;XIx@7(^SXqLPABC zUYk9W3t+a_i9C?5ldMC<^|7QvFqYbSYi*9S)+@E5esngB%g5=<_Xg>l(@+%?PdJJwPy?@{4lI!wSb({6;e6s_Z#8NvSb`uX>vK* zi`uI2R4o2{$47OvSy z+4u}brxRD|$*Rw8k1Wa947vwC1dEaOg?|6%HuiD>1bVI|9v6W z%p1@75NENxpZ*`(j_ZxKAM<9D7~Z~jiUnmNZ-%I62c8)zQEL7E4{hGucJULiJX{Ju!}@@{8~jy2B)wC-Kj1@`?QXXet%Wv5zeySM z{6OYP>5GI^%{|8-F$DC63D5_Lh;U_?0MhDI@XGK+nuy2v(2~#_K5C{waby7jz6l$c z?iZdw;|N_uEV^6)iPe$iR5p7&{SJow1q+`yIkR~5b# zLy6k(8^(@3CT9A4$@E;r_L4C)3tP4`rjE7g%$1A*wvcKHe z;nfJ~$#@|IzY5At9UZ>H3Gos*V8Kd7OfZcY;L@y)g+7e<_Y6o+{JmN|J_)M7-*SBC zdUOH9tI4HpY=BZxnNOtr11xK$o&qWd8R&m2CVe7!c~gdrRtSYi2`<$qV^4FEG$0zx zK?LmeyzxZ7BlRcT7N5?^gwhb9^_x=x6Xb(*BLD%;=lEk~xy`}D&43&_<=QQuu4nT# zJWyc56I2-I&jrJBe(SzTcuGn1dSXr{&2%2oQjhcCc)zC3pghtk+A%asI$?dxxS7f| z^N8pyE_M%{NJ)M^pYrwQq3C(cy)DW*x0g8N=eIESJbqaBR{)* zuAhPw1n2_S;Gg(Efaj}>>yzEMY2P;I6R}ZK2 zjizH5b!$eS1*9H8GIcq*g{eS@A7vF9E!6dDCVfz<%*)NG3mD0f(gb`&3x0r85FY@qWp+@m z`fyZdS7CNLnZPOwV_dTmmqsXde6%{uxYm4k*ghZ$0=nK&W=nFGa*e5FX!M)fkf;6% zkw&7$8>fG>zT+JSZ{b(y?yf1@&fPsYK343R)&d*P2wr)YjJd@mJH0Yg{_VG%PpNuv=8QH^x+?T-Lnk32xAFCwA>aZ=wL9C?(8D_piigI+vkecE znosAH$Y3*ip)D!cb8h<5HzM&N^Bm;(+RQPd>48dijI}zIh`;@_@b~z)Z3f;SYDDae zPZ|~K@-J~K5>ZvLD_HJ*K}7L5s^$ zJ2y>`f?0mO*&0)r7So0<;84X zpdDA;I=QPC`4kEvlaIGu~y!9uPPWSv7lKsp#u+UN zTM5C4xb=#gj$Z9|B_Q$qHiVaPQ7!jd6Xv-)`~v{-4u>HSOx0lrNG+Ye)foOQU3M6b-h%1=)fmHup^~`^u+gc_O})ds zfHnK(W#{|$w(c_PyIb%20mEfGE@|;4q}9jx`=T^2U>K+>NUx#eKU%qXw*cGvOnO z@_T^iwYc;!Jiq9hpq9qQ+)J?qOvS+_&h$IXficJ)2eCXy3&DG;s5qX&D0^b+bg{x- zuF;d-+VJ>U*Af@VDK!K(R%u}V^GGhe6r_@C1o;xz>fI5oKfN2!Y;ncEwSZm+gl|LI-8#sJ;X-sFhQFKiUXUXV#Gk;-^tP29KH{gzxf+MZ}_@(IJ_Z|2-5Y>|Bg-q0P08uOvEJG#VkYEA@P-iX@Cum zy1cPSk#PZ3XaOKVs^n+OO5c>pv0$4S@K5jWfF!o5ntdDV7U{yo0=QVC~9YLY#uCEdt_pu zoriQkI6~uQ)*e!emo^2nqb0rmu#H0Gq9LH}2Y3z83AS?z{L`PeFcxo+kzYat56B9w zw?T--ADL2_d(KvDB+Fz2YXZ3;*#~DQPb$MPr@`5qJ_<+Nf*wfC-YPvNpUEkkGU)_- zVdo2;`K9z-8oIO7;`vJN?tUjv++n^#wM@)_+gfH)b4E})vz3VE?JvJ`L|h0WU%`^< zst6g_XD*8JRT%mJHEUv|z|OAPbk;Zf{6CC6uRs;Bkfd!OfTIS>k?Pj34-o4h$K7bK z5!2@A_d-EU4XtkH1LHPWxW0j3b+fy$A4+l%=E5M&m-EH>yl@RyRiS&oPpcT#$4On+ zVKfkeyz5GUQG+Cr&BXf2W)Q9nn>vwGW284sN=^UB(3AL;GZWR}ItJ2!mi;$LVDSHz z0!D-Uxr4gWZo)%hLo!GOfdk_)fUW40hSi`JX?8HY;p-8JX1P(X$|!8m?PVHT>WpsG zXA5pwrXH>x$Kd}g(@+{|E8<6v#tuZjDuj42fttBH^ zZ%K};A-sexL*}u8_nYZE&t=FIaMPM_goF>PAX4s`# zZ8vjeiIFjpk{W0?c|d-E-9PBRMnkcCblLmh zt{1?<;)iFx#aQ}!dJVrex-bT|N;{o34x5Y<-~nQYR{N@uSj-v^&zjD|b1ViuqcNSt zj!##s8thPp{%T7@p&X&gNYCX&PhDIOwA6MEW+Y6Ve{06%-Tz zm$paTllI@4Pe09eLvO+}QW4q1;KTO8Cb8>34kfNy7s_PBf%u@V)%=h=B25FeY z<4YWT`u8_T4)JWiS_(`0K3W168r1$*9mjcK^fIg!-KSby_5Z2|^qaIMyma-mOa;OM z!)jY6P5e!R{4je^kNO@rsGxum{#$Gku^p0A62E47ka#gXIY-Y0%TiIN<8f7#M-n~h zOEpO~59YVDY#k=l?z>bV(BpqDI6h#2(Wwt2dij2~U1z zQ+$N3mz;~geW?1r3*qLCkdgBhW!x|OUS5xtYAm~0>)S-CRt-DAMaNCaw&| z(7Q*y^b{5GZPYV=-!}I9F8?JDk;~Ntd(1W9H8qPWMfu#(x@8<@!iOm z3s@QQ1xJ?lA|7&|3XvHRJT&hh%u|5T(dvze5MbbwMH{K>c+85vkNR+vXR$Il+S5SoHy8j>bfXAJdh zoFm(PO%ty3RaiSn)!;bD?Ls*Z8=o)<^e44*aLBjW?D+Z5Sc3CG=C!#-uSL>?3k{Q8 z-LR_XYl$wo840^kyY0WCpo|sVQP$(_guH6~1(r!;=1hIGl_DGOw!|ju@4{XN>li{J z@??l|5Avxdh2nx7mPVFSCC^xS?$jp9_FuV5HXbxU5jnX^r+6Ih z#twmsR<{0aCW@nA zlhkB}SU;uneO}F(wrE;%B~jqP?Gnp@PB&ba&^b=5K)ipjBen$PjJ( z9rycwKbISj4YFqyjhf~4%Q;S;SW}$u?=!j1Og@&=K2iGWifl(TNtl@LRL)2=6C2IQ zU+r_8;r(j;&9@eel~#L7S35~rm|IvJCHb3fGn|VzumXo0-ZIoBLy?|F4Ea$)#9T9a z3w1Am$N-KSe#&o3wq<|uAE)DsR<Pu;ZYN?Hy4h`d87ie4l$zBU`3^4JXi1pZ_; zj*R^F4^o{R+cs3!>_wb(sWaww<%c{|zjW@5{qLrUZ7my?=9q3NqU>rw4IGmNGXbGh z2(DB=b(Cs5x}csZr(*7qa(<;;q4MgmCXx;l=udT$%(O4);v#009xXms+jkpB#~!HZ z@P89z0Ke?cb9BaOthInMCT5Yxut?_4l90m+n1hSU+y%EoZ#b)1v6Z0Zd`2t%awho~ z`Ejq#@z}<{aHfl_J^6C3#EF*e19o&HtUd4W$xAMOwomI0EvVg@>z}iijt6n13wTO@ zC@ZPw8|$$5@9@GcY%4FrEf9nCF8VMtj?5E2DN% z@aAJ{)I3^kN9a5B7q5C{$5W@)st%t+ZfZj!pyG@J`i3~9It;jO zbgN3s7k`71nd2c+&~Nz?_qou0kIMfy%PkmE6QsIFX4Yy?AQABqQ}NA~@b+-UMJ(DB zcqR*5X1UcL&sYw;;NVLn1p$X4ARx*-Yd*hW8>+@+@|_&i?SFGz(gn|4SugR~vr&0|*L``>r>qd!?bxy?(H&y|6^s1qEJHi zR_1G!7BSL7A@eAcs6v+Vb$Oqf7f^6)=cl4)Tmkk8YFTDxVO?`~wt^@u#FthD<7pN8 zxcVmPE_Q`}`c3^I9^-aJNASFoPhsI3qi8^6q5)$ezq5j4;*hJWw+wBcY-D-T)k1oy zx_b&<^`&Wz+HoC36lq_pLFf{$PtiU5RQ{%2@yo2WvpAPPU zg4Pp}j|Uevwb=)_1T!Y2b1_}mwK2u!_9!Y9io~p%Q@rP^jbROT>z2?LYZ@u$h${F- z=38Zy&}nrHScA*h{85Ff-bGkFV2KiRrMr9N99M-&w2z_75FLZq8Dphfj}P}oiQrxi zXvbf`5wA|sGZt_<3FG3&13+yI`3ge8q_lovWi{($ixyb|E9=#ivRUQ}w+F%e!c$w{ z_u3W(&%5vbtQ}0t)@hqmYx=3iP+P_Scs9C2y1(}}--|s!M5BA?lh;JXF4Rmyci6`W zeiw$JGgW8?^RL|4D9WiVM|Z#+(HEk^l+`@IqEp0?Yw^Ex-xT2J%@MoO@4u$gG{zp% z1V1M}CNlkP{R91klpQ_q#P#XG)1jg|2TD(bI#*?d)0S^$xBzebwg4`Q%SB@1=g!bR zFDuezwKVq?^z3zmaa1dvdjZ6DF6vf5kp?(EtTBa&{Ut3u!yxIB67{TxV}6eDg})dv zeD8R*68@ctFPKRL^Kga?MTOhlL@#MQUav(WnSuwTK1}l|WHrCK6}U6jvSyw4`%@d) z7Y^7N?cTE|tXw8 z>mL{jO=V0rf|U~V6xJ@BtEe~?1n?wbRp;eh!R%OXx_*F6?^9-gxf)rrTQxhMojLQC z8In!zPs10zYI9Tx-x~rb`>2BzUkSbUNh~A;h}~R0-=OK2!DSYB`ko`oHW!q-Oc6Yc zEa~0(Y}VQ%TKhQ*cA#>EHbh5Pftg&mfF|O~^-T>$isuVrp2)VH>Vw&tU!d+5d?-`E zoJ7dyPF3=~wAA8kyGI1H%;L~5Ie?RzD)?Uw|G&9bLIRkgs+;ql{sa6p!NFn3Ox{wl z-F|3G!|iO0U1aC8Ocg!Tz>IIDlQDXW{63; zi0wjk%)x?hu*WwIp~+f5%o%u%Sea@mPKIk?ufO8;_9<&xo&^dN(2)7-801d~*U zock{=hWZy1$@@|*(-4DmbQKHC3n&%OIn(W|u{Zvc@Z)Sig33xWF9_3Mp@3D4Xqxh` z__%o^*e+U-x}zc+C(U2j*@9$e@5RD|S81@8!`}JL!>3;&fFr6tsS5Ud^rLoq zT%tODlZ_<0=pwp(e%`v_pRlGh_(d0Il~8h;D@1Ps>L$@Vk#nxk10>1BT_cHvmdN{G zpn`Qt$@=k68nE%t<(NHRY(LFpQ=&P9VYbgPJX1XR*EH?AKdbdW!f3h?!HbJ;A+$I! zw&^2RFcxblvNitF43oJl4CM@B%$HwmHIVj|LmbrlurveyayUa&iQ4raDkN)mg>3IJz;0p8<+zL!!>y9Gf z!&8^Um{~;9!g*#@{)#58Qd@e&>pb zM#ff(s+vZ?xd|v*)U2E3cm2$76e0q85-4%AOXJN5??YwXkb%H+u{N9Ch|>3g7}7>Y z@ajTyJ0xs#?#I)_?ybD_8K02ZFpJXh8}OiD!l6diCJO$WF#F>xJ&%_ia;J|k#%$y(J7WlLx583ms4%N9+0tfoYNY56UGC8d2D}ISIB+8HKX?Nk3(#*Bulg% zc;pA_Cz`y%9H<^5-U)TaK-gv%T^Kx(A2Z0)AACCBWzQ#)FcCpnRZ%;AEyrWsz0e$5 z3d9gaXwYs`5<+8nI(iXm9n*iWL8&VKhj>eq_AkqI;MR%Soqm1GKi$vsd$qOX}ezrq!+2x&gP<2q-d^zJdG%EAj>fmizDj~CNvuOQPwzlqr z?oavrQfSwGs55}nM%1cO*+xB)u=J(}BKa@uyx7D9fGg$@gex46=adKR5`^er0eT#= z+osP&aHZ?-?$ATnGyI;y3~a{4!MU+QAKo;te&+P9%kd9}3aA_{6Jq*->QXtrwO-#^ zOa4CqEJ4%0+ER(R=gFyJ6MDISB?VnO32Umt0EU9esX{|~g+3ql6gmtBl;GRvfrLc^ z-1>yx03^Z>wB;D(=`fM3vgM-C$G5N#q1)Z_Q{i!2>GtIBU?G*4Ji7i2>#tahM`Lg_ zhP(!^BuiLVJz71U9&MOHc5Kna31u_z?1}tV*>YnH((E>fZ&=3m9X3zL>D2nW??i_% zh_-zsjQ}7rL4W>|oXZA)W0|lUCg;55=3#(n+qSLR?3h0(V2^$Q(EV4fUKzJ17C3-D zaE9aGw*D5M*5v#0If9RcQ`W3bWNn9t?a^$7ge$he0J%M8)e&FJHVO zb6C)3ch7}=$cysgC7j!TK!57hJ&>M0e@^Ujmx*0}qe5xz+BMp&I0xrhAWGxTojWz< zaI}D^FgaePTp3!weg(aNRWSog+1;{{g$)9cMTgO-(ZlHJ?2{(y-yf z{&SJ63=Ql*5TMf?k)cvxhYlU6Y11!cqQ;=W_;KT5V(6zFmj65`xk8beH*cOGz&x=# z1JlAWV=zI-gjz{9Ajh3Ca|XHR;MK;|Ph93VEm}yyCQ*U-kCuGEN?qzpFyl(}0WdjY z#0aWYs}{9w2VMz5{4=gSYR#$y{)+_IvWF)}`ib91)v8ve&K|5yr#0PQ!pf-`0HMFdLc+CPdz1xbkju^CMFBpCDD>V9smc`Y zH;>m%(t9joQFmU--mI4vbOPU~Ll(->qQ3w*tiW1=Z^or|OIR-1Ql@fM$)!e1da-v2 z+7bm07(}?qS%@;1uMhCbl3W{iqAZo0k||vOeD-I~^pLLT0M^+sutt0OEEDC&5EJG8)wO}P$gIxYOYW$mD*1tr)mwQZ-qQ$ zOGW5C=(m3w;$K#?;7Vd+vr0E=I6QNg;yykQ01grnd|N|;}>S9>g+EUhfbBTsJa?@;ak zMB1L94#}tm$y~F!XwKtrfL4-lPjX;^{zFPe3Obokctkjb!d#VSL%hn$ZVYLe7;rgp z;)GPetJ^D9te{REJL;;8uXgBm#~a%d=1JJ%q>l5%kW*5}-*-$-)_x5gG87hKx2XA7 z&FPa*KA~_}h;8{}3;puTFBBXcOs#eLB zboT67s!^i`)&J}>%I4w{udnE3Prprcuz*WP>Dl)Ax)oNXa&|4r4r>A5(_6_DyeN4( zjf4BiM)Enjo(c?GhY8?2hEkM!cX}6!1~&t*IBF8yXD|V^^C}0WtsPcjVcVYuDJsa1 z9xNWFG5gon&EtqUTx=YQR3Ml7ty5iLe%G<-xR6d9}upUgzY%Cy47N~@IPT^RWad@tZ*^1pPD{K28ZnOFgI zEM5avHky3wTIV(JH&{PlMHR^$k+&>)j6?U23CB2qWP-frcA4P{6D9<~%<;t0wIo3? zwBYukzKB1*sP^mT>J689;94 zkP&OF(cp&Sb}^B&T|V$z;Fuw#C~y-k-FO)MVwMOl5+IX>&)Nz6}_GKS6o|Dda!ad zz1+PFJWj93sYZ*qcQF)EJ6Juv%OXkF?EqTEz^yIc*Y8r(Bx&Mzpz*G*CH#2LdN+7p1MgzH1 zo;!O^%szR0@1DJc(2-){!>{e-%U6&KkV+?@sTIlmw<)u};L~#L$wr$%+ zb?epD0Y%oBXjiX}7b;IMk%|>7MrY5Rr57Mj%S!mW0Z4#>TYl#E@83^*_UsYMr|;39GTQQqC$6Cnu8C`nnWdfX zUc~@(ih(&UuX^%qm3su6=ZD~cc<7@Wm~=*x9mq{N#X|0Z|C~ldt)rp;8LSA2{ z%%y9~wdo)E5Vym^LWL;2Q^z(KKkGpI!8Gh60GyP2$&Zc+o+(4)hhYl>;cp4od${o~ zv&rctP4~aBpB%xt!YlvbFCU^`M6h-SVqWwU^l{(AaGmKmN_abiZeP}1F3Plq;u;I3 z*tvEqxW=*71jvj3xj^Up@eU zqXHa zp>%T``U*(MovM8$V3#A_ciEeR#|6WG_^THbaC!%R3lRnX~esi=G2C4u-O`nz%((lNmGc|1KdEi$#0|7kgv z@{4Zo-o4}lvcC2m+S7^SC+Hto`CPqvmCBSUBlYk7bFWwpu_9f&c5U&Q|DneZ)USU( zYVi5zG;_vG+O=~RRj*kcfKV3NxPBwu^S%d5p|NuQzySlL%uhf4l%76)N+X7kAO@D| z0<__D`t)gf`RXM?Zac~LlP6E;*V(_y>iU5G1B6ehTJ>sl3Bb~!gNJD1q={6h5KM~o z5(8EYes%5IRd27xjIb!k&kpQA03X(ul*c2F9Op?1Pfj?od@o$MKmq;%0zUEY8#iuH zrOK6bfRmE1dGqE}zkYoUu^R78<-{$TH(%@G2S&&+_`&w<)dPwiuj#1C*d)LJ6hE71 z&YYoY)vD3w4H}S3)~p#eKVoGyXUpMGC~L-B8Ds_4DqBu5wP(dHVPdO;;5&Z{$ioq? z>=7l(RL^~oBhTa?xBylXnll3~o}s(5dm_a8ec8eL!=F4txb?rp9Ns#c2RW3|5Pm}U zM7}2!gjH5Hy=PY)`=X!7#F%@h2`m}{ubmU~e;YnltbDu)tQA~$@(-Sm87iv6C+Ox) z5COL%|9{RvA?+wiZiLS(ln)RLXvb&yNg)5nPHb3rUQ>tRps5=Y@-FwXz{ zUeuWjQFcmeuS+SxF#lshCg3Ssb7sQz)U91Z12`FGbJL_%P+Jil2KPPEk79$LP~rT! zb#CuzQekon#d|CC;dMOYJ@E`{A7Y$q4oidF9VUh(0scH#IE0+5H3R?4ZCGTiCpVPo4C{vHe=e19@y@WMh=%(OlbL6MD_txs zte)v(}^v^j4Sc%Gk#)~*}2A7!ew;t*P#H8 zi;y4QC(M&p7=-$q*qWH%Z{Bl<;{5`P8jybTaqiREoAtqXaSiWQ^yNbvuzdsWwg=Gn z;f9I`m!aTTdwpg*`JCKLuFpCNU>6naM@-mno!t#}x1eWR5h;_2gTdqW`p5(DxJq5WqE7AumtP#D@bHggm@S&;M9T*&2b+ zzf>)Hd2ls7TslE4IDL+8pa|b*l(|Zi_<}OTUjP?dHLnfC7{M0oyrhL}L93>;mq5{? zMPt3ay$7NuKXCHC*u8r2Avu_l;M zvPPE1Y5B6{VnvicUp~B~VnO`1UMzXaYC$JfoL@pA`|Y>i$lX1Mxc)Kdv~KM>0buUm zzfaAYH#0ravn%jKehJN4lI}IN(T+UU#nCzQFce8J6!XZ5e_?H+k zV;(0D{Be5u@+InTDBGGON4=2@CKP&r8wJru)jBPDZ=5Af|GL@}K(;6A~Xda6kawI(6z06G~>3 zGCb!^v!=%;z^y!{V(|J+Wlmv0d(>iGt&AP29aGSuE2+Z;SLkI*h$8?J-vDKg~{6kkhvzG(p> z>dca|n0(b@!*pFc8E|@Y`Uu^d*9R6ImU1pnuGuBg+TDX*{kfdpTsR`<9Cwx^!8AEXY;Az3Y@*wk77}g@5hC32O3Gw{+J~VaIVypa>BBS zr%j#+KmTOo&p7W_Jh!prQnfii=nhh5fuU>3`xlU@0&L>?Y~Ze#zyETy17V~wK7tt) z))PRS4J5IZ)6XN?N%T4(0T3$$p{BPaz;Y=73w)Chynh1u8N`ENKuP+K9!F@xrZM26 zd57YyEbmIZPw~*Z)NP5r9R{-dd2pdU1eZ7mDvUnGyloNwL3sZl>^ZCjBhk+}nV~;9 z7O6yTjeEhGumCv}Ef0&uv%>Ah{7_lS)FZ2^U%_p4GlhWTDc_It09f^*7dscq`D{7t z*=M0F?&NMa7SSN1LFm5}QaRT>@W$pxm`d2g=!I2##CPt0U{AuUcfv zDv|Z9vSINK^9`00TXykqV~`2J6PZM5d#u`T)9W6M88e1gWZ0@H(S+ls&`nK1A5aqS zfNuDFkB>Fai%k&m)sTYKCVBztPJ@$x@q$hmV0mT)TO6HG(`u+0MKVD6&T2*1c- zju}`vc<>i5?Wt|)@$ymR`Qub+9*11N zHLj(U!R~J1FCLJUs|RJP*G7)BD+_bH_Q4{fyteL_Xy0_HI~p#6 z!8gvpoZU*SA^370LfN%(FF+pMXJGPcN)MI{r@K?Xr{c5EQXnF4g@LOg=XayAO4}IL z9na|6pjvRf*@iIbmFU@yxtQ2P>4pUflOW%pKY+r0A4|OvFJ9BVIlU-Lr7tLFivb{M z4Fo{e78V=Bsn9q8caSIZcbGZ5Q@-A#5G~77ETH6M1OMXtt|T5K7cW~y1-$Z;TMk!I z;FV(^`hV`v^1*|o8C5g(in$HtR>MOekqH61vVb^ztiXuH0xa`=%GG`t_-MeR z7KW@ioG>x}Q=xHdWVZmp*aD7A_63SjiCG8X0vC$%Y-E_>GC8p&hf}3`=zsOVsT2&0 zLV(36Tbv^B-zr;nDmrrytOmnHxi-P|DCcIWP>1*v6%-81OB)cEGoX#*sMEPdQ*x@_ z6p{3TgwUMjz{fb5S^yj#z7%|L0N~P$-p)0V;8`(D=vt|2D=X#Ok%DDeDJNN zcSu0`sU-kI<|2&5gJ2+upS`?&`5lCA1za;>ih-+aiTOuyk2TL}i8%*#+uRpio3sPT zemhw7g@TkD;5YK|ehUYCD!U50wcdjvn|vJ4FZTsb`3KKK9|{wI$IKcb&avOU_b9vMemQ%YkUzj`ck@bl|zZB)z`$(F#kw@DxkHI6)^2@c#p!(4)t!*q9PW zEg3Ro2)S}d!8Az6jvbRpHM_lS-n?0AVB**yOw|5>#ZA*MzL0(P+Es6*2{CwMu`&_? zlU=qxV(TB~aVpuSByHNXNqC_+uZfvV0i;9AZ+!UxsA7UzwoH`3B& za%63el}>*C8Q5jl)_QQ)Z1XJu8)8?0w7pmSPUTg7YbGGY5AI(~N-QQniCq&`9$&$o zh23;49i1rfDl8GuFKzP_hDrVo$`hdholLE4C@UgP@k%ADMX%58hAYfX05Bs!Og<5$ z$N$5m6QPao-K5t{{Co2p@?GP~q(;_G2zbPk0L8pd0RX+SRBk|}DqIEM1$Zhh9TDyeGh9m)+!L5DidRuxYPBFs*Ic3~XK&h@ z{3m=Pbp>2IDpn`fS>3UUd>(nt#cjv;_-0M85FXcXjXA#?iTx$yoHQFSG^MB7cSuOE zfb>d%{9MoYWe!c8FpA7^|38+*?;!q|n?buXkd&Chny_iC{4v1FNl_kon?YC(Q~v7E z8bp2DBqaQ7Sz+s55U!)uG+++K2+jEzi@=ql06bC_14aCKM-s&|!Esh_W1%FPT0>ce zC|Lp3Ps(poTX3Hw1bVnVe6Ds5px++lJTticaMHh4-7)Y)B|N75W*PA(UYk*0a%3!p zrsEe!ljM-uV#TSwx9M2DQB=iCwF?(6BrCH>+(Tdbu4ygIp$tbA(0@MP7AO`e7|his z{cYZ*^b77o%C=-p=JTrQLz+1^gFu|5KjM6z7chur3JX_G3EQdsHs!f@!v2qQ6SkGh z;QoilHC~c^2>>^~7I@L>(p%-@h_a8{tF)a@NO-QU5JTCpwxR(OSCBP8PzE*FlcFm0 z88xMk1jdXRV}AeseS66MTh!PY3rMA8jwlbjrVZ=`qb5}XsUZQwdDEoiYB0}x_~;Sc zzI|8D;tmlGUZ1o`tll!$3%>$4|rxr(OGY#QaX2{<;2-uB-~>E6~2Z`$WP1`m3+VU+W^rq~r@0F3{ym zxWNNMUeCM&MlqmO1Ek*pL4owsxSyy{;X+gse@f!_CG#w8+PFzv@7P_hDy≫nKt| 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

                                          j2=IkPm&a{Wb~$2{BQzg0g! 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 diff --git a/nebula-exchange/doc-2.0/EN/figs/ex-ug-002.png b/nebula-exchange/doc-2.0/EN/figs/ex-ug-002.png deleted file mode 100644 index a4abbef115da17e612b6f6d43ee9728aaa3232d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60193 zcmeFZXIN9~);6jvR6qnmlOio3AVqp_5+HOCk=~>?0U;nr)kO=^l_I@KlisBSlp+Gs zMS74LdMHAGP`(-VUi;m9t-ZhZ{5$8m&if zRYmd9l`Ht*D_8Ki39bX5NRo)>T)D!0MO9J$vCq{_#Eo}sT^TDff_@F&b97tVTS&TD z-lj!r$0tofxz`{BWOihBp$(B@c-P6yRm49(3B^EPlJSer%Lmi5&C3wX%Nx#L`;GV; z|F-RBzsI`G_U%&FVMMb^#5n5oPV6T+Ff=Bl93O@6ds{{}J z`{RH2;lD=k|E4nx3E`idoU|?=+Q$7Zaxk)NL0P`&xkKdKcKS4Ip)(>#!2F?AD&sHY zp!&$$g8mpjnhIeM>A$gBO}3xu%`=i`0RaIP=1;4-&I@6#Lg+Jk5AT7qz^X24tc7M& zwcW#k#u8r5v$L~{B-_d4Uk$6dk>_Qw?QW!B2t1W?_pdR*K>@FrOu&7iGpLqL5_N*W z&@r$GEKtKLyywQp8{WZOU%_0}5SVvukKrn#?>CUxIuJOD((f;!8h+UDB9*JG+ z`HC<0rt}56A_@$x35ADdz@(zsc#lH=dJNf`1mDTPhk`8aer?TnjljXMZ6(yqO(eDv zi7l+=!Dg2C4FI2c_XK2#qgI?>hnACiSA@#VzzOz+EZai{ou}YkZ*3=KZ}PS5SiC?F z#?Ri=6e?zIFCj>2D~CK(~HPSIMeCd@g0@CqVm!0$pN!+AaQR2(I{fkqE1 zYuXsq$ITj~r|N7VY3#b7ijpE75}3{qLW)+0wIQV6g?ZG*W7JFswHsKGI87flGrq-$ zKGQ>DZ)L#RM8!}uN*?>jL6w;kD(|463v&09-tg)?(An#*c}F^lu)ppcGdYbG{A=~o z{`dO2JUN7G#I2=Zmb+ z02a)nzE>N+oxH0F1J=wXhCZ|QfDM>24K~E0ZnA5<+mVP&miafvAOGnYBqR#Lo`FVh zQ1j-jA>_LJE*xq>y9vj|cNM?GDi%~i2{bW7tJlwZo-4>eLS$xq7wDtO=F_pkgrwEM zz~7u&V@ICzp|{T~l1L8!O@dU!>mUT_Jo~DwsF5n{_{LRLzr*MGlP5nb`k=Ir=|MV! zh}W!C;79ZzyJT>Hj~#2fgaIwca(pAgO&Ai=`Hr*Q)Y-i{{I4hVga&Uc1Rg=baef;$ zQ&N?8Mt`$i0;6{48o#EiEhGfCZLt`TTK~|oC3Uld0*J}%-4lo zVazjj_5^Nf$;&+V=hY*70KEDgqZ>S!3x`@H*r*{{-82<_!Udho~oW91K%TJ2( zv#?AKJ|8$6@RJkitLDr9Wb<`c!n+L?03xhnNLNOnA*1?6++(NV+bW1V_)^t zMq|wVrq$fDfyNuTWug9RaLlgg6YY_Y|T>AeqR;;~y6&>)C^m-ZRZxrkrN2VsNlx#$QHq|dN54a_> zJ0o^-1YeQ~JV%SL{3(n(nBcJ!`5#W&zq*CDDF3PV4n%QU|0WypzuxH61gKJr1=8u` z`8h%Xzw{f6V$`gk=GQ;Pi>aiSUPK@;8R3`6mx&S~@cJ@p6`FqyTd%5EpJYHn;JfQ# z6tTE#s{ASlY5(;tM43@00|AHyRI{?`z~{~W(m7fvQ%KKpE;3b^J! zyxNa@itq=_G<I2|0Eeo03yI& zRQg}{$Ezcv8`#6n3B-5^@xNM6whN(QAsGwat0yf4hA9eghiRu*A%Ch$Xr%CPOQxxC z72m~OL(_~&jbr&&&#dLWxwKby2o zjy9MRjYTa)@{#zV5#Hjzh7^=3(KUmzX>+X96^KLQHAJ$xucM)JS>4`_x=iiY-Auo2 zLM*y1=$)Xg+R@Ko(siva;Gawbk{hL!OK;S}oXZ;vezi8ETctKDJ4h_|mU{BX>AhL6ox+Yp%>1RnwRJ%u~BTatgUTM0#(1Zv0=h?Yh0qC6cgC+>eZ`?g6*-G+eS9= zZJq-RKhv?kB61(SNni2wQ3GMUzasFUB*?(Nywz}J(64R4Dw6lGt+zZn-voy<05BOD zZF^^nuHK7C8LXJ@vk+mqQP#j%&(yTn%N<)n=Dy!A7S7;3BcMI19dt74-_}KK5~8au z<2B(qr4#`IQs!R6Tp;!q2)yzwg(5~`<((;UW#t!VIoQfKQ?_?d)Vi(a~FXV{`>tMgdFK)EB$H7*Nyfka6a1n zgXsOuzq`$=dXArnw(ovHdcOt9@${v`%IEy#1|_^ZAUAn`q4tFM`FGlYWZ;WNb2clx z8YMA|KcGw478>D4U~YVf=M(^Yc@JdVnH5u;?TbltMa}RIU)+l1t)I9kWpxQ2(V^Z} znMpk}g_3*oop=qHQD;>A* zbKne7uKKAcFUl+*^PWb(=>S3<>!9hWlDr1h- z&@q+6^^Zn0Ye)(2=yvx3v#gInNC`|c%{f+RaB+Q0 zJEMB{^)?@ApfqTEIAwiGy4KRxc46U^-#s#1KA8Vbd*B8IO$6CI!eZ9%q8M{-jSk3{ z_CpUwEib+KoI@(JkF)@{4K&*0s-MkttWKFA_1Q%^jWJ+$d%IJofZev;H%A}B7DdTf za_zK*LRx|)Gj)Z8>8#!}EC@3l5P;;)cVll5lGNDs_XZDfUezR|MQ?4^43f~hew;7L zExW7eFa?zqSv<$0nJDMvZ!l2)FopHYyVhyp!nUX17UcX74ul5sNunWFBn;Y=>|=Qq z%CgYW+S=;&eIJ!RZM2(62%kN%E3c?PU#M4fZ8Sd2sraTAjtT6k z{w0q3u>$~T+sU>K-y~ZjI{i8j2#L+JZYqg^55@Tc*nW8K=0IbR{sa#3t{|9bwzVxf ztYxRR8{hl;9#2R#)WNo2aRs5j>>Yb1Zjcfa6Q5cvCfiQd4`28hC7rdYzGXj)#ss?Z zNO39T=S4lm@9d1AxKIZNO0OX-4Cglh?|n{;ZCJ6xRy#5wu@;>^_Ii;GKLfLu^XL!b z^_IE4%e0o>YRjf*zZ!yvdp7U1-|T?WyHI|=H%=Mm7O-KmC@Qk}{;d`fcWEWWFyLTp z|EQwv{A4F>?v%Y@ExUH&a6X(VOo2p#ZL?{k`~{hTM%70w(_Tq%SnLS_eSqNfP_4?kFu%3rM+7s1TX%8VA+oN3;b@;JaM0P66f(^ zMmbk}&{(33L??#gmOL|dMTepnn`E=b)P=C^J)g7M1uuFK0PYPYJ%Gb;)RlS!m|TrD z&28$LyK$WT+FcuMkqo`fOWWywqD^vfE4sTz;z+DtZdUk>>(|eFfU0xk?)23adtt1; zOtNtQaM%|ifvm)Mfnp{GXUS;THt9ekwl`B@IH+!4>9*M~H>$9O(K%c#6=y-Hio{}C zFolns8_c~?Gb~8#WF55G2aT!m6s|_2(H6p*Z-HttkvowEHKTeE;<%tsjEY2JX#qDA z=7R8886hkzB~a#7)pW{h8k&pa?iLnvazH)#fx~rwF&%3wkgg@$;2&+H7y^}i59xGi zm`$QD^j}Ui;5r-L%}lL2JDet^1?9weaw$5jhe<9@$)5cht=w+f2-_c!;*;Ye0=c!F zJwI9zYoirDYp)li2Q~d5Vu9@TPT06BD(+66t{b!wm6SI*#S!FbF7(}R-h9KfVW9($ zI}7h1m22@pII!k=urNMtS}T|@%8TKWB=vK}rO&s{BqJn$PoEET35)Vj>3%|@31Ob5 zuj5n5bkGDh_YEk)Ef}dTak=;mxRtcz_zd74r>kzw-(vw^o6n9(0qSN~_3%_@a|CQ# z2sLw~i?0KTg;{-MO`V!YT%_i+_Ej&Z!`hN`G`%Ew%Z!rBYy#+sN`g<3~!=3ey;Xa#H-FujoV^mf{pF)(L{{0ZL zB@0#^8(|n*8V)aNl}o5d{efgOS$CHCf{xpInBR-MX~BfQK*!Q;N7fU9);)WuA!TiX zEa1S|bG9#1rAPCKx%($?FT8m6*%do0`YtvRK|CjZD%`ZVfa8ry535wqo|xXQ2}sw^ zA^EvBJScCh`aqZ6Dt!O-YO9xYkSU68&(*T?47E^s?Ee7{+lF8txmXmIY>i#z2}#VV z#~p%_D-fQYo=Bkz-VYWT``B)~vvr;xnT8R7QhT#eMQitMF|nPRx$%;df?TOH9L;Ri z&6PF_cH!h?&y%wA1(~Nw1{z!Zeb8cwEWNAeointGLtli?CSs01Y=3{D zPD?iS#Ros9Fv;|;itTDp_88qr*=z_w8D~z5YfZoCal&uWNtM?5&76u3MB)0ODh*nc zV9|*u!Ic0+d%VXptaAOnOMc{I_)r41K=m3|uOATSt7EHnztD$=Gx~BWJsz+6%klJs zvn`RMWv?Dj$USnIRHFbV5TMU`?=lptg{xY?A|W9wvwmn82>kr@FRB&~?cE6p@49^6 zlR+2J_mGega;Xo;ae=6r#ev4ig#e7!JN_Kcwa$0pxmCS`J+mu|CHvHanhr%8{c%`; zPm)C=E?z`!+zqHIUsU%(9`#p0eM5QyIY=NnQBP<=sEzqvVJfo5(o}Q#IxN;Ny0fwRXHs(b zs;Jq#A9_yzMQpdP99LjEOip#=$bjx(5fL;eDPepSdMr^vce3!{(=^?Rt`)r&X zYR2ffc9N|Lv@I`_#M-jH18G=baqfJ;4(x!wmiTgl?)BLpu8@${Dej7f8IQhf&nZd?a}d`(B*<+m+)UM!;{Q_Se_t?=CON!CZp!xv z(OTYpN}Q6Kqj$&Z#!+w3adObH6lx~p3rk;hXf@CDaKQ(0ROSwHj^0JOrS$II$UN5; z0B`AZ!r<=!vee#t>{xsF>N&=OB(5D zfhPBs(Ctt-P%?;QrB*%p{QK(*;FxPu;RW`Ofn#21#cucYoj=nRVq4|Z*md%}1O&Ww z1jl~>f+wB$xxBv#$#Q}qU)Z)HH^SVFUk1z@ux>d795ldtLkMokje8Pc0a~ai%pip< z=b3PeEM0$1D_NoC<85^*_h9geuKlCYs|npVUXObs*HPeR!fJ2O zXhAW-LUrXpBrCX<3kZ_zsF}>9+q~+IGi-{T*l!c7W^`uRDEoR+tHxfp*g?zI0{c$v zbwbc^nFewEN0xIzx~BJ-z&W;C-Kw8dpx?jMdE8L~$wZpM;q%kAk-cz&GFKLo;Xnm< z8-?XYlk_R)1oc`5j|Z8JM|>$OPXKq)>*@3Nzp(3k#-`|y8u>Ksw2CK+GbG_lRzX*c z2n4(`?;h=0jm>~<7#}q;j=qg_^k}#XIS5Q^bDf}19wq=?maQH=cRTW8Wm7SlBAXWK zvQA5#J}w6|B?)oa!}P|q?V@S94=KUlX>X@R-f!Z>aLMPU>hwBoQ+FF~Z3yTWgKkCg zwfcO-ZZ~uH@OLD7sD#3`WsliPt9!YQg-IBkr7lkQxl8O?j#tteUk�wMox-jhh9Z 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 diff --git a/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-para-import-command.md b/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-para-import-command.md deleted file mode 100644 index 2356002..0000000 --- a/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-para-import-command.md +++ /dev/null @@ -1,17 +0,0 @@ -# Import command parameters - -When the configuration file is ready, replace `master-node-url` and `exchange-2.x.y.jar` in this command and run it to import the data from the specified source into Nebula Graph. - -```bash -$SPARK_HOME/bin/spark-submit --master "master-node-url" --class com.vesoft.nebula.exchange.Exchange target/exchange-2.x.y.jar -c /path/to/conf/application.conf -``` - -This table lists all the parameters in the preceding command. - -| Parameters | Required? | Default | Description | -| :--- | :--- | :--- | :--- | -| `--master`  | Yes | None | Specifies the URL of the Master node of the specified Spark cluster. For more information, see [master-urls in Spark Documentation](https://spark.apache.org/docs/latest/submitting-applications.html#master-urls "Click to go to Apache Spark Documentation")。 | -| `--class`  | Yes | None | Specifies the entry point of Exchange. | -| `-c`  / `--config`  | Yes | None | Specifies the path of the Exchange configuration file. | -| `-h`  / `--hive`  | No | `false` | If you want to import data from Hive, add this parameter. | -| `-D`  / `--dry`  | No | `false` | Before data import, add this parameter to do a check of the format of the configuration file, but not the configuration of `tags` and `edges`. Do not use this parameter when you import data. | diff --git a/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-nebulagraph.md b/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-nebulagraph.md deleted file mode 100644 index 8958b75..0000000 --- a/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-nebulagraph.md +++ /dev/null @@ -1,16 +0,0 @@ -# Nebula Graph related parameters - -To import data, you must set parameters for Nebula Graph. This table lists all the Nebula Graph related parameters. For more information, see the [examples](../use-exchange/ex-ug-import-steps.md). - -| Parameters | Default | Data Type | Required? | Description | -| :--- | :--- | :--- | :--- | :--- | -| `nebula.address.graph` | None | `list[string]` | Yes | Specifies the addresses and ports used by the Graph Service of Nebula Graph. Multiple addresses must be separated with commas. In the format of `"ip1:port","ip2:port","ip3:port"`. | -| `nebula.address.meta` | None | `list[string]` | Yes | Specifies the addresses and ports used by the Meta Service of Nebula Graph. Multiple addresses must be separated with commas. In the format of `"ip1:port","ip2:port","ip3:port"`. | -| `nebula.user` | `user` | `string` | Yes | Specifies an account of Nebula Graph. The default value is `user`. If authentication is enabled in Nebula Graph:
                                          - If no account is created, use `root`.
                                          - If a specified account is created and given the write permission to a graph space, you can use this account. | -| `nebula.pswd` | `password` | `string` | Yes | Specifies the password of the specified account. The default password for the `user` account is `password`. If authentication is enabled in Nebula Graph:
                                          - For the `root` account, use `nebula`.
                                          - For another account, use the specified password. | -| `nebula.space` | None | `string` | Yes | Specifies the name of the graph space to import data. | -| `nebula.connection.timeout` | 3000 | `int` | No | Specifies the period of timeout for Thrift connection. Unit: ms. | -| `nebula.connection.retry` | 3 | `int` | No | Specifies the number of retries for Thrift connection. | -| `nebula.execution.retry` | 3 | `int` | No | Specifies the number of execution retries of an nGQL statements | -| `nebula.error.max` | 32 | `int` | No | Specifies the maximum number of failures during the import process. When the specified number of failures occur, the submitted Spark job stops automatically. | -| `nebula.error.output` | None | `string` | Yes | Specifies a logging directory on the Nebula Graph cluster for the error message. | diff --git a/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-spark.md b/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-spark.md deleted file mode 100644 index 6bce5c1..0000000 --- a/nebula-exchange/doc-2.0/EN/parameter-reference/ex-ug-paras-spark.md +++ /dev/null @@ -1,10 +0,0 @@ -# Spark related parameters - -To import data, you must set parameters for Spark. This table lists some generally-used parameters. For more Spark-related parameters, see [Apache Spark documentation](https://spark.apache.org/docs/latest/configuration.html#application-properties "Click to go go Spark documenation"). For more information, see the [examples](../use-exchange/ex-ug-import-steps.md). - -| Parameters | Default | Data type | Required? | Description | -| :--- | :--- | :--- | :--- | :--- | -| `spark.app.name` | Nebula Exchange 2.0 | `string` | No | Specifies the name of the Spark Driver Program.| -| `spark.driver.cores` | 1 | `int` | No | Specifies the number of cores to use for the driver process, only in cluster mode. | -| `spark.driver.maxResultSize` | 1G | `string` | No | Specifies the limit of the total size of serialized results of all partitions for each Spark action (e.g. collect) in bytes. Should be at least 1M, or 0 for unlimited. | -| `spark.cores.max` | None | `int` | No | When the driver program runs on a standalone deployed cluster or a Mesos cluster in "coarse-grained" sharing mode, the maximum amount of CPU cores to request for the application from across the cluster (not from each machine). If not set, the default will be `spark.deploy.defaultCores` on the standalone cluster manager of Spark, or infinite (all available cores) on Mesos. | diff --git a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-from-csv.md b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-from-csv.md deleted file mode 100644 index 171e51d..0000000 --- a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-from-csv.md +++ /dev/null @@ -1,312 +0,0 @@ -# Import data from CSV files - -This article uses an example to show how to use Exchange to import data from CSV files stored on HDFS into Nebula Graph. - -If you want to import data from local CSV files into Nebula Graph v2.x, see [Nebula Importer](https://github.com/vesoft-inc/nebula-importer "Click to go to GitHub"). - -## Dataset - -In this article, the [Social Network: MOOC User Action Dataset](https://snap.stanford.edu/data/act-mooc.html "Click to go to Stanford Network Analysis Platform") provided by Stanford Network Analysis Platform (SNAP) and 97 unique course names obtained from the public network are used as the sample dataset. The dataset contains: - -- Two vertex types (`user` and `course`), 7,144 vertices in total. -- One edge type (`action`), 411,749 edges in total. - -You can download the example dataset from the [nebula-web-docker](https://github.com/vesoft-inc/nebula-web-docker/tree/master/example/mooc-actions "Click to go to GitHub") repository. - -## Environment - -The practice is done in macOS. Here is the environment information: - -- Hardware specifications: - - CPU: 1.7 GHz Quad-Core Intel Core i7 - - Memory: 16 GB - -- Spark 2.4.7, deployed in the Standalone mode - -- Hadoop 2.9.2, deployed in the Pseudo-Distributed mode - -- Nebula Graph v2-nightly, deployed with Docker Compose. For more information, see [Deploy Nebula Graph with Docker Compose](https://github.com/vesoft-inc/nebula-docker-compose "Click to go to GitHub"). - -## Prerequisites - -To import data from CSV files on HDFS with Exchange v2.x, do a check of these: - -- Exchange v2.x is compiled. For more information, see [Compile Exchange v2.x](../ex-ug-compile.md). Exchange 2.0 is used in this example. - -- Spark is installed. - -- Hadoop is installed and started. - -- Nebula Graph is deployed and started. Get the information: - - IP addresses and ports of the Graph Service and the Meta Service. - - A Nebula Graph account with the privilege of writing data and its password. - -- Get the necessary information for schema creation in Nebula Graph, including tags and edge types. - -## Procedure - -### Step 1. Create a schema in Nebula Graph - -Analyze the data in the CSV files and follow these steps to create a schema in Nebula Graph: - -1. Confirm the essential elements of the schema. - - | Elements | Names | Properties | - | :--- | :--- | :--- | - | Tag | `user` | `userId string` | - | Tag | `course` | `courseId int, courseName string` | - | Edge Type | `action` | `actionId int, duration double, label bool, feature0 double, feature1 double, feature2 double, feature3 double` | - -2. In Nebula Graph, create a graph space named **csv** and create a schema. - - ```ngql - -- Create a graph space named csv - CREATE SPACE [IF NOT EXISTS] - [(partition_num = , - replica_factor = , - vid_type = {FIXED_STRING()) | INT64}]; - - -- Choose the csv graph space - USE csv; - - -- Create the user tag - CREATE TAG user(userId string); - - -- Create the course tag - CREATE TAG course(courseId int, courseName string); - - -- Create the action edge type - CREATE EDGE action (actionId int, duration double, label bool, feature0 double, feature1 double, feature2 double, feature3 double); - ``` - -For more information, see [Quick Start of Nebula Graph Database](https://docs.nebula-graph.io/2.0/2.quick-start/1.quick-start-workflow/). - -### Step 2. Prepare CSV files - -Do a check of these: - -1. The CSV files are processed to meet the requirements of the schema. - >**NOTE**: Exchange supports importing CSV files with or without headers. - -2. The CSV files must be stored in HDFS and get the file storage path. - -### Step 3. Edit configuration file - -After compiling of Exchange, copy the `target/classes/application.conf` file and edit the configuration for CSV files. In this example, a new configuration file is named `csv_ application.conf`. In this file, the vertex and edge related configuration is introduced in the comments and all the items that are not used in this example are commented out. For more information about the Spark and Nebula related parameters, see [Spark related parameters](../parameter-reference/ex-ug-paras-spark.md) and [Nebula Graph related parameters](../parameter-reference/ex-ug-paras-nebulagraph.md). - -```conf -{ - # Spark related configuration - spark: { - app: { - name: Nebula Exchange 2.0 - } - driver: { - cores: 1 - maxResultSize: 1G - } - executor: { - memory:1G - } - - cores { - max: 16 - } - } - - # Nebula Graph related configuration - nebula: { - address:{ - # Specifies the IP addresses and ports of the Graph Service and the Meta Service of Nebula Graph. - # If multiple servers are used, separate the addresses with commas. - # Format: "ip1:port","ip2:port","ip3:port". - graph:["127.0.0.1:9669"] - meta:["127.0.0.1:9559"] - } - - # Specifies an account that has the WriteData privilege in Nebula Graph and its password. - user: user - pswd: password - - # Specifies a graph space name - space: csv - connection { - timeout: 3000 - retry: 3 - } - execution { - retry: 3 - } - error: { - max: 32 - output: /tmp/errors - } - rate: { - limit: 1024 - timeout: 1000 - } - } - - # Process vertices - tags: [ - # Sets for the course tag - { - # Specifies a tag name defined in Nebula Graph. - name: course - type: { - # Specifies the data source. csv is used. - source: csv - - # Specifies how to import vertex data into Nebula Graph: client or sst. - # For more information about importing sst files, see Import SST files (doc_to_do). - sink: client - } - - # Specifies the HDFS path of the CSV file. - # Enclose the path with double quotes and start the path with hdfs://. - path: "hdfs://namenode_ip:port/path/to/course.csv" - - # If the CSV file has no header, use [_c0, _c1, _c2, ..., _cn] to - # represent its header and to indicate columns as the source of the property values. - fields: [_c0, _c1] - # If the CSV file has a header, use the actual column names. - - # Specifies property names defined in Nebula Graph. - # fields for the CSV file and nebula.fields for Nebula Graph must - # have the one-to-one correspondence relationship. - nebula.fields: [courseId, courseName] - - # Specifies a column as the source of VIDs. - # The value of vertex must be one column of the CSV file. - vertex: _c1 - # For now, only string type VIDs are supported in Nebula Graph v2.x. - # Do not use vertex.policy for mapping. - # vertex: { - # field: _c1, - # policy: "hash" - # } - - # Specifies the separator. The default value is commas. - separator: "," - - # If the CSV file has a header, set header to true. - # If the CSV file has no header, set header to false (default value). - header: false - - # Specifies the maximum number of vertex data to be written into - # Nebula Graph in a single batch. - batch: 256 - - # Specifies the partition number of Spark. - partition: 32 - } - - # Sets for the user tag - { - name: user - type: { - source: csv - sink: client - } - path: "hdfs://namenode_ip:port/path/to/user.csv" - - # fields for the CSV file and nebula.fields for Nebula Graph must - # have the one-to-one correspondence relationship. - fields: [userId] - - # Specifies property names defined in Nebula Graph. - # fields for the CSV file and nebula.fields for Nebula Graph must - # have the one-to-one correspondence relationship. - nebula.fields: [userId] - - # The value of vertex.field must be one column of the CSV file. - vertex: userId - separator: "," - header: true - batch: 256 - partition: 32 - } - - # If more tags are necessary, refer to the preceding configuration to add more. - ] - # Process edges - edges: [ - # Sets for the action edge type - { - # Specifies an edge type name defined in Nebula Graph - name: action - type: { - # Specifies the data source. csv is used. - source: csv - - # Specifies how to import vertex data into Nebula Graph: client or sst. - # For more information about importing sst files, see Import SST files (doc_to_do). - sink: client - } - - # Specifies the HDFS path of the CSV file. - # Enclose the path with double quotes and start the path with hdfs://. - path: "hdfs://namenode_ip:port/path/to/actions.csv" - - # If the CSV file has no header, use [_c0, _c1, _c2, ..., _cn] to - # represent its header and to indicate columns as the source of the property values. - fields: [_c0, _c3, _c4, _c5, _c6, _c7, _c8] - # If the CSV file has a header, use the actual column names. - - # Specifies property names defined in Nebula Graph. - # fields for the CSV file and nebula.fields for Nebula Graph must - # have the one-to-one correspondence relationship. - nebula.fields: [actionId, duration, feature0, feature1, feature2, feature3, label] - - # Specifies the columns as the source of the IDs of the source and target vertices. - source: _c1 - target: _c2 - # For now, only string type VIDs are supported in Nebula Graph v2.x. - # Do not use source.policy or target.policy for mapping. - #target: { - # field: _c2 - # policy: "hash" - #} - - # Specifies the separator. The default value is commas. - separator: "," - - # If the CSV file has a header, set header to true. - # If the CSV file has no header, set header to false (default value). - header: false - - # Specifies the maximum number of vertex data to be written into - # Nebula Graph in a single batch. - batch: 256 - - # Specifies the partition number of Spark. - partition: 32 - } - ] - # If more edge types are necessary, refer to the preceding configuration to add more. -} -``` - -### Step 4. Import data into Nebula Graph - -When the configuration is ready, run this command to import data from CSV files into Nebula Graph. For more information about the parameters, see [Import command parameters](../parameter-reference/ex-ug-para-import-command.md). - -```bash -$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange /path/to/nebula-exchange-2.0.0.jar -c /path/to/conf/csv_application.conf -``` - -### Step 5. (Optional) Verify data in Nebula Graph - -You can use a Nebula Graph client, such as Nebula Graph Studio, to verify the imported data. For example, in Nebula Graph Studio, run this statement. - -```ngql -GO FROM "1" OVER action; -``` - -If the queried destination vertices return, the data are imported into Nebula Graph. - -You can run the [`SHOW STATS`](../../3.ngql-guide/7.general-query-statements/6.show/14.show-stats.md) statement to count the data. - -### Step 6. (Optional) Create and rebuild indexes in Nebula Graph - -After the data is imported, you can create and rebuild indexes in Nebula Graph. For more information, see [nGQL User Guide](../../3.ngql-guide/14.native-index-statements/1.create-native-index.md). diff --git a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-hive.md b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-hive.md deleted file mode 100644 index cd73288..0000000 --- a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-hive.md +++ /dev/null @@ -1,374 +0,0 @@ -# Import data from Hive - -This article uses an example to show how to use Exchange to import data from Hive into Nebula Graph. - -## Dataset - -In this article, the [Social Network: MOOC User Action Dataset](https://snap.stanford.edu/data/act-mooc.html "Click to go to Stanford Network Analysis Platform") provided by Stanford Network Analysis Platform (SNAP) and 97 unique course names obtained from the public network are used as the sample dataset. The dataset contains: - -- Two vertex types (`user` and `course`), 7,144 vertices in total. -- One edge type (`action`), 411,749 edges in total. - -You can download the example dataset from the [nebula-web-docker](https://github.com/vesoft-inc/nebula-web-docker/tree/master/example/mooc-actions "Click to go to GitHub") repository. - -In this example, the dataset is stored in a database named `mooc` in Hive, and the information of all vertices and edges is stored in the `users`, `courses`, and `actions` tables. Here are the structures of all the tables. - -```sql -scala> sql("describe mooc.users").show -+--------+---------+-------+ -|col_name|data_type|comment| -+--------+---------+-------+ -| userid| string| null| -+--------+---------+-------+ - -scala> sql("describe mooc.courses").show -+----------+---------+-------+ -| col_name|data_type|comment| -+----------+---------+-------+ -| courseid| bigint| null| -|coursename| string| null| -+----------+---------+-------+ - -scala> sql("describe mooc.actions").show -+--------+---------+-------+ -|col_name|data_type|comment| -+--------+---------+-------+ -|actionid| bigint| null| -| srcid| string| null| -| dstid| string| null| -|duration| double| null| -|feature0| double| null| -|feature1| double| null| -|feature2| double| null| -|feature3| double| null| -| label| boolean| null| -+--------+---------+-------+ -``` - -> **NOTE**: `bigint` in Hive equals to `int` in Nebula Graph. - -## Environment - -The practice is done in macOS. Here is the environment information: - -- Hardware specifications: - - CPU: 1.7 GHz Quad-Core Intel Core i7 - - Memory: 16 GB - -- Spark 2.4.7, deployed in the Standalone mode - -- Hadoop 2.9.2, deployed in the Pseudo-Distributed mode - -- Hive 2.3.7, with MySQL 8.0.22 - -- Nebula Graph v2-nightly, deployed with Docker Compose. For more information, see [Deploy Nebula Graph with Docker Compose](https://github.com/vesoft-inc/nebula-docker-compose "Click to go to GitHub"). - -## Prerequisites - -To import data from Hive with Exchange v2.x, do a check of these: - -- Exchange v2.x is compiled. For more information, see [Compile Exchange v2.x](../ex-ug-compile.md). Exchange 2.0.0 is used in this example. - -- Spark is installed. - -- Hadoop is installed and started and the hive metastore database (MySQL is used in this example) is started. - -- Nebula Graph is deployed and started. Get the information: - - IP addresses and ports of the Graph Service and the Meta Service. - - A Nebula Graph account with the privilege of writing data and its password. - -- Get the necessary information for schema creation in Nebula Graph, including tags and edge types. - -## Procedure - -### Step 1. Create a schema in Nebula Graph - -Follow these steps to create a schema in Nebula Graph: - -1. Confirm the essential elements of the schema. - - | Elements | Names | Properties | - | :--- | :--- | :--- | - | Tag | `user` | `userId string` | - | Tag | `course` | `courseId int, courseName string` | - | Edge Type | `action` | `actionId int, duration double, label bool, feature0 double, feature1 double, feature2 double, feature3 double` | - -2. In Nebula Graph, create a graph space named **hive** and create a schema. - - ```ngql - -- Create a graph space named hive - CREATE SPACE hive(partition_num=10, replica_factor=1, vid_type=fixed_string(100)); - - -- Choose the hive graph space - USE hive; - - -- Create the user tag - CREATE TAG user(userId string); - - -- Create the course tag - CREATE TAG course(courseId int, courseName string); - - -- Create the action edge type - CREATE EDGE action (actionId int, duration double, label bool, feature0 double, feature1 double, feature2 double, feature3 double); - ``` - -For more information, see [Quick Start of Nebula Graph](../../2.quick-start/4.nebula-graph-crud.md). - -### Step 2. Verify the Hive SQL statements - -When spark-shell starts, run these statements one by one to make sure that Spark can read data from Hive. - -```sql -scala> sql("select userid from mooc.users").show -scala> sql("select courseid, coursename from mooc.courses").show -scala> sql("select actionid, srcid, dstid, duration, feature0, feature1, feature2, feature3, label from mooc.actions").show -``` - -Here is an example of data read from the `mooc.actions` table. - -```sql -+--------+-----+--------------------+--------+------------+------------+-----------+-----------+-----+ -|actionid|srcid| dstid|duration| feature0| feature1| feature2| feature3|label| -+--------+-----+--------------------+--------+------------+------------+-----------+-----------+-----+ -| 0| 0|Environmental Dis...| 0.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| -| 1| 0| History of Ecology| 6.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| -| 2| 0| Women in Islam| 41.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| -| 3| 0| History of Ecology| 49.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| -| 4| 0| Women in Islam| 51.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| -| 5| 0|Legacies of the A...| 55.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| -| 6| 0| ITP Core 2| 59.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| -| 7| 0|The Research Pape...| 62.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| -| 8| 0| Neurobiology| 65.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| -| 9| 0| Wikipedia| 113.0|-0.319991479|-0.435701433|1.108826104|12.77723482|false| -| 10| 0|Media History and...| 226.0|-0.319991479|-0.435701433|0.607804941|149.4512115|false| -| 11| 0| WIKISOO| 974.0|-0.319991479|-0.435701433|1.108826104|3.344522776|false| -| 12| 0|Environmental Dis...| 1000.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| -| 13| 0| WIKISOO| 1172.0|-0.319991479|-0.435701433|1.108826104|1.136866766|false| -| 14| 0| Women in Islam| 1182.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| -| 15| 0| History of Ecology| 1185.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| -| 16| 0|Human Development...| 1687.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| -| 17| 1|Human Development...| 7262.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| -| 18| 1| History of Ecology| 7266.0|-0.319991479|-0.435701433|0.106783779|-0.06730924|false| -| 19| 1| Women in Islam| 7273.0|-0.319991479|-0.435701433|0.607804941|0.936170765|false| -+--------+-----+--------------------+--------+------------+------------+-----------+-----------+-----+ -only showing top 20 rows -``` - -### Step 3. Edit configuration file - -After compiling of Exchange, copy the `target/classes/application.conf` file and edit the configuration for Hive. In this example, a new configuration file is named `hive_ application.conf`. In this file, the vertex and edge related configuration is introduced as comments and all the items that are not used in this example are commented out. For more information about the Spark and Nebula related parameters, see [Spark related parameters](../parameter-reference/ex-ug-paras-spark.md) and [Nebula Graph related parameters](../parameter-reference/ex-ug-paras-nebulagraph.md). - -```conf -{ - # Spark related configuration - spark: { - app: { - name: Nebula Exchange 2.0 - } - driver: { - cores: 1 - maxResultSize: 1G - } - executor: { - memory:1G - } - cores { - max: 16 - } - } - - # If Spark and Hive are deployed in the different clusters, - # configure these parameters for Hive. Otherwise, ignore them. - #hive: { - # waredir: "hdfs://NAMENODE_IP:9000/apps/svr/hive-xxx/warehouse/" - # connectionURL: "jdbc:mysql://your_ip:3306/hive_spark?characterEncoding=UTF-8" - # connectionDriverName: "com.mysql.jdbc.Driver" - # connectionUserName: "user" - # connectionPassword: "password" - #} - - # Nebula Graph related configuration - nebula: { - address:{ - # Specifies the IP addresses and ports of the Graph Service and the Meta Service of Nebula Graph - # If multiple servers are used, separate the addresses with commas. - # Format: "ip1:port","ip2:port","ip3:port" - graph:["127.0.0.1:9669"] - meta:["127.0.0.1:9559"] - } - - # Specifies an account that has the WriteData privilege in Nebula Graph and its password - user: user - pswd: password - - # Specifies a graph space name - space: hive - connection { - timeout: 3000 - retry: 3 - } - execution { - retry: 3 - } - error: { - max: 32 - output: /tmp/errors - } - rate: { - limit: 1024 - timeout: 1000 - } - } - - # Process vertices - tags: [ - # Sets for the user tag - { - # Specifies a tag name defined in Nebula Graph - name: user - type: { - # Specifies the data source. hive is used. - source: hive - # Specifies how to import vertex data into Nebula Graph: client or sst. - # For more information about importing sst files, see Import SST files (doc to do). - sink: client - } - - # Specifies the SQL statement to read data from the users table in the mooc database - exec: "select userid from mooc.users" - - # Specifies the column names from the users table to fields. - # Their values are used as the source of the userId (nebula.fields) property defined in Nebula Graph. - # If more than one column name is specified, separate them with commas. - # fields for the Hive and nebula.fields for Nebula Graph must have the one-to-one correspondence relationship. - fields: [userid] - nebula.fields: [userId] - - # Specifies a column as the source of VIDs. - # The value of vertex must be one column name in the exec sentence. - # If the values are not of the int type, use vertex.policy to - # set the mapping policy. "hash" is preferred. - # Refer to the configuration of the course tag. - vertex: userid - - # Specifies the maximum number of vertex data to be written into - # Nebula Graph in a single batch. - batch: 256 - - # Specifies the partition number of Spark. - partition: 32 - } - - # Sets for the course tag - { - name: course - type: { - source: hive - sink: client - } - exec: "select courseid, coursename from mooc.courses" - fields: [courseid, coursename] - nebula.fields: [courseId, courseName] - - # Specifies a column as the source of VIDs. - # The value of vertex.field must be one column name in the exec sentence. - vertex: coursename - # For now, only string type VIDs are supported in Nebula Graph v2.x. - # Do not use vertex.policy for mapping. - #vertex: { - # field: coursename - # policy: "hash" - #} - batch: 256 - partition: 32 - } - # If more tags are necessary, refer to the preceding configuration to add more. - ] - - # Process edges - edges: [ - # Sets for the action edge type - { - # Specifies an edge type name defined in Nebula Graph - name: action - - type: { - # Specifies the data source. hive is used. - source: hive - - # Specifies how to import vertex data into Nebula Graph: client or sst - # For more information about importing sst files, - # see Import SST files (doc to do). - sink: client - } - - # Specifies the SQL statement to read data from the actions table in - # the mooc database. - exec: "select actionid, srcid, dstid, duration, feature0, feature1, feature2, feature3, label from mooc.actions" - - # Specifies the column names from the actions table to fields. - # Their values are used as the source of the properties of - # the action edge type defined in Nebula Graph. - # If more than one column name is specified, separate them with commas. - # fields for the Hive and nebula.fields for Nebula Graph must - # have the one-to-one correspondence relationship. - fields: [actionid, duration, feature0, feature1, feature2, feature3, label] - nebula.fields: [actionId, duration, feature0, feature1, feature2, feature3, label] - - # source specifies a column as the source of the IDs of - # the source vertex of an edge. - # target specifies a column as the source of the IDs of - # the target vertex of an edge. - # The value of source.field and target.field must be - # column names set in the exec sentence. - source: srcid - target: dstid - # For now, only string type VIDs are supported in Nebula Graph v2.x. - # Do not use vertex.policy for mapping. - #target: { - # field: dstid - # policy: "hash" - #} - - # Specifies the maximum number of vertex data to be - # written into Nebula Graph in a single batch. - batch: 256 - - # Specifies the partition number of Spark. - partition: 32 - } - ] -} -``` - -### Step 4. (Optional) Verify the configuration - -After the configuration, run the import command with the `-D` parameter to verify the configuration file. For more information about the parameters, see [Import command parameters](../parameter-reference/ex-ug-para-import-command.md). - -```bash -$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange /path/to/nebula-exchange-2.0.0.jar -c /path/to/conf/hive_application.conf -h -D -``` - -### Step 5. Import data into Nebula Graph - -When the configuration is ready, run this command to import data from HIVE into Nebula Graph. For more information about the parameters, see [Import command parameters](../parameter-reference/ex-ug-para-import-command.md). - -```bash -$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange /path/to/nebula-exchange-2.0.0.jar -c /path/to/conf/hive_application.conf -h -``` - -### Step 6. (Optional) Verify data in Nebula Graph - -You can use a Nebula Graph client, such as Nebula Graph Studio, to verify the imported data. For example, in Nebula Graph Studio, run this statement. - -```ngql -GO FROM "1" OVER action; -``` - -If the queried destination vertices return, the data are imported into Nebula Graph. - -You can run the [`SHOW STATS`](../../3.ngql-guide/7.general-query-statements/6.show/14.show-stats.md) statement to count the data. - -### Step 7. (Optional) Create and rebuild indexes in Nebula Graph - -After the data is imported, you can create and rebuild indexes in Nebula Graph. For more information, see [nGQL User Guide](../../3.ngql-guide/14.native-index-statements/1.create-native-index.md). diff --git a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-json.md b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-json.md deleted file mode 100644 index 48bb8d5..0000000 --- a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-json.md +++ /dev/null @@ -1,288 +0,0 @@ -# Import data from JSON files - -This article uses an example to show how to use Exchange to import data from JSON files stored on HDFS into Nebula Graph. - -## Dataset - -The JSON file (test.json) used in this example is like `{"source":string, "target":string, "likeness":double}`, representing a `like` relationship between `source` and `target`. 21,645 records in total. - -Here are some sample data: - -```json -{"source":53802643,"target":87847387,"likeness":0.34} -{"source":29509860,"target":57501950,"likeness":0.40} -{"source":97319348,"target":50240344,"likeness":0.77} -{"source":94295709,"target":8189720,"likeness":0.82} -{"source":78707720,"target":53874070,"likeness":0.98} -{"source":23399562,"target":20136097,"likeness":0.47} -``` - -## Environment - -The practice is done in macOS. Here is the environment information: - -- Hardware specifications: - - CPU: 1.7 GHz Quad-Core Intel Core i7 - - Memory: 16 GB - -- Spark 2.4.7, deployed in the Standalone mode - -- Hadoop 2.9.2, deployed in the Pseudo-Distributed mode - -- Nebula Graph v2-nightly, deployed with Docker Compose. For more information, see [Deploy Nebula Graph with Docker Compose](https://github.com/vesoft-inc/nebula-docker-compose "Click to go to GitHub"). - -## Prerequisites - -To import data from JSON files on HDFS with Exchange v2.x, do a check of these: - -- Exchange v2.x is compiled. For more information, see [Compile Exchange v2.x](../ex-ug-compile.md). Exchange 2.0.0 is used in this example. - -- Spark is installed. - -- Hadoop is installed and started. - -- Nebula Graph is deployed and started. Get the information: - - IP addresses and ports of the Graph Service and the Meta Service. - - A Nebula Graph account with the privilege of writing data and its password. - -- Get the necessary information for schema creation in Nebula Graph, including tags and edge types. - -## Procedure - -### Step 1. Create a schema in Nebula Graph - -Analyze the data in the JSON files and follow these steps to create a schema in Nebula Graph: - -1. Confirm the essential elements of the schema. - - | Elements | Names | Properties | - | :--- | :--- | :--- | - | Tag | `source` | `srcId string` | - | Tag | `target` | `dstId string` | - | Edge Type | `like` | `likeness double` | - -2. In Nebula Graph, create a graph space named **json** and create a schema. - - ```ngql - -- Create a graph space named json - CREATE SPACE json(partition_num=10, replica_factor=1, vid_type=fixed_string(30)); - - -- Choose the json graph space - USE json; - - -- Create the source tag - CREATE TAG source (srcId string); - - -- Create the target tag - CREATE TAG target (dstId string); - - -- Create the like edge type - CREATE EDGE like (likeness double); - ``` - -For more information, see [Quick Start of Nebula Graph](../../2.quick-start/4.nebula-graph-crud.md). - -### Step 2. Prepare JSON files - -Create separate JSON files for vertex and edge data. Store the JSON files in HDFS and get the HDFS path of the files. - -> **NOTE**: In this example, only one JSON file is used to import vertex and edge data at the same time. Some vertex data representing source and target are duplicate. Therefore, during the import process, these vertices are written repeatedly. In Nebula Graph, data is overwritten when repeated insertion occurs, and the last write is read out. In practice, to increase the write speed, creating separate files for vertex and edge data is recommended. - -### Step 3. Edit configuration file - -After compiling of Exchange, copy the `target/classes/application.conf` file and edit the configuration for JSON files. In this example, a new configuration file is named `json_ application.conf`. In this file, the vertex and edge related configuration is introduced as comments and all the items that are not used in this example are commented out. For more information about the Spark and Nebula related parameters, see [Spark related parameters](../parameter-reference/ex-ug-paras-spark.md) and [Nebula Graph related parameters](../parameter-reference/ex-ug-paras-nebulagraph.md). - -```conf -{ - # Spark related configuration - spark: { - app: { - name: Spark Writer - } - - driver: { - cores: 1 - maxResultSize: 1G - } - - executor: { - memory:1G - } - - cores { - max: 16 - } - } - - # Nebula Graph related configuration - nebula: { - address:{ - # Specifies the IP addresses and ports of the Graph Service and the Meta Service of Nebula Graph. - # If multiple servers are used, separate the addresses with commas. - # Format: "ip1:port","ip2:port","ip3:port" - graph:["127.0.0.1:9669"] - meta:["127.0.0.1:9559"] - } - # Specifies an account that has the WriteData privilege in Nebula Graph and its password. - user: user - pswd: password - - # Specifies a graph space name - space: json - - connection { - timeout: 3000 - retry: 3 - } - - execution { - retry: 3 - } - - error: { - max: 32 - output: /tmp/errors - } - - rate: { - limit: 1024 - timeout: 1000 - } - } - - # Process vertices - tags: [ - # Sets for the source tag - { - # Specifies a tag name defined in Nebula Graph - name: source - type: { - # Specifies the data source. json is used. - source: json - - # Specifies how to import vertex data into Nebula Graph: client or sst. - # For more information about importing sst files, see Import SST files (doc to do). - sink: client - } - - # Specifies the HDFS path of the JSON file. - # Enclose the path with double quotes and start the path with hdfs://. - path: "hdfs://namenode_ip:port/path/to/test.json" - - # Specifies the keys in the JSON file. - # Their values are used as the source of the srcId property - # defined in Nebula Graph. - # If more than one key is specified, separate them with commas. - fields: ["source"] - nebula.fields: ["srcId"] - - # Specifies the values of a key in the JSON file as - # the source of the VID in Nebula Graph. - # For now, only string type VIDs are supported in Nebula Graph v2.x. - # Do not use vertex.policy for mapping. - # vertex: { - # field: key_name_in_json - # policy: "hash" - # } - vertex: source - - batch: 256 - partition: 32 - } - # Sets for the target tag - { - name: target - type: { - source: json - sink: client - } - path: "hdfs://namenode_ip:port/path/to/test.json" - fields: ["target"] - nebula.fields: ["dstId"] - vertex: "target" - batch: 256 - partition: 32 - isImplicit: true - } - # If more tags are necessary, refer to the preceding configuration to add more. - ] - - # Process edges - edges: [ - # Sets for the like edge type - { - # Specifies an edge type name defined in Nebula Graph - name: like - type: { - # Specifies the data source. json is used. - source: json - - # Specifies how to import vertex data into Nebula Graph: client or sst. - # For more information about importing sst files, see Import SST files (doc to do). - sink: client - } - - # Specifies the HDFS path of the JSON file. - # Enclose the path with double quotes and start the path with hdfs://. - path: "hdfs://namenode_ip:port/path/to/test.json" - - # Specifies the keys in the JSON file. - # Their values are used as the source of the likeness property defined in Nebula Graph. - # If more than one key is specified, separate them with commas. - fields: ["likeness"] - nebula.fields: ["likeness"] - - # Specifies the values of two keys in the JSON file as the source - # of the IDs of source and destination vertices of the like edges in Nebula Graph. - # For now, only string type VIDs are supported in Nebula Graph v2.x. - # Do not use vertex.policy for mapping. - # source: { - # field: key_name_in_json - # policy: "hash" - # } - # target: { - # field: key_name_in_json - # policy: "hash" - # } - source: "source" - target: "target" - - batch: 256 - partition: 32 - } - # If more edge types are necessary, refer to the preceding configuration to add more. - ] -} -``` - -### Step 4. (Optional) Verify the configuration - -After the configuration, run the import command with the `-D` parameter to verify the configuration file. For more information about the parameters, see [Import command parameters](../parameter-reference/ex-ug-para-import-command.md). - -```bash -$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange /path/to/nebula-exchange-2.0.0.jar -c /path/to/conf/json_application.conf -D -``` - -### Step 5. Import data into Nebula Graph - -When the configuration is ready, run this command to import data from JSON files into Nebula Graph. For more information about the parameters, see [Import command parameters](../parameter-reference/ex-ug-para-import-command.md). - -```bash -$SPARK_HOME/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange /path/to/nebula-exchange-2.0.0.jar -c /path/to/conf/json_application.conf -``` - -### Step 6. (Optional) Verify data in Nebula Graph - -You can use a Nebula Graph client, such as Nebula Graph Studio, to verify the imported data. For example, in Nebula Graph Studio, run this statement. - -```ngql -GO FROM "53802643" OVER like; -``` - -If the queried destination vertices return, the data are imported into Nebula Graph. - -You can run the [`SHOW STATS`](../../3.ngql-guide/7.general-query-statements/6.show/14.show-stats.md) statement to count the data. - -### Step 7. (Optional) Create and rebuild indexes in Nebula Graph - -After the data is imported, you can create and rebuild indexes in Nebula Graph. For more information, see [nGQL User Guide](../../3.ngql-guide/1.nGQL-overview/1.overview.md). diff --git a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-steps.md b/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-steps.md deleted file mode 100644 index 1f6a179..0000000 --- a/nebula-exchange/doc-2.0/EN/use-exchange/ex-ug-import-steps.md +++ /dev/null @@ -1,45 +0,0 @@ -# Use Exchange - -This article introduces the generally-used procedure on how to use Exchange to import data from a specified source to Nebula Graph. - -## Prerequisites - -- Nebula Graph is deployed and started. Get the information: - - IP addresses and ports of the Graph Service and the Meta Service. - - A Nebula Graph account with the privilege of writing data and its password. - -- Exchange is compiled. For more information, see [Compile Exchange](../ex-ug-compile.md). - -- Spark is installed. - -- Get the necessary information for schema creation in Nebula Graph, including tags and edge types. - -## Procedure - -To import data from a source to Nebula Graph, follow these steps: - -1. Create a graph space and a schema in Nebula Graph. - -2. (Optional) Process the source data. For example, to import data from a Neo4j database, create indexes for the specified tags in Neo4j to export the data from Neo4j more quickly. - -3. Edit the configuration file for Spark, Nebula Graph, vertices, and edges. - > **NOTE**: After compiling of Exchange, refer to the example configuration files in the `nebula-exchange/target/classes` directory for the configuration for different sources. - -4. (Optional) Run the import command with the `-D` parameter to verify the configuration. For more information, see [Import command parameters](../parameter-reference/ex-ug-para-import-command.md). - -5. Run the import command to import data into Nebula Graph. - -6. Verify the imported data in Nebula Graph. - -7. (Optional) Create and rebuild indexes in Nebula Graph. - -For more information, see the examples: - -- [Import data from Hive](ex-ug-import-hive.md) -- [Import data from CSV files](ex-ug-import-from-csv.md) -- [Import data from JSON files](ex-ug-import-json.md) - - - true + + **/*Test.* + **/*Suite.* + From 87b219d4bb27fd635f50f352562770ca84e20e10 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 29 Jun 2021 17:10:00 +0800 Subject: [PATCH 148/213] fix test --- .../nebula/exchange/NebulaGraphMock.scala | 20 +++++++++++-- .../nebula/exchange/config/ConfigsSuite.scala | 2 +- .../exchange/utils/NebulaUtilsSuite.scala | 29 ++++++++++++------- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala index a128941..fe32540 100644 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/NebulaGraphMock.scala @@ -9,11 +9,13 @@ package scala.com.vesoft.nebula.exchange import com.vesoft.nebula.client.graph.NebulaPoolConfig import com.vesoft.nebula.client.graph.data.HostAddress import com.vesoft.nebula.client.graph.net.NebulaPool +import org.apache.log4j.Logger import scala.collection.JavaConverters._ import scala.collection.mutable.ListBuffer class NebulaGraphMock { + private[this] val LOG = Logger.getLogger(this.getClass) @transient val nebulaPoolConfig = new NebulaPoolConfig @transient val pool: NebulaPool = new NebulaPool @@ -26,16 +28,17 @@ class NebulaGraphMock { def mockStringIdGraph(): Unit = { val session = pool.getSession("root", "nebula", true) - val createSpace = "CREATE SPACE IF NOT EXISTS test_string(partition_num=10);" + + val createSpace = "CREATE SPACE IF NOT EXISTS test_string(partition_num=10,vid_type=fixed_string(8));" + "USE test_string;" + "CREATE TAG IF NOT EXISTS person(col1 string, col2 fixed_string(8), col3 int8, col4 int16, col5 int32, col6 int64, col7 date, col8 datetime, col9 timestamp, col10 bool, col11 double, col12 float, col13 time);" + "CREATE EDGE IF NOT EXISTS friend(col1 string, col2 fixed_string(8), col3 int8, col4 int16, col5 int32, col6 int64, col7 date, col8 datetime, col9 timestamp, col10 bool, col11 double, col12 float, col13 time);"; val createResp = session.execute(createSpace) if (!createResp.isSucceeded) { close() + LOG.error("create string type space failed," + createResp.getErrorMessage) sys.exit(-1) } - Thread.sleep(3000) + Thread.sleep(10000) val insertTag = "INSERT VERTEX person(col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13) VALUES " + " \"1\":(\"person1\", \"person1\", 11, 200, 1000, 188888, date(\"2021-01-01\"), datetime(\"2021-01-01T12:00:00\"),timestamp(\"2021-01-01T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + @@ -58,6 +61,7 @@ class NebulaGraphMock { val insertTagResp = session.execute(insertTag) if (!insertTagResp.isSucceeded) { close() + LOG.error("insert vertex for string type space failed," + insertTagResp.getErrorMessage) sys.exit(-1) } @@ -79,6 +83,7 @@ class NebulaGraphMock { val insertEdgeResp = session.execute(insertEdge) if (!insertEdgeResp.isSucceeded) { close() + LOG.error("insert edge for string type space failed," + insertEdgeResp.getErrorMessage) sys.exit(-1) } } @@ -92,9 +97,11 @@ class NebulaGraphMock { val createResp = session.execute(createSpace) if (!createResp.isSucceeded) { close() + LOG.error("create int type space failed," + createResp.getErrorMessage) sys.exit(-1) } + Thread.sleep(10000) val insertTag = "INSERT VERTEX person(col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13) VALUES " + " 1:(\"person1\", \"person1\", 11, 200, 1000, 188888, date(\"2021-01-01\"), datetime(\"2021-01-01T12:00:00\"),timestamp(\"2021-01-01T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + @@ -108,10 +115,16 @@ class NebulaGraphMock { " 9:(\"person9\", \"person9\", 19, 1000, 9000, 988888, date(\"2021-01-09\"), datetime(\"2021-01-09T12:00:00\"),timestamp(\"2021-01-09T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + " 10:(\"person10\", \"person10\", 20, 1100, 10000, 1088888, date(\"2021-01-10\"), datetime(\"2021-01-10T12:00:00\"),timestamp(\"2021-01-10T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + " 11:(\"person11\", \"person11\", 21, 1200, 11000, 1188888, date(\"2021-01-11\"), datetime(\"2021-01-11T12:00:00\"),timestamp(\"2021-01-11T12:00:00\"), false, 1.0, 2.0, time(\"12:01:01\"))," + - " 12:(\"person12\", \"person11\", 22, 1300, 12000, 1288888, date(\"2021-01-12\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))" + " 12:(\"person12\", \"person11\", 22, 1300, 12000, 1288888, date(\"2021-01-12\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " -1:(\"person00\", \"person00\", 23, 1400, 13000, 1388888, date(\"2021-01-13\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " -2:(\"person01\", \"person01\", 24, 1500, 14000, 1488888, date(\"2021-01-14\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " -3:(\"person02\", \"person02\", 24, 1500, 14000, 1488888, date(\"2021-01-14\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " 19:(\"person19\", \"person22\", 25, 1500, 14000, 1488888, date(\"2021-01-14\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))," + + " 22:(\"person22\", \"person22\", 26, 1500, 14000, 1488888, date(\"2021-01-14\"), datetime(\"2021-01-12T12:00:00\"),timestamp(\"2021-01-12T12:00:00\"), true, 1.0, 2.0, time(\"12:01:01\"))" val insertTagResp = session.execute(insertTag) if (!insertTagResp.isSucceeded) { close() + LOG.error("insert vertex for int type space failed," + insertTagResp.getErrorMessage) sys.exit(-1) } @@ -131,6 +144,7 @@ class NebulaGraphMock { val insertEdgeResp = session.execute(insertEdge) if (!insertEdgeResp.isSucceeded) { close() + LOG.error("insert edge for int type space failed," + insertEdgeResp.getErrorMessage) sys.exit(-1) } } diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala index eb65f13..7a2dc9a 100644 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala @@ -59,7 +59,7 @@ class ConfigsSuite { assert(executionConfig.retry == 3) assert(executionConfig.interval == 3000) - assert(executionConfig.timeout == 3000) + assert(executionConfig.timeout == Integer.MAX_VALUE) assert(errorConfig.errorMaxSize == 32) assert(errorConfig.errorPath.equals("/tmp/errors")) diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala index 57aca8b..5a79434 100644 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala @@ -15,6 +15,7 @@ import com.vesoft.nebula.exchange.config.TagConfigEntry import com.vesoft.nebula.exchange.utils.NebulaUtils import com.vesoft.nebula.exchange.{KeyPolicy, MetaProvider, VidType} import com.vesoft.nebula.meta.PropertyType +import org.apache.log4j.Logger import org.junit.{After, Before, Test} import scala.collection.JavaConverters._ @@ -22,6 +23,8 @@ import scala.collection.mutable.ListBuffer import scala.com.vesoft.nebula.exchange.NebulaGraphMock class NebulaUtilsSuite { + private[this] val LOG = Logger.getLogger(this.getClass) + @transient val nebulaPoolConfig = new NebulaPoolConfig @transient val pool: NebulaPool = new NebulaPool val address = new ListBuffer[HostAddress]() @@ -68,16 +71,16 @@ class NebulaUtilsSuite { "col11", "col12") val label = "person" - val sourceConfig = new TagConfigEntry(label, - null, - null, - sourceFields, - nebulaFields, - null, - Some(KeyPolicy.UUID), - 1, - 1, - Some("")) + val sourceConfig = TagConfigEntry(label, + null, + null, + sourceFields, + nebulaFields, + "id", + Some(KeyPolicy.UUID), + 1, + 1, + Some("")) val space = "test_string" val address = new ListBuffer[HostAndPort]() @@ -124,6 +127,9 @@ class NebulaUtilsSuite { } } } + if (!containVertex) { + LOG.error("vid={},partId={}", vid, partitionId) + } assert(containVertex) } @@ -147,6 +153,9 @@ class NebulaUtilsSuite { } } } + if (!containVertex) { + LOG.error("vid={},partId={}", vid, partitionId) + } assert(containVertex) } } From d4f7563a8156ab7e9d4f3c674c874b0656f846f5 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 23 Jun 2021 19:15:41 +0800 Subject: [PATCH 149/213] add maxCompute datasource --- nebula-exchange/pom.xml | 5 +++ .../src/main/resources/application.conf | 22 ++++++++++++ .../nebula/exchange/config/Configs.scala | 34 +++++++++++++------ .../exchange/config/SourceConfigs.scala | 23 +++++++++++++ .../exchange/reader/ServerBaseReader.scala | 21 ++++++++++++ 5 files changed, 94 insertions(+), 11 deletions(-) diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml index 948b8c4..a3a3c58 100644 --- a/nebula-exchange/pom.xml +++ b/nebula-exchange/pom.xml @@ -700,6 +700,11 @@ scala-xml ${scala-xml.version} + + com.aliyun.odps + odps-spark-datasource_2.11 + 3.3.8-public + diff --git a/nebula-exchange/src/main/resources/application.conf b/nebula-exchange/src/main/resources/application.conf index a64d625..b1b95d8 100644 --- a/nebula-exchange/src/main/resources/application.conf +++ b/nebula-exchange/src/main/resources/application.conf @@ -237,6 +237,28 @@ batch: 10 interval.seconds: 10 } + + # MaxCompute + { + name: tag-name-8 + type:{ + source:maxcompute + sink:client + } + table:table + project:project + odpsUrl: + tunnelUrl: + accessKeyId: + accessKeySecret: + fields:[maxcompute-field-0, maxcompute-field-1] + nebula.fields:[nebula-field-0, nebula-field-1] + vertex:{ + field: maxcompute-field-3 + } + partition 10 + batch:10 + } ] # Processing edges diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala index 59ef44f..4ad7469 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala @@ -472,17 +472,18 @@ object Configs { */ private[this] def toSourceCategory(category: String): SourceCategory.Value = { category.trim.toUpperCase match { - case "PARQUET" => SourceCategory.PARQUET - case "ORC" => SourceCategory.ORC - case "JSON" => SourceCategory.JSON - case "CSV" => SourceCategory.CSV - case "HIVE" => SourceCategory.HIVE - case "NEO4J" => SourceCategory.NEO4J - case "KAFKA" => SourceCategory.KAFKA - case "MYSQL" => SourceCategory.MYSQL - case "PULSAR" => SourceCategory.PULSAR - case "HBASE" => SourceCategory.HBASE - case _ => throw new IllegalArgumentException(s"${category} not support") + case "PARQUET" => SourceCategory.PARQUET + case "ORC" => SourceCategory.ORC + case "JSON" => SourceCategory.JSON + case "CSV" => SourceCategory.CSV + case "HIVE" => SourceCategory.HIVE + case "NEO4J" => SourceCategory.NEO4J + case "KAFKA" => SourceCategory.KAFKA + case "MYSQL" => SourceCategory.MYSQL + case "PULSAR" => SourceCategory.PULSAR + case "HBASE" => SourceCategory.HBASE + case "MAXCOMPUTE" => SourceCategory.MAXCOMPUTE + case _ => throw new IllegalArgumentException(s"${category} not support") } } @@ -609,6 +610,17 @@ object Configs { config.getString("table"), config.getString("columnFamily"), fields.toSet.toList) + case SourceCategory.MAXCOMPUTE => { + MaxComputeConfigEntry( + SourceCategory.MAXCOMPUTE, + config.getString("table"), + config.getString("project"), + config.getString("odpsUrl"), + config.getString("tunnelUrl"), + config.getString("accessKeyId"), + config.getString("accessKeySecret") + ) + } case _ => throw new IllegalArgumentException("Unsupported data source") } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala index 542b34a..ec8a65d 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala @@ -25,6 +25,7 @@ object SourceCategory extends Enumeration { val JANUS_GRAPH = Value("JANUS GRAPH") val MYSQL = Value("MYSQL") val HBASE = Value("HBASE") + val MAXCOMPUTE = Value("MAXCOMPUTE") val SOCKET = Value("SOCKET") val KAFKA = Value("KAFKA") @@ -217,3 +218,25 @@ case class HBaseSourceConfigEntry(override val category: SourceCategory.Value, s"HBase source host: $host, port: $port, table: $table" } } + +/** + * MaxComputeConfigEntry + */ +case class MaxComputeConfigEntry(override val category: SourceCategory.Value, + odpsUrl: String, + tunnelUrl: String, + table: String, + project: String, + accessKeyId: String, + accessKeySecret: String) + extends ServerDataSourceConfigEntry() { + require( + !odpsUrl.trim.isEmpty && !tunnelUrl.trim.isEmpty && !table.trim.isEmpty && !project.trim.isEmpty && !accessKeyId.trim.isEmpty && !accessKeySecret.trim.isEmpty) + + override def sentence: String = null + + override def toString: String = { + s"MaxCompute source odpsUrl: $odpsUrl, tunnelUrl: $tunnelUrl, table: $table, project: $project, keyId: $accessKeyId, keySecret: $accessKeySecret" + } + +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala index ac5b7b2..5f15fa2 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala @@ -11,6 +11,7 @@ import com.vesoft.nebula.exchange.config.{ HBaseSourceConfigEntry, HiveSourceConfigEntry, JanusGraphSourceConfigEntry, + MaxComputeConfigEntry, MySQLSourceConfigEntry, Neo4JSourceConfigEntry, ServerDataSourceConfigEntry @@ -259,3 +260,23 @@ class HBaseReader(override val session: SparkSession, hbaseConfig: HBaseSourceCo dataFrame } } + +/** + * MaxCompute Reader + */ +class MaxcomputeReader(override val session: SparkSession, maxComputeConfig: MaxComputeConfigEntry) + extends ServerBaseReader(session, null) { + + override def read(): DataFrame = { + val df = session.read + .format("org.apache.spark.aliyun.maxcompute.datasource") + .option("odpsUrl", maxComputeConfig.odpsUrl) + .option("tunnelUrl", maxComputeConfig.tunnelUrl) + .option("table", maxComputeConfig.table) + .option("project", maxComputeConfig.project) + .option("accessKeyId", maxComputeConfig.accessKeyId) + .option("accessKeySecret", maxComputeConfig.accessKeySecret) + .load() + df + } +} From 35e2b67e8163c5e06541b61f04cf6b1064d26c08 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 25 Jun 2021 09:59:47 +0800 Subject: [PATCH 150/213] add maxCompute datasource --- nebula-exchange/pom.xml | 10 ++++++++++ nebula-exchange/src/main/resources/application.conf | 10 ++++++---- .../scala/com/vesoft/nebula/exchange/Exchange.scala | 10 ++++++++-- .../com/vesoft/nebula/exchange/config/Configs.scala | 4 ++-- .../nebula/exchange/reader/ServerBaseReader.scala | 2 +- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml index a3a3c58..bcd7ec0 100644 --- a/nebula-exchange/pom.xml +++ b/nebula-exchange/pom.xml @@ -705,6 +705,16 @@ odps-spark-datasource_2.11 3.3.8-public + + + + + + + com.aliyun.emr + emr-maxcompute_2.11 + 2.2.0 + diff --git a/nebula-exchange/src/main/resources/application.conf b/nebula-exchange/src/main/resources/application.conf index b1b95d8..66c32d5 100644 --- a/nebula-exchange/src/main/resources/application.conf +++ b/nebula-exchange/src/main/resources/application.conf @@ -247,10 +247,10 @@ } table:table project:project - odpsUrl: - tunnelUrl: - accessKeyId: - accessKeySecret: + odpsUrl:"http://service.cn-hangzhou.maxcompute.aliyun.com/api" + tunnelUrl:"http://dt.cn-hangzhou.maxcompute.aliyun.com" + accessKeyId:xxx + accessKeySecret:xxx fields:[maxcompute-field-0, maxcompute-field-1] nebula.fields:[nebula-field-0, nebula-field-1] vertex:{ @@ -442,5 +442,7 @@ batch: 1000 interval.seconds: 10 } + + # ] } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index 696d34a..7cb4fb6 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -17,6 +17,7 @@ import com.vesoft.nebula.exchange.config.{ HiveSourceConfigEntry, JanusGraphSourceConfigEntry, KafkaSourceConfigEntry, + MaxComputeConfigEntry, MySQLSourceConfigEntry, Neo4JSourceConfigEntry, PulsarSourceConfigEntry, @@ -31,13 +32,14 @@ import com.vesoft.nebula.exchange.reader.{ JSONReader, JanusGraphReader, KafkaReader, + MaxcomputeReader, MySQLReader, Neo4JReader, ORCReader, - ParquetReader + ParquetReader, + PulsarReader } import com.vesoft.nebula.exchange.processor.ReloadProcessor -import com.vesoft.nebula.exchange.reader.PulsarReader import org.apache.log4j.Logger import org.apache.spark.SparkConf @@ -272,6 +274,10 @@ object Exchange { val hbaseSourceConfigEntry = config.asInstanceOf[HBaseSourceConfigEntry] val reader = new HBaseReader(session, hbaseSourceConfigEntry) Some(reader.read()) + case SourceCategory.MAXCOMPUTE => + val maxComputeConfigEntry = config.asInstanceOf[MaxComputeConfigEntry] + val reader = new MaxcomputeReader(session, maxComputeConfigEntry) + Some(reader.read()) case _ => { LOG.error(s"Data source ${config.category} not supported") None diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala index 4ad7469..b90ef52 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala @@ -613,10 +613,10 @@ object Configs { case SourceCategory.MAXCOMPUTE => { MaxComputeConfigEntry( SourceCategory.MAXCOMPUTE, - config.getString("table"), - config.getString("project"), config.getString("odpsUrl"), config.getString("tunnelUrl"), + config.getString("table"), + config.getString("project"), config.getString("accessKeyId"), config.getString("accessKeySecret") ) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala index 5f15fa2..a4b2db3 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala @@ -269,7 +269,7 @@ class MaxcomputeReader(override val session: SparkSession, maxComputeConfig: Max override def read(): DataFrame = { val df = session.read - .format("org.apache.spark.aliyun.maxcompute.datasource") + .format("org.apache.spark.aliyun.odps.datasource") .option("odpsUrl", maxComputeConfig.odpsUrl) .option("tunnelUrl", maxComputeConfig.tunnelUrl) .option("table", maxComputeConfig.table) From 013e1047ee06fef579876aa76ccfe92e0f059e34 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 25 Jun 2021 16:44:03 +0800 Subject: [PATCH 151/213] add maxcompute config example --- .../src/main/resources/application.conf | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/nebula-exchange/src/main/resources/application.conf b/nebula-exchange/src/main/resources/application.conf index 66c32d5..ca24298 100644 --- a/nebula-exchange/src/main/resources/application.conf +++ b/nebula-exchange/src/main/resources/application.conf @@ -443,6 +443,29 @@ interval.seconds: 10 } - # + # MaxCompute + { + name: edge-name-7 + type:{ + source:maxcompute + sink:client + } + table:table + project:project + odpsUrl:"http://service.cn-hangzhou.maxcompute.aliyun.com/api" + tunnelUrl:"http://dt.cn-hangzhou.maxcompute.aliyun.com" + accessKeyId:xxx + accessKeySecret:xxx + fields:[maxcompute-field-0, maxcompute-field-1] + nebula.fields:[nebula-field-0, nebula-field-1] + source:{ + field: maxcompute-field-3 + } + target:{ + field: maxcompute-field-3 + } + partition 10 + batch:10 + } ] } From 6e0d467da25e8dc955c9e89a0f5eb5c414b2491c Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 25 Jun 2021 16:48:41 +0800 Subject: [PATCH 152/213] clean dependency --- nebula-exchange/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml index bcd7ec0..87fd936 100644 --- a/nebula-exchange/pom.xml +++ b/nebula-exchange/pom.xml @@ -705,11 +705,6 @@ odps-spark-datasource_2.11 3.3.8-public - - - - - com.aliyun.emr emr-maxcompute_2.11 From 3f10a5514639d70fd6f03b52f6bf2109fc51b692 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 28 Jun 2021 10:39:28 +0800 Subject: [PATCH 153/213] add sentence config to support sql query maxcompute in spark --- nebula-exchange/src/main/resources/application.conf | 8 ++++++-- .../com/vesoft/nebula/exchange/config/Configs.scala | 8 +++++++- .../vesoft/nebula/exchange/config/SourceConfigs.scala | 7 +++---- .../nebula/exchange/reader/ServerBaseReader.scala | 10 ++++++++-- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/nebula-exchange/src/main/resources/application.conf b/nebula-exchange/src/main/resources/application.conf index ca24298..0dc1415 100644 --- a/nebula-exchange/src/main/resources/application.conf +++ b/nebula-exchange/src/main/resources/application.conf @@ -251,10 +251,12 @@ tunnelUrl:"http://dt.cn-hangzhou.maxcompute.aliyun.com" accessKeyId:xxx accessKeySecret:xxx + # maxcompute sql sentence only uses table name. make sure that table name is the same with {table}'s value'. + sentence:"select id, maxcompute-field-0, maxcompute-field-1, maxcompute-field-2 from table where id < 10" fields:[maxcompute-field-0, maxcompute-field-1] nebula.fields:[nebula-field-0, nebula-field-1] vertex:{ - field: maxcompute-field-3 + field: maxcompute-field-2 } partition 10 batch:10 @@ -456,10 +458,12 @@ tunnelUrl:"http://dt.cn-hangzhou.maxcompute.aliyun.com" accessKeyId:xxx accessKeySecret:xxx + # maxcompute sql sentence only uses table name. + sentence:"select * from table" fields:[maxcompute-field-0, maxcompute-field-1] nebula.fields:[nebula-field-0, nebula-field-1] source:{ - field: maxcompute-field-3 + field: maxcompute-field-2 } target:{ field: maxcompute-field-3 diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala index b90ef52..6eb6ac6 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala @@ -611,6 +611,11 @@ object Configs { config.getString("columnFamily"), fields.toSet.toList) case SourceCategory.MAXCOMPUTE => { + val sentence = if (config.hasPath("sentence")) { + config.getString("sentence") + } else { + null + } MaxComputeConfigEntry( SourceCategory.MAXCOMPUTE, config.getString("odpsUrl"), @@ -618,7 +623,8 @@ object Configs { config.getString("table"), config.getString("project"), config.getString("accessKeyId"), - config.getString("accessKeySecret") + config.getString("accessKeySecret"), + sentence ) } case _ => diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala index ec8a65d..fa88d59 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala @@ -228,13 +228,12 @@ case class MaxComputeConfigEntry(override val category: SourceCategory.Value, table: String, project: String, accessKeyId: String, - accessKeySecret: String) - extends ServerDataSourceConfigEntry() { + accessKeySecret: String, + override val sentence: String) + extends ServerDataSourceConfigEntry { require( !odpsUrl.trim.isEmpty && !tunnelUrl.trim.isEmpty && !table.trim.isEmpty && !project.trim.isEmpty && !accessKeyId.trim.isEmpty && !accessKeySecret.trim.isEmpty) - override def sentence: String = null - override def toString: String = { s"MaxCompute source odpsUrl: $odpsUrl, tunnelUrl: $tunnelUrl, table: $table, project: $project, keyId: $accessKeyId, keySecret: $accessKeySecret" } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala index a4b2db3..ef3088a 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala @@ -265,7 +265,7 @@ class HBaseReader(override val session: SparkSession, hbaseConfig: HBaseSourceCo * MaxCompute Reader */ class MaxcomputeReader(override val session: SparkSession, maxComputeConfig: MaxComputeConfigEntry) - extends ServerBaseReader(session, null) { + extends ServerBaseReader(session, maxComputeConfig.sentence) { override def read(): DataFrame = { val df = session.read @@ -277,6 +277,12 @@ class MaxcomputeReader(override val session: SparkSession, maxComputeConfig: Max .option("accessKeyId", maxComputeConfig.accessKeyId) .option("accessKeySecret", maxComputeConfig.accessKeySecret) .load() - df + import session._ + if (maxComputeConfig.sentence == null) { + df + } else { + df.createOrReplaceTempView(s"${maxComputeConfig.table}") + session.sql(maxComputeConfig.sentence) + } } } From fad3fd309e141c11ad5270e5f008de4fc326bb8c Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 29 Jun 2021 11:45:20 +0800 Subject: [PATCH 154/213] support partition config for maxcompute --- nebula-exchange/src/main/resources/application.conf | 2 ++ .../com/vesoft/nebula/exchange/config/Configs.scala | 8 ++++++++ .../vesoft/nebula/exchange/config/SourceConfigs.scala | 8 ++++++-- .../nebula/exchange/reader/ServerBaseReader.scala | 10 ++++++++-- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/nebula-exchange/src/main/resources/application.conf b/nebula-exchange/src/main/resources/application.conf index 0dc1415..d13f17e 100644 --- a/nebula-exchange/src/main/resources/application.conf +++ b/nebula-exchange/src/main/resources/application.conf @@ -251,6 +251,7 @@ tunnelUrl:"http://dt.cn-hangzhou.maxcompute.aliyun.com" accessKeyId:xxx accessKeySecret:xxx + partitionSpec:"dt='partition1'" # maxcompute sql sentence only uses table name. make sure that table name is the same with {table}'s value'. sentence:"select id, maxcompute-field-0, maxcompute-field-1, maxcompute-field-2 from table where id < 10" fields:[maxcompute-field-0, maxcompute-field-1] @@ -458,6 +459,7 @@ tunnelUrl:"http://dt.cn-hangzhou.maxcompute.aliyun.com" accessKeyId:xxx accessKeySecret:xxx + partitionSpec:"dt='partition1'" # maxcompute sql sentence only uses table name. sentence:"select * from table" fields:[maxcompute-field-0, maxcompute-field-1] diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala index 6eb6ac6..78efcd7 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala @@ -611,11 +611,18 @@ object Configs { config.getString("columnFamily"), fields.toSet.toList) case SourceCategory.MAXCOMPUTE => { + val partitionSpec = if (config.hasPath("partitionSpec")) { + config.getString("partitionSpec") + } else { + null + } + val sentence = if (config.hasPath("sentence")) { config.getString("sentence") } else { null } + MaxComputeConfigEntry( SourceCategory.MAXCOMPUTE, config.getString("odpsUrl"), @@ -624,6 +631,7 @@ object Configs { config.getString("project"), config.getString("accessKeyId"), config.getString("accessKeySecret"), + partitionSpec, sentence ) } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala index fa88d59..14fcbe0 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala @@ -229,13 +229,17 @@ case class MaxComputeConfigEntry(override val category: SourceCategory.Value, project: String, accessKeyId: String, accessKeySecret: String, + partitionSpec: String, override val sentence: String) extends ServerDataSourceConfigEntry { require( - !odpsUrl.trim.isEmpty && !tunnelUrl.trim.isEmpty && !table.trim.isEmpty && !project.trim.isEmpty && !accessKeyId.trim.isEmpty && !accessKeySecret.trim.isEmpty) + !odpsUrl.trim.isEmpty && !tunnelUrl.trim.isEmpty && !table.trim.isEmpty && !project.trim.isEmpty + && !accessKeyId.trim.isEmpty && !accessKeySecret.trim.isEmpty) override def toString: String = { - s"MaxCompute source odpsUrl: $odpsUrl, tunnelUrl: $tunnelUrl, table: $table, project: $project, keyId: $accessKeyId, keySecret: $accessKeySecret" + s"MaxCompute source {odpsUrl: $odpsUrl, tunnelUrl: $tunnelUrl, table: $table, project: $project, " + + s"keyId: $accessKeyId, keySecret: $accessKeySecret, partitionSpec:$partitionSpec, " + + s"sentence:$sentence}" } } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala index ef3088a..b56682c 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala @@ -268,7 +268,7 @@ class MaxcomputeReader(override val session: SparkSession, maxComputeConfig: Max extends ServerBaseReader(session, maxComputeConfig.sentence) { override def read(): DataFrame = { - val df = session.read + var dfReader = session.read .format("org.apache.spark.aliyun.odps.datasource") .option("odpsUrl", maxComputeConfig.odpsUrl) .option("tunnelUrl", maxComputeConfig.tunnelUrl) @@ -276,7 +276,13 @@ class MaxcomputeReader(override val session: SparkSession, maxComputeConfig: Max .option("project", maxComputeConfig.project) .option("accessKeyId", maxComputeConfig.accessKeyId) .option("accessKeySecret", maxComputeConfig.accessKeySecret) - .load() + + // if use partition read + if (maxComputeConfig.partitionSpec != null) { + dfReader = dfReader.option("partitionSpec", maxComputeConfig.partitionSpec) + } + + val df = dfReader.load() import session._ if (maxComputeConfig.sentence == null) { df From 69ae829a0371c7b48f1bacc47ce575a7e8be201c Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 17 May 2021 14:55:48 +0800 Subject: [PATCH 155/213] add update mode for connector writer --- .../nebula/connector/NebulaConfig.scala | 60 ++++++++++--- .../vesoft/nebula/connector/NebulaEnum.scala | 7 ++ .../nebula/connector/NebulaOptions.scala | 32 ++++--- .../vesoft/nebula/connector/Template.scala | 4 + .../com/vesoft/nebula/connector/package.scala | 2 + .../connector/writer/NebulaEdgeWriter.scala | 12 ++- .../connector/writer/NebulaExecutor.scala | 50 +++++++++++ .../connector/writer/NebulaVertexWriter.scala | 14 ++- .../writer/NebulaExecutorSuite.scala | 90 +++++++++++++++++++ 9 files changed, 241 insertions(+), 30 deletions(-) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala index ecf6d58..af0d4f0 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala @@ -88,12 +88,17 @@ object NebulaConnectionConfig { /** * Base config needed when write dataframe into nebula graph */ -private[connector] class WriteNebulaConfig(space: String, user: String, passwd: String, batch: Int) +private[connector] class WriteNebulaConfig(space: String, + user: String, + passwd: String, + batch: Int, + writeMode: String) extends Serializable { - def getSpace = space - def getBatch = batch - def getUser = user - def getPasswd = passwd + def getSpace = space + def getBatch = batch + def getUser = user + def getPasswd = passwd + def getWriteMode = writeMode } /** @@ -112,8 +117,9 @@ class WriteNebulaVertexConfig(space: String, batch: Int, vidAsProp: Boolean, user: String, - passwd: String) - extends WriteNebulaConfig(space, user, passwd, batch) { + passwd: String, + writeMode: String) + extends WriteNebulaConfig(space, user, passwd, batch, writeMode) { def getTagName = tagName def getVidField = vidField def getVidPolicy = if (vidPolicy == null) "" else vidPolicy @@ -136,6 +142,7 @@ object WriteNebulaVertexConfig { var batch: Int = 1000 var user: String = "root" var passwd: String = "nebula" + var writeMode: String = "insert" /** whether set vid as property */ var vidAsProp: Boolean = false @@ -190,6 +197,11 @@ object WriteNebulaVertexConfig { this } + def withWriteMode(writeMode: String): WriteVertexConfigBuilder = { + this.writeMode = writeMode + this + } + def build(): WriteNebulaVertexConfig = { check() new WriteNebulaVertexConfig(space, @@ -199,7 +211,8 @@ object WriteNebulaVertexConfig { batch, vidAsProp, user, - passwd) + passwd, + writeMode) } private def check(): Unit = { @@ -213,8 +226,14 @@ object WriteNebulaVertexConfig { || vidPolicy.equalsIgnoreCase(KeyPolicy.UUID.toString), "config vidPolicy is illegal, please don't set vidPolicy or set vidPolicy \"HASH\" or \"UUID\"" ) + try { + WriteMode.withName(writeMode.toLowerCase()) + } catch { + case e: Throwable => + assert(false, s"optional write mode: insert or update, your write mode is $writeMode") + } LOG.info( - s"NebulaWriteVertexConfig={space=$space,tagName=$tagName,vidField=$vidField,vidPolicy=$vidPolicy,batch=$batch}") + s"NebulaWriteVertexConfig={space=$space,tagName=$tagName,vidField=$vidField,vidPolicy=$vidPolicy,batch=$batch,writeMode=$writeMode}") } } @@ -247,8 +266,9 @@ class WriteNebulaEdgeConfig(space: String, dstAsProp: Boolean, rankAsProp: Boolean, user: String, - passwd: String) - extends WriteNebulaConfig(space, user, passwd, batch) { + passwd: String, + writeMode: String) + extends WriteNebulaConfig(space, user, passwd, batch, writeMode) { def getEdgeName = edgeName def getSrcFiled = srcFiled def getSrcPolicy = if (srcPolicy == null) "" else srcPolicy @@ -292,6 +312,8 @@ object WriteNebulaEdgeConfig { /** whether set rank as property */ var rankAsProp: Boolean = false + var writeMode: String = WriteMode.INSERT.toString + def withSpace(space: String): WriteEdgeConfigBuilder = { this.space = space this @@ -379,6 +401,11 @@ object WriteNebulaEdgeConfig { this } + def withWriteMode(writeMode: String): WriteEdgeConfigBuilder = { + this.writeMode = writeMode + this + } + def build(): WriteNebulaEdgeConfig = { check() new WriteNebulaEdgeConfig(space, @@ -393,7 +420,8 @@ object WriteNebulaEdgeConfig { dstAsProp, rankAsProp, user, - passwd) + passwd, + writeMode) } private def check(): Unit = { @@ -414,8 +442,14 @@ object WriteNebulaEdgeConfig { "config dstPolicy is illegal, please don't set dstPolicy or set dstPolicy \"HASH\" or \"UUID\"" ) assert(batch > 0, s"config batch must be positive, your batch is $batch.") + try { + WriteMode.withName(writeMode.toLowerCase) + } catch { + case e: Throwable => + assert(false, s"optional write mode: insert or update, your write mode is $writeMode") + } LOG.info( - s"NebulaWriteEdgeConfig={space=$space,edgeName=$edgeName,srcField=$srcIdField,srcPolicy=$srcPolicy,dstField=$dstIdField,dstPolicy=$dstPolicy,rankField=$rankField}") + s"NebulaWriteEdgeConfig={space=$space,edgeName=$edgeName,srcField=$srcIdField,srcPolicy=$srcPolicy,dstField=$dstIdField,dstPolicy=$dstPolicy,rankField=$rankField,writeMode=$writeMode}") } } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaEnum.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaEnum.scala index d39203f..4bf8366 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaEnum.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaEnum.scala @@ -30,3 +30,10 @@ object OperaType extends Enumeration { val READ = Value("read") val WRITE = Value("write") } + +object WriteMode extends Enumeration { + + type Mode = Value + val INSERT = Value("insert") + val UPDATE = Value("update") +} diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaOptions.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaOptions.scala index f1eb17b..4063501 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaOptions.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaOptions.scala @@ -93,19 +93,20 @@ class NebulaOptions(@transient val parameters: CaseInsensitiveMap[String])( } /** write parameters */ - var graphAddress: String = _ - var vidPolicy: String = _ - var srcPolicy: String = _ - var dstPolicy: String = _ - var vertexField: String = _ - var srcVertexField: String = _ - var dstVertexField: String = _ - var rankField: String = _ - var batch: Int = _ - var vidAsProp: Boolean = _ - var srcAsProp: Boolean = _ - var dstAsProp: Boolean = _ - var rankAsProp: Boolean = _ + var graphAddress: String = _ + var vidPolicy: String = _ + var srcPolicy: String = _ + var dstPolicy: String = _ + var vertexField: String = _ + var srcVertexField: String = _ + var dstVertexField: String = _ + var rankField: String = _ + var batch: Int = _ + var vidAsProp: Boolean = _ + var srcAsProp: Boolean = _ + var dstAsProp: Boolean = _ + var rankAsProp: Boolean = _ + var writeMode: WriteMode.Value = _ if (operaType == OperaType.WRITE) { require(parameters.isDefinedAt(GRAPH_ADDRESS), @@ -139,6 +140,8 @@ class NebulaOptions(@transient val parameters: CaseInsensitiveMap[String])( srcAsProp = parameters.getOrElse(SRC_AS_PROP, false).toString.toBoolean dstAsProp = parameters.getOrElse(DST_AS_PROP, false).toString.toBoolean rankAsProp = parameters.getOrElse(RANK_AS_PROP, false).toString.toBoolean + writeMode = + WriteMode.withName(parameters.getOrElse(WRITE_MODE, DEFAULT_WRITE_MODE).toString.toLowerCase) } def getReturnCols: List[String] = { @@ -215,6 +218,7 @@ object NebulaOptions { val SRC_AS_PROP: String = "srcAsProp" val DST_AS_PROP: String = "dstAsProp" val RANK_AS_PROP: String = "rankAsProp" + val WRITE_MODE: String = "writeMode" val DEFAULT_TIMEOUT: Int = 3000 val DEFAULT_CONNECTION_TIMEOUT: Int = 3000 @@ -230,5 +234,7 @@ object NebulaOptions { val DEFAULT_POLICY: String = null val DEFAULT_BATCH: Int = 1000 + val DEFAULT_WRITE_MODE = WriteMode.INSERT + val EMPTY_STRING: String = "" } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala index ba8c28d..c9dc3a0 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala @@ -15,4 +15,8 @@ object NebulaTemplate { private[connector] val EDGE_VALUE_WITHOUT_RANKING_TEMPLATE = "%s->%s: (%s)" private[connector] val EDGE_VALUE_TEMPLATE = "%s->%s@%d: (%s)" private[connector] val USE_TEMPLATE = "USE %s" + + private[connector] val UPDATE_VERTEX_TEMPLATE = "UPDATE %s ON %s %s SET %s;" + private[connector] val UPDATE_EDGE_TEMPLATE = "UPDATE %s ON %s %s->%s@%d SET %s;" + private[connector] val UPDATE_VALUE_TEMPLATE = "%s=%s" } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala index 119cca7..5085f23 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala @@ -257,6 +257,7 @@ package object connector { .option(NebulaOptions.VID_POLICY, writeConfig.getVidPolicy) .option(NebulaOptions.BATCH, writeConfig.getBatch) .option(NebulaOptions.VID_AS_PROP, writeConfig.getVidAsProp) + .option(NebulaOptions.WRITE_MODE, writeConfig.getWriteMode) .option(NebulaOptions.META_ADDRESS, connectionConfig.getMetaAddress) .option(NebulaOptions.GRAPH_ADDRESS, connectionConfig.getGraphAddress) .option(NebulaOptions.TIMEOUT, connectionConfig.getTimeout) @@ -290,6 +291,7 @@ package object connector { .option(NebulaOptions.SRC_AS_PROP, writeConfig.getSrcAsProp) .option(NebulaOptions.DST_AS_PROP, writeConfig.getDstAsProp) .option(NebulaOptions.RANK_AS_PROP, writeConfig.getRankAsProp) + .option(NebulaOptions.WRITE_MODE, writeConfig.getWriteMode) .option(NebulaOptions.META_ADDRESS, connectionConfig.getMetaAddress) .option(NebulaOptions.GRAPH_ADDRESS, connectionConfig.getGraphAddress) .option(NebulaOptions.TIMEOUT, connectionConfig.getTimeout) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala index 1f1be2a..cde3b7f 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala @@ -7,7 +7,7 @@ package com.vesoft.nebula.connector.writer import com.vesoft.nebula.connector.connector.{NebulaEdge, NebulaEdges} -import com.vesoft.nebula.connector.{KeyPolicy, NebulaOptions} +import com.vesoft.nebula.connector.{KeyPolicy, NebulaOptions, WriteMode} import org.apache.spark.sql.catalyst.InternalRow import org.apache.spark.sql.sources.v2.writer.{DataWriter, WriterCommitMessage} import org.apache.spark.sql.types.StructType @@ -76,7 +76,15 @@ class NebulaEdgeWriter(nebulaOptions: NebulaOptions, def execute(): Unit = { val nebulaEdges = NebulaEdges(propNames, edges.toList, srcPolicy, dstPolicy) - val exec = NebulaExecutor.toExecuteSentence(nebulaOptions.label, nebulaEdges) + val exec = if (nebulaOptions.writeMode == WriteMode.INSERT) { + NebulaExecutor.toExecuteSentence(nebulaOptions.label, nebulaEdges) + } else { + nebulaEdges.values + .map { edge => + NebulaExecutor.toUpdateExecuteStatement(nebulaOptions.label, nebulaEdges.propNames, edge) + } + .mkString(";") + } edges.clear() submit(exec) } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala index fed688b..c02c336 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala @@ -11,12 +11,17 @@ import com.vesoft.nebula.connector.NebulaTemplate.{ EDGE_VALUE_TEMPLATE, EDGE_VALUE_WITHOUT_RANKING_TEMPLATE, ENDPOINT_TEMPLATE, + UPDATE_EDGE_TEMPLATE, + UPDATE_VALUE_TEMPLATE, + UPDATE_VERTEX_TEMPLATE, VERTEX_VALUE_TEMPLATE, VERTEX_VALUE_TEMPLATE_WITH_POLICY } import com.vesoft.nebula.connector.connector.{ EdgeRank, + NebulaEdge, NebulaEdges, + NebulaVertex, NebulaVertices, PropertyNames, PropertyValues @@ -26,6 +31,7 @@ import com.vesoft.nebula.meta.PropertyType import org.apache.spark.sql.catalyst.InternalRow import org.apache.spark.sql.types.StructType +import scala.collection.JavaConversions.seqAsJavaList import scala.collection.mutable.ListBuffer object NebulaExecutor { @@ -264,6 +270,50 @@ object NebulaExecutor { BATCH_INSERT_TEMPLATE.format(DataTypeEnum.EDGE.toString, edgeName, edges.propertyNames, values) } + /** + * construct update statement for vertex + */ + def toUpdateExecuteStatement(tagName: String, + propertyNames: PropertyNames, + vertex: NebulaVertex): String = { + var index = 0 + UPDATE_VERTEX_TEMPLATE.format( + DataTypeEnum.VERTEX.toString.toUpperCase, + tagName, + vertex.vertexIDSlice, + vertex.values + .map { value => + val updateValue = UPDATE_VALUE_TEMPLATE.format(propertyNames.get(index), value) + index += 1 + updateValue + } + .mkString(",") + ) + } + + /** + * construct update statement for edge + */ + def toUpdateExecuteStatement(edgeName: String, + propertyNames: PropertyNames, + edge: NebulaEdge): String = { + var index = 0 + UPDATE_EDGE_TEMPLATE.format( + DataTypeEnum.EDGE.toString.toUpperCase, + edgeName, + edge.source, + edge.target, + edge.rank.get, + edge.values + .map { value => + val updateValue = UPDATE_VALUE_TEMPLATE.format(propertyNames.get(index), value) + index += 1 + updateValue + } + .mkString(",") + ) + } + /** * escape nebula property name, add `` for each property. * diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala index ce20ded..1039e91 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala @@ -7,7 +7,7 @@ package com.vesoft.nebula.connector.writer import com.vesoft.nebula.connector.connector.{NebulaVertex, NebulaVertices} -import com.vesoft.nebula.connector.{KeyPolicy, NebulaOptions} +import com.vesoft.nebula.connector.{KeyPolicy, NebulaOptions, WriteMode} import org.apache.spark.sql.catalyst.InternalRow import org.apache.spark.sql.sources.v2.writer.{DataWriter, WriterCommitMessage} import org.apache.spark.sql.types.StructType @@ -54,7 +54,17 @@ class NebulaVertexWriter(nebulaOptions: NebulaOptions, vertexIndex: Int, schema: def execute(): Unit = { val nebulaVertices = NebulaVertices(propNames, vertices.toList, policy) - val exec = NebulaExecutor.toExecuteSentence(nebulaOptions.label, nebulaVertices) + val exec = if (nebulaOptions.writeMode == WriteMode.INSERT) { + NebulaExecutor.toExecuteSentence(nebulaOptions.label, nebulaVertices) + } else { + nebulaVertices.values + .map { vertex => + NebulaExecutor.toUpdateExecuteStatement(nebulaOptions.label, + nebulaVertices.propNames, + vertex) + } + .mkString(";") + } vertices.clear() submit(exec) } diff --git a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala index 8a941ce..c33f145 100644 --- a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala +++ b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala @@ -7,6 +7,8 @@ package com.vesoft.nebula.connector.writer import com.vesoft.nebula.connector.KeyPolicy +import com.vesoft.nebula.connector.connector.{NebulaEdge, NebulaEdges, NebulaVertex, NebulaVertices} +import org.apache.spark.api.java.Optional import org.apache.spark.sql.catalyst.InternalRow import org.apache.spark.sql.catalyst.expressions.GenericInternalRow import org.apache.spark.sql.types.{ @@ -119,4 +121,92 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { assert(propNames1.isEmpty) } + test("test toExecuteSentence for vertex") { + val vertices: ListBuffer[NebulaVertex] = new ListBuffer[NebulaVertex] + val tagName = "person" + val propNames = List("col_string", + "col_fixed_string", + "col_bool", + "col_int", + "col_int64", + "col_double", + "col_date") + + val props1 = List("\"Tom\"", "\"Tom\"", true, 10, 100L, 1.0, "2021-11-12") + val props2 = List("\"Bob\"", "\"Bob\"", false, 20, 200L, 2.0, "2021-05-01") + vertices.append(NebulaVertex("\"vid1\"", props1)) + vertices.append(NebulaVertex("\"vid2\"", props2)) + + val nebulaVertices = NebulaVertices(propNames, vertices.toList, None) + val vertexStatement = NebulaExecutor.toExecuteSentence(tagName, nebulaVertices) + + val expectStatement = "INSERT vertex `person`(`col_string`,`col_fixed_string`,`col_bool`," + + "`col_int`,`col_int64`,`col_double`,`col_date`) VALUES \"vid1\": (" + props1.mkString(", ") + + "), \"vid2\": (" + props2.mkString(", ") + ")" + assert(expectStatement.equals(vertexStatement)) + } + + test("test toExecuteSentence for edge") { + val edges: ListBuffer[NebulaEdge] = new ListBuffer[NebulaEdge] + val edgeName = "friend" + val propNames = List("col_string", + "col_fixed_string", + "col_bool", + "col_int", + "col_int64", + "col_double", + "col_date") + val props1 = List("\"Tom\"", "\"Tom\"", true, 10, 100L, 1.0, "2021-11-12") + val props2 = List("\"Bob\"", "\"Bob\"", false, 20, 200L, 2.0, "2021-05-01") + edges.append(NebulaEdge("\"vid1\"", "\"vid2\"", Some(1L), props1)) + edges.append(NebulaEdge("\"vid2\"", "\"vid1\"", Some(2L), props2)) + + val nebulaEdges = NebulaEdges(propNames, edges.toList, None, None) + val edgeStatement = NebulaExecutor.toExecuteSentence(edgeName, nebulaEdges) + + val expectStatement = "INSERT edge `friend`(`col_string`,`col_fixed_string`,`col_bool`,`col_int`" + + ",`col_int64`,`col_double`,`col_date`) VALUES \"vid1\"->\"vid2\"@1: (" + props1.mkString(", ") + + "), \"vid2\"->\"vid1\"@2: (" + props2.mkString(", ") + ")" + assert(expectStatement.equals(edgeStatement)) + } + + test("test toUpdateExecuteSentence for vertex") { + val props = List("\"name\"", "\"name\"", true, 10, 100L, 1.0, "2021-11-12") + val propNames = List("col_string", + "col_fixed_string", + "col_bool", + "col_int", + "col_int64", + "col_double", + "col_date") + + val vertexId = "\"vid1\"" + val nebulaVertex = NebulaVertex(vertexId, props) + val updateVertexStatement = + NebulaExecutor.toUpdateExecuteStatement("person", propNames, nebulaVertex) + val expectVertexUpdate = + "UPDATE VERTEX ON person \"vid1\" SET col_string=\"name\",col_fixed_string=\"name\",col_bool=true,col_int=10,col_int64=100,col_double=1.0,col_date=2021-11-12;" + assert(expectVertexUpdate.equals(updateVertexStatement)) + } + + test("test toUpdateExecuteSentence for edge") { + val props = List("\"name\"", "\"name\"", true, 10, 100L, 1.0, "2021-11-12") + val propNames = List("col_string", + "col_fixed_string", + "col_bool", + "col_int", + "col_int64", + "col_double", + "col_date") + + val source = "\"source\"" + val target = "\"target\"" + val rank = Some(0L) + val nebulaEdge = NebulaEdge(source, target, rank, props) + val updateEdgeStatement = + NebulaExecutor.toUpdateExecuteStatement("friend", propNames, nebulaEdge) + val expectEdgeUpdate = + "UPDATE EDGE ON friend \"source\"->\"target\"@0 SET col_string=\"name\",col_fixed_string=\"name\",col_bool=true,col_int=10,col_int64=100,col_double=1.0,col_date=2021-11-12;" + assert(expectEdgeUpdate.equals(updateEdgeStatement)) + } } From 417205058f47fb126aa5c7608cbd592a09182bf3 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 17 May 2021 15:36:41 +0800 Subject: [PATCH 156/213] update vertex example data --- example/src/main/resources/vertex | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/example/src/main/resources/vertex b/example/src/main/resources/vertex index 7694dac..f66c62f 100644 --- a/example/src/main/resources/vertex +++ b/example/src/main/resources/vertex @@ -1,10 +1,10 @@ -{"id":"aa","name":"Tom","age":10,"timep": "2020-01-01"} -{"id":"\ns","name":"Bob","age":11,"timep": "2020-01-02"} -{"id":14,"name":"Jane","age":12,"timep": "2020-01-03"} -{"id":15,"name":"Jena","age":13,"timep": "2020-01-04"} -{"id":16,"name":"Ni\tc","age":14,"timep": "2020-01-05"} -{"id":17,"name":"Mei","age":15,"timep": "2020-01-06"} -{"id":18,"name":"HH","age":16,"timep": "2020-01-07"} -{"id":19,"name":"Ty\nler","age":17,"timep": "2020-01-08"} -{"id":20,"name":"Ber","age":18,"timep": "2020-01-09"} -{"id":21,"name":"Mercy","age":19,"timep": "2020-01-10"} \ No newline at end of file +{"id":12,"name":"Tom","age":20,"born": "2000-01-01"} +{"id":13,"name":"Bob","age":21,"born": "1999-01-02"} +{"id":14,"name":"Jane","age":22,"born": "1998-01-03"} +{"id":15,"name":"Jena","age":23,"born": "1997-01-04"} +{"id":16,"name":"Nic","age":24,"born": "1996-01-05"} +{"id":17,"name":"Mei","age":25,"born": "1995-01-06"} +{"id":18,"name":"HH","age":26,"born": "1994-01-07"} +{"id":19,"name":"Tyler","age":27,"born": "1993-01-08"} +{"id":20,"name":"Ber","age":28,"born": "1992-01-09"} +{"id":21,"name":"Mercy","age":29,"born": "1991-01-10"} \ No newline at end of file From 2bd0858fe547198c7c9ab88399b2d14629d7a6c1 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 25 May 2021 19:43:50 +0800 Subject: [PATCH 157/213] add example for update mode --- .../connector/NebulaSparkWriterExample.scala | 84 +++++++++++++++++-- 1 file changed, 79 insertions(+), 5 deletions(-) diff --git a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala index c3dc75f..e669e91 100644 --- a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala +++ b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala @@ -36,10 +36,17 @@ object NebulaSparkWriterExample { writeVertex(spark) writeEdge(spark) + updateVertex(spark) + updateEdge(spark) + spark.close() sys.exit() } + /** + * for this example, your nebula tag schema should have property names: name, age, born + * if your withVidAsProp is true, then tag schema also should have property name: id + */ def writeVertex(spark: SparkSession): Unit = { LOG.info("start to write nebula vertices") val df = spark.read.json("example/src/main/resources/vertex") @@ -57,12 +64,18 @@ object NebulaSparkWriterExample { .withSpace("test") .withTag("person") .withVidField("id") - .withVidAsProp(true) + .withVidAsProp(false) .withBatch(1000) .build() df.write.nebula(config, nebulaWriteVertexConfig).writeVertices() } + /** + * for this example, your nebula edge schema should have property names: descr, timp + * if your withSrcAsProperty is true, then edge schema also should have property name: src + * if your withDstAsProperty is true, then edge schema also should have property name: dst + * if your withRankAsProperty is true, then edge schema also should have property name: degree + */ def writeEdge(spark: SparkSession): Unit = { LOG.info("start to write nebula edges") val df = spark.read.json("example/src/main/resources/edge") @@ -74,7 +87,67 @@ object NebulaSparkWriterExample { .builder() .withMetaAddress("127.0.0.1:9559") .withGraphAddress("127.0.0.1:9669") - .build + .build() + val nebulaWriteEdgeConfig: WriteNebulaEdgeConfig = WriteNebulaEdgeConfig + .builder() + .withSpace("test") + .withEdge("friend") + .withSrcIdField("src") + .withDstIdField("dst") + .withRankField("degree") + .withSrcAsProperty(false) + .withDstAsProperty(false) + .withRankAsProperty(false) + .withBatch(1000) + .build() + df.write.nebula(config, nebulaWriteEdgeConfig).writeEdges() + } + + /** + * We only update property that exists in DataFrame. For this example, update property `name`. + */ + def updateVertex(spark: SparkSession): Unit = { + LOG.info("start to write nebula vertices") + val df = spark.read.json("example/src/main/resources/vertex").select("id", "age") + df.show() + + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:9559") + .withGraphAddress("127.0.0.1:9669") + .withConenctionRetry(2) + .build() + val nebulaWriteVertexConfig: WriteNebulaVertexConfig = WriteNebulaVertexConfig + .builder() + .withSpace("test") + .withTag("person") + .withVidField("id") + .withVidAsProp(false) + .withBatch(1000) + .withWriteMode("update") + .build() + df.write.nebula(config, nebulaWriteVertexConfig).writeVertices() + } + + /** + * we only update property that exists in DataFrame. For this example, we only update property `descr`. + * if withRankField is not set when execute {@link writeEdge}, then don't set it too in this example. + */ + def updateEdge(spark: SparkSession): Unit = { + LOG.info("start to write nebula edges") + val df = spark.read + .json("example/src/main/resources/edge") + .select("src", "dst", "degree", "descr") + df.show() + df.persist(StorageLevel.MEMORY_AND_DISK_SER) + + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:9559") + .withGraphAddress("127.0.0.1:9669") + .build() val nebulaWriteEdgeConfig: WriteNebulaEdgeConfig = WriteNebulaEdgeConfig .builder() .withSpace("test") @@ -82,10 +155,11 @@ object NebulaSparkWriterExample { .withSrcIdField("src") .withDstIdField("dst") .withRankField("degree") - .withSrcAsProperty(true) - .withDstAsProperty(true) - .withRankAsProperty(true) + .withSrcAsProperty(false) + .withDstAsProperty(false) + .withRankAsProperty(false) .withBatch(1000) + .withWriteMode("update") .build() df.write.nebula(config, nebulaWriteEdgeConfig).writeEdges() } From a970945925570f536ca21b3b39608e14f6008be9 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 30 Jun 2021 09:55:42 +0800 Subject: [PATCH 158/213] add escape for tag/edge/property name --- .../main/scala/com/vesoft/nebula/connector/Template.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala index c9dc3a0..73639e2 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala @@ -16,7 +16,7 @@ object NebulaTemplate { private[connector] val EDGE_VALUE_TEMPLATE = "%s->%s@%d: (%s)" private[connector] val USE_TEMPLATE = "USE %s" - private[connector] val UPDATE_VERTEX_TEMPLATE = "UPDATE %s ON %s %s SET %s;" - private[connector] val UPDATE_EDGE_TEMPLATE = "UPDATE %s ON %s %s->%s@%d SET %s;" - private[connector] val UPDATE_VALUE_TEMPLATE = "%s=%s" + private[connector] val UPDATE_VERTEX_TEMPLATE = "UPDATE %s ON `%s` %s SET %s;" + private[connector] val UPDATE_EDGE_TEMPLATE = "UPDATE %s ON `%s` %s->%s@%d SET %s;" + private[connector] val UPDATE_VALUE_TEMPLATE = "`%s`=%s" } From c1ae08cd946cb15742ac4d503ca1e421d90f0d73 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 30 Jun 2021 09:56:03 +0800 Subject: [PATCH 159/213] modify entry parameter to Enum --- .../scala/com/vesoft/nebula/connector/NebulaConfig.scala | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala index af0d4f0..f20d58a 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala @@ -197,8 +197,8 @@ object WriteNebulaVertexConfig { this } - def withWriteMode(writeMode: String): WriteVertexConfigBuilder = { - this.writeMode = writeMode + def withWriteMode(writeMode: WriteMode.Value): WriteVertexConfigBuilder = { + this.writeMode = writeMode.toString this } @@ -401,8 +401,8 @@ object WriteNebulaEdgeConfig { this } - def withWriteMode(writeMode: String): WriteEdgeConfigBuilder = { - this.writeMode = writeMode + def withWriteMode(writeMode: WriteMode.Value): WriteEdgeConfigBuilder = { + this.writeMode = writeMode.toString this } From 07f3beae0d0d0a28c43135c95e1a866cae545be3 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 30 Jun 2021 09:56:15 +0800 Subject: [PATCH 160/213] update ut --- .../nebula/connector/writer/NebulaExecutorSuite.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala index c33f145..b940082 100644 --- a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala +++ b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala @@ -185,7 +185,8 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { val updateVertexStatement = NebulaExecutor.toUpdateExecuteStatement("person", propNames, nebulaVertex) val expectVertexUpdate = - "UPDATE VERTEX ON person \"vid1\" SET col_string=\"name\",col_fixed_string=\"name\",col_bool=true,col_int=10,col_int64=100,col_double=1.0,col_date=2021-11-12;" + "UPDATE VERTEX ON `person` \"vid1\" SET `col_string`=\"name\",`col_fixed_string`=\"name\"," + + "`col_bool`=true,`col_int`=10,`col_int64`=100,`col_double`=1.0,`col_date`=2021-11-12;" assert(expectVertexUpdate.equals(updateVertexStatement)) } @@ -206,7 +207,9 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { val updateEdgeStatement = NebulaExecutor.toUpdateExecuteStatement("friend", propNames, nebulaEdge) val expectEdgeUpdate = - "UPDATE EDGE ON friend \"source\"->\"target\"@0 SET col_string=\"name\",col_fixed_string=\"name\",col_bool=true,col_int=10,col_int64=100,col_double=1.0,col_date=2021-11-12;" + "UPDATE EDGE ON `friend` \"source\"->\"target\"@0 SET `col_string`=\"name\"," + + "`col_fixed_string`=\"name\",`col_bool`=true,`col_int`=10,`col_int64`=100," + + "`col_double`=1.0,`col_date`=2021-11-12;" assert(expectEdgeUpdate.equals(updateEdgeStatement)) } } From 02ddc8540cc0164bb180064e120a4c511e0f5b92 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 30 Jun 2021 09:56:42 +0800 Subject: [PATCH 161/213] update example with writeMode --- .../examples/connector/NebulaSparkWriterExample.scala | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala index e669e91..22319de 100644 --- a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala +++ b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala @@ -9,6 +9,7 @@ package com.vesoft.nebula.examples.connector import com.facebook.thrift.protocol.TCompactProtocol import com.vesoft.nebula.connector.{ NebulaConnectionConfig, + WriteMode, WriteNebulaEdgeConfig, WriteNebulaVertexConfig } @@ -33,11 +34,11 @@ object NebulaSparkWriterExample { .config(sparkConf) .getOrCreate() - writeVertex(spark) - writeEdge(spark) +// writeVertex(spark) +// writeEdge(spark) updateVertex(spark) - updateEdge(spark) + //updateEdge(spark) spark.close() sys.exit() @@ -125,7 +126,7 @@ object NebulaSparkWriterExample { .withVidField("id") .withVidAsProp(false) .withBatch(1000) - .withWriteMode("update") + .withWriteMode(WriteMode.UPDATE) .build() df.write.nebula(config, nebulaWriteVertexConfig).writeVertices() } @@ -159,7 +160,7 @@ object NebulaSparkWriterExample { .withDstAsProperty(false) .withRankAsProperty(false) .withBatch(1000) - .withWriteMode("update") + .withWriteMode(WriteMode.UPDATE) .build() df.write.nebula(config, nebulaWriteEdgeConfig).writeEdges() } From 511ce433a48c4152362bc3ea05aed80e9ad2fe6e Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 30 Jun 2021 10:35:53 +0800 Subject: [PATCH 162/213] remove ; for template --- .../src/main/scala/com/vesoft/nebula/connector/Template.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala index 73639e2..0f1f911 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala @@ -16,7 +16,7 @@ object NebulaTemplate { private[connector] val EDGE_VALUE_TEMPLATE = "%s->%s@%d: (%s)" private[connector] val USE_TEMPLATE = "USE %s" - private[connector] val UPDATE_VERTEX_TEMPLATE = "UPDATE %s ON `%s` %s SET %s;" - private[connector] val UPDATE_EDGE_TEMPLATE = "UPDATE %s ON `%s` %s->%s@%d SET %s;" + private[connector] val UPDATE_VERTEX_TEMPLATE = "UPDATE %s ON `%s` %s SET %s" + private[connector] val UPDATE_EDGE_TEMPLATE = "UPDATE %s ON `%s` %s->%s@%d SET %s" private[connector] val UPDATE_VALUE_TEMPLATE = "`%s`=%s" } From b8e09b9ad0203518cb30efdac4a6056262a01c0a Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 16 Jun 2021 19:14:40 +0800 Subject: [PATCH 163/213] clean the error path before reload --- .../vesoft/nebula/exchange/ErrorHandler.scala | 12 ++++++ .../exchange/processor/ReloadProcessor.scala | 37 +++++++++++++------ .../exchange/writer/ServerBaseWriter.scala | 18 +++++++++ 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala index 056d654..dfdd44a 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala @@ -11,6 +11,18 @@ import org.apache.hadoop.fs.{FileSystem, Path} import scala.collection.mutable.ArrayBuffer object ErrorHandler { + + /** + * clean all the failed data for error path before reload. + */ + def clear(path: String): Unit = { + val fileSystem = FileSystem.get(new Configuration()) + fileSystem.removeAcl(new Path(path)) + } + + /** + * save the failed execute statement. + */ def save(buffer: ArrayBuffer[String], path: String): Unit = { val fileSystem = FileSystem.get(new Configuration()) val errors = fileSystem.create(new Path(path)) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala index 2bc353b..b91d809 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala @@ -8,6 +8,8 @@ package com.vesoft.nebula.exchange.processor import com.vesoft.nebula.exchange.{ErrorHandler, GraphProvider} import com.vesoft.nebula.exchange.config.Configs +import com.vesoft.nebula.exchange.writer.NebulaGraphClientWriter +import org.apache.log4j.Logger import org.apache.spark.TaskContext import org.apache.spark.sql.{DataFrame, Row} import org.apache.spark.util.LongAccumulator @@ -19,6 +21,7 @@ class ReloadProcessor(data: DataFrame, batchSuccess: LongAccumulator, batchFailure: LongAccumulator) extends Processor { + private val LOG = Logger.getLogger(this.getClass) override def process(): Unit = { data.foreachPartition(processEachPartition(_)) @@ -27,27 +30,37 @@ class ReloadProcessor(data: DataFrame, private def processEachPartition(iterator: Iterator[Row]): Unit = { val graphProvider = new GraphProvider(config.databaseConfig.getGraphAddress, config.connectionConfig.timeout) - val session = graphProvider.getGraphClient(config.userConfig) - if (session == null) { - throw new IllegalArgumentException("connect to graph failed.") - } + + val writer = new NebulaGraphClientWriter(config.databaseConfig, + config.userConfig, + config.rateConfig, + null, + graphProvider) val errorBuffer = ArrayBuffer[String]() + ErrorHandler.clear(config.errorConfig.errorPath) - iterator.foreach(row => { - val exec = row.getString(0) - val result = session.execute(exec) - if (result == null || !result.isSucceeded) { - errorBuffer.append(exec) - batchFailure.add(1) - } else { + writer.prepare() + // batch write tags + val startTime = System.currentTimeMillis + iterator.foreach { row => + val failStatement = writer.writeNgql(row.getString(0)) + if (failStatement == null) { batchSuccess.add(1) + } else { + errorBuffer.append(failStatement) + batchFailure.add(1) } - }) + } if (errorBuffer.nonEmpty) { ErrorHandler.save(errorBuffer, s"${config.errorConfig.errorPath}/reload.${TaskContext.getPartitionId()}") errorBuffer.clear() } + LOG.info( + s"spark partition for vertex reload time:" + + s"${TaskContext.getPartitionId()}-${System.currentTimeMillis() - startTime}") + writer.close() + graphProvider.close() } } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala index be25ba5..cd67463 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala @@ -111,6 +111,8 @@ abstract class ServerBaseWriter extends Writer { def writeVertices(vertices: Vertices): String def writeEdges(edges: Edges): String + + def writeNgql(ngql: String): String } /** @@ -173,6 +175,20 @@ class NebulaGraphClientWriter(dataBaseConfigEntry: DataBaseConfigEntry, sentence } + override def writeNgql(ngql: String): String = { + if (rateLimiter.tryAcquire(rateConfig.timeout, TimeUnit.MILLISECONDS)) { + val result = graphProvider.submit(session, ngql) + if (result.isSucceeded) { + return null + } + LOG.error(s"rewrite ngql failed for ${result.getErrorMessage}") + } else { + LOG.error(s"rewrite ngql failed because write speed is too fast") + } + LOG.info(ngql) + ngql + } + override def close(): Unit = { graphProvider.releaseGraphClient(session) } @@ -241,5 +257,7 @@ class NebulaStorageClientWriter(addresses: List[(String, Int)], space: String) override def writeEdges(edges: Edges): String = ??? + override def writeNgql(ngql: String): String = ??? + override def close(): Unit = {} } From b088ec35ab9550dc311adc596e8f348ca1126b03 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 25 Jun 2021 16:42:12 +0800 Subject: [PATCH 164/213] add more comment --- .../main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala index dfdd44a..7a27440 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala @@ -37,6 +37,9 @@ object ErrorHandler { } } + /** + * check if path exists + */ def existError(path: String): Boolean = { val fileSystem = FileSystem.get(new Configuration()) fileSystem.exists(new Path(path)) From 1af6bdea2b1bcb94815ea35212a57750e946d985 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 30 Jun 2021 15:22:20 +0800 Subject: [PATCH 165/213] optimize reload --- .../src/main/resources/application.conf | 4 ++-- .../vesoft/nebula/exchange/ErrorHandler.scala | 21 +++++++++++++++++-- .../com/vesoft/nebula/exchange/Exchange.scala | 10 +++++++-- .../exchange/processor/EdgeProcessor.scala | 5 ++--- .../exchange/processor/ReloadProcessor.scala | 12 +++++------ .../processor/VerticesProcessor.scala | 5 ++--- .../exchange/writer/ServerBaseWriter.scala | 4 ++-- 7 files changed, 41 insertions(+), 20 deletions(-) diff --git a/nebula-exchange/src/main/resources/application.conf b/nebula-exchange/src/main/resources/application.conf index a64d625..288b34c 100644 --- a/nebula-exchange/src/main/resources/application.conf +++ b/nebula-exchange/src/main/resources/application.conf @@ -39,8 +39,8 @@ graph:["127.0.0.1:9669"] meta:["127.0.0.1:9559"] } - user: user - pswd: password + user: root + pswd: nebula space: test # parameters for SST import, not required diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala index 7a27440..8803544 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala @@ -6,8 +6,11 @@ package com.vesoft.nebula.exchange +import java.io.File + import org.apache.hadoop.conf.Configuration import org.apache.hadoop.fs.{FileSystem, Path} + import scala.collection.mutable.ArrayBuffer object ErrorHandler { @@ -16,8 +19,22 @@ object ErrorHandler { * clean all the failed data for error path before reload. */ def clear(path: String): Unit = { - val fileSystem = FileSystem.get(new Configuration()) - fileSystem.removeAcl(new Path(path)) + if (path.startsWith("hdfs://")) { + val fileSystem = FileSystem.get(new Configuration()) + fileSystem.removeAcl(new Path(path)) + } else { + val directory = new File(path) + if (directory.exists()) { + val content: Array[String] = directory.list() + for (fileName <- content) { + if (!fileName.startsWith("reload.")) { + val tmp = new File(path, fileName) + tmp.delete() + } + } + } + } + } /** diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index 696d34a..c1ba037 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -117,6 +117,9 @@ object Exchange { sys.exit(0) } + // record the failed batch number + var failures: Long = 0L + // import tags if (configs.tagsConfig.nonEmpty) { for (tagConfig <- configs.tagsConfig) { @@ -146,6 +149,7 @@ object Exchange { if (tagConfig.dataSinkConfigEntry.category == SinkCategory.CLIENT) { LOG.info(s"Client-Import: batchSuccess.${tagConfig.name}: ${batchSuccess.value}") LOG.info(s"Client-Import: batchFailure.${tagConfig.name}: ${batchFailure.value}") + failures += batchFailure.value } else { LOG.info(s"SST-Import: failure.${tagConfig.name}: ${batchFailure.value}") } @@ -182,6 +186,7 @@ object Exchange { if (edgeConfig.dataSinkConfigEntry.category == SinkCategory.CLIENT) { LOG.info(s"Client-Import: batchSuccess.${edgeConfig.name}: ${batchSuccess.value}") LOG.info(s"Client-Import: batchFailure.${edgeConfig.name}: ${batchFailure.value}") + failures += batchFailure.value } else { LOG.info(s"SST-Import: failure.${edgeConfig.name}: ${batchFailure.value}") } @@ -192,11 +197,12 @@ object Exchange { } // reimport for failed tags and edges - if (ErrorHandler.existError(configs.errorConfig.errorPath)) { + if (failures > 0 && ErrorHandler.existError(configs.errorConfig.errorPath)) { val batchSuccess = spark.sparkContext.longAccumulator(s"batchSuccess.reimport") val batchFailure = spark.sparkContext.longAccumulator(s"batchFailure.reimport") val data = spark.read.text(configs.errorConfig.errorPath) - val processor = new ReloadProcessor(data, configs, batchSuccess, batchFailure) + data.count() + val processor = new ReloadProcessor(data, configs, batchSuccess, batchFailure) processor.process() LOG.info(s"batchSuccess.reimport: ${batchSuccess.value}") LOG.info(s"batchFailure.reimport: ${batchFailure.value}") diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index 91a98bf..ab82d63 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -85,9 +85,8 @@ class EdgeProcessor(data: DataFrame, s"${config.errorConfig.errorPath}/${edgeConfig.name}.${TaskContext.getPartitionId}") errorBuffer.clear() } - LOG.info( - s"spark partition for edge cost time:" + - s"${TaskContext.getPartitionId()}-${System.currentTimeMillis() - startTime}") + LOG.info(s"edge ${edgeConfig.name} import in spark partition ${TaskContext + .getPartitionId()} cost ${System.currentTimeMillis() - startTime}ms") writer.close() graphProvider.close() } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala index b91d809..62fedd9 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala @@ -21,10 +21,12 @@ class ReloadProcessor(data: DataFrame, batchSuccess: LongAccumulator, batchFailure: LongAccumulator) extends Processor { - private val LOG = Logger.getLogger(this.getClass) + @transient + private[this] lazy val LOG = Logger.getLogger(this.getClass) override def process(): Unit = { data.foreachPartition(processEachPartition(_)) + ErrorHandler.clear(config.errorConfig.errorPath) } private def processEachPartition(iterator: Iterator[Row]): Unit = { @@ -38,10 +40,9 @@ class ReloadProcessor(data: DataFrame, graphProvider) val errorBuffer = ArrayBuffer[String]() - ErrorHandler.clear(config.errorConfig.errorPath) writer.prepare() - // batch write tags + // batch write val startTime = System.currentTimeMillis iterator.foreach { row => val failStatement = writer.writeNgql(row.getString(0)) @@ -57,9 +58,8 @@ class ReloadProcessor(data: DataFrame, s"${config.errorConfig.errorPath}/reload.${TaskContext.getPartitionId()}") errorBuffer.clear() } - LOG.info( - s"spark partition for vertex reload time:" + - s"${TaskContext.getPartitionId()}-${System.currentTimeMillis() - startTime}") + LOG.info(s"data reload in partition ${TaskContext + .getPartitionId()} cost ${System.currentTimeMillis() - startTime}ms") writer.close() graphProvider.close() } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index f6568ab..7a24a3c 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -93,9 +93,8 @@ class VerticesProcessor(data: DataFrame, s"${config.errorConfig.errorPath}/${tagConfig.name}.${TaskContext.getPartitionId()}") errorBuffer.clear() } - LOG.info( - s"spark partition for vertex cost time:" + - s"${TaskContext.getPartitionId()}-${System.currentTimeMillis() - startTime}") + LOG.info(s"tag ${tagConfig.name} import in spark partition ${TaskContext + .getPartitionId()} cost ${System.currentTimeMillis() - startTime} ms") writer.close() graphProvider.close() } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala index cd67463..e0bc2d4 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala @@ -181,9 +181,9 @@ class NebulaGraphClientWriter(dataBaseConfigEntry: DataBaseConfigEntry, if (result.isSucceeded) { return null } - LOG.error(s"rewrite ngql failed for ${result.getErrorMessage}") + LOG.error(s"reimport ngql failed for ${result.getErrorMessage}") } else { - LOG.error(s"rewrite ngql failed because write speed is too fast") + LOG.error(s"reimport ngql failed because write speed is too fast") } LOG.info(ngql) ngql From 42766a07ff5f8d995e5c5d667d2d9f0f7ea4ed78 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 1 Jul 2021 15:25:14 +0800 Subject: [PATCH 166/213] clean the error path before reimport --- .../vesoft/nebula/exchange/ErrorHandler.scala | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala index 8803544..4917bc9 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/ErrorHandler.scala @@ -6,41 +6,47 @@ package com.vesoft.nebula.exchange -import java.io.File - import org.apache.hadoop.conf.Configuration import org.apache.hadoop.fs.{FileSystem, Path} +import org.apache.log4j.Logger import scala.collection.mutable.ArrayBuffer object ErrorHandler { + @transient + private[this] val LOG = Logger.getLogger(this.getClass) /** * clean all the failed data for error path before reload. + * + * @param path path to clean */ def clear(path: String): Unit = { - if (path.startsWith("hdfs://")) { - val fileSystem = FileSystem.get(new Configuration()) - fileSystem.removeAcl(new Path(path)) - } else { - val directory = new File(path) - if (directory.exists()) { - val content: Array[String] = directory.list() - for (fileName <- content) { - if (!fileName.startsWith("reload.")) { - val tmp = new File(path, fileName) - tmp.delete() - } + try { + val fileSystem = FileSystem.get(new Configuration()) + val filesStatus = fileSystem.listStatus(new Path(path)) + for (file <- filesStatus) { + if (!file.getPath.getName.startsWith("reload.")) { + fileSystem.delete(file.getPath, true) } } + } catch { + case e: Throwable => { + LOG.error(s"$path cannot be clean, but this error does not affect the import result, " + + s"you can only focus on the reload files.", + e) + } } - } /** * save the failed execute statement. + * + * @param buffer buffer saved failed ngql + * @param path path to write these buffer ngql */ def save(buffer: ArrayBuffer[String], path: String): Unit = { + LOG.info(s"create reload path $path") val fileSystem = FileSystem.get(new Configuration()) val errors = fileSystem.create(new Path(path)) @@ -56,6 +62,9 @@ object ErrorHandler { /** * check if path exists + * + * @param path error path + *@return true if path exists */ def existError(path: String): Boolean = { val fileSystem = FileSystem.get(new Configuration()) From 5be083b95444aef0190da15f1432edca4a22437e Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 2 Jul 2021 12:43:26 +0800 Subject: [PATCH 167/213] remove the clear operation --- .../com/vesoft/nebula/exchange/processor/ReloadProcessor.scala | 1 - 1 file changed, 1 deletion(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala index 62fedd9..29401e0 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/ReloadProcessor.scala @@ -26,7 +26,6 @@ class ReloadProcessor(data: DataFrame, override def process(): Unit = { data.foreachPartition(processEachPartition(_)) - ErrorHandler.clear(config.errorConfig.errorPath) } private def processEachPartition(iterator: Iterator[Row]): Unit = { From ac867d70afdedbaec158d38cb4e604d598420683 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 7 Jul 2021 10:47:22 +0800 Subject: [PATCH 168/213] reconstruct getPartitionId test --- .../exchange/utils/NebulaUtilsSuite.scala | 86 ++++++++----------- 1 file changed, 34 insertions(+), 52 deletions(-) diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala index 5a79434..e2e6f46 100644 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala @@ -105,59 +105,41 @@ class NebulaUtilsSuite { @Test def getPartitionId(): Unit = { - val storageClient = new StorageClient("127.0.0.1", 9559) - storageClient.connect() - for (i <- 1 to 17) { - val vid = - if (i <= 12) Integer.toString(i) - else if (i == 13) "-1" - else if (i == 14) "-2" - else if (i == 15) "-3" - else if (i == 16) "19" - else "22" - val partitionId = NebulaUtils.getPartitionId(vid, 10, VidType.STRING) - val scanResultIter = storageClient.scanVertex("test_string", partitionId, "person") - var containVertex = false - while (scanResultIter.hasNext) { - val scanResult = scanResultIter.next() - val map = scanResult.getVidVertices - for (value <- map.keySet().asScala if !containVertex) { - if (value.asString().equals(vid)) { - containVertex = true - } - } - } - if (!containVertex) { - LOG.error("vid={},partId={}", vid, partitionId) - } - assert(containVertex) - } + // for String type vid + assert(NebulaUtils.getPartitionId("1", 10, VidType.STRING) == 6) + assert(NebulaUtils.getPartitionId("2", 10, VidType.STRING) == 1) + assert(NebulaUtils.getPartitionId("3", 10, VidType.STRING) == 4) + assert(NebulaUtils.getPartitionId("4", 10, VidType.STRING) == 7) + assert(NebulaUtils.getPartitionId("5", 10, VidType.STRING) == 10) + assert(NebulaUtils.getPartitionId("6", 10, VidType.STRING) == 2) + assert(NebulaUtils.getPartitionId("7", 10, VidType.STRING) == 3) + assert(NebulaUtils.getPartitionId("8", 10, VidType.STRING) == 7) + assert(NebulaUtils.getPartitionId("9", 10, VidType.STRING) == 5) + assert(NebulaUtils.getPartitionId("10", 10, VidType.STRING) == 4) + assert(NebulaUtils.getPartitionId("11", 10, VidType.STRING) == 9) + assert(NebulaUtils.getPartitionId("12", 10, VidType.STRING) == 4) + assert(NebulaUtils.getPartitionId("-1", 10, VidType.STRING) == 1) + assert(NebulaUtils.getPartitionId("-2", 10, VidType.STRING) == 6) + assert(NebulaUtils.getPartitionId("-3", 10, VidType.STRING) == 1) + assert(NebulaUtils.getPartitionId("19", 10, VidType.STRING) == 9) + assert(NebulaUtils.getPartitionId("22", 10, VidType.STRING) == 8) - for (i <- 1 to 17) { - val vid = - if (i <= 12) Integer.toString(i) - else if (i == 13) "-1" - else if (i == 14) "-2" - else if (i == 15) "-3" - else if (i == 16) "19" - else "22" - val partitionId = NebulaUtils.getPartitionId(vid, 10, VidType.INT) - val scanResultIter = storageClient.scanVertex("test_int", partitionId, "person") - var containVertex = false - while (scanResultIter.hasNext) { - val scanResult = scanResultIter.next() - val map = scanResult.getVidVertices - for (value <- map.keySet().asScala if !containVertex) { - if (value.asLong() == vid.toLong) { - containVertex = true - } - } - } - if (!containVertex) { - LOG.error("vid={},partId={}", vid, partitionId) - } - assert(containVertex) - } + // for int type vid + assert(NebulaUtils.getPartitionId("1", 10, VidType.INT) == 2) + assert(NebulaUtils.getPartitionId("2", 10, VidType.INT) == 3) + assert(NebulaUtils.getPartitionId("3", 10, VidType.INT) == 4) + assert(NebulaUtils.getPartitionId("4", 10, VidType.INT) == 5) + assert(NebulaUtils.getPartitionId("5", 10, VidType.INT) == 6) + assert(NebulaUtils.getPartitionId("6", 10, VidType.INT) == 7) + assert(NebulaUtils.getPartitionId("7", 10, VidType.INT) == 8) + assert(NebulaUtils.getPartitionId("8", 10, VidType.INT) == 9) + assert(NebulaUtils.getPartitionId("9", 10, VidType.INT) == 10) + assert(NebulaUtils.getPartitionId("10", 10, VidType.INT) == 1) + assert(NebulaUtils.getPartitionId("11", 10, VidType.INT) == 2) + assert(NebulaUtils.getPartitionId("12", 10, VidType.INT) == 3) + assert(NebulaUtils.getPartitionId("-1", 10, VidType.INT) == 6) + assert(NebulaUtils.getPartitionId("-2", 10, VidType.INT) == 5) + assert(NebulaUtils.getPartitionId("-3", 10, VidType.INT) == 4) } @Test From e36043609741bf9874f82f3b41630b031b277dea Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 6 Jul 2021 11:41:02 +0800 Subject: [PATCH 169/213] add clickhouse config --- .../src/main/resources/application.conf | 55 ++++++++++++++++++- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/nebula-exchange/src/main/resources/application.conf b/nebula-exchange/src/main/resources/application.conf index d13f17e..597ee87 100644 --- a/nebula-exchange/src/main/resources/application.conf +++ b/nebula-exchange/src/main/resources/application.conf @@ -87,7 +87,7 @@ } path: hdfs tag path 0 fields: [parquet-field-0, parquet-field-1, parquet-field-2] - nebula.fields: [nebula-field-0 nebula-field-1 nebula-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] vertex: { field:parquet-field-0 #policy:hash @@ -259,9 +259,31 @@ vertex:{ field: maxcompute-field-2 } - partition 10 + partition:10 batch:10 } + + # ClickHouse + { + name: tag-name-8 + type: { + source: clickhouse + sink: client + } + url:"jdbc:clickhouse://127.0.0.1:8123/database" + user:"user" + passwd:"clickhouse" + numPartition:"5" + sentence:"select * from table" + fields: [clickhouse-field-0, clickhouse-field-1, clickhouse-field-2] + nebula.fields: [nebula-field-0, nebula-field-1, nebula-field-2] + vertex: { + field:clickhouse-field-0 + #policy:hash + } + batch: 256 + partition: 32 + } ] # Processing edges @@ -470,8 +492,35 @@ target:{ field: maxcompute-field-3 } - partition 10 + partition:10 batch:10 } + + # ClickHouse + { + name: edge-name-7 + type: { + source: clickhouse + sink: client + } + url:"jdbc:clickhouse://127.0.0.1:8123/database" + user:"user" + passwd:"clickhouse" + numPartition:"5" + sentence:"select * from table" + fields: [clickhouse-field-2] + nebula.fields: [nebula-field-2] + source: { + field:clickhouse-field-0 + #policy:hash + } + target: { + field:clickhouse-field-1 + #policy:hash + } + batch: 256 + partition: 32 + } + ] } From fa953525695e50b7cc7d7cc1684f9a8d1cd8a505 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 6 Jul 2021 11:41:33 +0800 Subject: [PATCH 170/213] add clickhouse driver dependency --- nebula-exchange/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml index 87fd936..13cd01a 100644 --- a/nebula-exchange/pom.xml +++ b/nebula-exchange/pom.xml @@ -710,6 +710,11 @@ emr-maxcompute_2.11 2.2.0 + + ru.yandex.clickhouse + clickhouse-jdbc + 0.2.5 + From ea75c202adeb97dc8a9e252e3bc81abcb4a6c34c Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 6 Jul 2021 11:42:15 +0800 Subject: [PATCH 171/213] add clickhouse datasource --- .../com/vesoft/nebula/exchange/Exchange.scala | 7 ++++++ .../nebula/exchange/config/Configs.scala | 14 ++++++++++++ .../exchange/config/SourceConfigs.scala | 16 ++++++++++++++ .../exchange/reader/ServerBaseReader.scala | 22 +++++++++++++++++++ 4 files changed, 59 insertions(+) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index 7cb4fb6..d2457b0 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -10,6 +10,7 @@ import org.apache.spark.sql.{DataFrame, SparkSession} import java.io.File import com.vesoft.nebula.exchange.config.{ + ClickHouseConfigEntry, Configs, DataSourceConfigEntry, FileBaseSourceConfigEntry, @@ -27,6 +28,7 @@ import com.vesoft.nebula.exchange.config.{ import com.vesoft.nebula.exchange.processor.{EdgeProcessor, VerticesProcessor} import com.vesoft.nebula.exchange.reader.{ CSVReader, + ClickhouseReader, HBaseReader, HiveReader, JSONReader, @@ -278,6 +280,11 @@ object Exchange { val maxComputeConfigEntry = config.asInstanceOf[MaxComputeConfigEntry] val reader = new MaxcomputeReader(session, maxComputeConfigEntry) Some(reader.read()) + case SourceCategory.CLICKHOUSE => { + val clickhouseConfigEntry = config.asInstanceOf[ClickHouseConfigEntry] + val reader = new ClickhouseReader(session, clickhouseConfigEntry) + Some(reader.read()) + } case _ => { LOG.error(s"Data source ${config.category} not supported") None diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala index 78efcd7..b1bcbef 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala @@ -483,6 +483,7 @@ object Configs { case "PULSAR" => SourceCategory.PULSAR case "HBASE" => SourceCategory.HBASE case "MAXCOMPUTE" => SourceCategory.MAXCOMPUTE + case "CLICKHOUSE" => SourceCategory.CLICKHOUSE case _ => throw new IllegalArgumentException(s"${category} not support") } } @@ -635,6 +636,19 @@ object Configs { sentence ) } + case SourceCategory.CLICKHOUSE => { + val partition: String = if (config.hasPath("numPartition")) { + config.getString("numPartition") + } else { + "1" + } + ClickHouseConfigEntry(SourceCategory.CLICKHOUSE, + config.getString("url"), + config.getString("user"), + config.getString("passwd"), + partition, + config.getString("sentence")) + } case _ => throw new IllegalArgumentException("Unsupported data source") } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala index 14fcbe0..76844e5 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/SourceConfigs.scala @@ -26,6 +26,7 @@ object SourceCategory extends Enumeration { val MYSQL = Value("MYSQL") val HBASE = Value("HBASE") val MAXCOMPUTE = Value("MAXCOMPUTE") + val CLICKHOUSE = Value("CLICKHOUSE") val SOCKET = Value("SOCKET") val KAFKA = Value("KAFKA") @@ -243,3 +244,18 @@ case class MaxComputeConfigEntry(override val category: SourceCategory.Value, } } + +/** + * ClickHouseConfigEntry + */ +case class ClickHouseConfigEntry(override val category: SourceCategory.Value, + url: String, + user: String, + passwd: String, + numPartition: String, + override val sentence: String) + extends ServerDataSourceConfigEntry { + override def toString: String = { + s"ClickHouse source {url:$url, user:$user, passwd:$passwd, numPartition:$numPartition, sentence:$sentence}" + } +} diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala index b56682c..d0abb75 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/reader/ServerBaseReader.scala @@ -8,6 +8,7 @@ package com.vesoft.nebula.exchange.reader import com.google.common.collect.Maps import com.vesoft.nebula.exchange.config.{ + ClickHouseConfigEntry, HBaseSourceConfigEntry, HiveSourceConfigEntry, JanusGraphSourceConfigEntry, @@ -292,3 +293,24 @@ class MaxcomputeReader(override val session: SparkSession, maxComputeConfig: Max } } } + +/** + * Clickhouse reader + */ +class ClickhouseReader(override val session: SparkSession, + clickHouseConfigEntry: ClickHouseConfigEntry) + extends ServerBaseReader(session, clickHouseConfigEntry.sentence) { + Class.forName("ru.yandex.clickhouse.ClickHouseDriver") + override def read(): DataFrame = { + val df = session.read + .format("jdbc") + .option("driver", "ru.yandex.clickhouse.ClickHouseDriver") + .option("url", clickHouseConfigEntry.url) + .option("user", clickHouseConfigEntry.user) + .option("password", clickHouseConfigEntry.passwd) + .option("numPartitions", clickHouseConfigEntry.numPartition) + .option("query", clickHouseConfigEntry.sentence) + .load() + df + } +} From 2e6d1c38ef602bd5dbee609777610f888c1141b6 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 9 Jul 2021 15:50:06 +0800 Subject: [PATCH 172/213] fix wrong address log --- .../com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala index be25ba5..11295a4 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala @@ -140,7 +140,7 @@ class NebulaGraphClientWriter(dataBaseConfigEntry: DataBaseConfigEntry, throw new RuntimeException("Switch Failed") } - LOG.info(s"Connection to ${dataBaseConfigEntry.metaAddresses}") + LOG.info(s"Connection to ${dataBaseConfigEntry.graphAddress}") } override def writeVertices(vertices: Vertices): String = { From e60fef2bec0a9259271fbe4dd8a3acb6905d66f9 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 9 Jul 2021 15:58:43 +0800 Subject: [PATCH 173/213] unify password key --- nebula-exchange/src/main/resources/application.conf | 4 ++-- .../scala/com/vesoft/nebula/exchange/config/Configs.scala | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/nebula-exchange/src/main/resources/application.conf b/nebula-exchange/src/main/resources/application.conf index 597ee87..6b866db 100644 --- a/nebula-exchange/src/main/resources/application.conf +++ b/nebula-exchange/src/main/resources/application.conf @@ -272,7 +272,7 @@ } url:"jdbc:clickhouse://127.0.0.1:8123/database" user:"user" - passwd:"clickhouse" + password:"clickhouse" numPartition:"5" sentence:"select * from table" fields: [clickhouse-field-0, clickhouse-field-1, clickhouse-field-2] @@ -505,7 +505,7 @@ } url:"jdbc:clickhouse://127.0.0.1:8123/database" user:"user" - passwd:"clickhouse" + password:"clickhouse" numPartition:"5" sentence:"select * from table" fields: [clickhouse-field-2] diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala index b1bcbef..1710f3a 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala @@ -645,7 +645,7 @@ object Configs { ClickHouseConfigEntry(SourceCategory.CLICKHOUSE, config.getString("url"), config.getString("user"), - config.getString("passwd"), + config.getString("password"), partition, config.getString("sentence")) } From 0d5162d9d3df384237aed1dea8febaf74cdac603 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Fri, 16 Jul 2021 15:00:30 +0800 Subject: [PATCH 174/213] add more check for config file --- .../nebula/exchange/config/Configs.scala | 17 +++++- .../nebula/exchange/config/ConfigsSuite.scala | 57 +++++++++++++++++++ 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala index 1710f3a..27efc56 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/config/Configs.scala @@ -36,9 +36,20 @@ object Type extends Enumeration { case class DataBaseConfigEntry(graphAddress: List[String], space: String, metaAddresses: List[String]) { - require(graphAddress.nonEmpty) - require(metaAddresses.nonEmpty) - require(space.trim.nonEmpty) + require(graphAddress.nonEmpty, "nebula.address.graph cannot be empty") + require(metaAddresses.nonEmpty, "nebula.address.meta cannot be empty") + require(space.trim.nonEmpty, "nebula.space cannot be empty") + + for (address <- graphAddress) { + require( + !address.contains(",") && !address.contains(","), + "nebula.address.graph has wrong format, please make sure the format is [\"ip1:port1\",\"ip2:port2\"]") + } + for (address <- metaAddresses) { + require( + !address.contains(",") && !address.contains(","), + "nebula.address.meta has wrong format,,please make sure the format is [\"ip1:port1\",\"ip2:port2\"]") + } override def toString: String = super.toString diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala index 7a2dc9a..9c00e52 100644 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala @@ -10,6 +10,7 @@ import java.io.File import com.vesoft.nebula.exchange.config.{ Configs, + DataBaseConfigEntry, FileBaseSourceConfigEntry, FileDataSourceConfigEntry, HBaseSourceConfigEntry, @@ -20,9 +21,12 @@ import com.vesoft.nebula.exchange.config.{ SourceCategory } import com.vesoft.nebula.exchange.{Argument, KeyPolicy} +import org.apache.log4j.Logger import org.junit.Test class ConfigsSuite { + private[this] val LOG = Logger.getLogger(this.getClass) + @Test def configsSuite(): Unit = { val args = List("-c", "src/test/resources/application.conf", "-h", "-d") @@ -237,4 +241,57 @@ class ConfigsSuite { } } } + + @Test + def DataBaseConfigsSuite(): Unit = { + // correct config + val graphAddress = List("127.0.0.1:9669", "127.0.0.1:9670") + val metaAddress = List("127.0.0.1:9559", "127.0.0.1:9560") + val space = "test" + DataBaseConfigEntry(graphAddress, space, metaAddress) + + // empty space + try { + DataBaseConfigEntry(graphAddress, "", metaAddress) + } catch { + case e: IllegalArgumentException => { + LOG.error("we expect here, ", e) + assert(true) + } + case e: Throwable => { + LOG.error("DataBaseConfigSuite failed, ", e) + assert(false) + } + } + + // wrong graph address + val wrongGraphAddress = List("127.0.0.1:9669,127.0.0.1:9670") + try { + DataBaseConfigEntry(wrongGraphAddress, space, metaAddress) + } catch { + case e: IllegalArgumentException => { + LOG.error("we expect here, ", e) + assert(true) + } + case e: Throwable => { + LOG.error("DataBaseConfigSuite failed, ", e) + assert(false) + } + } + + // wrong meta Address + val wrongMetaAddress = List("127.0.0.1:9559,127.0.0.1:9560") + try { + DataBaseConfigEntry(graphAddress, space, wrongMetaAddress) + } catch { + case e: IllegalArgumentException => { + LOG.error("we expect here, ", e) + assert(true) + } + case e: Throwable => { + LOG.error("DataBaseConfigSuite failed, ", e) + assert(false) + } + } + } } From 173400997555315a3b45d16b1e1f5faed0275390 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 21 Jul 2021 10:06:33 +0800 Subject: [PATCH 175/213] split multi test --- .../nebula/exchange/config/ConfigsSuite.scala | 68 +++++++++---------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala index 9c00e52..8f86cdf 100644 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/config/ConfigsSuite.scala @@ -23,6 +23,7 @@ import com.vesoft.nebula.exchange.config.{ import com.vesoft.nebula.exchange.{Argument, KeyPolicy} import org.apache.log4j.Logger import org.junit.Test +import org.scalatest.Assertions.assertThrows class ConfigsSuite { private[this] val LOG = Logger.getLogger(this.getClass) @@ -242,56 +243,53 @@ class ConfigsSuite { } } + /** + * correct config + */ @Test - def DataBaseConfigsSuite(): Unit = { - // correct config + def dataBaseConfigSuite(): Unit = { val graphAddress = List("127.0.0.1:9669", "127.0.0.1:9670") val metaAddress = List("127.0.0.1:9559", "127.0.0.1:9560") val space = "test" DataBaseConfigEntry(graphAddress, space, metaAddress) + } - // empty space - try { + /** + * empty space + */ + @Test + def dataBaseConfigEmptySpaceSuite: Unit = { + val graphAddress = List("127.0.0.1:9669", "127.0.0.1:9670") + val metaAddress = List("127.0.0.1:9559", "127.0.0.1:9560") + assertThrows[IllegalArgumentException] { DataBaseConfigEntry(graphAddress, "", metaAddress) - } catch { - case e: IllegalArgumentException => { - LOG.error("we expect here, ", e) - assert(true) - } - case e: Throwable => { - LOG.error("DataBaseConfigSuite failed, ", e) - assert(false) - } } + } - // wrong graph address + /** + * wrong graph address + */ + @Test + def dataBaseConfigWrongGraphSuite: Unit = { val wrongGraphAddress = List("127.0.0.1:9669,127.0.0.1:9670") - try { + val space = "test" + val metaAddress = List("127.0.0.1:9559", "127.0.0.1:9560") + + assertThrows[IllegalArgumentException] { DataBaseConfigEntry(wrongGraphAddress, space, metaAddress) - } catch { - case e: IllegalArgumentException => { - LOG.error("we expect here, ", e) - assert(true) - } - case e: Throwable => { - LOG.error("DataBaseConfigSuite failed, ", e) - assert(false) - } } + } - // wrong meta Address + /** + * wrong meta Address + */ + @Test + def dataBaseConfigWrongMetaSuite: Unit = { + val graphAddress = List("127.0.0.1:9669", "127.0.0.1:9670") + val space = "test" val wrongMetaAddress = List("127.0.0.1:9559,127.0.0.1:9560") - try { + assertThrows[IllegalArgumentException] { DataBaseConfigEntry(graphAddress, space, wrongMetaAddress) - } catch { - case e: IllegalArgumentException => { - LOG.error("we expect here, ", e) - assert(true) - } - case e: Throwable => { - LOG.error("DataBaseConfigSuite failed, ", e) - assert(false) - } } } } From e57e443845abbdf56c378659b667a12b0fa3ebeb Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 28 Jul 2021 11:22:40 +0800 Subject: [PATCH 176/213] remove useless repository --- nebula-exchange/pom.xml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml index 13cd01a..cb92bc5 100644 --- a/nebula-exchange/pom.xml +++ b/nebula-exchange/pom.xml @@ -141,7 +141,8 @@ javax.inject:javax.inject org.spark-project.hive:hive-exec stax:stax-api - org.glassfish.hk2.external:aopalliance-repackaged + org.glassfish.hk2.external:aopalliance-repackaged + @@ -209,7 +210,8 @@ maven-javadoc-plugin 3.2.0 - com.facebook.thrift:com.facebook.thrift.* + com.facebook.thrift:com.facebook.thrift.* + @@ -721,11 +723,6 @@ SparkPackagesRepo https://repos.spark-packages.org - - bintray-streamnative-maven - bintray - https://dl.bintray.com/streamnative/maven - snapshots https://oss.sonatype.org/content/repositories/snapshots/ From a33b2080fc58a6b09df47d386866e09fabdf5c38 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 28 Jul 2021 11:59:38 +0800 Subject: [PATCH 177/213] add pulsar dependency --- .github/workflows/maven.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 3154bc7..84762c7 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -30,12 +30,14 @@ jobs: key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-maven- - - name: download neo4j-contrib & graphframes dependency + - name: download neo4j-contrib & graphframes & pulsar-spark-connector dependency run: | wget https://oss-cdn.nebula-graph.com.cn/jar-packages/neo4j-contrib.zip wget https://oss-cdn.nebula-graph.com.cn/jar-packages/graphframes.zip + wget https://oss-cdn.nebula-graph.com.cn/jar-packages/streamnative.zip unzip -o -d ~/.m2/repository/ neo4j-contrib.zip unzip -o -d ~/.m2/repository/ graphframes.zip + unzip -o -d ~/.m2/repository/io streamnative.zip - name: Install nebula-graph run: | From 3abe0fba32b68c937fda458c2d22ac57a69a8dc2 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 2 Aug 2021 09:45:43 +0800 Subject: [PATCH 178/213] add / for directory --- .github/workflows/maven.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 84762c7..0bf453e 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -37,7 +37,7 @@ jobs: wget https://oss-cdn.nebula-graph.com.cn/jar-packages/streamnative.zip unzip -o -d ~/.m2/repository/ neo4j-contrib.zip unzip -o -d ~/.m2/repository/ graphframes.zip - unzip -o -d ~/.m2/repository/io streamnative.zip + unzip -o -d ~/.m2/repository/io/ streamnative.zip - name: Install nebula-graph run: | From a183ef0d6d1646b483cea1cd9a436d02588aad92 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 2 Aug 2021 14:57:21 +0800 Subject: [PATCH 179/213] remove streamnative before unzip --- .github/workflows/maven.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 0bf453e..059388d 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -37,6 +37,7 @@ jobs: wget https://oss-cdn.nebula-graph.com.cn/jar-packages/streamnative.zip unzip -o -d ~/.m2/repository/ neo4j-contrib.zip unzip -o -d ~/.m2/repository/ graphframes.zip + rm -rf ~/.m2/repository/io/streamnative unzip -o -d ~/.m2/repository/io/ streamnative.zip - name: Install nebula-graph From 25cf0bbc636b7a7ec88d649bfc3f72288ae89220 Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 2 Aug 2021 16:19:11 +0800 Subject: [PATCH 180/213] format example --- .../examples/connector/NebulaSparkWriterExample.scala | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala index 22319de..d62c2dd 100644 --- a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala +++ b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala @@ -34,14 +34,13 @@ object NebulaSparkWriterExample { .config(sparkConf) .getOrCreate() -// writeVertex(spark) -// writeEdge(spark) + writeVertex(spark) + writeEdge(spark) updateVertex(spark) - //updateEdge(spark) + updateEdge(spark) spark.close() - sys.exit() } /** From 994dd7855b1880f06b092517692f02040a5f8fba Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 2 Aug 2021 16:19:40 +0800 Subject: [PATCH 181/213] add close for writer & add test plugin --- nebula-spark-connector/pom.xml | 32 ++++++++++++++++--- .../nebula/connector/NebulaConfig.scala | 4 +++ .../connector/writer/NebulaEdgeWriter.scala | 1 + .../connector/writer/NebulaVertexWriter.scala | 1 + .../writer/NebulaExecutorSuite.scala | 4 +-- 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/nebula-spark-connector/pom.xml b/nebula-spark-connector/pom.xml index 35854df..a946aa4 100644 --- a/nebula-spark-connector/pom.xml +++ b/nebula-spark-connector/pom.xml @@ -117,7 +117,8 @@ javax.inject:javax.inject org.spark-project.hive:hive-exec stax:stax-api - org.glassfish.hk2.external:aopalliance-repackaged + org.glassfish.hk2.external:aopalliance-repackaged + @@ -150,13 +151,36 @@ - + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*Test.* + **/*Suite.* + + + + + org.scalatest + scalatest-maven-plugin + 2.0.0 + + + test + + test + + + + org.apache.maven.plugins maven-javadoc-plugin 3.2.0 - com.facebook.thrift:com.facebook.thrift.* + com.facebook.thrift:com.facebook.thrift.* + @@ -179,4 +203,4 @@ - \ No newline at end of file + diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala index f20d58a..83d6627 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala @@ -226,6 +226,8 @@ object WriteNebulaVertexConfig { || vidPolicy.equalsIgnoreCase(KeyPolicy.UUID.toString), "config vidPolicy is illegal, please don't set vidPolicy or set vidPolicy \"HASH\" or \"UUID\"" ) + assert(user != null && !user.isEmpty, "user is empty") + assert(passwd != null && !passwd.isEmpty, "passwd is empty") try { WriteMode.withName(writeMode.toLowerCase()) } catch { @@ -442,6 +444,8 @@ object WriteNebulaEdgeConfig { "config dstPolicy is illegal, please don't set dstPolicy or set dstPolicy \"HASH\" or \"UUID\"" ) assert(batch > 0, s"config batch must be positive, your batch is $batch.") + assert(user != null && !user.isEmpty, "user is empty") + assert(passwd != null && !passwd.isEmpty, "passwd is empty") try { WriteMode.withName(writeMode.toLowerCase) } catch { diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala index cde3b7f..7dfe283 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala @@ -93,6 +93,7 @@ class NebulaEdgeWriter(nebulaOptions: NebulaOptions, if (edges.nonEmpty) { execute() } + graphProvider.close() NebulaCommitMessage.apply(failedExecs.toList) } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala index 1039e91..c663765 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala @@ -73,6 +73,7 @@ class NebulaVertexWriter(nebulaOptions: NebulaOptions, vertexIndex: Int, schema: if (vertices.nonEmpty) { execute() } + graphProvider.close() NebulaCommitMessage(failedExecs.toList) } diff --git a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala index b940082..c273a5b 100644 --- a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala +++ b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala @@ -186,7 +186,7 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { NebulaExecutor.toUpdateExecuteStatement("person", propNames, nebulaVertex) val expectVertexUpdate = "UPDATE VERTEX ON `person` \"vid1\" SET `col_string`=\"name\",`col_fixed_string`=\"name\"," + - "`col_bool`=true,`col_int`=10,`col_int64`=100,`col_double`=1.0,`col_date`=2021-11-12;" + "`col_bool`=true,`col_int`=10,`col_int64`=100,`col_double`=1.0,`col_date`=2021-11-12" assert(expectVertexUpdate.equals(updateVertexStatement)) } @@ -209,7 +209,7 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { val expectEdgeUpdate = "UPDATE EDGE ON `friend` \"source\"->\"target\"@0 SET `col_string`=\"name\"," + "`col_fixed_string`=\"name\",`col_bool`=true,`col_int`=10,`col_int64`=100," + - "`col_double`=1.0,`col_date`=2021-11-12;" + "`col_double`=1.0,`col_date`=2021-11-12" assert(expectEdgeUpdate.equals(updateEdgeStatement)) } } From 947fd097fdd781185e82d08409cfe71d1bf9f79c Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Mon, 2 Aug 2021 16:20:19 +0800 Subject: [PATCH 182/213] add log for switch error & remove sys.exit --- .../src/main/scala/com/vesoft/nebula/exchange/Exchange.scala | 1 - .../main/scala/com/vesoft/nebula/exchange/GraphProvider.scala | 4 ++-- .../com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index 21ffcc7..9ddb669 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -212,7 +212,6 @@ object Exchange { LOG.info(s"batchFailure.reimport: ${batchFailure.value}") } spark.close() - sys.exit(0) } /** diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala index 84b8307..6404df0 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/GraphProvider.scala @@ -47,11 +47,11 @@ class GraphProvider(addresses: List[HostAndPort], timeout: Int) pool.close() } - def switchSpace(session: Session, space: String): Boolean = { + def switchSpace(session: Session, space: String): ResultSet = { val switchStatment = s"use $space" LOG.info(s"switch space $space") val result = submit(session, switchStatment) - result.isSucceeded + result } def submit(session: Session, statement: String): ResultSet = { diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala index e469dd8..8dba520 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/writer/ServerBaseWriter.scala @@ -137,9 +137,9 @@ class NebulaGraphClientWriter(dataBaseConfigEntry: DataBaseConfigEntry, def prepare(): Unit = { val switchResult = graphProvider.switchSpace(session, dataBaseConfigEntry.space) - if (!switchResult) { + if (!switchResult.isSucceeded) { this.close() - throw new RuntimeException("Switch Failed") + throw new RuntimeException("Switch Failed for " + switchResult.getErrorMessage) } LOG.info(s"Connection to ${dataBaseConfigEntry.graphAddress}") From 1e7e7d9fc1e0cd4acc57437b176a5bbfb9ffab5c Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Tue, 3 Aug 2021 14:06:33 +0800 Subject: [PATCH 183/213] add summary report for import --- .../com/vesoft/nebula/exchange/Exchange.scala | 20 ++++++++++++++++--- .../nebula/exchange/utils/HDFSUtils.scala | 14 +++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index 9ddb669..5f90dd4 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -8,7 +8,6 @@ package com.vesoft.nebula.exchange import org.apache.spark.sql.{DataFrame, SparkSession} import java.io.File - import com.vesoft.nebula.exchange.config.{ ClickHouseConfigEntry, Configs, @@ -136,6 +135,8 @@ object Exchange { val data = createDataSource(spark, tagConfig.dataSourceConfigEntry) if (data.isDefined && !c.dry) { + val count = data.get.count() + val startTime = System.currentTimeMillis() val batchSuccess = spark.sparkContext.longAccumulator(s"batchSuccess.${tagConfig.name}") val batchFailure = @@ -150,6 +151,10 @@ object Exchange { batchSuccess, batchFailure) processor.process() + val costTime = ((System.currentTimeMillis() - startTime) / 1000).formatted("%.2f") + LOG.info( + s"data source count: ${count}, " + + s"import for tag ${tagConfig.name} cost time: ${costTime} s") if (tagConfig.dataSinkConfigEntry.category == SinkCategory.CLIENT) { LOG.info(s"Client-Import: batchSuccess.${tagConfig.name}: ${batchSuccess.value}") LOG.info(s"Client-Import: batchFailure.${tagConfig.name}: ${batchFailure.value}") @@ -174,6 +179,8 @@ object Exchange { LOG.info(s"nebula keys: ${nebulaKeys.mkString(", ")}") val data = createDataSource(spark, edgeConfig.dataSourceConfigEntry) if (data.isDefined && !c.dry) { + val count = data.get.count() + val startTime = System.currentTimeMillis() val batchSuccess = spark.sparkContext.longAccumulator(s"batchSuccess.${edgeConfig.name}") val batchFailure = spark.sparkContext.longAccumulator(s"batchFailure.${edgeConfig.name}") @@ -187,6 +194,10 @@ object Exchange { batchFailure ) processor.process() + val costTime = ((System.currentTimeMillis() - startTime) / 1000).formatted("%.2f") + LOG.info( + s"data source count: ${count}, " + + s"import for edge ${edgeConfig.name} cost time: ${costTime} s") if (edgeConfig.dataSinkConfigEntry.category == SinkCategory.CLIENT) { LOG.info(s"Client-Import: batchSuccess.${edgeConfig.name}: ${batchSuccess.value}") LOG.info(s"Client-Import: batchFailure.${edgeConfig.name}: ${batchFailure.value}") @@ -205,9 +216,12 @@ object Exchange { val batchSuccess = spark.sparkContext.longAccumulator(s"batchSuccess.reimport") val batchFailure = spark.sparkContext.longAccumulator(s"batchFailure.reimport") val data = spark.read.text(configs.errorConfig.errorPath) - data.count() - val processor = new ReloadProcessor(data, configs, batchSuccess, batchFailure) + val count = data.count() + val startTime = System.currentTimeMillis() + val processor = new ReloadProcessor(data, configs, batchSuccess, batchFailure) processor.process() + val costTime = ((System.currentTimeMillis() - startTime) / 1000).formatted("%.2f") + LOG.info(s"reimport ngql count: ${count}, cost time: ${costTime}") LOG.info(s"batchSuccess.reimport: ${batchSuccess.value}") LOG.info(s"batchFailure.reimport: ${batchFailure.value}") } diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala index 9e78486..3b2c009 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala @@ -6,12 +6,15 @@ package com.vesoft.nebula.exchange.utils +import java.io.File import java.nio.charset.Charset import org.apache.hadoop.conf.Configuration import org.apache.hadoop.fs.{FileSystem, Path} +import org.apache.log4j.Logger import scala.io.Source object HDFSUtils { + private[this] val LOG = Logger.getLogger(this.getClass) def getFileSystem(namenode: String = null): FileSystem = { val conf = new Configuration() @@ -63,6 +66,17 @@ object HDFSUtils { } def upload(localPath: String, remotePath: String, namenode: String = null): Unit = { + try { + val localFile = new File(localPath) + if (!localFile.exists() || localFile.length() <= 0) { + return + } + } catch { + case e: Throwable => + LOG.warn("check for empty local file error, but you can ignore this check error. " + + "If there is empty sst file in your hdfs, please delete it manually", + e) + } val system = getFileSystem(namenode) try { system.copyFromLocalFile(new Path(localPath), new Path(remotePath)) From a8d9e9b2b34f1c05b320423e0abdeb814d956ab3 Mon Sep 17 00:00:00 2001 From: Qishang Zhong Date: Tue, 3 Aug 2021 16:39:33 +0800 Subject: [PATCH 184/213] fix package & add plugin `maven-scala-plugin` --- example/pom.xml | 41 +++++++++++++++++++ .../connector/NebulaSparkReaderExample.scala | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/example/pom.xml b/example/pom.xml index ade407f..8c35472 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -88,6 +88,47 @@ + + org.scala-tools + maven-scala-plugin + 2.15.2 + + 2.11.12 + + -target:jvm-1.8 + + + -Xss4096K + + + + + scala-compile + + compile + + + + com/vesoft/tools/** + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + scala-test-compile + + testCompile + + + + com/vesoft/tools/** + + + + + diff --git a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala index a11ae2b..3cc581e 100644 --- a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala +++ b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkReaderExample.scala @@ -4,7 +4,7 @@ * attached with Common Clause Condition 1.0, found in the LICENSES directory. */ -package main.scala.com.vesoft.nebula.examples.connector +package com.vesoft.nebula.examples.connector import com.facebook.thrift.protocol.TCompactProtocol import com.vesoft.nebula.connector.connector.NebulaDataFrameReader From 484194fd9ee595c9e79e1f554af356a0a9a7a97c Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Wed, 4 Aug 2021 16:01:56 +0800 Subject: [PATCH 185/213] update readme --- README.md | 2 ++ nebula-spark-connector/README.md | 21 ++++++++++++++++++++- nebula-spark-connector/README_CN.md | 22 +++++++++++++++++++++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 88d8329..42c2f85 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ There are the version correspondence between Nebula Spark utils and Nebula: |:-----------------------:|:------------------------------:|:------------------------:|:--------------:| | 2.0.0 | 2.0.0 | 2.0.0 | 2.0.0, 2.0.1 | | 2.0.1 | 2.0.1 | -- | 2.0.0, 2.0.1 | +| 2.1.0 | 2.1.0 | 2.1.0 | 2.0.0, 2.0.1 | +| 2.5.0 | 2.5.0 | 2.5.0 | 2.5.0 | | 2.0-SNAPSHOT | 2.0-SNAPSHOT | 2.0-SNAPSHOT | v2-nightly | If the Nebula version and the uitls' version are not in the same line, then they are incompatible. diff --git a/nebula-spark-connector/README.md b/nebula-spark-connector/README.md index 47b8380..75d672c 100644 --- a/nebula-spark-connector/README.md +++ b/nebula-spark-connector/README.md @@ -23,10 +23,11 @@ Nebula Spark Connector 2.0 only supports Nebula Graph 2.x. If you are using Nebu * Spark Reader Supports non-property, all-property, and specific-properties read. * Spark Reader Supports reading data from Nebula Graph to Graphx as VertexRD and EdgeRDD, it also supports String type vertexId. * Nebula Spark Connector 2.0 uniformly uses SparkSQL's DataSourceV2 for data source expansion. +* Nebula Spark Connector 2.1.0 support UPDATE write mode to NebulaGraph, see [Update Vertex](https://docs.nebula-graph.io/2.0.1/3.ngql-guide/12.vertex-statements/2.update-vertex/) . ## How to Use - Write DataFrame into Nebula Graph as Vertices: + Write DataFrame `INSERT` into Nebula Graph as Vertices: ``` val config = NebulaConnectionConfig .builder() @@ -43,6 +44,24 @@ Nebula Spark Connector 2.0 only supports Nebula Graph 2.x. If you are using Nebu .build() df.write.nebula(config, nebulaWriteVertexConfig).writeVertices() ``` + Write DataFrame `UPDATE` into Nebula Graph as Vertices: + ``` + val config = NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:9559") + .withGraphAddress("127.0.0.1:9669") + .build() + val nebulaWriteVertexConfig: WriteNebulaVertexConfig = WriteNebulaVertexConfig + .builder() + .withSpace("test") + .withTag("person") + .withVidField("id") + .withVidAsProp(true) + .withBatch(1000) + .withWriteMode(WriteMode.UPDATE) + .build() + df.write.nebula(config, nebulaWriteVertexConfig).writeVertices() + ``` Read vertices from Nebula Graph: ``` val config = NebulaConnectionConfig diff --git a/nebula-spark-connector/README_CN.md b/nebula-spark-connector/README_CN.md index f5382d2..e2ce44a 100644 --- a/nebula-spark-connector/README_CN.md +++ b/nebula-spark-connector/README_CN.md @@ -23,10 +23,11 @@ Nebula Spark Connector 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Ne * Spark Reader 支持无属性读取,支持全属性读取 * Spark Reader 支持将 Nebula Graph 数据读取成 Graphx 的 VertexRD 和 EdgeRDD,支持非 Long 型 vertexId * Nebula Spark Connector 2.0 统一了 SparkSQL 的扩展数据源,统一采用 DataSourceV2 进行 Nebula Graph 数据扩展 +* Nebula Spark Connector 2.1.0 增加了 UPDATE 写入模式,相关说明参考[Update Vertex](https://docs.nebula-graph.com.cn/2.0.1/3.ngql-guide/12.vertex-statements/2.update-vertex/) 。 ## 使用说明 - 将 DataFrame 作为点写入 Nebula Graph : + 将 DataFrame 作为点 `INSERT` 写入 Nebula Graph : ``` val config = NebulaConnectionConfig .builder() @@ -43,6 +44,25 @@ Nebula Spark Connector 2.0 仅支持 Nebula Graph 2.x。如果您正在使用 Ne .build() df.write.nebula(config, nebulaWriteVertexConfig).writeVertices() ``` + 将 DataFrame 作为点 `UPDATE` 写入 Nebula Graph : + ``` + val config = NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:9559") + .withGraphAddress("127.0.0.1:9669") + .build() + val nebulaWriteVertexConfig = WriteNebulaVertexConfig + .builder() + .withSpace("test") + .withTag("person") + .withVidField("id") + .withVidAsProp(true) + .withBatch(1000) + .withWriteMode(WriteMode.UPDATE) + .build() + df.write.nebula(config, nebulaWriteVertexConfig).writeVertices() + ``` + 读取 Nebula Graph 的点数据: ``` val config = NebulaConnectionConfig From 1ede5958aaedbd2367ee5ecd216d63607425703a Mon Sep 17 00:00:00 2001 From: Nicole00 <16240361+Nicole00@users.noreply.github.com> Date: Thu, 5 Aug 2021 16:45:04 +0800 Subject: [PATCH 186/213] fix double format --- .../main/scala/com/vesoft/nebula/exchange/Exchange.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index 5f90dd4..9624b56 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -151,7 +151,7 @@ object Exchange { batchSuccess, batchFailure) processor.process() - val costTime = ((System.currentTimeMillis() - startTime) / 1000).formatted("%.2f") + val costTime = ((System.currentTimeMillis() - startTime) / 1000.0).formatted("%.2f") LOG.info( s"data source count: ${count}, " + s"import for tag ${tagConfig.name} cost time: ${costTime} s") @@ -194,7 +194,7 @@ object Exchange { batchFailure ) processor.process() - val costTime = ((System.currentTimeMillis() - startTime) / 1000).formatted("%.2f") + val costTime = ((System.currentTimeMillis() - startTime) / 1000.0).formatted("%.2f") LOG.info( s"data source count: ${count}, " + s"import for edge ${edgeConfig.name} cost time: ${costTime} s") @@ -220,7 +220,7 @@ object Exchange { val startTime = System.currentTimeMillis() val processor = new ReloadProcessor(data, configs, batchSuccess, batchFailure) processor.process() - val costTime = ((System.currentTimeMillis() - startTime) / 1000).formatted("%.2f") + val costTime = ((System.currentTimeMillis() - startTime) / 1000.0).formatted("%.2f") LOG.info(s"reimport ngql count: ${count}, cost time: ${costTime}") LOG.info(s"batchSuccess.reimport: ${batchSuccess.value}") LOG.info(s"batchFailure.reimport: ${batchFailure.value}") From 882c787806fe2b9c3c48bc93bf607c4553343e8b Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Thu, 19 Aug 2021 16:39:48 +0800 Subject: [PATCH 187/213] fix numeric check --- .../vesoft/nebula/connector/NebulaUtils.scala | 6 +++- .../com/vesoft/nebula/connector/package.scala | 30 ++++--------------- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala index 8af710c..ef7da4f 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala @@ -85,7 +85,11 @@ object NebulaUtils { } def isNumic(str: String): Boolean = { - for (char <- str.toCharArray) { + val newStr: String = if (str.startsWith("-")) { + str.substring(1) + } else { str } + + for (char <- newStr.toCharArray) { if (!Character.isDigit(char)) return false } true diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala index 5085f23..556d840 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/package.scala @@ -155,18 +155,10 @@ package object connector { implicit val encoder: Encoder[NebulaGraphxVertex] = Encoders.bean[NebulaGraphxVertex](classOf[NebulaGraphxVertex]) - val fields = vertexDataset.schema.fields vertexDataset .map(row => { - val vertexId = row.get(0) - val vid: Long = if (row.schema.fields(0).dataType == LongType) { - vertexId.toString.toLong - } else { - MurmurHash2.hash64(vertexId.toString.getBytes(), - vertexId.toString.getBytes().length, - 0xc70f6907) - } - + val vertexId = row.get(0) + val vid: Long = vertexId.toString.toLong val props: ListBuffer[Any] = ListBuffer() for (i <- row.schema.fields.indices) { if (i != 0) { @@ -187,7 +179,6 @@ package object connector { implicit val encoder: Encoder[NebulaGraphxEdge] = Encoders.bean[NebulaGraphxEdge](classOf[NebulaGraphxEdge]) - val fields = edgeDataset.schema.fields edgeDataset .map(row => { val props: ListBuffer[Any] = ListBuffer() @@ -196,19 +187,10 @@ package object connector { props.append(row.get(i)) } } - val srcId = row.get(0).toString.getBytes() - val dstId = row.get(1).toString.getBytes() - val edgeSrc = if (row.schema.fields(0).dataType == LongType) { - srcId.toString.toLong - } else { - MurmurHash2.hash64(srcId, srcId.length, 0xc70f6907) - } - val edgeDst = if (row.schema.fields(0).dataType == LongType) { - dstId.toString.toLong - } else { - MurmurHash2.hash64(dstId, dstId.length, 0xc70f6907) - } - + val srcId = row.get(0) + val dstId = row.get(1) + val edgeSrc = srcId.toString.toLong + val edgeDst = dstId.toString.toLong val edgeProp = (row.get(2).toString.toLong, props.toList) org.apache.spark.graphx .Edge(edgeSrc, edgeDst, edgeProp) From 764cf8c20a7b07b6fae4eecb76a416c0546e30ed Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Wed, 25 Aug 2021 09:56:38 +0800 Subject: [PATCH 188/213] add cache for dataframe --- .../main/scala/com/vesoft/nebula/exchange/Exchange.scala | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index 9624b56..34068ce 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -135,6 +135,7 @@ object Exchange { val data = createDataSource(spark, tagConfig.dataSourceConfigEntry) if (data.isDefined && !c.dry) { + data.get.cache() val count = data.get.count() val startTime = System.currentTimeMillis() val batchSuccess = @@ -179,6 +180,7 @@ object Exchange { LOG.info(s"nebula keys: ${nebulaKeys.mkString(", ")}") val data = createDataSource(spark, edgeConfig.dataSourceConfigEntry) if (data.isDefined && !c.dry) { + data.get.cache() val count = data.get.count() val startTime = System.currentTimeMillis() val batchSuccess = spark.sparkContext.longAccumulator(s"batchSuccess.${edgeConfig.name}") @@ -216,9 +218,10 @@ object Exchange { val batchSuccess = spark.sparkContext.longAccumulator(s"batchSuccess.reimport") val batchFailure = spark.sparkContext.longAccumulator(s"batchFailure.reimport") val data = spark.read.text(configs.errorConfig.errorPath) - val count = data.count() - val startTime = System.currentTimeMillis() - val processor = new ReloadProcessor(data, configs, batchSuccess, batchFailure) + data.cache() + val count = data.count() + val startTime = System.currentTimeMillis() + val processor = new ReloadProcessor(data, configs, batchSuccess, batchFailure) processor.process() val costTime = ((System.currentTimeMillis() - startTime) / 1000.0).formatted("%.2f") LOG.info(s"reimport ngql count: ${count}, cost time: ${costTime}") From d26079740c281119c0093f922a3f9cb524f051fd Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Wed, 25 Aug 2021 10:37:54 +0800 Subject: [PATCH 189/213] modify snapshot version --- nebula-algorithm/pom.xml | 4 ++-- nebula-exchange/pom.xml | 2 +- nebula-spark-connector/pom.xml | 2 +- pom.xml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/nebula-algorithm/pom.xml b/nebula-algorithm/pom.xml index a4b433e..2fbbc92 100644 --- a/nebula-algorithm/pom.xml +++ b/nebula-algorithm/pom.xml @@ -6,7 +6,7 @@ nebula-spark com.vesoft - 2.0-SNAPSHOT + 2.5-SNAPSHOT ../pom.xml 4.0.0 @@ -288,4 +288,4 @@ - \ No newline at end of file + diff --git a/nebula-exchange/pom.xml b/nebula-exchange/pom.xml index cb92bc5..78d6d87 100644 --- a/nebula-exchange/pom.xml +++ b/nebula-exchange/pom.xml @@ -5,7 +5,7 @@ nebula-spark com.vesoft - 2.0-SNAPSHOT + 2.5-SNAPSHOT ../pom.xml 4.0.0 diff --git a/nebula-spark-connector/pom.xml b/nebula-spark-connector/pom.xml index a946aa4..20d5c3a 100644 --- a/nebula-spark-connector/pom.xml +++ b/nebula-spark-connector/pom.xml @@ -5,7 +5,7 @@ nebula-spark com.vesoft - 2.0-SNAPSHOT + 2.5-SNAPSHOT ../pom.xml 4.0.0 diff --git a/pom.xml b/pom.xml index ebbd7ca..0ada1c3 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ com.vesoft nebula-spark pom - 2.0-SNAPSHOT + 2.5-SNAPSHOT UTF-8 From 61afff1e2f4893819640f06fb9c1226d232c419f Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Fri, 27 Aug 2021 17:17:24 +0800 Subject: [PATCH 190/213] update SNAPSHOT version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 42c2f85..5cb2a12 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ There are the version correspondence between Nebula Spark utils and Nebula: | 2.0.1 | 2.0.1 | -- | 2.0.0, 2.0.1 | | 2.1.0 | 2.1.0 | 2.1.0 | 2.0.0, 2.0.1 | | 2.5.0 | 2.5.0 | 2.5.0 | 2.5.0 | -| 2.0-SNAPSHOT | 2.0-SNAPSHOT | 2.0-SNAPSHOT | v2-nightly | +| 2.5-SNAPSHOT | 2.5-SNAPSHOT | 2.5-SNAPSHOT | v2-nightly | If the Nebula version and the uitls' version are not in the same line, then they are incompatible. For Nebula Graph v2.x, see [nebula-graph](https://github.com/vesoft-inc/nebula-graph). From 62f86855b968753c747faac33943407512db94b6 Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Fri, 27 Aug 2021 17:17:58 +0800 Subject: [PATCH 191/213] use latest version --- example/pom.xml | 6 +++--- nebula-algorithm/pom.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/example/pom.xml b/example/pom.xml index 8c35472..370941d 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -5,7 +5,7 @@ nebula-spark com.vesoft - 2.0-SNAPSHOT + 2.5-SNAPSHOT ../pom.xml 4.0.0 @@ -158,7 +158,7 @@ com.vesoft nebula-spark-connector - 2.0-SNAPSHOT + 2.5-SNAPSHOT - \ No newline at end of file + diff --git a/nebula-algorithm/pom.xml b/nebula-algorithm/pom.xml index 2fbbc92..f37a49e 100644 --- a/nebula-algorithm/pom.xml +++ b/nebula-algorithm/pom.xml @@ -15,7 +15,7 @@ 2.4.4 - 2.0-SNAPSHOT + 2.5-SNAPSHOT 1.4.0 3.7.1 3.2.0 From 604ddcbfe9f1b02667b82c568ebd5992d51976ee Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Mon, 30 Aug 2021 09:02:30 +0800 Subject: [PATCH 192/213] fix hash policy for vertexId --- .../vesoft/nebula/connector/Template.scala | 2 +- .../writer/NebulaExecutorSuite.scala | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala index 0f1f911..c65a889 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala @@ -10,7 +10,7 @@ object NebulaTemplate { private[connector] val BATCH_INSERT_TEMPLATE = "INSERT %s `%s`(%s) VALUES %s" private[connector] val VERTEX_VALUE_TEMPLATE = "%s: (%s)" - private[connector] val VERTEX_VALUE_TEMPLATE_WITH_POLICY = "%s(%s): (%s)" + private[connector] val VERTEX_VALUE_TEMPLATE_WITH_POLICY = "%s(\"%s\"): (%s)" private[connector] val ENDPOINT_TEMPLATE = "%s(\"%s\")" private[connector] val EDGE_VALUE_WITHOUT_RANKING_TEMPLATE = "%s->%s: (%s)" private[connector] val EDGE_VALUE_TEMPLATE = "%s->%s@%d: (%s)" diff --git a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala index c273a5b..c838ed8 100644 --- a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala +++ b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala @@ -146,6 +146,32 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { assert(expectStatement.equals(vertexStatement)) } + test("test toExecuteSentence for vertex with hash policy") { + val vertices: ListBuffer[NebulaVertex] = new ListBuffer[NebulaVertex] + val tagName = "person" + val propNames = List("col_string", + "col_fixed_string", + "col_bool", + "col_int", + "col_int64", + "col_double", + "col_date") + + val props1 = List("\"Tom\"", "\"Tom\"", true, 10, 100L, 1.0, "2021-11-12") + val props2 = List("\"Bob\"", "\"Bob\"", false, 20, 200L, 2.0, "2021-05-01") + vertices.append(NebulaVertex("vid1", props1)) + vertices.append(NebulaVertex("vid2", props2)) + + val nebulaVertices = NebulaVertices(propNames, vertices.toList, Some(KeyPolicy.HASH)) + val vertexStatement = NebulaExecutor.toExecuteSentence(tagName, nebulaVertices) + + val expectStatement = "INSERT vertex `person`(`col_string`,`col_fixed_string`,`col_bool`," + + "`col_int`,`col_int64`,`col_double`,`col_date`) VALUES hash(\"vid1\"): (" + props1.mkString( + ", ") + + "), hash(\"vid2\"): (" + props2.mkString(", ") + ")" + assert(expectStatement.equals(vertexStatement)) + } + test("test toExecuteSentence for edge") { val edges: ListBuffer[NebulaEdge] = new ListBuffer[NebulaEdge] val edgeName = "friend" From 2873780ce796dffb855f4c57c5953354e3b19009 Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Fri, 27 Aug 2021 16:58:32 +0800 Subject: [PATCH 193/213] add example for DELETE mode --- .../connector/NebulaSparkWriterExample.scala | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala index d62c2dd..11eea86 100644 --- a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala +++ b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala @@ -40,6 +40,8 @@ object NebulaSparkWriterExample { updateVertex(spark) updateEdge(spark) + deleteVertex(spark) + spark.close() } @@ -164,4 +166,56 @@ object NebulaSparkWriterExample { df.write.nebula(config, nebulaWriteEdgeConfig).writeEdges() } + def deleteVertex(spark: SparkSession): Unit = { + LOG.info("start to delete nebula vertices") + val df = spark.read + .json("example/src/main/resources/vertex") + .select("id") + df.show() + df.persist(StorageLevel.MEMORY_AND_DISK_SER) + + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.01:9559") + .withGraphAddress("127.0.0.1:9669") + .build() + val nebulaWriteVertexConfig: WriteNebulaVertexConfig = WriteNebulaVertexConfig + .builder() + .withSpace("test") + .withVidField("id") + .withBatch(1) + .withUser("root") + .withPasswd("nebula") + .withWriteMode(WriteMode.DELETE) + .build() + df.write.nebula(config, nebulaWriteVertexConfig).writeVertices() + } + + def deletEdge(spark: SparkSession): Unit = { + LOG.info("start to delete nebula edges") + val df = spark.read + .json("example/src/main/resources/edge") + .select("src", "dst", "degree", "descr") + df.show() + df.persist(StorageLevel.MEMORY_AND_DISK_SER) + + val config = + NebulaConnectionConfig + .builder() + .withMetaAddress("127.0.0.1:9559") + .withGraphAddress("127.0.0.1:9669") + .build() + val nebulaWriteEdgeConfig: WriteNebulaEdgeConfig = WriteNebulaEdgeConfig + .builder() + .withSpace("test") + .withSrcIdField("src") + .withDstIdField("dst") + .withRankField("degree") + .withBatch(1000) + .withWriteMode(WriteMode.DELETE) + .build() + df.write.nebula(config, nebulaWriteEdgeConfig).writeEdges() + } + } From 9067182089f0ed7936c50241c4708c34f046f086 Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Fri, 27 Aug 2021 16:58:51 +0800 Subject: [PATCH 194/213] support DELETE mode for connector --- .../nebula/connector/NebulaConfig.scala | 14 ++- .../vesoft/nebula/connector/NebulaEnum.scala | 1 + .../vesoft/nebula/connector/Template.scala | 4 + .../connector/writer/NebulaEdgeWriter.scala | 28 +++-- .../connector/writer/NebulaExecutor.scala | 66 +++++++++- .../connector/writer/NebulaVertexWriter.scala | 23 ++-- .../writer/NebulaExecutorSuite.scala | 119 +++++++++++++++++- 7 files changed, 232 insertions(+), 23 deletions(-) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala index 83d6627..f4b3f37 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala @@ -217,7 +217,7 @@ object WriteNebulaVertexConfig { private def check(): Unit = { assert(space != null && !space.isEmpty, s"config space is empty.") - assert(tagName != null && !tagName.isEmpty, s"config tagName is empty.") + assert(vidField != null && !vidField.isEmpty, "config vidField is empty.") assert(batch > 0, s"config batch must be positive, your batch is $batch.") assert( @@ -234,6 +234,11 @@ object WriteNebulaVertexConfig { case e: Throwable => assert(false, s"optional write mode: insert or update, your write mode is $writeMode") } + if (!writeMode.equalsIgnoreCase(WriteMode.DELETE.toString)) { + assert(tagName != null && !tagName.isEmpty, s"config tagName is empty.") + } else { + if (tagName == null) tagName = "tag" + } LOG.info( s"NebulaWriteVertexConfig={space=$space,tagName=$tagName,vidField=$vidField,vidPolicy=$vidPolicy,batch=$batch,writeMode=$writeMode}") } @@ -428,7 +433,7 @@ object WriteNebulaEdgeConfig { private def check(): Unit = { assert(space != null && !space.isEmpty, s"config space is empty.") - assert(edgeName != null && !edgeName.isEmpty, s"config edgeName is empty.") + assert(srcIdField != null && !srcIdField.isEmpty, "config srcIdField is empty.") assert(dstIdField != null && !dstIdField.isEmpty, "config dstIdField is empty.") assert( @@ -452,6 +457,11 @@ object WriteNebulaEdgeConfig { case e: Throwable => assert(false, s"optional write mode: insert or update, your write mode is $writeMode") } + if (!writeMode.equalsIgnoreCase(WriteMode.DELETE.toString)) { + assert(edgeName != null && !edgeName.isEmpty, s"config edgeName is empty.") + } else { + if (edgeName == null) edgeName = "edge" + } LOG.info( s"NebulaWriteEdgeConfig={space=$space,edgeName=$edgeName,srcField=$srcIdField,srcPolicy=$srcPolicy,dstField=$dstIdField,dstPolicy=$dstPolicy,rankField=$rankField,writeMode=$writeMode}") } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaEnum.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaEnum.scala index 4bf8366..f60751b 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaEnum.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaEnum.scala @@ -36,4 +36,5 @@ object WriteMode extends Enumeration { type Mode = Value val INSERT = Value("insert") val UPDATE = Value("update") + val DELETE = Value("delete") } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala index c65a889..e1f72bd 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala @@ -19,4 +19,8 @@ object NebulaTemplate { private[connector] val UPDATE_VERTEX_TEMPLATE = "UPDATE %s ON `%s` %s SET %s" private[connector] val UPDATE_EDGE_TEMPLATE = "UPDATE %s ON `%s` %s->%s@%d SET %s" private[connector] val UPDATE_VALUE_TEMPLATE = "`%s`=%s" + + private[connector] val DELETE_VERTEX_TEMPLATE = "DELETE VERTEX %s" + private[connector] val DELETE_EDGE_TEMPLATE = "DELETE EDGE %s" + private[connector] val EDGE_ENDPOINT_TEMPLATE = "%s->%s@%d" } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala index 7dfe283..9f629e8 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala @@ -33,7 +33,9 @@ class NebulaEdgeWriter(nebulaOptions: NebulaOptions, nebulaOptions.srcAsProp, nebulaOptions.dstAsProp, nebulaOptions.rankAsProp) - val fieldTypMap = metaProvider.getEdgeSchema(nebulaOptions.spaceName, nebulaOptions.label) + val fieldTypMap: Map[String, Integer] = + if (nebulaOptions.writeMode == WriteMode.DELETE) Map[String, Integer]() + else metaProvider.getEdgeSchema(nebulaOptions.spaceName, nebulaOptions.label) val srcPolicy = if (nebulaOptions.srcPolicy.isEmpty) Option.empty @@ -58,15 +60,17 @@ class NebulaEdgeWriter(nebulaOptions: NebulaOptions, if (rankIndex.isEmpty) Option.empty else Option(NebulaExecutor.extraRank(schema, row, rankIndex.get)) val values = - NebulaExecutor.assignEdgeValues(schema, - row, - srcIndex, - dstIndex, - rankIdx, - nebulaOptions.srcAsProp, - nebulaOptions.dstAsProp, - nebulaOptions.rankAsProp, - fieldTypMap) + if (nebulaOptions.writeMode == WriteMode.DELETE) List() + else + NebulaExecutor.assignEdgeValues(schema, + row, + srcIndex, + dstIndex, + rankIdx, + nebulaOptions.srcAsProp, + nebulaOptions.dstAsProp, + nebulaOptions.rankAsProp, + fieldTypMap) val nebulaEdge = NebulaEdge(srcId, dstId, rank, values) edges.append(nebulaEdge) if (edges.size >= nebulaOptions.batch) { @@ -78,12 +82,14 @@ class NebulaEdgeWriter(nebulaOptions: NebulaOptions, val nebulaEdges = NebulaEdges(propNames, edges.toList, srcPolicy, dstPolicy) val exec = if (nebulaOptions.writeMode == WriteMode.INSERT) { NebulaExecutor.toExecuteSentence(nebulaOptions.label, nebulaEdges) - } else { + } else if (nebulaOptions.writeMode == WriteMode.UPDATE) { nebulaEdges.values .map { edge => NebulaExecutor.toUpdateExecuteStatement(nebulaOptions.label, nebulaEdges.propNames, edge) } .mkString(";") + } else { + NebulaExecutor.toDeleteExecuteStatement(nebulaEdges) } edges.clear() submit(exec) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala index c02c336..37d0441 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala @@ -8,6 +8,9 @@ package com.vesoft.nebula.connector.writer import com.vesoft.nebula.connector.NebulaTemplate.{ BATCH_INSERT_TEMPLATE, + DELETE_EDGE_TEMPLATE, + DELETE_VERTEX_TEMPLATE, + EDGE_ENDPOINT_TEMPLATE, EDGE_VALUE_TEMPLATE, EDGE_VALUE_WITHOUT_RANKING_TEMPLATE, ENDPOINT_TEMPLATE, @@ -298,12 +301,13 @@ object NebulaExecutor { propertyNames: PropertyNames, edge: NebulaEdge): String = { var index = 0 + val rank = if (edge.rank.isEmpty) { 0 } else { edge.rank.get } UPDATE_EDGE_TEMPLATE.format( DataTypeEnum.EDGE.toString.toUpperCase, edgeName, edge.source, edge.target, - edge.rank.get, + rank, edge.values .map { value => val updateValue = UPDATE_VALUE_TEMPLATE.format(propertyNames.get(index), value) @@ -314,6 +318,66 @@ object NebulaExecutor { ) } + /** + * construct delete statement for vertex + */ + def toDeleteExecuteStatement(vertices: NebulaVertices): String = { + DELETE_VERTEX_TEMPLATE.format( + vertices.values + .map { value => + vertices.policy match { + case Some(KeyPolicy.HASH) => + ENDPOINT_TEMPLATE.format(KeyPolicy.HASH.toString, value.vertexIDSlice) + + case Some(KeyPolicy.UUID) => + ENDPOINT_TEMPLATE.format(KeyPolicy.UUID.toString, value.vertexIDSlice) + + case None => + value.vertexIDSlice + case _ => + throw new IllegalArgumentException( + s"vertex policy ${vertices.policy.get} is not supported") + } + } + .mkString(",") + ) + } + + /** + * construct delete statement for edge + */ + def toDeleteExecuteStatement(edges: NebulaEdges): String = { + DELETE_EDGE_TEMPLATE.format( + edges.values + .map { value => + EDGE_ENDPOINT_TEMPLATE.format( + edges.getSourcePolicy match { + case Some(KeyPolicy.HASH) => + ENDPOINT_TEMPLATE.format(KeyPolicy.HASH.toString, value.source) + case Some(KeyPolicy.UUID) => + ENDPOINT_TEMPLATE.format(KeyPolicy.UUID.toString, value.source) + case None => value.source + case _ => + throw new IllegalArgumentException( + s"source vertex policy ${edges.getSourcePolicy.get} is not supported") + }, + edges.getTargetPolicy match { + case Some(KeyPolicy.HASH) => + ENDPOINT_TEMPLATE.format(KeyPolicy.HASH.toString, value.target) + case Some(KeyPolicy.UUID) => + ENDPOINT_TEMPLATE.format(KeyPolicy.UUID.toString, value.target) + case None => value.target + case _ => + throw new IllegalArgumentException( + s"target vertex policy ${edges.getTargetPolicy.get} is not supported") + }, + if (value.rank.isEmpty) 0 else value.rank.get + ) + } + .mkString(",") + ) + } + /** * escape nebula property name, add `` for each property. * diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala index c663765..dba1fc7 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala @@ -21,8 +21,10 @@ class NebulaVertexWriter(nebulaOptions: NebulaOptions, vertexIndex: Int, schema: private val LOG = LoggerFactory.getLogger(this.getClass) - val propNames = NebulaExecutor.assignVertexPropNames(schema, vertexIndex, nebulaOptions.vidAsProp) - val fieldTypMap = metaProvider.getTagSchema(nebulaOptions.spaceName, nebulaOptions.label) + val propNames = NebulaExecutor.assignVertexPropNames(schema, vertexIndex, nebulaOptions.vidAsProp) + val fieldTypMap: Map[String, Integer] = + if (nebulaOptions.writeMode == WriteMode.DELETE) Map[String, Integer]() + else metaProvider.getTagSchema(nebulaOptions.spaceName, nebulaOptions.label) val policy = { if (nebulaOptions.vidPolicy.isEmpty) Option.empty @@ -40,11 +42,14 @@ class NebulaVertexWriter(nebulaOptions: NebulaOptions, vertexIndex: Int, schema: override def write(row: InternalRow): Unit = { val vertex = NebulaExecutor.extraID(schema, row, vertexIndex, policy, isVidStringType) - val values = NebulaExecutor.assignVertexPropValues(schema, - row, - vertexIndex, - nebulaOptions.vidAsProp, - fieldTypMap) + val values = + if (nebulaOptions.writeMode == WriteMode.DELETE) List() + else + NebulaExecutor.assignVertexPropValues(schema, + row, + vertexIndex, + nebulaOptions.vidAsProp, + fieldTypMap) val nebulaVertex = NebulaVertex(vertex, values) vertices.append(nebulaVertex) if (vertices.size >= nebulaOptions.batch) { @@ -56,7 +61,7 @@ class NebulaVertexWriter(nebulaOptions: NebulaOptions, vertexIndex: Int, schema: val nebulaVertices = NebulaVertices(propNames, vertices.toList, policy) val exec = if (nebulaOptions.writeMode == WriteMode.INSERT) { NebulaExecutor.toExecuteSentence(nebulaOptions.label, nebulaVertices) - } else { + } else if (nebulaOptions.writeMode == WriteMode.UPDATE) { nebulaVertices.values .map { vertex => NebulaExecutor.toUpdateExecuteStatement(nebulaOptions.label, @@ -64,6 +69,8 @@ class NebulaVertexWriter(nebulaOptions: NebulaOptions, vertexIndex: Int, schema: vertex) } .mkString(";") + } else { + NebulaExecutor.toDeleteExecuteStatement(nebulaVertices) } vertices.clear() submit(exec) diff --git a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala index c838ed8..f13512a 100644 --- a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala +++ b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala @@ -172,6 +172,32 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { assert(expectStatement.equals(vertexStatement)) } + test("test toExecuteSentence for vertex with hash policy") { + val vertices: ListBuffer[NebulaVertex] = new ListBuffer[NebulaVertex] + val tagName = "person" + val propNames = List("col_string", + "col_fixed_string", + "col_bool", + "col_int", + "col_int64", + "col_double", + "col_date") + + val props1 = List("\"Tom\"", "\"Tom\"", true, 10, 100L, 1.0, "2021-11-12") + val props2 = List("\"Bob\"", "\"Bob\"", false, 20, 200L, 2.0, "2021-05-01") + vertices.append(NebulaVertex("\"vid1\"", props1)) + vertices.append(NebulaVertex("\"vid2\"", props2)) + + val nebulaVertices = NebulaVertices(propNames, vertices.toList, Some(KeyPolicy.HASH)) + val vertexStatement = NebulaExecutor.toExecuteSentence(tagName, nebulaVertices) + + val expectStatement = "INSERT vertex `person`(`col_string`,`col_fixed_string`,`col_bool`," + + "`col_int`,`col_int64`,`col_double`,`col_date`) VALUES hash(\"vid1\"): (" + props1.mkString( + ", ") + + "), hash(\"vid2\"): (" + props2.mkString(", ") + ")" + assert(expectStatement.equals(vertexStatement)) + } + test("test toExecuteSentence for edge") { val edges: ListBuffer[NebulaEdge] = new ListBuffer[NebulaEdge] val edgeName = "friend" @@ -228,7 +254,30 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { val source = "\"source\"" val target = "\"target\"" - val rank = Some(0L) + val rank = Some(1L) + val nebulaEdge = NebulaEdge(source, target, rank, props) + val updateEdgeStatement = + NebulaExecutor.toUpdateExecuteStatement("friend", propNames, nebulaEdge) + val expectEdgeUpdate = + "UPDATE EDGE ON `friend` \"source\"->\"target\"@1 SET `col_string`=\"name\"," + + "`col_fixed_string`=\"name\",`col_bool`=true,`col_int`=10,`col_int64`=100," + + "`col_double`=1.0,`col_date`=2021-11-12" + assert(expectEdgeUpdate.equals(updateEdgeStatement)) + } + + test("test toUpdateExecuteSentence for edge without rank") { + val props = List("\"name\"", "\"name\"", true, 10, 100L, 1.0, "2021-11-12") + val propNames = List("col_string", + "col_fixed_string", + "col_bool", + "col_int", + "col_int64", + "col_double", + "col_date") + + val source = "\"source\"" + val target = "\"target\"" + val rank = Option.empty val nebulaEdge = NebulaEdge(source, target, rank, props) val updateEdgeStatement = NebulaExecutor.toUpdateExecuteStatement("friend", propNames, nebulaEdge) @@ -238,4 +287,72 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { "`col_double`=1.0,`col_date`=2021-11-12" assert(expectEdgeUpdate.equals(updateEdgeStatement)) } + + test("test toDeleteExecuteStatement for vertex") { + val vertices: ListBuffer[NebulaVertex] = new ListBuffer[NebulaVertex] + vertices.append(NebulaVertex("\"vid1\"", List())) + vertices.append(NebulaVertex("\"vid2\"", List())) + + val nebulaVertices = NebulaVertices(List(), vertices.toList, None) + val vertexStatement = NebulaExecutor.toDeleteExecuteStatement(nebulaVertices) + val expectVertexDeleteStatement = "DELETE VERTEX \"vid1\",\"vid2\"" + assert(expectVertexDeleteStatement.equals(vertexStatement)) + } + + test("test toDeleteExecuteStatement for vertex with HASH policy") { + val vertices: ListBuffer[NebulaVertex] = new ListBuffer[NebulaVertex] + vertices.append(NebulaVertex("vid1", List())) + vertices.append(NebulaVertex("vid2", List())) + + val nebulaVertices = NebulaVertices(List(), vertices.toList, Some(KeyPolicy.HASH)) + val vertexStatement = NebulaExecutor.toDeleteExecuteStatement(nebulaVertices) + val expectVertexDeleteStatement = "DELETE VERTEX hash(\"vid1\"),hash(\"vid2\")" + assert(expectVertexDeleteStatement.equals(vertexStatement)) + } + + test("test toDeleteExecuteStatement for edge") { + val edges: ListBuffer[NebulaEdge] = new ListBuffer[NebulaEdge] + edges.append(NebulaEdge("\"vid1\"", "\"vid2\"", Some(1L), List())) + edges.append(NebulaEdge("\"vid2\"", "\"vid1\"", Some(2L), List())) + + val nebulaEdges = NebulaEdges(List(), edges.toList, None, None) + val edgeStatement = NebulaExecutor.toDeleteExecuteStatement(nebulaEdges) + val expectEdgeDeleteStatement = "DELETE EDGE \"vid1\"->\"vid2\"@1,\"vid2\"->\"vid1\"@2" + assert(expectEdgeDeleteStatement.equals(edgeStatement)) + } + + test("test toDeleteExecuteStatement for edge without rank") { + val edges: ListBuffer[NebulaEdge] = new ListBuffer[NebulaEdge] + edges.append(NebulaEdge("\"vid1\"", "\"vid2\"", Option.empty, List())) + edges.append(NebulaEdge("\"vid2\"", "\"vid1\"", Option.empty, List())) + + val nebulaEdges = NebulaEdges(List(), edges.toList, None, None) + val edgeStatement = NebulaExecutor.toDeleteExecuteStatement(nebulaEdges) + val expectEdgeDeleteStatement = "DELETE EDGE \"vid1\"->\"vid2\"@0,\"vid2\"->\"vid1\"@0" + assert(expectEdgeDeleteStatement.equals(edgeStatement)) + } + + test("test toDeleteExecuteStatement for edge with src HASH policy") { + val edges: ListBuffer[NebulaEdge] = new ListBuffer[NebulaEdge] + edges.append(NebulaEdge("vid1", "\"vid2\"", Some(1L), List())) + edges.append(NebulaEdge("vid2", "\"vid1\"", Some(2L), List())) + + val nebulaEdges = NebulaEdges(List(), edges.toList, Some(KeyPolicy.HASH), None) + val edgeStatement = NebulaExecutor.toDeleteExecuteStatement(nebulaEdges) + val expectEdgeDeleteStatement = + "DELETE EDGE hash(\"vid1\")->\"vid2\"@1,hash(\"vid2\")->\"vid1\"@2" + assert(expectEdgeDeleteStatement.equals(edgeStatement)) + } + + test("test toDeleteExecuteStatement for edge with all HASH policy") { + val edges: ListBuffer[NebulaEdge] = new ListBuffer[NebulaEdge] + edges.append(NebulaEdge("vid1", "vid2", Some(1L), List())) + edges.append(NebulaEdge("vid2", "vid1", Some(2L), List())) + + val nebulaEdges = NebulaEdges(List(), edges.toList, Some(KeyPolicy.HASH), Some(KeyPolicy.HASH)) + val edgeStatement = NebulaExecutor.toDeleteExecuteStatement(nebulaEdges) + val expectEdgeDeleteStatement = + "DELETE EDGE hash(\"vid1\")->hash(\"vid2\")@1,hash(\"vid2\")->hash(\"vid1\")@2" + assert(expectEdgeDeleteStatement.equals(edgeStatement)) + } } From 17c00280a9a7b5e50d9b18fdebbb8aad42dfd072 Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Fri, 3 Sep 2021 09:29:04 +0800 Subject: [PATCH 195/213] support delete mode for connector --- .../nebula/connector/NebulaConfig.scala | 16 ++++--- .../vesoft/nebula/connector/Template.scala | 2 +- .../connector/writer/NebulaEdgeWriter.scala | 2 +- .../connector/writer/NebulaExecutor.scala | 3 +- .../writer/NebulaExecutorSuite.scala | 42 ++++--------------- 5 files changed, 19 insertions(+), 46 deletions(-) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala index f4b3f37..9a8a3ec 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaConfig.scala @@ -7,7 +7,6 @@ package com.vesoft.nebula.connector import org.slf4j.{Logger, LoggerFactory} - import scala.collection.mutable.ListBuffer class NebulaConnectionConfig(metaAddress: String, @@ -237,10 +236,11 @@ object WriteNebulaVertexConfig { if (!writeMode.equalsIgnoreCase(WriteMode.DELETE.toString)) { assert(tagName != null && !tagName.isEmpty, s"config tagName is empty.") } else { - if (tagName == null) tagName = "tag" + if (tagName == null) tagName = "tag" // set a default for delete mode, happy to pass the option check. } LOG.info( - s"NebulaWriteVertexConfig={space=$space,tagName=$tagName,vidField=$vidField,vidPolicy=$vidPolicy,batch=$batch,writeMode=$writeMode}") + s"NebulaWriteVertexConfig={space=$space,tagName=$tagName,vidField=$vidField," + + s"vidPolicy=$vidPolicy,batch=$batch,writeMode=$writeMode}") } } @@ -457,13 +457,11 @@ object WriteNebulaEdgeConfig { case e: Throwable => assert(false, s"optional write mode: insert or update, your write mode is $writeMode") } - if (!writeMode.equalsIgnoreCase(WriteMode.DELETE.toString)) { - assert(edgeName != null && !edgeName.isEmpty, s"config edgeName is empty.") - } else { - if (edgeName == null) edgeName = "edge" - } + assert(edgeName != null && !edgeName.isEmpty, s"config edgeName is empty.") LOG.info( - s"NebulaWriteEdgeConfig={space=$space,edgeName=$edgeName,srcField=$srcIdField,srcPolicy=$srcPolicy,dstField=$dstIdField,dstPolicy=$dstPolicy,rankField=$rankField,writeMode=$writeMode}") + s"NebulaWriteEdgeConfig={space=$space,edgeName=$edgeName,srcField=$srcIdField," + + s"srcPolicy=$srcPolicy,dstField=$dstIdField,dstPolicy=$dstPolicy,rankField=$rankField," + + s"writeMode=$writeMode}") } } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala index e1f72bd..d6c0bfd 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala @@ -21,6 +21,6 @@ object NebulaTemplate { private[connector] val UPDATE_VALUE_TEMPLATE = "`%s`=%s" private[connector] val DELETE_VERTEX_TEMPLATE = "DELETE VERTEX %s" - private[connector] val DELETE_EDGE_TEMPLATE = "DELETE EDGE %s" + private[connector] val DELETE_EDGE_TEMPLATE = "DELETE EDGE %s %s" private[connector] val EDGE_ENDPOINT_TEMPLATE = "%s->%s@%d" } diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala index 9f629e8..b6272c2 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala @@ -89,7 +89,7 @@ class NebulaEdgeWriter(nebulaOptions: NebulaOptions, } .mkString(";") } else { - NebulaExecutor.toDeleteExecuteStatement(nebulaEdges) + NebulaExecutor.toDeleteExecuteStatement(nebulaOptions.label, nebulaEdges) } edges.clear() submit(exec) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala index 37d0441..4968ecf 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala @@ -346,8 +346,9 @@ object NebulaExecutor { /** * construct delete statement for edge */ - def toDeleteExecuteStatement(edges: NebulaEdges): String = { + def toDeleteExecuteStatement(edgeName: String, edges: NebulaEdges): String = { DELETE_EDGE_TEMPLATE.format( + edgeName, edges.values .map { value => EDGE_ENDPOINT_TEMPLATE.format( diff --git a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala index f13512a..898cf0c 100644 --- a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala +++ b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala @@ -172,32 +172,6 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { assert(expectStatement.equals(vertexStatement)) } - test("test toExecuteSentence for vertex with hash policy") { - val vertices: ListBuffer[NebulaVertex] = new ListBuffer[NebulaVertex] - val tagName = "person" - val propNames = List("col_string", - "col_fixed_string", - "col_bool", - "col_int", - "col_int64", - "col_double", - "col_date") - - val props1 = List("\"Tom\"", "\"Tom\"", true, 10, 100L, 1.0, "2021-11-12") - val props2 = List("\"Bob\"", "\"Bob\"", false, 20, 200L, 2.0, "2021-05-01") - vertices.append(NebulaVertex("\"vid1\"", props1)) - vertices.append(NebulaVertex("\"vid2\"", props2)) - - val nebulaVertices = NebulaVertices(propNames, vertices.toList, Some(KeyPolicy.HASH)) - val vertexStatement = NebulaExecutor.toExecuteSentence(tagName, nebulaVertices) - - val expectStatement = "INSERT vertex `person`(`col_string`,`col_fixed_string`,`col_bool`," + - "`col_int`,`col_int64`,`col_double`,`col_date`) VALUES hash(\"vid1\"): (" + props1.mkString( - ", ") + - "), hash(\"vid2\"): (" + props2.mkString(", ") + ")" - assert(expectStatement.equals(vertexStatement)) - } - test("test toExecuteSentence for edge") { val edges: ListBuffer[NebulaEdge] = new ListBuffer[NebulaEdge] val edgeName = "friend" @@ -316,8 +290,8 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { edges.append(NebulaEdge("\"vid2\"", "\"vid1\"", Some(2L), List())) val nebulaEdges = NebulaEdges(List(), edges.toList, None, None) - val edgeStatement = NebulaExecutor.toDeleteExecuteStatement(nebulaEdges) - val expectEdgeDeleteStatement = "DELETE EDGE \"vid1\"->\"vid2\"@1,\"vid2\"->\"vid1\"@2" + val edgeStatement = NebulaExecutor.toDeleteExecuteStatement("friend", nebulaEdges) + val expectEdgeDeleteStatement = "DELETE EDGE friend \"vid1\"->\"vid2\"@1,\"vid2\"->\"vid1\"@2" assert(expectEdgeDeleteStatement.equals(edgeStatement)) } @@ -327,8 +301,8 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { edges.append(NebulaEdge("\"vid2\"", "\"vid1\"", Option.empty, List())) val nebulaEdges = NebulaEdges(List(), edges.toList, None, None) - val edgeStatement = NebulaExecutor.toDeleteExecuteStatement(nebulaEdges) - val expectEdgeDeleteStatement = "DELETE EDGE \"vid1\"->\"vid2\"@0,\"vid2\"->\"vid1\"@0" + val edgeStatement = NebulaExecutor.toDeleteExecuteStatement("friend", nebulaEdges) + val expectEdgeDeleteStatement = "DELETE EDGE friend \"vid1\"->\"vid2\"@0,\"vid2\"->\"vid1\"@0" assert(expectEdgeDeleteStatement.equals(edgeStatement)) } @@ -338,9 +312,9 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { edges.append(NebulaEdge("vid2", "\"vid1\"", Some(2L), List())) val nebulaEdges = NebulaEdges(List(), edges.toList, Some(KeyPolicy.HASH), None) - val edgeStatement = NebulaExecutor.toDeleteExecuteStatement(nebulaEdges) + val edgeStatement = NebulaExecutor.toDeleteExecuteStatement("friend", nebulaEdges) val expectEdgeDeleteStatement = - "DELETE EDGE hash(\"vid1\")->\"vid2\"@1,hash(\"vid2\")->\"vid1\"@2" + "DELETE EDGE friend hash(\"vid1\")->\"vid2\"@1,hash(\"vid2\")->\"vid1\"@2" assert(expectEdgeDeleteStatement.equals(edgeStatement)) } @@ -350,9 +324,9 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { edges.append(NebulaEdge("vid2", "vid1", Some(2L), List())) val nebulaEdges = NebulaEdges(List(), edges.toList, Some(KeyPolicy.HASH), Some(KeyPolicy.HASH)) - val edgeStatement = NebulaExecutor.toDeleteExecuteStatement(nebulaEdges) + val edgeStatement = NebulaExecutor.toDeleteExecuteStatement("friend", nebulaEdges) val expectEdgeDeleteStatement = - "DELETE EDGE hash(\"vid1\")->hash(\"vid2\")@1,hash(\"vid2\")->hash(\"vid1\")@2" + "DELETE EDGE friend hash(\"vid1\")->hash(\"vid2\")@1,hash(\"vid2\")->hash(\"vid1\")@2" assert(expectEdgeDeleteStatement.equals(edgeStatement)) } } From 4b3a814ada54b5b57e5375e2b7d7eb1aa1ce9474 Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Fri, 3 Sep 2021 09:30:27 +0800 Subject: [PATCH 196/213] update example --- .../examples/connector/NebulaSparkWriterExample.scala | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala index 11eea86..bd926ab 100644 --- a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala +++ b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala @@ -41,6 +41,7 @@ object NebulaSparkWriterExample { updateEdge(spark) deleteVertex(spark) + deleteEdge(spark) spark.close() } @@ -192,11 +193,11 @@ object NebulaSparkWriterExample { df.write.nebula(config, nebulaWriteVertexConfig).writeVertices() } - def deletEdge(spark: SparkSession): Unit = { + def deleteEdge(spark: SparkSession): Unit = { LOG.info("start to delete nebula edges") val df = spark.read .json("example/src/main/resources/edge") - .select("src", "dst", "degree", "descr") + .select("src", "dst", "degree") df.show() df.persist(StorageLevel.MEMORY_AND_DISK_SER) @@ -209,10 +210,11 @@ object NebulaSparkWriterExample { val nebulaWriteEdgeConfig: WriteNebulaEdgeConfig = WriteNebulaEdgeConfig .builder() .withSpace("test") + .withEdge("friend") .withSrcIdField("src") .withDstIdField("dst") .withRankField("degree") - .withBatch(1000) + .withBatch(10) .withWriteMode(WriteMode.DELETE) .build() df.write.nebula(config, nebulaWriteEdgeConfig).writeEdges() From 65bea548cd63a2657843a94b389d33b50cb70713 Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Mon, 6 Sep 2021 14:47:23 +0800 Subject: [PATCH 197/213] update DateTime and Time's str interface --- .../com/vesoft/nebula/connector/NebulaUtils.scala | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala index ef7da4f..2a15d0e 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/NebulaUtils.scala @@ -6,6 +6,7 @@ package com.vesoft.nebula.connector +import com.vesoft.nebula.client.graph.data.{DateTimeWrapper, DateWrapper, TimeWrapper} import com.vesoft.nebula.meta.{ColumnDef, ColumnTypeDef, PropertyType} import org.apache.spark.sql.Row import org.apache.spark.sql.catalyst.InternalRow @@ -41,7 +42,7 @@ object NebulaUtils { LongType case PropertyType.BOOL => BooleanType case PropertyType.FLOAT | PropertyType.DOUBLE => DoubleType - case PropertyType.TIMESTAMP => TimestampType + case PropertyType.TIMESTAMP => LongType case PropertyType.FIXED_STRING | PropertyType.STRING | PropertyType.DATE | PropertyType.TIME | PropertyType.DATETIME => StringType @@ -80,7 +81,14 @@ object NebulaUtils { row.setInt(pos, prop.asInstanceOf[Int]) case _ => (prop: Any, row: InternalRow, pos: Int) => - row.update(pos, UTF8String.fromString(String.valueOf(prop))) + if (prop.isInstanceOf[DateTimeWrapper]) { + row.update(pos, + UTF8String.fromString(prop.asInstanceOf[DateTimeWrapper].getUTCDateTimeStr)) + } else if (prop.isInstanceOf[TimeWrapper]) { + row.update(pos, UTF8String.fromString(prop.asInstanceOf[TimeWrapper].getUTCTimeStr)) + } else { + row.update(pos, UTF8String.fromString(String.valueOf(prop))) + } } } From 059a55a99efa7efa5f70d59ac4720d5ef5d60a32 Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Tue, 7 Sep 2021 14:20:41 +0800 Subject: [PATCH 198/213] add desc for GraphTriangleCount --- nebula-algorithm/README-CN.md | 1 + nebula-algorithm/README.md | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/nebula-algorithm/README-CN.md b/nebula-algorithm/README-CN.md index afcb7ee..0eef982 100644 --- a/nebula-algorithm/README-CN.md +++ b/nebula-algorithm/README-CN.md @@ -13,6 +13,7 @@ nebula-algorithm 是一款基于 [GraphX](https://spark.apache.org/graphx/) 的 |StronglyConnectedComponent| 强联通分量 |社区发现| | ShortestPath | 最短路径 |路径规划、网络规划| | TriangleCount | 三角形计数 |网络结构分析| + | GraphTriangleCount |全图三角形计数|网络紧密性分析| | BetweennessCentrality | 介数中心性 |关键节点挖掘,节点影响力计算| | DegreeStatic | 度统计 |图结构分析| diff --git a/nebula-algorithm/README.md b/nebula-algorithm/README.md index 60ccf65..a0f65d5 100644 --- a/nebula-algorithm/README.md +++ b/nebula-algorithm/README.md @@ -17,6 +17,7 @@ nebula-algorithm is a Spark Application based on [GraphX](https://spark.apache.o |StronglyConnectedComponent| community detection| | ShortestPath | path plan, network plan| | TriangleCount | network structure analysis| +| GraphTriangleCount | network structure and tightness analysis| | BetweennessCentrality | important node digging, node influence calculation| | DegreeStatic | graph structure analysis| @@ -82,4 +83,4 @@ Nebula Algorithm is open source, you are more than welcomed to contribute in the - Discuss in the community via [the forum](https://discuss.nebula-graph.io/) or raise issues here. - Compose or improve our documents. -- Pull Request to help improve the code itself here. \ No newline at end of file +- Pull Request to help improve the code itself here. From e1b3b019fa7d9f70f16f3258e79aa8a09775e740 Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Wed, 8 Sep 2021 10:21:26 +0800 Subject: [PATCH 199/213] fix conflict --- .../connector/writer/NebulaEdgeWriter.scala | 18 ++- .../connector/writer/NebulaExecutor.scala | 107 ++++++++++++------ .../connector/writer/NebulaVertexWriter.scala | 19 ++-- .../writer/NebulaExecutorSuite.scala | 95 +++++++++++----- 4 files changed, 155 insertions(+), 84 deletions(-) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala index b6272c2..a6b331f 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaEdgeWriter.scala @@ -80,16 +80,14 @@ class NebulaEdgeWriter(nebulaOptions: NebulaOptions, def execute(): Unit = { val nebulaEdges = NebulaEdges(propNames, edges.toList, srcPolicy, dstPolicy) - val exec = if (nebulaOptions.writeMode == WriteMode.INSERT) { - NebulaExecutor.toExecuteSentence(nebulaOptions.label, nebulaEdges) - } else if (nebulaOptions.writeMode == WriteMode.UPDATE) { - nebulaEdges.values - .map { edge => - NebulaExecutor.toUpdateExecuteStatement(nebulaOptions.label, nebulaEdges.propNames, edge) - } - .mkString(";") - } else { - NebulaExecutor.toDeleteExecuteStatement(nebulaOptions.label, nebulaEdges) + val exec = nebulaOptions.writeMode match { + case WriteMode.INSERT => NebulaExecutor.toExecuteSentence(nebulaOptions.label, nebulaEdges) + case WriteMode.UPDATE => + NebulaExecutor.toUpdateExecuteStatement(nebulaOptions.label, nebulaEdges) + case WriteMode.DELETE => + NebulaExecutor.toDeleteExecuteStatement(nebulaOptions.label, nebulaEdges) + case _ => + throw new IllegalArgumentException(s"write mode ${nebulaOptions.writeMode} not supported.") } edges.clear() submit(exec) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala index 4968ecf..797b737 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala @@ -276,46 +276,83 @@ object NebulaExecutor { /** * construct update statement for vertex */ - def toUpdateExecuteStatement(tagName: String, - propertyNames: PropertyNames, - vertex: NebulaVertex): String = { - var index = 0 - UPDATE_VERTEX_TEMPLATE.format( - DataTypeEnum.VERTEX.toString.toUpperCase, - tagName, - vertex.vertexIDSlice, - vertex.values - .map { value => - val updateValue = UPDATE_VALUE_TEMPLATE.format(propertyNames.get(index), value) - index += 1 - updateValue - } - .mkString(",") - ) + def toUpdateExecuteStatement(tagName: String, nebulaVertices: NebulaVertices): String = { + nebulaVertices.values + .map { vertex => + var index = 0 + UPDATE_VERTEX_TEMPLATE.format( + DataTypeEnum.VERTEX.toString.toUpperCase, + tagName, + nebulaVertices.policy match { + case Some(KeyPolicy.HASH) => + ENDPOINT_TEMPLATE.format(KeyPolicy.HASH.toString, vertex.vertexIDSlice) + case Some(KeyPolicy.UUID) => + ENDPOINT_TEMPLATE.format(KeyPolicy.UUID.toString, vertex.vertexIDSlice) + case None => + vertex.vertexIDSlice + case _ => + throw new IllegalArgumentException( + s"vertex id policy ${nebulaVertices.policy.get} is not supported") + }, + vertex.values + .map { value => + val updateValue = + UPDATE_VALUE_TEMPLATE.format(nebulaVertices.propNames.get(index), value) + index += 1 + updateValue + } + .mkString(",") + ) + } + .mkString(";") } /** * construct update statement for edge */ - def toUpdateExecuteStatement(edgeName: String, - propertyNames: PropertyNames, - edge: NebulaEdge): String = { - var index = 0 - val rank = if (edge.rank.isEmpty) { 0 } else { edge.rank.get } - UPDATE_EDGE_TEMPLATE.format( - DataTypeEnum.EDGE.toString.toUpperCase, - edgeName, - edge.source, - edge.target, - rank, - edge.values - .map { value => - val updateValue = UPDATE_VALUE_TEMPLATE.format(propertyNames.get(index), value) - index += 1 - updateValue - } - .mkString(",") - ) + def toUpdateExecuteStatement(edgeName: String, nebulaEdges: NebulaEdges): String = { + + nebulaEdges.values + .map { edge => + var index = 0 + val rank = if (edge.rank.isEmpty) { 0 } else { edge.rank.get } + UPDATE_EDGE_TEMPLATE.format( + DataTypeEnum.EDGE.toString.toUpperCase, + edgeName, + nebulaEdges.getSourcePolicy match { + case Some(KeyPolicy.HASH) => + ENDPOINT_TEMPLATE.format(KeyPolicy.HASH.toString, edge.source) + case Some(KeyPolicy.UUID) => + ENDPOINT_TEMPLATE.format(KeyPolicy.UUID.toString, edge.source) + case None => + edge.source + case _ => + throw new IllegalArgumentException( + s"source policy ${nebulaEdges.getTargetPolicy.get} is not supported") + }, + nebulaEdges.getTargetPolicy match { + case Some(KeyPolicy.HASH) => + ENDPOINT_TEMPLATE.format(KeyPolicy.HASH.toString, edge.target) + case Some(KeyPolicy.UUID) => + ENDPOINT_TEMPLATE.format(KeyPolicy.UUID.toString, edge.target) + case None => + edge.target + case _ => + throw new IllegalArgumentException( + s"target policy ${nebulaEdges.getTargetPolicy.get} is not supported") + }, + rank, + edge.values + .map { value => + val updateValue = + UPDATE_VALUE_TEMPLATE.format(nebulaEdges.propNames.get(index), value) + index += 1 + updateValue + } + .mkString(",") + ) + } + .mkString(";") } /** diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala index dba1fc7..46ec62b 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaVertexWriter.scala @@ -59,18 +59,13 @@ class NebulaVertexWriter(nebulaOptions: NebulaOptions, vertexIndex: Int, schema: def execute(): Unit = { val nebulaVertices = NebulaVertices(propNames, vertices.toList, policy) - val exec = if (nebulaOptions.writeMode == WriteMode.INSERT) { - NebulaExecutor.toExecuteSentence(nebulaOptions.label, nebulaVertices) - } else if (nebulaOptions.writeMode == WriteMode.UPDATE) { - nebulaVertices.values - .map { vertex => - NebulaExecutor.toUpdateExecuteStatement(nebulaOptions.label, - nebulaVertices.propNames, - vertex) - } - .mkString(";") - } else { - NebulaExecutor.toDeleteExecuteStatement(nebulaVertices) + val exec = nebulaOptions.writeMode match { + case WriteMode.INSERT => NebulaExecutor.toExecuteSentence(nebulaOptions.label, nebulaVertices) + case WriteMode.UPDATE => + NebulaExecutor.toUpdateExecuteStatement(nebulaOptions.label, nebulaVertices) + case WriteMode.DELETE => NebulaExecutor.toDeleteExecuteStatement(nebulaVertices) + case _ => + throw new IllegalArgumentException(s"write mode ${nebulaOptions.writeMode} not supported.") } vertices.clear() submit(exec) diff --git a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala index 898cf0c..25ece82 100644 --- a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala +++ b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala @@ -8,7 +8,6 @@ package com.vesoft.nebula.connector.writer import com.vesoft.nebula.connector.KeyPolicy import com.vesoft.nebula.connector.connector.{NebulaEdge, NebulaEdges, NebulaVertex, NebulaVertices} -import org.apache.spark.api.java.Optional import org.apache.spark.sql.catalyst.InternalRow import org.apache.spark.sql.catalyst.expressions.GenericInternalRow import org.apache.spark.sql.types.{ @@ -197,7 +196,7 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { } test("test toUpdateExecuteSentence for vertex") { - val props = List("\"name\"", "\"name\"", true, 10, 100L, 1.0, "2021-11-12") + val vertices: ListBuffer[NebulaVertex] = new ListBuffer[NebulaVertex] val propNames = List("col_string", "col_fixed_string", "col_bool", @@ -206,18 +205,53 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { "col_double", "col_date") - val vertexId = "\"vid1\"" - val nebulaVertex = NebulaVertex(vertexId, props) + val props1 = List("\"name\"", "\"name\"", true, 10, 100L, 1.0, "2021-11-12") + val props2 = List("\"name2\"", "\"name2\"", false, 11, 101L, 2.0, "2021-11-13") + + vertices.append(NebulaVertex("\"vid1\"", props1)) + vertices.append(NebulaVertex("\"vid2\"", props2)) + val nebulaVertices = NebulaVertices(propNames, vertices.toList, None) + val updateVertexStatement = - NebulaExecutor.toUpdateExecuteStatement("person", propNames, nebulaVertex) + NebulaExecutor.toUpdateExecuteStatement("person", nebulaVertices) + val expectVertexUpdate = "UPDATE VERTEX ON `person` \"vid1\" SET `col_string`=\"name\",`col_fixed_string`=\"name\"," + - "`col_bool`=true,`col_int`=10,`col_int64`=100,`col_double`=1.0,`col_date`=2021-11-12" + "`col_bool`=true,`col_int`=10,`col_int64`=100,`col_double`=1.0,`col_date`=2021-11-12;" + + "UPDATE VERTEX ON `person` \"vid2\" SET `col_string`=\"name2\",`col_fixed_string`=\"name2\"," + + "`col_bool`=false,`col_int`=11,`col_int64`=101,`col_double`=2.0,`col_date`=2021-11-13" + assert(expectVertexUpdate.equals(updateVertexStatement)) + } + + test("test toUpdateExecuteSentence for vertex with hash policy") { + val vertices: ListBuffer[NebulaVertex] = new ListBuffer[NebulaVertex] + val propNames = List("col_string", + "col_fixed_string", + "col_bool", + "col_int", + "col_int64", + "col_double", + "col_date") + + val props1 = List("\"name\"", "\"name\"", true, 10, 100L, 1.0, "2021-11-12") + val props2 = List("\"name2\"", "\"name2\"", false, 11, 101L, 2.0, "2021-11-13") + + vertices.append(NebulaVertex("vid1", props1)) + vertices.append(NebulaVertex("vid2", props2)) + val nebulaVertices = NebulaVertices(propNames, vertices.toList, Some(KeyPolicy.HASH)) + + val updateVertexStatement = + NebulaExecutor.toUpdateExecuteStatement("person", nebulaVertices) + val expectVertexUpdate = + "UPDATE VERTEX ON `person` hash(\"vid1\") SET `col_string`=\"name\",`col_fixed_string`=\"name\"," + + "`col_bool`=true,`col_int`=10,`col_int64`=100,`col_double`=1.0,`col_date`=2021-11-12;" + + "UPDATE VERTEX ON `person` hash(\"vid2\") SET `col_string`=\"name2\",`col_fixed_string`=\"name2\"," + + "`col_bool`=false,`col_int`=11,`col_int64`=101,`col_double`=2.0,`col_date`=2021-11-13" assert(expectVertexUpdate.equals(updateVertexStatement)) } test("test toUpdateExecuteSentence for edge") { - val props = List("\"name\"", "\"name\"", true, 10, 100L, 1.0, "2021-11-12") + val edges: ListBuffer[NebulaEdge] = new ListBuffer[NebulaEdge] val propNames = List("col_string", "col_fixed_string", "col_bool", @@ -225,22 +259,25 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { "col_int64", "col_double", "col_date") + val props1 = List("\"Tom\"", "\"Tom\"", true, 10, 100L, 1.0, "2021-11-12") + val props2 = List("\"Bob\"", "\"Bob\"", false, 20, 200L, 2.0, "2021-05-01") + edges.append(NebulaEdge("\"vid1\"", "\"vid2\"", Some(1L), props1)) + edges.append(NebulaEdge("\"vid2\"", "\"vid1\"", Some(2L), props2)) - val source = "\"source\"" - val target = "\"target\"" - val rank = Some(1L) - val nebulaEdge = NebulaEdge(source, target, rank, props) - val updateEdgeStatement = - NebulaExecutor.toUpdateExecuteStatement("friend", propNames, nebulaEdge) + val nebulaEdges = NebulaEdges(propNames, edges.toList, None, None) + val updateEdgeStatement = NebulaExecutor.toUpdateExecuteStatement("friend", nebulaEdges) val expectEdgeUpdate = - "UPDATE EDGE ON `friend` \"source\"->\"target\"@1 SET `col_string`=\"name\"," + - "`col_fixed_string`=\"name\",`col_bool`=true,`col_int`=10,`col_int64`=100," + - "`col_double`=1.0,`col_date`=2021-11-12" + "UPDATE EDGE ON `friend` \"vid1\"->\"vid2\"@1 SET `col_string`=\"Tom\"," + + "`col_fixed_string`=\"Tom\",`col_bool`=true,`col_int`=10,`col_int64`=100," + + "`col_double`=1.0,`col_date`=2021-11-12;" + + "UPDATE EDGE ON `friend` \"vid2\"->\"vid1\"@2 SET `col_string`=\"Bob\"," + + "`col_fixed_string`=\"Bob\",`col_bool`=false,`col_int`=20,`col_int64`=200," + + "`col_double`=2.0,`col_date`=2021-05-01" assert(expectEdgeUpdate.equals(updateEdgeStatement)) } - test("test toUpdateExecuteSentence for edge without rank") { - val props = List("\"name\"", "\"name\"", true, 10, 100L, 1.0, "2021-11-12") + test("test toUpdateExecuteSentence for edge with hash policy") { + val edges: ListBuffer[NebulaEdge] = new ListBuffer[NebulaEdge] val propNames = List("col_string", "col_fixed_string", "col_bool", @@ -248,17 +285,21 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { "col_int64", "col_double", "col_date") + val props1 = List("\"Tom\"", "\"Tom\"", true, 10, 100L, 1.0, "2021-11-12") + val props2 = List("\"Bob\"", "\"Bob\"", false, 20, 200L, 2.0, "2021-05-01") + edges.append(NebulaEdge("vid1", "vid2", Some(1L), props1)) + edges.append(NebulaEdge("vid2", "vid1", Some(2L), props2)) - val source = "\"source\"" - val target = "\"target\"" - val rank = Option.empty - val nebulaEdge = NebulaEdge(source, target, rank, props) - val updateEdgeStatement = - NebulaExecutor.toUpdateExecuteStatement("friend", propNames, nebulaEdge) + val nebulaEdges = + NebulaEdges(propNames, edges.toList, Some(KeyPolicy.HASH), Some(KeyPolicy.HASH)) + val updateEdgeStatement = NebulaExecutor.toUpdateExecuteStatement("friend", nebulaEdges) val expectEdgeUpdate = - "UPDATE EDGE ON `friend` \"source\"->\"target\"@0 SET `col_string`=\"name\"," + - "`col_fixed_string`=\"name\",`col_bool`=true,`col_int`=10,`col_int64`=100," + - "`col_double`=1.0,`col_date`=2021-11-12" + "UPDATE EDGE ON `friend` hash(\"vid1\")->hash(\"vid2\")@1 SET `col_string`=\"Tom\"," + + "`col_fixed_string`=\"Tom\",`col_bool`=true,`col_int`=10,`col_int64`=100," + + "`col_double`=1.0,`col_date`=2021-11-12;" + + "UPDATE EDGE ON `friend` hash(\"vid2\")->hash(\"vid1\")@2 SET `col_string`=\"Bob\"," + + "`col_fixed_string`=\"Bob\",`col_bool`=false,`col_int`=20,`col_int64`=200," + + "`col_double`=2.0,`col_date`=2021-05-01" assert(expectEdgeUpdate.equals(updateEdgeStatement)) } From 3598cae3da82a79deec2484ab5057dda4792569a Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Wed, 8 Sep 2021 11:56:49 +0800 Subject: [PATCH 200/213] add escape for edgeType --- .../main/scala/com/vesoft/nebula/connector/Template.scala | 2 +- .../nebula/connector/writer/NebulaExecutorSuite.scala | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala index d6c0bfd..d4f0a9f 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/Template.scala @@ -21,6 +21,6 @@ object NebulaTemplate { private[connector] val UPDATE_VALUE_TEMPLATE = "`%s`=%s" private[connector] val DELETE_VERTEX_TEMPLATE = "DELETE VERTEX %s" - private[connector] val DELETE_EDGE_TEMPLATE = "DELETE EDGE %s %s" + private[connector] val DELETE_EDGE_TEMPLATE = "DELETE EDGE `%s` %s" private[connector] val EDGE_ENDPOINT_TEMPLATE = "%s->%s@%d" } diff --git a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala index 25ece82..acdcc8b 100644 --- a/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala +++ b/nebula-spark-connector/src/test/scala/com/vesoft/nebula/connector/writer/NebulaExecutorSuite.scala @@ -332,7 +332,7 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { val nebulaEdges = NebulaEdges(List(), edges.toList, None, None) val edgeStatement = NebulaExecutor.toDeleteExecuteStatement("friend", nebulaEdges) - val expectEdgeDeleteStatement = "DELETE EDGE friend \"vid1\"->\"vid2\"@1,\"vid2\"->\"vid1\"@2" + val expectEdgeDeleteStatement = "DELETE EDGE `friend` \"vid1\"->\"vid2\"@1,\"vid2\"->\"vid1\"@2" assert(expectEdgeDeleteStatement.equals(edgeStatement)) } @@ -343,7 +343,7 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { val nebulaEdges = NebulaEdges(List(), edges.toList, None, None) val edgeStatement = NebulaExecutor.toDeleteExecuteStatement("friend", nebulaEdges) - val expectEdgeDeleteStatement = "DELETE EDGE friend \"vid1\"->\"vid2\"@0,\"vid2\"->\"vid1\"@0" + val expectEdgeDeleteStatement = "DELETE EDGE `friend` \"vid1\"->\"vid2\"@0,\"vid2\"->\"vid1\"@0" assert(expectEdgeDeleteStatement.equals(edgeStatement)) } @@ -355,7 +355,7 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { val nebulaEdges = NebulaEdges(List(), edges.toList, Some(KeyPolicy.HASH), None) val edgeStatement = NebulaExecutor.toDeleteExecuteStatement("friend", nebulaEdges) val expectEdgeDeleteStatement = - "DELETE EDGE friend hash(\"vid1\")->\"vid2\"@1,hash(\"vid2\")->\"vid1\"@2" + "DELETE EDGE `friend` hash(\"vid1\")->\"vid2\"@1,hash(\"vid2\")->\"vid1\"@2" assert(expectEdgeDeleteStatement.equals(edgeStatement)) } @@ -367,7 +367,7 @@ class NebulaExecutorSuite extends AnyFunSuite with BeforeAndAfterAll { val nebulaEdges = NebulaEdges(List(), edges.toList, Some(KeyPolicy.HASH), Some(KeyPolicy.HASH)) val edgeStatement = NebulaExecutor.toDeleteExecuteStatement("friend", nebulaEdges) val expectEdgeDeleteStatement = - "DELETE EDGE friend hash(\"vid1\")->hash(\"vid2\")@1,hash(\"vid2\")->hash(\"vid1\")@2" + "DELETE EDGE `friend` hash(\"vid1\")->hash(\"vid2\")@1,hash(\"vid2\")->hash(\"vid1\")@2" assert(expectEdgeDeleteStatement.equals(edgeStatement)) } } From a9a9ab057c8688099dea8365b3bd3a53b362b858 Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Wed, 8 Sep 2021 19:24:06 +0800 Subject: [PATCH 201/213] fix cache bug for streaming data --- .../com/vesoft/nebula/exchange/Exchange.scala | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala index 34068ce..6494649 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/Exchange.scala @@ -135,8 +135,6 @@ object Exchange { val data = createDataSource(spark, tagConfig.dataSourceConfigEntry) if (data.isDefined && !c.dry) { - data.get.cache() - val count = data.get.count() val startTime = System.currentTimeMillis() val batchSuccess = spark.sparkContext.longAccumulator(s"batchSuccess.${tagConfig.name}") @@ -153,9 +151,7 @@ object Exchange { batchFailure) processor.process() val costTime = ((System.currentTimeMillis() - startTime) / 1000.0).formatted("%.2f") - LOG.info( - s"data source count: ${count}, " + - s"import for tag ${tagConfig.name} cost time: ${costTime} s") + LOG.info(s"import for tag ${tagConfig.name} cost time: ${costTime} s") if (tagConfig.dataSinkConfigEntry.category == SinkCategory.CLIENT) { LOG.info(s"Client-Import: batchSuccess.${tagConfig.name}: ${batchSuccess.value}") LOG.info(s"Client-Import: batchFailure.${tagConfig.name}: ${batchFailure.value}") @@ -180,8 +176,6 @@ object Exchange { LOG.info(s"nebula keys: ${nebulaKeys.mkString(", ")}") val data = createDataSource(spark, edgeConfig.dataSourceConfigEntry) if (data.isDefined && !c.dry) { - data.get.cache() - val count = data.get.count() val startTime = System.currentTimeMillis() val batchSuccess = spark.sparkContext.longAccumulator(s"batchSuccess.${edgeConfig.name}") val batchFailure = spark.sparkContext.longAccumulator(s"batchFailure.${edgeConfig.name}") @@ -197,9 +191,7 @@ object Exchange { ) processor.process() val costTime = ((System.currentTimeMillis() - startTime) / 1000.0).formatted("%.2f") - LOG.info( - s"data source count: ${count}, " + - s"import for edge ${edgeConfig.name} cost time: ${costTime} s") + LOG.info(s"import for edge ${edgeConfig.name} cost time: ${costTime} s") if (edgeConfig.dataSinkConfigEntry.category == SinkCategory.CLIENT) { LOG.info(s"Client-Import: batchSuccess.${edgeConfig.name}: ${batchSuccess.value}") LOG.info(s"Client-Import: batchFailure.${edgeConfig.name}: ${batchFailure.value}") @@ -218,13 +210,11 @@ object Exchange { val batchSuccess = spark.sparkContext.longAccumulator(s"batchSuccess.reimport") val batchFailure = spark.sparkContext.longAccumulator(s"batchFailure.reimport") val data = spark.read.text(configs.errorConfig.errorPath) - data.cache() - val count = data.count() - val startTime = System.currentTimeMillis() - val processor = new ReloadProcessor(data, configs, batchSuccess, batchFailure) + val startTime = System.currentTimeMillis() + val processor = new ReloadProcessor(data, configs, batchSuccess, batchFailure) processor.process() val costTime = ((System.currentTimeMillis() - startTime) / 1000.0).formatted("%.2f") - LOG.info(s"reimport ngql count: ${count}, cost time: ${costTime}") + LOG.info(s"reimport ngql cost time: ${costTime}") LOG.info(s"batchSuccess.reimport: ${batchSuccess.value}") LOG.info(s"batchFailure.reimport: ${batchFailure.value}") } From 4874b35a957ff7978979db42bd9e49dfb3dac857 Mon Sep 17 00:00:00 2001 From: Yee <2520865+yixinglu@users.noreply.github.com> Date: Wed, 15 Sep 2021 10:16:59 +0800 Subject: [PATCH 202/213] Replace v2-nightly tag with nightly for docker image as title --- .../src/test/resources/docker-compose.yaml | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/nebula-exchange/src/test/resources/docker-compose.yaml b/nebula-exchange/src/test/resources/docker-compose.yaml index 1f112e0..a2c5a37 100644 --- a/nebula-exchange/src/test/resources/docker-compose.yaml +++ b/nebula-exchange/src/test/resources/docker-compose.yaml @@ -1,7 +1,7 @@ version: '3.4' services: metad0: - image: vesoft/nebula-metad:v2-nightly + image: vesoft/nebula-metad:nightly environment: USER: root TZ: "${TZ}" @@ -36,7 +36,7 @@ services: - SYS_PTRACE metad1: - image: vesoft/nebula-metad:v2-nightly + image: vesoft/nebula-metad:nightly environment: USER: root TZ: "${TZ}" @@ -71,7 +71,7 @@ services: - SYS_PTRACE metad2: - image: vesoft/nebula-metad:v2-nightly + image: vesoft/nebula-metad:nightly environment: USER: root TZ: "${TZ}" @@ -106,7 +106,7 @@ services: - SYS_PTRACE storaged0: - image: vesoft/nebula-storaged:v2-nightly + image: vesoft/nebula-storaged:nightly environment: USER: root TZ: "${TZ}" @@ -145,7 +145,7 @@ services: - SYS_PTRACE storaged1: - image: vesoft/nebula-storaged:v2-nightly + image: vesoft/nebula-storaged:nightly environment: USER: root TZ: "${TZ}" @@ -184,7 +184,7 @@ services: - SYS_PTRACE storaged2: - image: vesoft/nebula-storaged:v2-nightly + image: vesoft/nebula-storaged:nightly environment: USER: root TZ: "${TZ}" @@ -223,7 +223,7 @@ services: - SYS_PTRACE graphd0: - image: vesoft/nebula-graphd:v2-nightly + image: vesoft/nebula-graphd:nightly environment: USER: root TZ: "${TZ}" @@ -259,7 +259,7 @@ services: - SYS_PTRACE graphd1: - image: vesoft/nebula-graphd:v2-nightly + image: vesoft/nebula-graphd:nightly environment: USER: root TZ: "${TZ}" @@ -295,7 +295,7 @@ services: - SYS_PTRACE graphd2: - image: vesoft/nebula-graphd:v2-nightly + image: vesoft/nebula-graphd:nightly environment: USER: root TZ: "${TZ}" @@ -335,4 +335,4 @@ networks: ipam: driver: default config: - - subnet: 172.28.0.0/16 \ No newline at end of file + - subnet: 172.28.0.0/16 From 12dc6811e3e6873916fdae551688b030a2deabdd Mon Sep 17 00:00:00 2001 From: yixinglu <2520865+yixinglu@users.noreply.github.com> Date: Wed, 15 Sep 2021 10:26:34 +0800 Subject: [PATCH 203/213] Update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5cb2a12..6fd4196 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ There are the version correspondence between Nebula Spark utils and Nebula: | 2.0.1 | 2.0.1 | -- | 2.0.0, 2.0.1 | | 2.1.0 | 2.1.0 | 2.1.0 | 2.0.0, 2.0.1 | | 2.5.0 | 2.5.0 | 2.5.0 | 2.5.0 | -| 2.5-SNAPSHOT | 2.5-SNAPSHOT | 2.5-SNAPSHOT | v2-nightly | +| 2.5-SNAPSHOT | 2.5-SNAPSHOT | 2.5-SNAPSHOT | nightly | If the Nebula version and the uitls' version are not in the same line, then they are incompatible. -For Nebula Graph v2.x, see [nebula-graph](https://github.com/vesoft-inc/nebula-graph). +For Nebula Graph v2.x, see [nebula](https://github.com/vesoft-inc/nebula). If you want to use Spark utilities for [Nebula Graph v1.x](https://github.com/vesoft-inc/nebula), visit [the v1.0 branch of nebula-java](https://github.com/vesoft-inc/nebula-java/tree/v1.0). From a41e1a02e62e92cd2aacdfe3667516c69eab1616 Mon Sep 17 00:00:00 2001 From: yixinglu <2520865+yixinglu@users.noreply.github.com> Date: Wed, 15 Sep 2021 11:38:09 +0800 Subject: [PATCH 204/213] Trigger CLA checks From 944dee000932ff51eeb7bcc4c4b6a1c5fcb00e17 Mon Sep 17 00:00:00 2001 From: liyanl Date: Thu, 16 Sep 2021 20:04:29 +0800 Subject: [PATCH 205/213] fix error " FileSystem closed" , disable hdfs cache --- .../main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala index 3b2c009..e3a7b2a 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala @@ -22,6 +22,7 @@ object HDFSUtils { conf.set("fs.default.name", namenode) conf.set("fs.defaultFS", namenode) } + conf.set("fs.hdfs.impl.disable.cache", "true") FileSystem.get(conf) } From 10a1b8ea01bc4eff7fc6fb7543012bb085680b15 Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Fri, 17 Sep 2021 15:12:01 +0800 Subject: [PATCH 206/213] remove the close for hdfs system --- .../nebula/exchange/utils/HDFSUtils.scala | 25 +++---------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala index e3a7b2a..ba37676 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/utils/HDFSUtils.scala @@ -22,36 +22,23 @@ object HDFSUtils { conf.set("fs.default.name", namenode) conf.set("fs.defaultFS", namenode) } - conf.set("fs.hdfs.impl.disable.cache", "true") FileSystem.get(conf) } def list(path: String): List[String] = { val system = getFileSystem() - try { - system.listStatus(new Path(path)).map(_.getPath.getName).toList - } finally { - system.close() - } + system.listStatus(new Path(path)).map(_.getPath.getName).toList } def exists(path: String): Boolean = { val system = getFileSystem() - try { - system.exists(new Path(path)) - } finally { - system.close() - } + system.exists(new Path(path)) } def getContent(path: String): String = { val system = getFileSystem() val inputStream = system.open(new Path(path)) - try { - Source.fromInputStream(inputStream).mkString - } finally { - system.close() - } + Source.fromInputStream(inputStream).mkString } def saveContent(path: String, @@ -79,10 +66,6 @@ object HDFSUtils { e) } val system = getFileSystem(namenode) - try { - system.copyFromLocalFile(new Path(localPath), new Path(remotePath)) - } finally { - system.close() - } + system.copyFromLocalFile(new Path(localPath), new Path(remotePath)) } } From d607eaa043a54e6eaed0a9cc139e4563b43bebef Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Fri, 17 Sep 2021 18:51:57 +0800 Subject: [PATCH 207/213] fix test for config --- .../vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala index e2e6f46..16aab12 100644 --- a/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala +++ b/nebula-exchange/src/test/scala/com/vesoft/nebula/exchange/utils/NebulaUtilsSuite.scala @@ -11,7 +11,7 @@ import com.vesoft.nebula.client.graph.NebulaPoolConfig import com.vesoft.nebula.client.graph.data.HostAddress import com.vesoft.nebula.client.graph.net.NebulaPool import com.vesoft.nebula.client.storage.StorageClient -import com.vesoft.nebula.exchange.config.TagConfigEntry +import com.vesoft.nebula.exchange.config.{NebulaSinkConfigEntry, SinkCategory, TagConfigEntry} import com.vesoft.nebula.exchange.utils.NebulaUtils import com.vesoft.nebula.exchange.{KeyPolicy, MetaProvider, VidType} import com.vesoft.nebula.meta.PropertyType @@ -70,10 +70,11 @@ class NebulaUtilsSuite { "col10", "col11", "col12") - val label = "person" + val label = "person" + val dataSinkConfigEntry = NebulaSinkConfigEntry(SinkCategory.SST, List("127.0.0.1:9669")) val sourceConfig = TagConfigEntry(label, null, - null, + dataSinkConfigEntry, sourceFields, nebulaFields, "id", From 4153d3c45da033b49a460bffbb6f87d9ddb86ec5 Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Sat, 18 Sep 2021 11:52:43 +0800 Subject: [PATCH 208/213] fix sst write error for duplicated key --- .../vesoft/nebula/exchange/processor/EdgeProcessor.scala | 9 ++++++++- .../nebula/exchange/processor/VerticesProcessor.scala | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index ab82d63..122ab2c 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -112,7 +112,14 @@ class EdgeProcessor(data: DataFrame, val spaceVidLen = metaProvider.getSpaceVidLen(space) val edgeItem = metaProvider.getEdgeItem(space, edgeName) - data + val distintData = if (edgeConfig.rankingField.isDefined) { + data.dropDuplicates(edgeConfig.sourceField, + edgeConfig.targetField, + edgeConfig.rankingField.get) + } else { + data.dropDuplicates(edgeConfig.sourceField, edgeConfig.targetField) + } + distintData .mapPartitions { iter => iter.map { row => val srcIndex: Int = row.schema.fieldIndex(edgeConfig.sourceField) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala index 7a24a3c..a27ddcf 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/VerticesProcessor.scala @@ -121,6 +121,7 @@ class VerticesProcessor(data: DataFrame, val tagItem = metaProvider.getTagItem(space, tagName) data + .dropDuplicates(tagConfig.vertexField) .mapPartitions { iter => iter.map { row => val index: Int = row.schema.fieldIndex(tagConfig.vertexField) From c0fed61d6e221b6635652d6daef0d456367d2fb1 Mon Sep 17 00:00:00 2001 From: liyanl Date: Wed, 22 Sep 2021 16:45:27 +0800 Subject: [PATCH 209/213] add rank null assert --- .../com/vesoft/nebula/exchange/processor/EdgeProcessor.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala index ab82d63..26b8b3c 100644 --- a/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala +++ b/nebula-exchange/src/main/scala/com/vesoft/nebula/exchange/processor/EdgeProcessor.scala @@ -156,6 +156,8 @@ class EdgeProcessor(data: DataFrame, val ranking: Long = if (edgeConfig.rankingField.isDefined) { val rankIndex = row.schema.fieldIndex(edgeConfig.rankingField.get) + assert(rankIndex >= 0 && !row.isNullAt(rankIndex), + s"rank must exist and cannot be null, your row data is $row") row.get(rankIndex).toString.toLong } else { 0 From 81e5680fe31324a7c37f4e2741451e3795171ffd Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Mon, 27 Sep 2021 18:47:27 +0800 Subject: [PATCH 210/213] fix buffer overwrite bug --- .../nebula/connector/writer/NebulaExecutor.scala | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala index 797b737..89d7c78 100644 --- a/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala +++ b/nebula-spark-connector/src/main/scala/com/vesoft/nebula/connector/writer/NebulaExecutor.scala @@ -141,8 +141,11 @@ object NebulaExecutor { fieldTypeMap: Map[String, Integer]): Any = { if (record.isNullAt(index)) return null - val types = schema.fields.map(field => field.dataType) - val propValue = record.get(index, types(index)) + val types = schema.fields.map(field => field.dataType) + val propValue = record.get(index, types(index)) + val propValueTypeClassName = propValue.getClass.getName + val simpleName = propValueTypeClassName.substring(propValueTypeClassName.lastIndexOf(".") + 1, + propValueTypeClassName.length) val fieldName = schema.fields(index).name PropertyType.findByValue(fieldTypeMap(fieldName)) match { @@ -153,12 +156,16 @@ object NebulaExecutor { case PropertyType.TIME => "time(\"" + propValue + "\")" case PropertyType.TIMESTAMP => { if (NebulaUtils.isNumic(propValue.toString)) { - propValue + if (simpleName.equalsIgnoreCase("UTF8String")) propValue.toString + else propValue } else { "timestamp(\"" + propValue + "\")" } } - case _ => propValue + case _ => { + if (simpleName.equalsIgnoreCase("UTF8String")) propValue.toString + else propValue + } } } From e8db0b0a3eae1dce660b35babbd540e5148e35db Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Mon, 27 Sep 2021 18:47:41 +0800 Subject: [PATCH 211/213] add csv example data --- example/src/main/resources/vertex.csv | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 example/src/main/resources/vertex.csv diff --git a/example/src/main/resources/vertex.csv b/example/src/main/resources/vertex.csv new file mode 100644 index 0000000..e560572 --- /dev/null +++ b/example/src/main/resources/vertex.csv @@ -0,0 +1,3 @@ +id,col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11,col12,col13 +1,中文,tom,10,20,30,40,2021-09-27,2021-09-27T12:10:10,43535232,true,1.0,2.0,10:10:10 +2,Jina,Jina,11,21,31,41,2020-09-27,2020-09-27T12:10:10,43535232,false,1.1,2.1,11:10:10 From cb5a7eb972ce498b081ce18fc7db31510ee02349 Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Tue, 28 Sep 2021 15:48:43 +0800 Subject: [PATCH 212/213] fix wrong ip and add data for example --- example/src/main/resources/data.csv | 14 ++++++++++++++ example/src/main/resources/vertex.csv | 3 --- .../connector/NebulaSparkWriterExample.scala | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 example/src/main/resources/data.csv delete mode 100644 example/src/main/resources/vertex.csv diff --git a/example/src/main/resources/data.csv b/example/src/main/resources/data.csv new file mode 100644 index 0000000..d4966c1 --- /dev/null +++ b/example/src/main/resources/data.csv @@ -0,0 +1,14 @@ +id,col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11,col12,col13 +1,Tom,tom,10,20,30,40,2021-01-27,2021-01-01T12:10:10,43535232,true,1.0,2.0,10:10:10 +2,Jina,Jina,11,21,31,41,2021-01-28,2021-01-02T12:10:10,43535232,false,1.1,2.1,11:10:10 +3,Tim,Tim,12,22,32,42,2021-01-29,2021-01-03T12:10:10,43535232,false,1.2,2.2,12:10:10 +4,张三,张三,13,23,33,43,2021-01-30,2021-01-04T12:10:10,43535232,true,1.3,2.3,13:10:10 +5,李四,李四,14,24,34,44,2021-02-01,2021-01-05T12:10:10,43535232,false,1.4,2.4,14:10:10 +6,王五,王五,15,25,35,45,2021-02-02,2021-01-06T12:10:10,0,false,1.5,2.5,15:10:10 +7,Jina,Jina,16,26,36,46,2021-02-03,2021-01-07T12:10:10,43535232,true,1.6,2.6,16:10:10 +8,Jina,Jina,17,27,37,47,2021-02-04,2021-01-08T12:10:10,43535232,false,1.7,2.7,17:10:10 +9,Jina,Jina,18,28,38,48,2021-02-05,2021-01-09T12:10:10,43535232,true,1.8,2.8,18:10:10 +10,Jina,Jina,19,29,39,49,2021-02-06,2021-01-10T12:10:10,43535232,false,1.9,2.9,19:10:10 +-1,Jina,Jina,20,30,40,50,2021-02-07,2021-02-11T12:10:10,43535232,false,2.0,3.0,20:10:10 +-2,Jina,Jina,21,31,41,51,2021-02-08,2021-03-12T12:10:10,43535232,false,2.1,3.1,21:10:10 +-3,Jina,Jina,22,32,42,52,2021-02-09,2021-04-13T12:10:10,43535232,false,2.2,3.2,22:10:10 diff --git a/example/src/main/resources/vertex.csv b/example/src/main/resources/vertex.csv deleted file mode 100644 index e560572..0000000 --- a/example/src/main/resources/vertex.csv +++ /dev/null @@ -1,3 +0,0 @@ -id,col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11,col12,col13 -1,中文,tom,10,20,30,40,2021-09-27,2021-09-27T12:10:10,43535232,true,1.0,2.0,10:10:10 -2,Jina,Jina,11,21,31,41,2020-09-27,2020-09-27T12:10:10,43535232,false,1.1,2.1,11:10:10 diff --git a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala index bd926ab..37a5054 100644 --- a/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala +++ b/example/src/main/scala/com/vesoft/nebula/examples/connector/NebulaSparkWriterExample.scala @@ -178,7 +178,7 @@ object NebulaSparkWriterExample { val config = NebulaConnectionConfig .builder() - .withMetaAddress("127.0.01:9559") + .withMetaAddress("127.0.0.1:9559") .withGraphAddress("127.0.0.1:9669") .build() val nebulaWriteVertexConfig: WriteNebulaVertexConfig = WriteNebulaVertexConfig From d5a22463ee46cead9058f8e7f627b35df859a250 Mon Sep 17 00:00:00 2001 From: Nicole00 Date: Wed, 13 Oct 2021 16:54:32 +0800 Subject: [PATCH 213/213] add snapshot repo for dependency --- nebula-algorithm/pom.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/nebula-algorithm/pom.xml b/nebula-algorithm/pom.xml index f37a49e..9f07775 100644 --- a/nebula-algorithm/pom.xml +++ b/nebula-algorithm/pom.xml @@ -287,5 +287,10 @@ - + + + snapshots + https://oss.sonatype.org/content/repositories/snapshots/ + +

                                          j2=IkPm&a{Wb~$2{BQzg0g! zSYm$t>IxeH8H0aZ~Fpwz&Tt zB7KWt(rXSSZAr|^l4Xwa!HLi&_I?~WXg1HtTqrik%p$qt@geZd1_$FpnNP58gp~N$ z1|Sr{_x}7;Gt&b+m%ffdZRV3kTC+M4H;ir*rma%CmH?cWE%~kMfq|+eywiDeu5 z!xopRNWblY_B`5kCIlH@Mv*`oN{MIJ_T4||YXoKJ2DZCh{-^U3(5zr2svXlZHx#BDGnrtzq1;WDLPdK`27#ZOjv zjXLakBtGWI`1N;t_83_j!uHV;oEZou9a^@?^@o?(CsY#E6J$o3_Im>MXZ-MP59Nv# z4%C109e%2k-6gU#)Cyehcck83CJhuBw=Eve#v=<@Xx)Ku{KUk99+A-j659x_Qc}Us z&D(s(%Jo<1uV&lQD!Wn>VbjyoNx})#r>jO809Jc6EJW^yLL}j)gev(g z!2vXeW)!I0-rhzNN)r%RO{!V^p_s1oc=DC&zLwV8rXTKhxxxBpoDZ>nco^$J%-hZm zCPUtWUqM^JD?U4yR5~yrmSJtl5jRnI<+HIW9q*Eu8T11nlP}^{x`fOFOcDWeP0RJzURtY^h#(JMpe$rpx60 z;k-70V8E26sHCK|lNb?U&#*J{=>LRRtdcLadvKt|fYj{$Zm%NU-i)T&{O#{ZA9rXs z>|%_zqo}lCY2upyJzT=Chn^O}D%heY*sU|6t$2|(3Ehl5W`*bys#aYLw48ZK+mQB^sbm4+*1#ES3}!l#DAA^xSP;*9kLXpXTM& zPR_e4YCa*Z&^sQ1#MIt)0?0DpG3lAU^48j!uwA$A-rW|5)7trD!sBk>RcMNbPV*Wj z%tZ3^>MnL+d@C(L*Dh-%Cs<7VO6^Pha)5ZzyP7kS9c!>>TN6304L*KMWIYTi+H~!p ztGB@VHk@5sIpLSG1C7y0Uml?X`8}m4Lfo(WG(24dT-}fdQE45surF=DdrxA0kl@pH z=#`j-6F*IZ`W%PH1|nF)%by{?Z?R8yDL5YZnqo^K(r@g2f~=(R;#*_7%m#Pp<&kYh z%iY|-?$BCFx_1f)^$|jsl$2QAh>!U?IIuD5)Wfgfxxdx#yEfR8#QE?s2hPl~V02B3 z0%ZY>J3mpj8ks6FI=?jNyP!PTkNd6>7oPL zc`I8+lf*5q(|3vu0z3{G3Yz}f#o3DHl%oy*j550$oc2O>Wx{#WHX1-HOdI6uI88m_ zaoOgm6q!y9#s1N)trPOaAyQiAgvH)orRyo{xq6vM`p+(g5S*TFuu8o0F)R|OK{%x8 zUi$U$@**R0p~Kl8dz>DT5|UDd<2q1k;mH>0!;kqx`oy^aE~Pd}gN zhYfAfv$EOm*QmWN^YmnbEsxZ;G;;B3cAR!M6+GpAQK{ck7fslZ12>Ll%rzWZel?#i zH`;uG4iqc!`dET$!@wDD^9mquVa9-3y(0!NP3Q03lWUq+YS$GVC*Z?S=lOh`xh^+) z6E5pc>FOa-WlXylgU$aU1fKxI3g#em}=U36x#@`*69D zvD(xzc#emSZM7pcU$fOU-z24$#0RHWrbt5d6@rV&@BMn;$Fuh)BqUUI?f$$YR{He; zUrLYN4Ky@Y{gjKu4%>J@p?0{J?5Z)D)I5BCc?K+x*PV7_oeM40Z26_PSU?tstK3Tq zpG*j18MDhXgH;WjOfbLs6=s6ei29f^+IBK&}}SJLE~=)Imnaf&tVym-XE4BhSoe*eQ;2}*r z4GhtGv9!OHvF&7fr~LHdb~gCLhF=4W*vbh-`V=^4rv{G632Owy|NKe# zsm>|oOPY6!tdRUEEqFkd-`M)xh7c=nRaA~Y{0Yn{SJB1v%^jR%bI(<8b3nD;stf3T zIkd!Nv%%g9dd-4A`I(jop%RN);Zq1{psqtDhnfb=2nG91uQ7WXIcKWMs7?rV-N~dd zMc7K3?1ewrFwG-nsE1ntFPiO{@qL}d zzbPuYpM5HlY0QTrpUQp@h7U0YWR*H$n>@WA*EL?R6)~Swxz@s_OuHyc5KHdXYJtTw zXfRmou2^G|7(51jqe~Y)s4z1|!bYhiR@X32$Ejeed2__6((A#En6{+jYsjm^-?N;p zO)ind{a)>nE1f5Do3(&PIfV<#gi;eybgXy!+=h*8UA+U?sc z(_=8bnxD>Aq=>U6k*^}9;oBKPvGblJCP?fJcS#!g ze>+$QDauj@31 zVqaM+WF6k}q94MliOFlWw)=*-81j$T)$4;`=LLXPXWY3zDPanORgdwym9W^XO#8s6 zrl3FsTP}S*P8llg3o2S6BqA~!)7mp=Q;lR#gzAMu2%|Q`$&Edy5Boio=N5#7i6q(O z@uX;k6te&M2(;KK0RGmbxo-+{$euGk*Mz6}p16xjN?>-Bxl<3!1$wIyf&E%_#IOOf zYr#YKFfOmv@gTZh=U*3VdfDPPvmumnosML2b`C4pxIiu@5LrUfKhX4&C!cRuDI2O} z)m1FzY9$QxPFhu(EafUpk=hc#lq`FDsl|U!1p!6Q($R61cU)?=+F@Hmn5FK$0~Dnc z0EblZc(PiPBV)PdO2xBvhQlZ?1M#x|#c=yK{{aa4L6-pI#{v7J2^36BN@?3On@Ne8 z(t2K>c{hQa7%|N1`&tOKRAAU@0O*dIN=e9Zd-=LsQ8nWH4;PgNNdg9GYM1jF|G#JR z1n8<2OzbufG~jN;lK+8HB*DIuW(V`}W_EhtPUXl+OBdE0`iKA>(R1TsVw3}sD|qhW z=Dh$}F2Ci&i1`Ws7X*}sqTd0!Jo9?oO|mUOS0wMr$jY*kkdei8u*n{v&6;G)V>Eza z(T(pLF8yj8;MU^R-6R(N6W> z|Ifni$LV^=&9x?d5+LAez?m2UBB%VI1EO2J^le-&DRj*hRwHK15>daLf>o+f&Po@-CHq?l2~ZlrTVN&A z+Il=+H&wOPSm#(u;!YCO3-l8?UQin<-*DM{2n{t8_r7dLo?VOWrYW0{;QkN#wfr4u z?K;h}kGZg16OT)B;&e*9L3}q^kxQ)m-{{z&$acb)x1d&w6|lEqkFGP+D?ZBhUOX*a z*d3yo1_Jl|D}>v%g>x$nM-*7i#OmH`Y-)1At%pi$f8Ux_2%nu@J*)EHsK8}wZ*Mma z4e_K=!+#_KIJ)dDL(ubJ4#)Nl%7pNCiFcKzS^l|VTjN0}pFxb$)RmgEJs1tY7B8ttD#WhZX z01CtPdrEx2JdYQ())W*SNC(M?6%sORD5)m)d00hzx3=_Pc{6|F20qXKAjq=PCcpIn ze(`ocz}yJ=J~mEJP*ICsmwvfoPqyP7yjYyY=Qi$vS?i#H!{G8?o5Eu zEaBb#ePNibY@r3AQLe!6xvP5^Wsxg^zwaxJC^qj06enN>X2yF!brJ|`5+#HZaDHt- zkS({wAlaslkw%O4zE1;0WL-IdIoiUyo16P5mw&S0t`6Xr#2qwd~)j=0UrX*`Cq+G+qgI6N%XLGwl! z%k~3g35ax>-XG5fm`tXL;BY$0L%L{>yNG5N&ao7vKmv;@Hxgkxs8c*J5pnr8{Y=#F z>^Qkf%WOi*5QrU$4D88fG+T!j*>-iQSBU(3ne2=p(G(~9ry!t?dV)XixC1lS?f$~e zCdl!M5D*YVYooy~yroKQeQiHnP4*5BqoK2l5SqQXiF=~P7^ zhx)!L^Z0aEf*2E%`-az=V=|E{Ko*^Y&(`v%6;*`CxOGg>2eZ6cM*mRFc*S?lvFf}x7G1TcD3FZMnqV6Ti#FWpOO{@(?WSV?!?|a`Og3i z6bkJ3Wc?p-KZ;w(dSt$=KVwvDG-ZJ7m9D>=$b2cGO2RrtJ7}=#?ve=PpkRt~isobc z6eug?@vn~;QdOEQglcAxP~TM`w#TWe!@eQQ!l2U>s!*v>EO5|#lVXR(0p`LyoRT=J zfQkSKOl183H09r>xhkrQnbO+=94P*5K$DTvjsAi5pXPm=@4S{6I&uEE?7-vwy)?Q> zB|a!g4+5Peu3PBvb^w1hbQ@A*xlk_BkL#0av8T0I^QfC1-+k-n*UaDba+pzOz1G}# zvLz#_8MjuKG~P>*|0{xlU27xx-&9K<3(QU7>S9j@NCwFV-YfEXe`|**SgE0S(ulz} zgD|co9bvnj!}t^>ob#8l2)nVd$*g5fk0={Uo5X49Jeol7D1x0lK%%5jYk3))E7@sm zlJC1q{h#=AZP@P$bsd?5GH9F z0Sp4$th_~Q&4~RumYKO54w2N~<<&BKD>qsj!?w;_C?Qjg`HU#FUuEyNJibwCTt#f- zkVeLZb6i)Gxk3sdm4T36US4MFt@iUk8v}yO%=&v0r30LQqV!sJZ;yQ_Nhv9!fCw^9 zG8~m^?Y8+b#RBHWo8oz0BSd?NE~SW&f@W!7gD0AJeP{ER&O-x?9G8D=G+6&Xr#~yE zbqEOZz<**^uv`)RW% zvPj~2X{OOIR4!Uk?y5l{^B%zp`)m0(?CCUaN2jM_f`8%&eq3G2;rZS(Tx|8^XeSjS zi<7Bg-zvaiFP*(t3$L1eiXQ-pM}koF=I0j|GGubug=tKt@n3A8_s_^N5y}$0UXzAs zmt>dEA&gTvMY%3rqdX&}pE+5n!uGy&1k+HK z7Pi&OIlZ(P@2e67{#jkmb92x3OdPgHoa6HNY&)W0A-W3W6s5$+_uI_+qMrjh?az1GlB;*<2ZaL(rsBWAo6n^3HX!2R$P6+0txC?n zQn)J?h+<;Pi{|=Jvbm{po}(&GZhI=qhWzUGRl2H^^z40(=_z=hE`}35ykgRx=kmZi zJl^75FGx{V?+_jOMvX~Mv^zuLE}xIWKDS4k{Y=yJ zj-LbezmmN?ECE^rAs+YV3km8$$-~#T+U^gjcVayYIh4*g(s^AF3Wq^^PKO<3`)KlE zf4DZwh%=Esbp%X%as+f$&J=^tbR>>0MNdqpXHP^DN)?Yn$dw@hqafGo6U^ETYb`OrIMoLrJ^{VbxckZ{cT! zMqo?I6cKl7!v>y9J9ep4?YMnlSUy9U%gYk`9xJI#$B-)~sXjx>?_))2YMo9LsT5kB zzace-L@76 zawS!pTDh$K7i|d)6>t9fJaPHsHd7)hx>(2-o`6BXupuJHOtFy!?R;`QT@DdwnQLu%FH*V%m`Epq!UzC;%{$OX>}$Fa%QxEA%0gK7>E52`raLOTVu zfJKE7IxaCk*CH)`SXQb^j!E9b-NeC6i2TRr$`o>|8TKEScJL>2NE8ppvJN5pf5ZmM zE$VXIFQJNrKg8<3sEbIis;DN-!?Kp3)<~`*=nm)5AwMY{Km-Nvi1!WY$Yu&+cs2KH zn|zZ_l#WRAvt;BMB{chYLkj1FWc~-nk(P}D85$yphjr_u9;EOi_o>R#&L87HN+iu|C zTy@qBv9d7P8}Uf4vp~&57O2#efEE)JoSf;OpKrG9poIyT@br||{F5$4lzr@sSp9o@ zyhMaVr62>sFBrIFvO=!`5*eB2*yXwfoFdFtW{-Qsmn#iwS%-s2$~2nI+gc{WNCaWA zC8&D8=64}knETJwZ4vz=NcliH?k@Q!x|M(GTWVBeUOdzd!i&e_q!2vsdMq^ z>7qaqElINcj;p;UH~xbi#EtDnJ8GsZ+{Vh2tVPtE-11}eAv=zkT{>cdmh+SQg|r`c?m(-JqDz_D_NmFK!bqmsSoKoDoq{a_P_Tn?zGvzS+}ZHopU;|c zvM0k&zw3_$)6nG1x#RV?x>wl2?mO(ZvsP2l~maFD?S@fg% zQ$#^@`772zP0Duvq=2%$wVVmo{s0Nx%JI3yCoZ*6bU8O4i{yZnsLAm;{> zoslI)0m)hh-6EG&9E)3446x~?NHiaQB&>!iWx^&%7Oj{;>KLhx=8{IO_|5s;&v}nL zG-f!AA@DKI?HCD|##S`Uaea6-BYK#rR#${3e!D41{Qf(cr^`|_UTtzU5!DmpDSA8G zpK%H=WMIy~slw_wDA&OeUB&lU!Y~-|@c4~R@zy^o(ZvZ8E#Dw9sQChG1qlZ5AkXDg z(94R0_=#PV!cNk zo)poW3tXoPF6A8ow|)t43|U}p*4XFxa6>WHW)J@yi0XXFQn5^ZE7KOoEW}%p&`{_0 zRIL={ec%`GKVbrp?j-GyL_`qC z=*YhpZ2?L~bs0~X<+eA31CZwhhF;v1yd<{X!HbJN1dMHjxHW?s3+1m?c!1tkEd81C zdTTzFqy2nE9jUBRzFLsGerIj3J#`c(ydtHWfc<0Jl_S{BR|r)mg#22uCE>ZKbQ*_) z!eLIb>Vv8!=-Gc|0vm4Q>Qo?x>kj5kFunI5=|Kb0c4~vW^pJ_qBL`Gg!!HyaROs8? zh=R%Csubls>(#&@L^SsePp6VG70Nj}zAr)ZlaqbWBoH2mXJFMU+yfJ!w+O$((C7ww zy1UQ5;dRzT;(cBB|9IVnId&uJ;?BJ*IlIs~8AR8WzlrpAuLM*rp`BIEy+5$&Rk*ns zOp7Vq)#bH$6hN`#d2)ShxT-uJPHXXx`>MnF*JwX@ZL~X|bYWak2e84wT$2?K|Sr|{N zqZ%)sf*&=2BvDsaXGXM$tXMUr1B>h$8~siJZTiyvZloe`bGQGM{CIIPN|r<2D2t9# zE&h}W)(1jQ#*w_sYLnZWjN{HDA!BMIWT&g19jx3RvA=sFl)^?`V03P$di8{j^Kq_0 z0t~voqI0-|%gxpDP`J+k6+psKtYPu$E1_}`AllLu zdQJSr`Pzpp-&f|xJb;n#^D8&Qroc^_k^{EWqh|T!dpX0kF$+WY^LUE#)8LAFZt&dB z6Kf0 z^;XOdUseC{L6C%nAMUdmF#hHJN)Q!6ZOJaGETx-Y9HofI$Mff5PVRF*n#fs2k3gVf zq19tICCX+!Ppc5uol&1hY`EMc>R`?B5?SkbyN zTYgO1mJnz68s<+AWK>Llt#QHkl9yjZ<*dlaLFKtZ$%Ok6Lj8e7seKpmel)$}^}Nbo zmUl-(!9ok)MaFf>0Y?M}7XeqG_ydqS_P=jl`S3luoH9Wc+>&YbLMLV7I+*I}F?a3e zIMQyVWQgnijx_UhbiSfDlHP)MpPj%?@~}Dz^pY?0oq(=47^|q?nNyp9DdW(w$7t>} zYZW(#);7;(x^&Da>7sFmF_Ef}V!)FaT<0I}Wq1AJoy$6kx0J zmb16sqO{y}Uk)8L@mz1w%5;WYccW$8Rah)cG1^P9-HsPAu-_=>-`F{1h~F&eL8;Uw z8PDm4T9S>s#5jmdd2ESE;DmIJgT0CpSkbFiendOkpo4|XCdlA*7h?6{EzX~+y|?l` z!;0VRf~RiQuD_3C(qC!oOVoNwOJBi3i`gqgu@Uj*^X9m{B69cr`lDs?hnbzVQ-sWT ztnmx%ob?<)B1QZuyx!tX3ykD3ys*}2J!fle>>_uD=hf8IdrY-@-Z#EepunI#Ez^k( zyk-(S?Jw$nK$VkR^!#EKV&rvW#&Ae$6P;Uq7y#yTPZmfG8au~OO^pT5+((#WHL`zw z*YMhcZpEAUqh)RCWwio!Qx2Wo^f2MHlOCkV>>g%x|BJk=^^wi%v)p}%mHScKeCEq( zh1t4u{=^{=@o%{5-rju#+wPu{rMYYWxG4F!$CtTdj+xs!$01Q4TRnkk(6x*LU(;RP7U)oP4o6Zwaj@Q%z?1pRF+W?;$9H#IeC*AGfY^?_4({Jl(M4dQcfioL;^Q3Y2&q@^z=~of%D5Mb zX_pWUX2Cn!f}KrLjwg}vZo)|wdZ|+w_^Bu&4#;~O*y)!}QJ(O(o^ez!`NKUnVkLiv zhDM;kk6yh4P9h>4o66?<>}3O*GI4F2(qXXYJx*rDa2Zt97Lp`lirVe7ou@be1zIf@ z(+8)`YboxsPz+Ha+LTzlJ_^Y^-VB)GllnpPFsk5P*YPg6)FJ7k0~uDQ$~rr!*3W+hmCZ{T#n(8W8>M5VH(x{UAczea-L#UvcwE}se0 zpU@#PJM={Od%Ree>`NhvK#-(Zx$f z1hM~Xw4aGnZo?u@Ofdlsp)orCqQ~odL?O)eEHM^d5d?qiUr>b6DDM`|BO9o(Bf&t* zSlFDdKh5!2PpOCTJ|nZDP5?{Ff+q&Eh)(l?ebu8)BIrp*5{#!zoSx}eoF1>}$6*dq zK2t?ZUTp8k7!`Yj0tPC<7+6|`wq3xuQSZ$u3sPPZy;z{HxF6VK62DQnY-theuXFyP z*V_Bd!>6X#4n4g+T$YftkjLzzWSP~dqn0f%Dm7jAqAd$C8UYA+3~G!A#{JZSm}HG% zY@#i%JJ>PP(PMP64B*ts_lqXS_ofZe#mSpY7gHrx(Y0evmTO_%MULx&nFC^NmDa&x zqp*95$J0Y*LnT%7PmNrVNYE`Jb?N+t_#UPCIT>o{JivT)-dxnFyjt~?bqSX428-1y zc4?@SG;8}XB`wYT(fbvnq(A7yX~hq>-{!aE^%*&AAvK;WHXO$r7F%I+)~wuKAPbK z`qoczU3HqU`*LloyYkzw?Y&?4ZCx-_^_*QQgSU#b(l1lsAxoX(b=&LjwT zg#0~cUXo)ob+Vn!@O|*_%i8`|HNVge(rESrLGTlS(*$dObWTs~RE%7FYw+Z(Mc_DW zx8@LADZDH9fC2wYdX`53GqxAp03sAQf^P2J;>p9fjS=&Qn z*4%v)MJ&L>Hfb!Nm`4|cXXr!5kY$HZsP`sDSSL6=^H$E#UjbflHu>Z#wSMh|UB9mO zBx30z$K*VaOOKPfO1q6D9tNhou-JNsOwC05Wu8TU?xexyzDF(M6RR)Fl$OmT{G}fS4JW>fYBWk-T=oz2JZvbF zAj{9-k$Lc|)&s>BOJC-BI#xoJBEefoXzXv_or7d778QQ%P&V(!F%|X2effb8K-r3Y zA7SI|LR_~~9oHkGrB8-R`@#et2N{^?iz25Ldhm@rn-5W6RhML|V(xK7pZcS+NzG*a zbz*mRX4f)G&o?d=QMf@uC%(Z8iZ4Ey47k7|IP3;v%aHEUF2oS7G_EC8JR7_HgX6}r z>7TO4wWGL%@MZ%wK0-J6*MmfBQQ~`b)uB*Lz;@G=HkmoX=-tj|0%S|h^Zk&WuU4Dm z$}GKPU`9^3nG_xu`~#JU&)WMk!Lq>2J_`wvFkj? zy0TKA33oWWZ!GwZ`T)0Vxk$I)F^hj+-xsZITW=r?52EKpsdEr*^nK!(vlcJx%)u)1 zX_$6ML)e2Ub4llI32-j4BaU1g&7F2p<3D())1n4zH?dZwhTljdI_yGP()IK4B=29B zQe{qux=}%@NlmjncEu%_LGIJ*p73MbMVA$yc;5zy0` znhL>4uS9syiWxhzsq>|6j? z4!Op$ANkd5HtUUuu&Oa$@1w(q2ih&>GqwH{Vi>nAK~!9HI8UbwQn)^D?3K~HNosoT zDxy8~n%UlHU03*%*&hM+aZ-}fjH)s;z)WvF-$6Bi4zY2bvvLau>inkLolM(pIMu`| z@|L?;@w;nynBzjVHy2T*`Ffd|G$_PRaf{h}5g{)bE3m#o#GzM{{5j5=@6mCeHs9i8 z;Va=Rx)KZXvuOUFsDmrxtliaa`jBksV#SzLz6dbS(ph>~6Zc=tS^5_)ikZhp_kD5E zEM!`mbIK0tCl^Ul`t;9(8PBr8c6ECNbi3;VTK&!qC0H&s7VeaKW^iX~axz_MsUw)X zr+E+C=qf6fB>VJwuv}Au?er{}_pR<%U06Y!kN$RkkdEqb!`y_<*ngw`;Uc-63c}=W z9m=_zH;R84s|joU{_cE-RLYPG;Cu@DHIK@mgEls%W+M>LfKZp{fjJI2*ZXs1-rrgV zfCZ+?lRvnMK#Xb;fKo zB7Tk-0R<#mF{ZKe+(5!=1(8Q-iZvPL?CT9>st37n!XI|XKmYSln@q;dcqE;KAeCTK()%y@8wOj}` zAP?|#;?S02dCbsVyMfj6K;N|$6xF%eMxxU#Wys#$KIMX3OhUk{&DP~|h8LM&T36!Y zdCxYB#EeQ(Ejur@J+u6z(dzaY2IH81-PX9TeIN&GVJcd|uuBoyv_C<;fb(W8TdT1e zas*wXtkxWeIjc;u2rQK6<@pQUr@QFLR{-Cv%T%>8bB0)RAvY?bT{LNDsq^r+=i1<{)N`Se1m>^Fz^{V|@v-#T(lAi!6 zAU^XRUtBBt!^GpPs$~K_2be@S&uzqPi<+w}{_3;%1Sqk^Yv8)LRH_P5E}bpBiJAW) zQN=n>DY*V-7xq{lNC7x^zdUM zx<8|tXNuCE&I}=L`=dW(*3?GHRtAj zTSjIudk}lGM>dj)*R@FBF-9kSs5OQq{Xqi@7E=>pxPU7t;Yoew2l2-@l97!K7D8`l zA#y|Z(P`VkGc7zCGJ8I#nh-rpxvxMVzyt6L#4Lf-A}P?G2rABGU3?cgFJ764p`4?K z(qRx~ie))lE&bpNQT^N31dm*)8)itKti`MEaF(m&lZ~!gd$~yC63pRpR7-1APIMpo zBnUF31dYS)X%UtyEiA~nc;ND3Ku|(Hpc=>S3s6XBa4J|J(95+M(-|wq(f)mt_YB#v zD>3LYu?amhAjf}!Xh0i%x7hmmI7rg{!ik%5vb1wc5^LA*EdsSR{ZbCR2B$|Rgk3or zq5@e!?uId=0X$zeD7VOcB}7i7EHc|${s~vH)*_F6ZYSKI(*m^P!x}RHJ#fkTg#lGnCzR2VOLF&RvA6Au=?GXBXQUQ>xaj zmC2>^i3NGT)o71%^y7d^U6nwbld>qFTbe13zZTjo_uAQ(&ro>f(RFWq2u`)@G1f{b zcc&AaPhtnqhO||h)Y!AfGt{ii>Y{a!Z(P_0#zU%qVw z-dKq(8#5C_HQK@FRT?wvJZdKqhKi48%h4>5{C~Uv_A-p}6a3pv+<7kroZo&5 zLP8qf9`&21zu9$Y-Fx^S2B_$Jjv`A^-a~J;M|o+%;hbmJ5+d9WzFXc20Uw#Hz2EKq@R0ccfk$E$?;z`Sgbhl ztQNy!@n2tmM7*b~%;)OAT-gb9EkRY%Ooyy#2B0D6Z4I%-g3U4X)|b#Fkp|Eup`mX< z8Z=c{y*=`|J?;>}t}3RFUE2@HqEUAz+;q}u-jQkF{Xl^Ef%~I1dH2jH6_=VNTS+v= zkP>EUd6~Q9K~#xl2cqDjUva?guD62VBDdd&>ahp(@_KSwU}DJ_#`xj+tw{F@nZO9g zuzAsNNEifI{&CXyx#lPW3%!$U4LZdwy>MV-B0ml47er-$4t3A>5lE+gAdR z&WUxl(MeY(K4ffLP7U2+X>NjYJTHmR2;EMjiW*H0NtvFwUabV8W#HpLdkFow`>;}q zmPfx5{~_Pc7gJZo3CvqCbnWup&$}>fchOwN z2p)4vQu(6^WaA5JdR-YbT@i_MhA}*(OWNL1(iyBWvfL-a60*{)_W7hT=~mK{e9zmU zd+n^gpI#h?>Q|sO7DE=OMJKXQ5KDTlJiGVYl+)23i|P(#z=W@)@ISx~rhD`ZNS924 znd0L!8$L<5{0w^hE~_VOuR=Q1BpZZx$66Hy;SG3$P($>X7rL@KPOJJ>?G_{@Ihc?D zKTCjqDN&@@egAeu+kTwiDn;8?$jizIiV5btz&PnMbGD3ID_dm#(M30kR^X)VEMJH8 zSDE*AEz%$&8pr%$JWB^6^Af_5ia{pbxNyWcOW!%9#!UCD5XEV$V#$9IorXXNLrfEk zg0mF5<%hUIY-6AVLV9C1S+-k#=8qPD(|~t*8NghKfuteAUSREY10_^|BYwFO7Be+t zJN?mr$%Cu`mKt7i<`*^U1?Eb4OoDLgA|&aBwWMeJ>~_w0P8)dC(B|=mNphI={6XIn zK675f_e?!3K8%1=g(&0k$WhW~(@!9&;aSe#U4^TQ3*TgAiptC@+$1z8vEv!?<<5s$ z)$=F)CEI}rI9Hf#(qmZVuHp_H7!?ufbb6*!Q6!>EujQQ%KUkQ^eMMsdx(1C&9WUK$OL>TR%8x|V9K{)E5ndXVHol|4b z=2;GH(9yPfquJ_$6O=$-!mg0g*HX%({U$uoGI@;2*-KOSlQJ*+rYzhAOV(m#y4z&z z&8<0xASQbCkx^o4#dQB`=|^>aE13nIrsdaN>q&i=8;%D+h~Cy2QPO5b`t<25#E2l* zonyd(ia?=x(ru}=377ksa3#F=6SHMV>#?}Io^6m9+wMbPqNHZH|F0cR^*G>CD&2r|x)hG-O)4 zNQAM{0%+3ao;o+M^kkHVcR2zq!EfN3T1J9Frvf}JAqOlu!O>c3_Ez3$JuIkuLsEo_ z4*0J6L*j%bEPYe0UJh}bQg6cU-7dMjB1dD}d18cg_h!({NF~x}CZ5<)!*M8_2f$M{ zBD#Sby zNuUgE(|$#0J{H%G0QM;-n4WMP8yFp*L%@JQ2w}`WAY@EKuP}}qZRk~lG1Po>-F*mL zyebVu@1oJZJU^_x=l1tD)UM?;+-rQ%vb8u(NN3SX5*bXYQJ1p0ElkL<&nkvw-CrMnxbL@x z7!Ce{&AD~mmQzLjLRHt@kPV`9HU-pWHIlW%(01|EA7~-NbQOdp|NQAO z>1n#lCF)c^ZijDJRWS51tG^h!Nlu&S{&C7uKf2_Yv0=G}_7R1<5h+!GSYTIPI#a;) z^w9@tCPQ}e-di{fpfUlU+Bh<&u~-n$t8UR(k2dC{o@2la7-z6u@%_BZxp>y0(7A0m z(*Ko{Nz1GEnKo84wpN{07i+naAA}dJ6P5mpOW%CqX4BOO=g;#Y zbt=K4ptG%$RF|%hKE}6kQM>4hgwSUSwz1?Z(t^HMJ;Uf4G-zB@P8R>JAp!Fszm2n! zNMW`UK0z}{0sU)<_{AplKVeVtJ$O8GUS0Dk3qt{P2_UWK2Sly5JMBH4i`*`{><`R- z&2TP&6iFC8BbKtDSPh#gh0LB*JTvdyMP$y>-qc84C(iZza;tZ%pY6Xt6)<7jp^~xj z^80kmrraS<(gIdTfMnKa+~9Y)rlA0 zjBD-X=G_=E?^|bk?~L!*kY&(kX=vNQqb|5dv+wHmKN$M&;f%(v9MP?uIVwew@Ev^l z2DSg(U_=$(3E`z*=18^J(7!QO2l*d0!v+~5v3~=hL^0KU`?)S;+Y56boavivuW=ID zDsf|OM+3~jK%LeJvqWQcsaV~vNRYK#C~kzNejZ^hpU&9!5gF>kWm&2J-GE}i6O4db+2s=_$B^v;`s z%NCkP!mU@%xc+CDWjEU}GP)K)X$|_tZI@h|56$x@o9J1n@6Z(p>j~#?i7S7636uPW zK9t9cMPadaZVo=s%bZs-9JsE3PIi83aL?t$BHa^WLBgyF2j%iS+sm zj5{q_|HF0{^spoiM(M@U_ zsipUdzdOhSMX=IQ!#?20=`=xSqNPJd+trQDeJe#lMcy||?iDEHSp9;*mY(NEGX^R! z7EM;dfz4|i#k)D_-J3!575@!7mVY0y)?_++qe|c-7>3jJMERwv1LD+S!4@~>gQ4o1 zu2@3!NWYFVT|}N9Zc`E|YP&}5rV@yhJj-;ivFnC+OQruZgE^o>G4hufQhJO-8O)9E(H_17%V@%3od}*h1;IA*?@60(c1(7a z9nz2*$Jafk9qRV_&>bBuPI5K7+{Kwr4Gxd(!|No$QMt{Rf_^3*&Ia*Zui-V=ftD zTQ#>TMBbpuGHc}+GVC}>QX!Hkh01B+7yMCw!fbS1f~NiOKOl5>>ZC#?MuF#0c+#d0YPE%yiJ)4C)4?-ekz zYNZ8Je*7PvX_{aH%JdP+>h&E(O(|y}S*iqMY3KKReDjQBvXAYU^y}G+#_6`(wplF| zTP{8-DQB$dkH+0D*0wb@$to@}W{=#Hwzgx%XW)wx;H;>tAa}FQaKseusL#q^bJYRx z^yahIr&i&|0yuFrxZ$|)6GBGdLl!}e*mIoJN)?5`q)kXNytz*Vs6+Q!zBjhDTm;HL zX3_<%?XVM-l61bQhCSyi2UV}PrC2XPImDg0s_qPP7b3%5jxh zK5HORD`<4BP))mXD&vT)Hk8yc%)@OAS0#h9O_whp3qo+?~vp-K>0BC8Jc0C#(pWUfL5NmFi74CcIy< z{IyWq*h*5Okknx}U@Ir@b9b`}2kXtQ)?0YzXPvh!Ry8UNixM0by1{T@SbauOCJ2$qSDobsVi%C*cf1q z4d^(XE;8(hzZp(mdMe7V3^YdURn%y$!x)2jzB|gg>wUkdS9N8+Fvd>!2JQFnFxNVx zR-+M-J*N!n7lQixHL;hngf!s?1-iDKzZv>9=cKYD*gfyp`(1%i|4`ItR=Ieg-Z@o_ z3cCYQuzY;sQWcT&+#Ct$o(e!d9Ql;6RW4Zl7<{5h|5YX%)|W1Lxe;gWN6q zFH2mj2L`vEZPep39tAvt{=4+aK;kGk^DyD|cn?rLmG8@_*{_tRbEoAaa)4fakUV-O zt*&6*@3&IwN(+claz(19Kx3d-(d*GA-8Ia!UqT5(n_IHT_v=p*(1XI5z z6xqm5)_qr(`>TpPTTH7(Kn$e69XSc^B?G<*>DN~=fgIVV|L6Aqy@)L+Wy4resS(S4|=CfbJ?zwyQ(bKy*w?SQa6Qr~dcL`mfdcf&C5n*8THt&F&c+ zE}2*wTDbT)u%bhx0*(JiU7vq%r+8lLY6_hmEtkuAERfVK$+`PIh_lRz(RGu1bYvtJ z?s)T&|J3LRH8m_~b6vB=CW_V(3u3CeS+o7)%J3##`Wf0(f%0*O% z#w3Cg_>3ZCB>6TwUxb*ViG&KvIQ6Ul97p%TW&AJC1U~p7+xx84$~4 zZtwTbO)q+5wOj`6myUJhnrVYrp{1ovCLn{0z1VYU*2d(H5MklTPV>VY`)3Vbh>=cPrgp8w8}K8>J+qL%KVqyAkP@W^YgO(e1IkP&z$L&1Cs> zPEF5?BP5w1#V8d;zSobQ;FCg6I?M_z^t|5H+KlA}-|T+(l6kzA#nk{b&3@URb9qk% zbTJR{ugY(aeE!%n16>6go3 zP^MEOJ6WN}0`#57d=-0?iZ92~c2XsDjl-bcH>Kyn6e)C8&uKk3-6eCMsW-k5>kMDw zJT0kMJK#H%JaqMEH~&Gpn(h3{<6KTnEddy52v2jKql=|hh)EATivxz{!ukp%VZb~c z`MVudE_Ayz!P_;J?S+=6o3mLP`&-AU)Orc}iaGnAOp8`g0ze+~IJSfDr001=#s3X9$WAnT<(Y89xk)o$tvtrw`eK=Bdm*QZ zAYVS2{Cwek#mpHHYxf0VP;~iE%hG(Z^)1?T{M87x|9NcuEnk8C-FME0qk!io%N_nf zG!uo&t=B)rc8~fxJ3kNinsmhu_f;-OhIU!3<#d`M zCl-(qC72=|ywD27?kIH4#$4pood!D8O?>XIh-y_(>| z;>PirWJ^Jy%^*4!$}f}h(uy89#}u<>dMwwj0&UkZ$@~ee0?_cl>N|IA0>5R;+sU1Z zp3-w0WJC|pWj7lle8s@5;No(5p}qXb+*ERu#Ec&rj$n=$`$|<#&HoRR(2?q0+xcLT z&)}=bC|xr;fgIi=Fg*jBfl_7*gD+J#RkyN+hTnvM|3l-g(# z(_i}HIF2l-*Ki%65_31qsIpx2esjo^X(^0jD9U-!WlH1cC+CF*cDoh6qMO9Q9>DJ=`P>pcS-7cnFL%aik=Z-+rB;%Fzp2D67BZvuLKpso|}*u`!*w+(E}le9Muz7H1sW))O&C zx@;N#T3Oj}?mMXN^Un!8;Onw{cCNI5K zKPG!|ufO)~5O4UY&%JD_`G@ zqQgh3sE`ex&t*0p4tIs_n2dAyN*Wsa&V^~nKGU<{m|ImXeHAVJz>LIoi!7h;S#1C6 zne^d8%lfW`UMjbe`WweQ&9jN|3i>przzh$%Y_`mU`dcR>9EbBa&d(F;xE4Ol zYZqAF72`YXvGqRtD&>~-oLk>}`{4m~{SYwjO%ICC-o--w`in~q{MopTepku%w|qE3 zrJ9y+<|5$Mu&T+w{)sQ>UXT5?YHv~Tmv#itl{taHl|(YHWASokdEox{npipJ*6Fur zCmh50lJsFSbkiLpK^Thd-5AV{<)Rfz8)_ERys?jHPqwY{eQV9}(`ro006vjNd%tW> z{tv_S)xp{8Jg+929+9Qf^6u|sz86HfKvpdTMF&uhz`8ek95Y`liO76><1A2Lf&w8< zT9m*8jtTQ_JL-8(ogR&<_!yTl3JYVk4_Cb!uTjlbz-qp+#{GQW+5Sv(GpP4Csb0o1 z*kPBc4u(YHN!o&b$h7GBvn&`ml}JE}b79mZQP0$=U`08zBU24ZZ)*{CAo4MSOLUk6 z;#f^nKR2g?#Q~s9Z5}fgdujc&Pej@|x|5Lf8?)y$9}(6SE6oEYMm#%`+|9oJmTTnJ z_)R2jZ8cITA?p_xwwlSH{9AfQmT_*y+v{^K$ID)!AyyZ2bWh8p)18tE*oaEt)z8A| zYafN8tud?w^%O?+^t*|Ul*Q4D-d9xlDx8ycHalxU36rn|)r4JeIKpshW|pxeC1etO z5rn+3%yzEexr|Dzv|)@4-gYdTv}l~Dr6XNVWLTo1k?{r>lR+A?RX#n6oJ`Ui}hfetiGv;59oJ?Q!>3!;B`DO?xLUHR-wp<32P)U{nfa5 z@9^|_MaHR>X%S>e!wYa_fcc*ZZ$0x#EsOrGj~RdHukQB!`2L5|@S; zkEQrNIEJmFVDTq4_4lI;iMKo#*1@(1xuUT@3=}3$nWVZ%kjnkK+^^FN$fe7Z-h>dp zQ1HHe2oy)0TLLtJ86-c7V*OfCfK6GgO!t8tIa~u#0EmigAM;h#LoI8t@Voe;lC)kH zd1qTJXZ!a&qZ1Gy%2rh8VEJ*E(^7mYacIkHK4!8LW2$JSyJI@_^rOJ=!d;YD^L3?H z2~`Z5lk($iASjbVfAYGnX6p0itjoip3f?l2uM@oR1<40~v){BN-L!h?ONso*Y||4| zcHJmT)An+IJ|gmJz64^0^|~pZkpe!5Q-N(#rYmW1Dti7(9 z2iL6}#)+oBmn#{@@khc-__u6-El()V(%_wwoc#+$Kha{ctJd#p5>EYerA$nLs)ktk ztBhMtiT&acUe?Y{ahqfJ&c-FjbZ3{(TkRLS9{pD8yJ~5Ar_K`|#CCER&U7CoA#DBUx=gb{I1}igYeU64d7;Y$zmV+$k zZ0L$oBofLIuY$>IdCCvoS+eEI^d3B`cHmhh`2`{3{Os|Lb^L3U{-dGkjQ`%mlClSYlAmU??F(*ypneJwd1N(%k9HB6Iqgh&wC>f0PKh^a~M=%~e__bh|t&MPIcOv@tqt z53KJgtL{9am1d6Y0lJdvRkOcMWM_wbBKLVf4M|RbR$4XhMx-h*7F=}kBKxM1I&w6B ztwT>j<_JOtp}9|v>)y#9y1rUqwI_|@cHh03|7qcv(+uNF`>3_}5`wO^lxN5np5(mJ zNx+At6q;J@2tZXnJGJb|Q=Gi#bebe{l<*wLcNE{Uc#rM_R@FHOrq*X464BlDF+Q`= zBB)h7mHtL4XMfQ=FBCLatOW`*Hg68g_qUjs_~BD~Y>5|`(UP>B)q zTy%`0(Wj7D6gRM&z$fmo_UD^fkieW}S;vQ0Q_GLmoRG;g*?@p&FXBFW)S}3Ml}<9p zza?~5*JciV21-s&E`0oHK=zBI-R~O6crO>$=YG_L1_Yk960?;36z248 zTkwkj>-Uwi@h3@V@`5ba9aP1lB`>HkLZ@UMej zn^g;Y8&;dTlp&p$;*X6}ELzu6K3_b!Xnx8(t1+-YG&HKRt6V?zklNuwY?KayTp*MA z3>06HVyT8atNE;#hWQnv)F&6b&1xb25~_ft|(Nf-H{fKN;e zWthhBJ1{$$0J6NIPg)d@1xwK`<39`W)!{`X1YxWt<+{*Y1}6mTTM!ZZa3 zk8S+$wPPzK6_pGyJoV;wYB5?9Bf&KT#ht^WQ9hktCMGsEPcyd1ek}N7u42Z*E2}%B z_;wgwdB<2k=Z#@=+8d!)Yls^BOnn%a!JttEsZ46Io29CID`&NHj(q+!WyVCDiTu4L zUCy)}fQ6k(oY^A7H>-UizUb(UVRY5tXUi_vq>Slz(+2%~9~P{A-S{%u#3p9HL1rJ29?sDZp76!}Ci&^hPJvMdjzgPJJrb@brvo2KITmHv-P z&#UyBKSZzLVM|-mU-vG|BSxN>JnP(z6!J_2@Gu<4CMNwD9%S4Sc2&*3vGDTj9*5&c zAI5s!-cpyj5Mt+dF7@Py;Wlq4u0*$Ctf&yL!0|PzGgjfkYV4iR-a~30AQFXxS-gQr$_H7l`Ea@9>YDN0k_gz%(?o7buryUdUZE;w` zh|OyC?KV(Smk%$QgiIBkan6;MpQBE+jeaP@UFI>RG4a;MOt<}q6P9a1iU|kvXbD1z zj6TlsVnYIl{C2#f>;@s0AQKZ4b^yfVMTCWknfs=x_Ei}(H|o(ctpx0c4u{O`-iaKh ziiA-75zg9_4;sGUpY3m$nsOX4iO^tBkMj*1O82Nu7|zOSdQwlpB_sIZW1zU)Wz+6ogQa zy`Y~sndZScFVD9=QJ!l16%8aeb^3>f5?oK&b3JBXy4BhFm9GbJl{3~Ej|Pa~)cVg^YtCplfl*bx+L8LuuSft_SXeI;n> zPWbnfI116jdmr$5lyvkapm)C^{u!j3$<}P$dTH9V%E|{rIIYwT$$f*-OfTx)4nn}>F~a^T zmg2Z=*(1M*d6XAiuZi%5T*O!J_%D`Nli7?UyA`qwUqdC35nHl`lR2cy+YYp5T0NTh zPsde`Z^JBt$Vpxl>@Sd@$c?b1ausc<_ULB3CA=?z{FcHChxB!G*|cr>33%F7#cNaW zZ9t_-eNn`FXZhrXp@IewUxw9pgfjjGz>M5}077?@0CjzjOgIp7gM|wQManHH=sf1y zFR7rUq3Mm|AQRM0_qe0FwB9JKq;(F*?O>XHD@QYLqpRtl)A#}w#YgeSs&A>h%Xjz@ zSs3zMu2V7UD14^LAw&m`kYqH$+(7=jK30OufuAe%@B57+`GY8mHb@tiR)&RyWPwAH zNr}*TrGe}%{bq)jPgl1~iJr0+dE3p+m%~2on7BCF7B`XuA*_&)5aWfp2BorQ=j6CJ z<84O`mNp;`RU&O0N)6=R&?O^fVtVaL{QX-SKMUXo4FAG;#0y>9jy^eQw3m(~Hf`9b ze~=A3Y`djKqe;kNCOF-ZIk%p_f!8FyWNKno7b!F7d^84(`u%mx1SC#ZBtqTc^T_4% z;=Il~YkIA~5rLXj4s>US?Pt~$eU5u0qiy^Q3~~uf+NQ8WpLh+pT3PO!+1k5xtI6_s zV00isoy2^rLaMyQx5gT;OW11$llkwC0g=o$i>)7l2MwE- z5(PJN{4NJGX5p1tnlG%!a$~lt1>Bm#2ruI>-Z{9y)tJJ!a=)c;4%1{1k{unPNMc(q zX0>3XIVA6Z?pwPsB8AY{82T9x$L^bV9UAg$tR{g>YoviomEBYRYBNO&UYEp>QjO0Y zZ93hF6j!IQ<>$^dcyK*PoMhOKjYClu>j#m1LqX6p)W>+taRnK~binCpTWf<Wt zg5jD+X?yEJU%TIR_#LhIZLRzMc)tuJGe`S%1>g6`y8tH+ zKOq_Xm10#9j|)kAE3j5lqz4->QVBQDTW|YW-bBhvWM#t)^bhwQ`4n!-?ULG?nAZB3 zYLHvVBs}5u^maeHRBc#pELra&>rHjvb2Kv9JCjx;bf88Tr%{--*j{`1we9c9%l(DY z1Mu-10Gya=sb4qu5JjBdXA2|EJun-w)cd~HfDCQb{}v@US*FQsS(e-H+b_-DMFM{i zs8c5^notji54gYCc!T6Mzf-w;8$LkK!ljH!i9?G(jTFh;tI)TwFd#vkWOLl9Q5Hs@ zkUF!l-Wa~II;%T%bf{K0WsO0a`daH?c5cn4$We8DJ!$z(=UbA37p2uLTF;Z$v?C6d zDs|3FJ}$_6Ab#9iH+5UIFALO+aI7S1d~&jGV-xv#NIjNt9vy}xrs{PELu~H`>8YUZ zanP|XFrMS0lFt>l<-IEjxY%CzIwL6Pr=!UrEn}a3M5ykzKaIaiTftu78wpFm9QZ8E zI?}`SQmHcGPtL4@?P1M_)MpV)T>KdKb-y!d(j9Rc3Wtk_G&Z+is$R;7h>-b_RItWG zL0Hg&p!Kgl#LklB%v?V=41UP)obMqt)kU(J4x?m_f&S7>Uwj5o8*oAMQ@~!<| z8{xGQMvu{BKJaikU43!B`HYm#i(_>>QJiT|EL-B}u~Dn$ zK}leF&bjiJW_&nX+m8L4-tbF()2}$gO><_RIdIMgZz8I+Vg2>sN6b=Z^jkg^2eOxx zlwAamS#GxjWQJj{OV*Qeu6Gq<$J0h~>3b*mI3({HP4e^{K=oyL0lHzT=@XQH*w61& zQ4bU!cs(Y>vJNaQna8v{q=XQFvlShR1KiqjuKEi|6xa=WdcspP`|HC?l3Fa44Pyv} zerO;Q>)Pc)T^n2a!eV1%!$T9r9#ZDI1~vG_4_4pFd~8}+5_v!ceTaKwJuY45K%Y=h zFcnSqF*5c8GIwz&kZGUt0gZ2gA z3=&Ad=fYmMmHb~67zo^Ngeksnp8-84v(s~-+y4?xJZ0&NCS$! z(y*$y{RY>m$!B~q^pnUpO>N`J|5$A%=Cp5QtIwkQvVSFYA)me}B_t1QDCY1z^&=jw zpK6_8qPkR`;eyX`QD3l16RA=Rh0E60@`wtZqHXZkHHLY*Y+iV*1?B(qa2ddDpX))fBP=F|CRX(Y7hB8 zp3FVk4jW5Ju3$eeUN;SXWc40fJ^3|-PbNm8!#bEr-4tjMfVhLKFZ*j9lt(RG$Z!gl z#7rapG%3m6A<$V6AK`fryg{LgzM@+XxIclBxur^kGeqITN~!O%1~e^;#HYSYSgH_2 z{44wY*OyaNQr{|A1=Zu0^^*T-Z5z-;^kfDtnGHo812F{p%7Ilgev4Y4#{`M@0b`|= zrni1T_jBVQV4@=m!0~Y7xZrA089uCC``PWMpOq1 zG7xQlO*>0O7ZbjcYZ+aQ6mD2YB{TGc)mc_v-Y}?$l}BA8Yy?vp3PsyTOXB;B)4~@J z+Yf7XL`OK;D*T_G!q#Jd(2>fCf|eD$vsFHjkR(KaZ@@k1)lNEhu~HHRYP??%s9R@c znflv5R@BCJE=M5+3XmocITY7E?z)W?4nm=%rVjXkK9K&G=RnGcyhL%h;(ingg*J-} zGiGjK^sC@*BLcQ72L?e>;NPU(tyvat53x=!u5!1GN-*U$X z1}XQcd-NQ!T9R zFE%PD0lwT8F~-gXuiob|(a}Zwg1mHorp&UPi-Qa#Gb;;`sZigB2WTQ{68`lPpIh?G zvV*+K2w6oJ{IlWdih+6zlrCCe)7e~?H23?cfWx>|7y~~&Rp*oOE?YUD#at^*_^@3j zGyIbO-C@(FQ^Vl`A2}YS92E4Ga*6(_sr5kU-zX`fN`nCs|g1=ZQJ9Z46(v?2A$GLT3jx7DsQ%Ix#>2>?U zaJStzw!IazZ+IB5;LDiYTC3^TQ^55z^g;MO6Y5MU?UXE?{V4BMj%nmtvz_0m6r*Z} zBc+c%paj^AF#~~M%OLM>WTA7`qq=)LyUbr?8T;wJfF^V4s zBL7Kxm}2y=1_(@s#E-3;D;PE*i9eA}FyB3fHZoMV34Iz{99t0kmqX$sJRJnhM=4Dh zVl^@*_ff*M6}Md-+hAXo2B6TJA6^EFr6lbvNgU5A1hZGNHGVO=M?v|#!Dy#A>mvJ@ zyO|ZZXZdu9#wUp)3OE;Qf!g5Zz`r`3ULsbPZ5|dv>V90PB7Jn;@4k=f_5^$?G1A7A zVnR2@i^hr87t}vm#k4PAD9LaTub8S%gTFT8EohyyQg1dW$XG? z*=c~ya|Rhu@LG)4Tsz-~=Pi^Fnhck@WAG$&f=LaB*H{i%BlVHhzAomP<$sJVL=!wm z%(Hru#lAG1Ls2rv$b{k-!9MVZ)He} zQT*b!uqSdgc`%XLeLe?jGb|a_L71I9PAL?50?sFC;7^HuE>lBrYIQ`Yd-nbl%aC@U zw0CS*raMH2|H$cEK}z+O^DkJ+^S3R5OC~s3X+3@HmBGRVwm}~V1{;P7mxVxO97p$! zfB0`t^ZJ(VBVyQ62VuX(-9$7|4t?Gvw^p1hc`Ri?+>y21&u!L3Rj}SGSAwn1ln~NH z{fBRcOzC}gQm0LC$Yb#o1~;B-wklns*Tx76kf8RtrBZUsj_oxHuZ2Vh+$TlbP{M>J zwQMgH)3@tmBBm->gKb}>RSD`^?{6J@rOg};G?4ve!v7V$ccCISCtK6o!xU$UV$8i_ zYDWgWwHLy0z@;=Oe!jx{60fQlo5?wV+y)^nqH{9;lXKoSi*GCZ1#jufTjZ{VcRTn0 zjP_n4^VczIV!Hdr`m?PR+_7h6yl8p}>+pyXu7)h7T2vFtOj4KvM8d9!vpN%}^A(=W zS_~9pU(CLm3ZIGf#Q_B2Z}i?Y4M@n0rY~VEL<5@8N|y*5@qqa;+zY6nTdRk*Nh2B4TjSGfswIQc2tKbmsfdel~RZC!7UAk2Ai>Y>mDZ>fc0lQN3?Wf!dfR*zC1LbcLE^7ctDYaC#F!_w1G{f2ZoRguL^`2$X4thfA*6FYMtJ<*>N*C- z;e?ogJ_rjc>5>c0T05cCchHn8VAr7kPtfEK4B-O4!*ZE~yi1<_bdE`@}h@B(TV@ z6iRmf4}lB^U_F#V!7$i5YW>XDhN0A#Id~E3YNRmkPQDpw?%(+zWCsd$qU@_KgSKg> zp+d`*lYyhocfa6Eb?(FpE1@VkpwdH4B|$ZcOZyaM{={;UT?HTDm`It3JE^!+GDHaeRIh7psc`ET zgTfytqX8c@wYPG+WAA%h{uVG`&;x~1M8y~MU&+)i>o~8aC{fW3b9A|kGS`cf;BUp_kaec$wsPGN(zsHx4&7`;Sj?0~gDne2XGBjw%a#HsRqT$X0?$KQXczGq{K=n@G2*v9)_&vLRIk9_b&#_>;HSKuZ(5L$29c54@*wvhd+&eeoNHv`-6xXC z^Th~##0h=X4JG8@{;Ag(hL_T$(qQ(-Yvgs>8;`X3%NVPSDSbonIC@l~XgQw$&Q4o0 zRx_*SFs*db?^zLPBco8d74FlN>8Y#v^j<(kg|`5+fJ&sjArCT;(C2RS9;~2{N@z09 zCt8(x_bFk6&-fyPE@pFOpR^PW|FPI_E;pdGpNKEtip4ayHdgtoxEJ>yjN9Fo>YcL~ z0eVbXSpmLCXsGC_7eocirKl~@GW92tA@i}-7~&QHn<{$mcNd~?cwr)QfNV$%adJ)N zyfpYdp3$Ji<=z*h~7%{hyELzhJp;)JkYVjTmxc#yu~k^6;T{GUUvO zPw>6`Uc4J_uzh;30f3u>EuR9ok>q~uTd`#^b{=b-aHb4Rr@GIyZgj-sER2eAid8XP z-3Y4~_MDmkvgt1q4rqRYRKjL&zk*k8KP)@sumE?#$)Kz4MTK}{i(~GoQJ9M1sZ6FC z!0lq3y*WA*KSV_MarKol)Um-NY2UISPu36lbTok5nb?f(Nt0=6>ivFm>AU=RR zWFb&zp!NZZM`$+`mBKPbTYgfji7;2 zLU3^}&c4gOD)zxB`P};PdcB}psv?q>_WtF)^Yoi8R#JE)9W&T5Z!aJ9MF>0d(HuaG zrYQR=C5mF+_>xq+qBa@zg8nHR2oGQYF;%By|1m4Lfa)Py@MH5FtsoLzU2^rBgO5Y+ z?;SzQw00=jtyPOS<9(P~2KlfrZN=lHb9l^?PItlUfZK`|e9?+u#`1Zs)}PK^EtH*L zx>8kn^)u;`m2w$&65rp&f^AYtF9d`q`7+`nssKlVctBno-EhB&;3{IZOBBRK@fSK^ zUYO=8bF5YG`4_=R9@bJ;6hAsdEnfd^AA`@*nYGAa`wW}dc>QdUc-cMntzHV6JNGCY z7H4Mp_@d{d52f4jsN4i1{_qY+w}2u{bxjvtCtd;U3mntreUZ9t)wz*t0YkjZC3M?| zc!!pIMxUG7hm}-Vu7H&r8Q5z-97HgF2JP{!1kfz9O2|&!;`zxKOs(;Y`e zn1(E{Lm&Ub#2;urPNkM|@X-8#8KexVb_f}J0Jj9D+hKmVmbQAIT4awZUeNksY10Co z)G4GlO{|TzrIB97S}%&6q(bqOxk?-1EacCU2oM|Dx*Ai>Z4vvKe8ZB9HBqY-i}CP{ zO^de!*1P;}EO(U~75Wl4LWXn?2qEeA&`=(WgOe^(w{TbQ}}yvF+qrb2!mwr?}Is8FtRpU!x6Z$iI{=wnEeVj_p}bv$#rWE}20 zwr>z%eoag-^+WRKh}81Lu}o7@TI&m_sdZ>9wtE_Hd6qWRLX8paVyVP}6NnH0R!RgE zRq`d3*gKd)RR8WO2H{+cvU}b53>~7{S>sbd_hN>58xw1urcU*$4tK(`I07%=zXBz~ z5a_>4gvcr&qsXdbrRrt8Uuy(UnYIxFsmyq>^5UN-DAEgCJP_$F;7_DFd}j-D(=4)= zZq#<2WQZNWj^tDny(#!m<2{CI_%7rXs_$>#=Ijjbm)K04cluOq4bvz-{fH&h1q1UK zG^wK=3gqI{;kVf(Gcs?s=9r&=;Q59G0_AO|LT&`TfC-2e0W7OAAx%OIxFe)p+oS9q z?MRvW@adeM8l#y;Li18kqU%=nWX6g@r>L=A>jSau?OUi@yVa+q=yXQ`dvnPm$$nQ-te3oPek)oni{a1O!M~e(J5?rs{mn zLXgbM_EN96Sj|hZW#d&}v20k|KMI`5j;Kvq%wM;Xs73o)b{b*7ImTWtgcUoEFLxwN z!d@S-t!$i3oAs?~Xg+xmbRD_ZTjAtEE|wm{zAD>82AcZeqSsiZn_fTS;DJYcYo}a~ zw0Rm2u-zWq+lb#+MC0>WN<$Br9{7&?J7&p7pNzRG|AVQfi2Nf6si4KG=yRf@Ru-+9 z$_N;9XIOK{Y&2V0591s4St`@8ZSf$*(-Bgc-r{Zif+ALb@AaZ-O~X&xF_k(^V+!qo ztb>cQ^+)=9xJc|{0cbiPwzDMn8sxhhM`F)wl{}KxhKa$SHtoM{QlSXwwIk`gV>|y- zkEO}Ur#&O?^0eT0F%1t&!(ePVPoVFv3@Wj`WChT|Btnj;UOmhM$(Izy9op-AXRbZB zXPb2AbU9z0uYs=qg3?V)9n4xFR@oLxsPH_=2wCrDkL3Sct6F9Dq`DI6KISziRXR$* zds<^abZ_bty-i#KD0(PRkBZPX2T!VHWn#XKBJg0gq1$oiarn_5sxxvLf|#-@=Q6@1 zP3koE*b)**AGM>cS#z0($@}$0JL41(T&wr`d3{fOKe2d6WN7FN2TiSV{-delARhq_ zhLXm)n;sIk)`$l{x9>i>({&fZ^OAbw<$aZ26NxIE*cD7Y?PG#ux z2&OTRKnOAg(tp{PTUFMS5N5DG;%SPOja#4%>*Uv5xy=u}jRIp|x8vliWxfl4ung#t zc_7c_jh46Sia+J=uiAX3zk*lrHX7B4L-GAL3x&o3u9t25Lamp5-`a{bjcv>-?tQ<% zY?$~1#CIp)Tv?$9UKja;ed&>(^|;6Q9a;s@V=L8sFB{E=dw7y6(gwCFalUDjQkD6y zU(rXZsEyCi%SmOtT{k4S&zC*9_nkf>rM;&1u_b4{L*BKClR~mN{!qG%9$Hh#kiuvd zO2{u(TFRRgp#5gjsc4p4B&BgRm#wR)$9!O1%BYaIG=Iln)xnRl@Z)6>@^Bm~5goxQ z<%dP8Y>_x`6BKhAi=+Z>KgOU=r)O`3J&rlk^RBkY$g#hx@s=sjzf-jcK8Z|j@8g=B z`B&oX-;G#Gso)#jm8(|@&)M)tUXHCv<~(Aezd0d2!4&1qLdh{m9q>NYG5;1vmL4lP z!PtF+S*qvD3f8?@q0_dzY?MRy@YlbX3OIQy761hhU2wBq)=hXkeM@}duQs&bC=&+NNH6u$ zUzd-WmQ=+F0Rmze?~M|PSrTv7^1HME%JKJ4R17fB=Jo9A{}|T4{m*;9#sUx+!>b=( zj(_*&{<(%c1MZ7<#y8wI+5g`^VRAe`)-p`z zf1xfP2<}6+JBML^AVvP>vatDmnDtbBL-xN@$95mn$dh=g{aqCJZQlXr{{OB2f7*I| zaT<7)Xe{6VB0PZZ(1B`)ume#_NZW)Hm@nZUu~i@%n*UuC?&~K?Uu7JrCsJ2rWm9gM zs!my_YKc@o`SvF9{1f8*z4yR{uso)%h^?%&w8pd8c(c6!E+^9NI=EQMfH9E4?|fyB>(^b diff --git a/nebula-exchange/doc-2.0/CN/figs/ex-ug-002.png b/nebula-exchange/doc-2.0/CN/figs/ex-ug-002.png deleted file mode 100644 index a4abbef115da17e612b6f6d43ee9728aaa3232d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60193 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�wMox-jhh9Z zM_J!}V@Yxe(iLt&82-X~#Q223aU{SfdoVwftF5GVCp! zMABu=D?C;5viwCNoFE}xmVT%is6cw(H%-5dJH>e^P2J841!@l4EtvDsiB&(DZKg4m z;Ds~e5h3#il3A>vIZd>Mek+ah>oBPC1RSnN98YGM$G2yB98Cb)+B02n2*sqs(l%}) z!uHgq;ibBupD-kLe=J2ag@i-V;eF`wST86ZtG>ccPe3;ummaGE=a-isoXjjPgR@x2 zt+4N^yMO0aH1w_Y9sq1HpU-y3eaPa@LHte7TEKHtO?YMPUF@3shj7K$_M3rQyiuM` zP+vsMqUpm@12|mNI-$^PgP_^Eg=WJy6fU*>k=26e(RI>6@x>^9`+;=-Yec*`#cMRi z3m&mDhhL>?jdcJ*+nlCAeJWj@9HMXRm_I|^4$v2wg==rr@Ao7pCIsM{jURr#!L(EY zRf!r(xE666GZz$e?qwm$(h1>qZaG?rY`g#pDwa~j;ncj;+_Bcg^J$k3YLln&sNn+d zB89-Ec;%HBdhd*7AfxnOtVc(3jpwZZV&qmggSTnivqy(df0>F9DL$7@_)=Cs#dW%H zyNv+db`dDP|4j&XRrR_QRc3u*R-oiyVbsI*V^td?tBAYpllEB*t^hd22GCRoZPksh z57gswYD_V^3g;h?ryu-~CPt=1(w3-A10Ls>UUK1nDk&v#;?e}voCYYZTZq}wQ%O`( z^mbxQsTp4s{2|J)gmEN0#EVsSLA ztxq#gmWMdt*n40r8^kD(**k8tZ;f?e)^Vg22Irb(s!KL0K;FW(4Xu-6;Bf+@Usvq< z(hd)ZKtQ3!T;03H)afUZ|3u+t#W$#8>U99`QnG8MAKeyk@pVn>wE(Dsl(f!78VlJs z?fAsAs-<3kXaO4UhH-MUf_XB1W<%gC4CFU0uw2jOxWEuW5mr8-R1db#%A90|rg>NYVoiRC)nCtO71}BC0xEyH&_&B)BjadPBUHC=X#fUiX?I0@(L|anY+#R7z zkU(}xBld`NPZXM!1XA5%G%2M!TSHuw2Qc$vJeibRw&Ln_M>hUwCm2JRNrJ``qRL)J z=K$VB{y~pSc<(d0nXOZpenJsVy5|6*B+NjD75x2bBwqW>LTsUzN(O9{CvZBA477FQ zag?hh>QGE>*SNJMck{}-=0oE!p+I>tdeHR5fsNx}hmBA>UHp{uvC_Uh7Kk~3g9!@) z&|X1=fw>3W+G`EQQ&}BWAr}%&r6)*gvKwH`eYG5`1T`#dC_su?EERd+MBRm z^4u~quuaM5k(BMSZ{Nwm=`fC-=OKp5Bo$x03k5|wpmPBOujS#G0wUb0~`6r41!Alk7Cv|29KI>;CE0lJ6 zv8r9eW70xXeP*}Xp}CtnVB4m4nDO`rkg)aJlmL8Ia^`qY=rh-*zpvYIHc{zaHuCsNzGsU$h`X0lb*8mx7!c)6}!m?-i|Z_0^#SO5TnX^U*3=(06Iy zjP7ODI>~lC2It2QHnZpG7LAmii;O&jvMP2yGd?#JCSog4($x~~QqtJJ9vg9`8qF-{ z{^C)DV1*MU#IwYS6`YZp6XQcHmF3E+09VQ>&IpBbY8atpW~aZVRwq8}u+!AgBGFUq?!xk`OUecm6$`3&E0tBwGb6}FF&9pg3obE za&2NSnoJyP zuycFs9STv!5YFkHJ`SW;E0@#LP$qUW{^b`D{efrS-jy!Jfc!Aq$9AI!pD=`gwHw!> zdXP*;QwFs5q*QVhcKObIdT9y*@7$OS8iL~+?ZnDGFuwn*B2qj9X5a1S&DoeV4Ud!W zI!ct_KB{j4_OS%xAS!o_ zBb7Y+>*AwWy0bX#L;)6vg^8yOU4}oOY;)eSDA0o5nCYd-hixYwY1ne==sKC}cQ?OT zlM{)es|E?A7Sq;qg+oO-Gpa`)s=Q4K9&@7XIL{wt7{T@KiXB3MtMX>=*Yp3lkN`W2a(V5w7xTlR_ihNAb`=DQ?A$Or%~!oHBp9MQuBr5 zjMkZfXY8{1dv9KU6*c>w^ifL}q@37FhK?`GpUE^Z4OP!$P`fBC*A9WJFDB^UbT-Pk zeL>EW{TL1(RmhCCm1XjZFKF;7jc0aO>m3mw)pjs0huS-_g_IYcQCB$H3Tf&LyZtQs zdpi_!eoTXmyZ5Q9R$mH(tEJEBDir4y;9OOw47oeO8Bfi1H=r!EZVDs2$%))`LLCvH}HiXOc3TRkUl5#Usda z2If+BySEuMQ&bi;^vS;7GIIL<(#%baB{v>L-X>mjHJ3`8F;ZPLFlVUfU7@YeqQ~3D z?4O8>j{rN_y|$O(%eYHB`GFP<9ainLlP%<5@G48)D-cOvDyYt;lD6u25M32n&12F_ zce8pU$3Ew}ns8nXMY?dDpL$fp{Dpbm zmFoa)gjVU(U%0>vEz!KyY9rYfni>YKQc$ozC|z)3OiXlS)8a%F&%WWDTHjiO85NRV72vTVs$6E8+$ExMjO5t%EFhC2l=+>t+fqQ(*^rN77V zwJn4Ijqt*+_`&&_?M}4HSE+})j9%|+t-9lQk9X^swwf^Oo&bfcq%rq2l6%`W9X9m+ zrc(Ksu%}E+*ic~ZU9PoSy|B8CRLNHYBmj`tlU~=~?cQ%RG*4}8An|GfLxnn+HYzt8 zse6^pmNlXqg#%Jo$h$JWOUV7$(L*DU$tg}gT^@%iNu-)GQmF4we0vLM91q?YJ91Ni zNBFnI14Tv?*hC-}kzuBZt*>H#RF9OO)XcuaJ|~PC+RdT*t?4 zZ;Epv=W6#oE7q>kU1hP>T)&e)K4N{Vc+_A6dj7t$PgcovUH1ca%>Dd~zQb!~;Wfy3 zLGXgya;=J_L{pyMTSRiKI8v@)|9gZ+8-(LrjkFuvn80pD852R~-og31<7C-M(|eEU zuNDBKXfP5oej-WbV*72JfFc5vDjJWhu%>0@E`45;3?*GNfj2XR+%C9n3ZgKFG+TCx&@zzG=zI<-;-vxl|=gpB#)(PiWmiyhF=ItOkpQsj!n(1HYBXNok$z%RS9yDz$>B$A*Z1kqZR zI=Lqgb4eNXSHh-m7ix;5NRltwYd?iOOO+`SZ-VH$x9RgT(|-DKBj=;w*Jwe=eUO6&%?=qF+O(+ouMYXqb~M6XbyH`< z*P;2r6^_iJ;P;%0oIvV>3ZPT>xbxymx`)db;`wA;4msGk*mR)-a12TmoXava=~Cp&7SvA>(47Xn}Nr4}HLU?bO6E2QrurT+uF13CIOMdfuiNGGT7 zj~PkuWmmfCqm?7Svr*F4V!Gd_^Mzk6gPYRZK}>x^)5XmN`V+6U?b_5JigoW3BJQjh z0ru@^1R#wIMWZ_l94B7PxaIu($!H?= zmY(t?zAZY=JjD5Gf~FJN32z$lVZ3!2S)yC(X8p2Y+n(G^w>AxaI9aUwbUWTk)gO){ z(;>A?d&BHUId+BC;R=#sXI3&WW2|L>-2LH{Sn7B( ziY}VT6JH%%WUJ6ne&V1Dq-{&ueB6Ih*O*LGIzoER9Q@e*F6G%flm)1F zL2EWOK1NtNhGmEcuS(#Zn1;mp=rdRGDAF4ta63fTEUgy6*5>Yto!1M8i;CoYGqk2V4Ai^)O zNayCsvs}68qc}OK@m3&tOYI_AzHqrXK`j*(mEdshy5$2zRLrW*M;`)0g^hCIy$JY z+4H+^ikYTy0lfy4Gn|9OdM$9mGZq0Dzja(8P0!OQN>xB^T znsG5=dt%Et^KF&9%wwYg0=bT;BWVi?=X`^@bBVF0Vjh@wn?(PvJvtwY#D*^38F~S< z8ZRDed~E%F;*Jh4)^U6>_V9tJRjsE*`g#u2-~vD+y(bHL7tR10{^n`OIH8c8f^Q{} z6kjzcB4pbB`vVcYghnTuXJU9&dFMHbuNFp@t$7s<>B6Qt`VuV6f1wZ-kMizXO9UyZ zzrTI9YC0;l%u%mLl30C)E8xx{7^BiuA4!r*w!|i5dYAkcx)zi#m*w9vRdF6x8*(%L-R`7X9)WxM} zWrzg71(S-pcMW;I*%uNfm^z(z0)h=75 zX4)mkm)S;%sZK8wuf+??U*kf}#PXclz3*tZB7Ic_CZi7q#39$-Jqstx{&q|LcLm4; zi*p3V_#kJGO180dVDI(rlti(guXHL1U5WtugG^GW=asPOzCb{zD(H2T0edR~7CMod^9w3I?a8)DPs*i| z^*oOU#JXh(py_)aSTkIouaop12d8N?o!5X2i$ao`X_77X3p8JR8s%s}}DC#CUCLBL#`l z_unFdzgHx60@CF%hcKsl)<+kTF<-dt`{HbXHv|L4GN9mnwda^e_8P-RyhnOB70>ur zhr}N_f|ZSo3hUNsn_qjqUNOYL(=`Za^HI^`SEQvKre4tG^@XQkFc>#7bQWKi90TIv zmZ1Uxu4(&CV!Wcw=OS&_M^%I}cV1oO3ghcr;r9e&P`9h4K6p~LFHquXa**}$vVv2! zlCG41vcKuE1~&&@WWX>Is2^oe1q)OjNLkaKb9OTr3Yef(+5=r#i~BV3Jh!;L5?EBD zJ&Np@O#(%71rddriwg-ulH2j0`zjoJKTL6Z9d+OQ#|y9w0oKR|h!;f>gHWD{H@a&g zQa?V>8w;vqN(2@Vb3=5WIsj>A@WSie!Y^EM$%gx_^1EFX%;fB0#8fW&k~|ihEJGT2 zhxhrxxhancoy7rfoL_xbMvE`3DWBoDl?Gz8{6oAyWQ|Wp1%!VSX_37I+sTISoT|#& z6F_frg;R9%o*1o#nm{*npWfY5sTJA?bS!-ag^v%A6%1z?Dah$>p6};9h+o-(;LAxM zP(PlUxCr6H6(?}}Z-2ZC*~?Ep6Z_b>SxA^Z)c=X1Qu#OCM3paYn?@lGB_IEQFy{bU?>5F)7)$dF@nAnG=N?c`$K8NeC1U=OLj4d z4uLqQ=3|*JT+3}bERYPr$w;{6Qpt0}Q|bmxU;)gP9yR0dZ0Lv9771Dlq+C-8o~Hqf z^oi|lmfST5!b&2*@u>L4|4Fe}oB8Qdsnvqnx5}&I(~OU}+EJFua?wwAg|aP)wC<>` z{)ML$_m?V-B-`#T&)#>-2|$0i@1p-yjGMvH=Z-?Q5x!Mpm!WOVOL8quV3$(iJO8Av z8zREPsZ_QQL2S>D+_(yI^l-U*8i|cXV6qMm4tTBB);Bh=Y8o3#fLy{RtG(QDj#!@U zR;)FFaO9PYcDs1CbYH-R*6)VO{nK8!vjW1SCfIh*gkiv}1ZJ@7s|kyu5Bi2M11k|p zH|5B$7eKEckW^StWocKiD!vyMcjdtIB${4x`~@}Ugduj*d+z?jBv)zhB6+I6TCiuF z8GJwHQ$KY8_`%;&UFQ)&J$@B;AJi$@(mMpEQg; z8pi3?2O8|}Gl5xOf&;d*_8^)Xmo0HAu=`(c&SFZrSI$cL7M6+D|qrvb66OiL>7T)No$; zLN2Fa(@f7NEPH0}&~b;rEzLFV|4Cm8EbPa&Y5>QjhV75IA@FN3a8>YF(Qc(kIWOjOH-zir=@-INf2x53Z#@bccUGoKO6K6n6sX zWfu^tgop#pE%p4DOlPagmS_Zq(L)muG&%X7?sn(ru?y#0mz32L-8OypInHl+2T)Cg z-P0`yp?7Pk`sLdoWsDQNu5>Mt|HIZVcjA>RAXIHP2io1#o7H{yEt|LMZ;m~czwDnq zbO-i_bmY1Q+y}eW&;bav=t(43vv+`IkN#;oY(T;?!|MlO>Y>ieeLyw;Y|61PG(Xv# zj>QU?lJVN`Q~L9sKgcF}We&94f3sTuUToP#Wl-8^T3q13Q`Jcx{8Z%~8B4spu8`=g z=V&F+-b1x_2n|Y8;54y2z;RHEz~xc6b{+&DqL|n~ZvQ_K;Bu$TG_rw??+r#DW`C5_ zTu&E4Ur^oIlygOfcEG$ z|LVf)(9%DhX%Y03NId?>GWQseiY3=U=*P%o?Y9Y##VPvn!bha`&|Hk_M!;v2tP^@~fKv)@n z0GsCT3)SJDa4gJdZ$xF9c#^Oy5;r~!?*QyEHS)Il{YIOK7pRO5To2G3PytJBZ!+@f zuNaEtm6T8m{!<{tg_!JgK(+4YG8P52tMA>$OEPh7%(kAk*_Y3wu^ULIO#)8+8Q>4o z`Mu_l5cd*$zTsC}a)dNOA@DtKa)ZBYCZH8Zuql2OU*;+)B^N$`v@0|Pp#A1b;KXUJ zO^!paX}UDItyWv(PpLXqmticEb_Jl;noJ6&DKcDBV+T)QP6 z^X`(U`HzogSB(0I`F2Z_^-_lZpI#RPPW>^+o=tbjxFxi`{RsKj5tdb_OX+;ku-}Tu z=%v7Zb^Sx=w?8=xC&%UZLBT-{VbS$VT4EW^R{j_JzZ?p1`jy!@Bm6g#rpbu~_NS|Q zFXjBXj%QEtKKyNP;#ewz`%mUy&VKnkI)wdwvFOWfC@(kui<5XAfwfx=SY#=X*mNu<_m~X$ycSmpM zCN&QM5NmABNggxS&pw}iHtRJ$Mpb|lDf}nz23Q@OKF}Z2Ja=n+l?WexFj(ki``Ufdvt!= z!haVh7%x~5Mc&{@e+EGwk2{0_0&%`o?z39Q(RMoLQc$MvdhyO)A76M`15)yi*LR&u zBx9fX!tQQFG1=~fb!_Ot4->vS-ZSpUUeV_`X?gqA8+RV=2KC%cUK)Lb12+DW?WIOF zT;rbnnUGFE)K2@u+;6M$hp}@gZgfVwn?hR}R6l8#_6$(buArvSz^C&&9i)TG58$CL zqF_jiaH@jslkJ(tV~6CL0ZDGTI2O2?Ct-WlfleT=o?ywnhvP|V=raEXvBZY zDVvHw>1s-A_V~sTAPVcnww(C7WvtgyJk?eG7S^E>Lg2M9#?qiUN-8?#z$(>``H|DG zbHnUT@Y`6qb8(GKX^Hfp^Wzt*m|1U&A&0PPO;#zk(h22>{s0dGUYi%?Rf|<_9 z0rOSa1G^&QrWBdLlV=>>E1d%FyQE7YY_+hO7ds#|#!eZf2*<&teJTOUuyX)IXH`zS zHX8{a2eyO~DEWS&wGSCHu#j=E`5K7bGBD~=9NfbVdnw;>SCmb)?6@WNR0Zw>Xzo4i zdfS%GM&)WDa2N8IwZHeO^uGGPM+1TYz2uB5)1_~xNWO5{vRVPybihU4;pC;uMrn=K z{fDdm!ho(OXZ%;#e7!ya&<5Ajy(=sORd<*Ywf++2ANp2X?o8O*$x|_8^GT7vgR%M~ zJ4glG=@x{YuI|&Dy_C;+jX_rafx-S(_a#tNYFYBKKsxpfOkC=AfRTww++q@Fx$=O)Z`C-I4Jd>@JHFGaUF&Ra=vWF`kSyI#G)Ml$y@U+u^V-`=`b{9 zVSMkCMZnG8RXk@gAt&e7l3aVwtOF6HNHX>4nW@Zw%2LF7KS!w~*nz7(;ht_gt~O$P zu@o<@G8sD5OD9NBJkTcjbLu;b98geth*f>(qIx|ZWmT|78@Y&6rr`!0f`3n%$X%mJ z)ymV86;4z<9sz#Oqp_E(WJy<@$BoRD9|MFJCip(L;p2$QCoIc3z!7mVf{G_qC@Nc-W$Bp%~-rdXXEiB2b@0WJ@ z_@QFk&^-HWq}~l5H(x9H`ih*D^|6W4LOiNR`TbrI3ZjC5)JyPT#B4yI2B2`BDWNcsFn#x#;rN^ zRFvFQ?{dw)P3w-+-$uhqPS#_VuTAl}V4=8y+3Y-m9ahn#HoXuT;;VsQr9Kom#C943 z6S`LK#3I!-|F%^!>sKBLyu0G^v7mMP;5rm*`%GX7Hyi!H8h>hDc{9<#oKTtZh0ViY zG~iz)nDFeibKJz|ngxq1kYkgJ@Ivi$c{4ZUZ*I#|N*JQ^ERxqk|b9}%Xx)Eiya z`CsVW?zkcjetc-)jxNl2ZhSQ0-AeHsAS+(C*%denTV{BUsN%-U2mnQ@<%G>!&GwZv zH%4H9)k1G1<<5=*a)NuB${YA*kv$|+maUQK8)75iHNY?4ir>+_+yUrb!Gd=SfpFd} z3@|tu3d|44x&`B?fjr-=z}-lTrL7b<|3&&dBKwbNS$^A%&t}}am)FjY2ZPLaPk`JJ z0;H$=rhZ#>R1E@>*=K_0*V27}gWF~wiejp=d;Ckte&A^%ndPw|a7$+*5HR+u|4!2D z!|ce;c|+To%Vo+2MA7fUcY*w~0{O}sD=ql+-83+WMaGhAM#K_OSgS-)Wmo))1uyh?;>(vEKkGV$r(h?(ehVWIFyC;!NC^@92cc zFm=23%C2sHWgugkk_Cd!kzI|-C$mJKjJKU1#1Vl84cfn@<&* zAYhE8VW+heOMPk|qN7I(!4DCoiw9MBMsHFb|c8+ODU-}*q zsB6R8-F#38h{ORmln?-&XX-Esq|+OX;bg#yTi4%j-!Vd!e+0gR=6+wbSxE%>N}D;$ zLjAPsO<>U3?%~-;ahhUp2Z97|x>Va$ko&-Uede9PIBi zy8(2US8OXz|F47Di0*c08!8n|Cj=z}p|=PrGCRY?V)dPniTz6Swua~w-=g7{2;fTq zR;}>*PeAHit2=#{+R%(RXantj=_q`&w+131e+J)rmLI^Z1B>@!PA<%v2ZTM^tBm{Xo zn$szaY&gR7`&B@Hn4@D3P+Zx1s>cMviTS>r9=IHLNL}s5f!FWUkwWGUkZO;SZ=s}3 zns6Tg%D-ln1|q?z`U7L;p>2HO&2c}u#I_5YpXpM-*MX$d8C84n+x8~xY`FzVmDY}^ z$urCY1R4Luqqft%zHlmiLl(-Q^yfesvcq(-%Y>t(zO{*)dyVNGyCtI4&JichGI8P>-QW3?7Wh*=Obu+%eE}6`o=-+S6 z_gV&6GdjRclPk|pHc(rXbq2D){7}n88d=q#EH)%sbc)k|KW&Z}AZm?m*Mr+7=0hmj z0qn;Zcru!`g8AAy4q&Iu@hSuJ7q-g>_b9*v()-_}&GU6!-UIX7V2Af3&!)E;<}w?G zzyC;J;H{(8m9kp<9tBX#H=?KR(9jgUA8c<0%7i^}+Xl76lI@oLfzuJ(cy6I8`s1d_ zT53TrSLWQ=ws#{_z9pc6AJ{KyasVd3iE1s3=bk%a0y)-#KQZH}Dp)TC(QMihXS?ZdHZn#O}KES!#9QfWhUFCi&8gcE!Jypb6Kk)v6;nUFy&2@qz zp$aCZX(WKEdXqgUz~3#$q~*>&t=-U(6Yk$u{L1+@ka+8cvD_oI8W*5E+wEpTIcn^K zgHmNJAt3`}Mh2ODKv9wHmtZGCU~{w=8+4j?O~xSzfcYrQ3^1}EJY(DP$Z{4oC=)z0 z`Zkv=$GJ;*?FDB#G}BF>wAwzkpm5W0S!toa?E>3&gSJCWEW%8UK8WApJ@G_yT2gWK z;`8-qC7_Cy52HIk0J=7o1q==K(Id2F4j%g)FDG{ZfjmR3paFpG*DNXvR>a=J*^uz??bc!V}6YjyaFa(r$F)S_L+E! zn`f+FZ01=9Gp712w3h?(up-)kmS5)q`rXtu-#PQ3vxC#%HzUsge_ZM^-Xho3#eOCY zjB5yBd$5{u+M^x##zKr`;k&MO{~TXHrOvdLrK$gJSE7M}i+rSR%ySC>sp~!*TNypX z6^ZlI)3S*w3!MBBL_i>~;2se4FY`tMv!eWBgo2JIzbuuvbjPZu60`z1ADQKB0onB1 zDEO7ame#HbFwWgkkmj0dF)kOHJk``Z=NmZUJL{SnC@?wNEd(XVyF|&TJFrY~frhNufUHo5~ z+K?!dZx)k6nxk(SokPAZ^}O9@at$!LC)Cn&JM>48j>GP4WXopBY4TZORFqHCsIubf zMpkQW{=uttsfgsM$Ki%%*0;RUG82Kqxnv*&sCngpFW?9!1bq+_5z#{DhMoykM6>CD?bW&5)-2FPiE?}A)?ZU3OIx|u>5G#tEy?< z6uL;2krW)ph*D6#F0pf2<1Uv`1Rz|LqbZKjXK*snfddCLa;ScOI)#{1Jz?gDzvN;#6X=GKB@yDf(+Z{| zF&_eXmYxHh0%L}Bv6$t8Fpo+7&G*!UUa^4$?^_L~OXX9DK(>y>&o5MFwz#JNuUwSR z6XhYM0RK{YBo}529F95g>aFNNOtU56t9&=XZp4w!yCpB9;VN130xzMVaKVBf4^*?< z1cGb_Yu^mO#@*yg>FS=flo6*87# z8_Ez7A~QvX$UJ1WZ5fh8rie_LMVaT!WS+@PBr+62?|J#&-}`x<`}aQg{X35LkGDTM zifcH}b*^)rYkk&dt?RMrG5=GL3k|FL1zLrPTQH;a=n5C#9c8hKi}{Vh6Ow7lo1f5&1VnRU{yb4Rz`YSbPB5;^Bq%QGD}&*$s78fVJi zsTZ?&mxO%dq3x$GYOjmqtv4aPV*CSLCp4hP89(UFUgy|ud)gz&isER}VGDjbZ^Kj; z)h7scIv*>(HZ5A@!%X#9@KL4Pw{S07IB(_hHsDl7Mu$Bv_n=pSC~*qPt9M-4#|g~Us(cKyUtaI zNv)2xa~v7R72ino^IwFa*ls55l>e4;eu(X=Th}x)(bVbhQI0O^#71XdShJf3NMPz1 z{-`bJyutDNDpOFQ$X?DxN8mb5rC)W0AdRB=9;TfF%{E}|>1RQnMMlFrp6RGCI#BtF z&1?5b=UjbUKTh@~)$*5}`d;xVawg{s_^LX0o-S;$ON7!uK8&oknA^Pz8|TpW4`0oa zXz-7uP4bixyz$OXLYn`Y$Q@7)MHIGi%-_kZ5=GzHx&w7AL)TEWH~^Q4hNogDdik!; zh$0h31_ejP`=>Jd&JSdTZ!?o-D05qS%evqr(jb%N5JjnyF5GtL?4!lajO8hWbTzaR zyWv?GXbchC>zw2s_Dm{YK`XF&Ydm6bv~zH5`J* z#Nlar=p&zSIcg4NsgchRVtRDp@w5;eD6>5#L}Q}tSM$%&Lt)@V)$p~v{2+$LD6<-5%V0Fa5~cR!hWgdiWYyT}sZvJu_byLlhx8?; z>>pzL#9qo1y|AAxJ{^m>4>J@&jrfoUmDe`S_dy*z@JO9b z-3GpoRgH8eJ9>3g#K*`7@jZa&iC`dg!G+!>euHQDC%_l(_ znk#NaJ0y+9MC+FP9(!VkU~#l<(*&Ue8RDB0zj1pQT`0MSUf9ze;^adLOH9Ee=;gf>A;y_ZPAnYZj@&8Aqho^f{gSxWY+ zT#iRZe3%XmqI4_kiSMN%q7R$JHzeKyxR1mSG&;#=h`Q47)x>mlucAo;_l9YGgo(_3 z>ud>z2Q7T=w#KJhDoQLD`P$|UQA;yM;&}Z9omsH~Bg-vfns>er|A^xdb@O$5mMzo4 zzTlJ@S-|qF-DE5H?)#4ian}Tm3YPalix!Jerep80;Y<3gTrKfk!Ryju-$riq>%s*a z1Oms&Te^fo;<@AHRWFrP8uluw(a}@%=Y7|&d-K)lot+o}x^5c_aVF#!l-;~m(Ylje zZ8)^PC(RXT^m(k_^If#wNfE%f3eLsqvfX{q()DapOucsWz8{2>T&fzr3Dl@g%Zeg|V*XU2u=k2;k9% z@|$bt2juqY&*X5cIzaUietVSpnjXH*4wL-ogCg06$%M>_0+@$}&Ad}Vp#w|t< z-ArxM_oBpiNlSI@1oN!s4IUU%$heh^Fnrj5HIjJ8Ac^#iSkZ`6{9wVGpocd6VvfblxkTfBKodb9kVt$w}Oz5<1pU`~$4 zuNw%hmhn~!3OBt;t8I;xC6!dWPnp;vJ=i45~cTXT*1DAl&*SFsivk$d1l~Z|NQn22 zE-(6q`-kA(6mtuSA=YGvfd`4c_<%*hO!q8bJnSi1HBAkpMh|!D)!bym6@jweduCcw z7;Akt{{o8aJhO*Wwykm3Dphr3H255jM7YdvIfy*5(l($Ld@5chDs@{&Q%p(GuaL7? z{Kd6`+@T^TZnHJZNU1GqHrnjT$cJn;@34Bv!P4-z*1~y{3J+COLtY+Kf=tYEw-=v! zXyI|EhV#R?gvp0b^=&18O}p^Rcc~UF=uBzqI8?;ODC^|ST#(n9SA~z@_@iFkNg-`l z_MB9qt1trU2a$fP)Xs}P*G#{bjdbP0Cw1I!zyHuXt8FEn19k!P)|8ToG}psX0hfDf z_&AFcKffD=_Rh($anpn>h_2T~XUB{9lTLzp93axp9oAv{h>#hGj>aSWD0SVhHEEag zK5$pXG9@`Y9C(jo^!){^Zij;12D1D{!sW(o5TyR!9&-7Ac?cGH$s+oH+|KFurSgsZ z894Kn zHecC1l5(ygs10B)7Q!^kxZzdB(4dhlN7KOXF$i;AHI59Wa$ zykxm`tPURhhcT7_dN4Hby|)+oW7UlS0-Amr2o>`f!iL)mmv4QepiZ9?M?_DZy$f}= zZia(ATb-)Vx|M4y$=wDZ+iNblC(|#U)$Lx=KSpI<#LIULd4`v$>I0%fnd#b(K;+hkpZ%!aEks?bfxQ zeV;`MKklY+NJ3mIGdD>E%&mto!On7!#X+pIK~pH?1_LlWZJlKYnio7*Nddi!8C6ov z!jZxKWao9{Fm&!S-+^-x0^sQen49e3xb*cQ+UY)j>=H!M_*dcj|NkOfa1xH)bI~|M zTtQwH36jCZB@pHTNPr*Sa!OCCf-LSQr*ZSJQ0oL^_j36=-y8ms5TE#|4q1$n^>_JL z&~~sS_NOu>oqz%I1L)QQb@jqRt&Kn@D)D;&>xz$oUIEqI0U6|rIVsdoq|(TRe&Z zJ6zsr8tUno9)&P4Hc`VJEVBKP$TiIqUI$sn9`=u#Qnv9(b1y%T0ra_v)2jdCyQ|Ud zS3ib$0a})s#TZS5L)kp>cL-Hdpi3{{xzBudN?o|n@MC~_A{p;Ih;L7 zV%CNSQ)EtgUVEa`q+I@IE}RO~7Ser~z#)DN+EBg>ta4e! zf>Si~EE^6rU3k3psP>2QIB3ZMq4m`6019_H*&j0!3I0iH7tS4z_y_E978DF$he$z& zY5_-;702Oq^1uKQH912CUxDIiGq*#~etCjeVl~C3>nL$?<$^RJHLIvYtN6slN|2A< z)zP4@1ntUp7u(tVWwy-n-xms=L%W{-f6Rp^DR2(70UXEG@oPNtjfRez?ge$+I0$^8 z4xWF-_{~@Ae?)Bq1ZjEoYXiWUc?wFJNvqPIS0}JSX38e>X~0{s^JQ;z{m-$?9w1W+v-N7xy(EvkX;4~d z!l956_38$$RAb25v1*wPB-J7IE5tRd1SlVIl|BGF!;tbP1dwW10If9YP8(OeEV!(n*T zD~Y4EOlCUt&oBOee3i&U-&`+bDEn^-@poS@0oc^Lzas`LmoS7hdKvBs2-hDhIJKfw zmNFT|0ThM}!2wW|`$6`x(QL)zr+SD|4Oom`UnSVKy?HCM{})CQbPt07uHBc^dt&ve z;uE-W&&4PgBV^JwvnfCWrQy=DVeZ8t+}7+0k%ORTU2|~uO@LjWJETsE-(tLSKLkQG z=Ap^OORusi@&%>1y*~sp6``o z!s>HU(XvPWq>7D!0isd1r}q_S+rRpOF)|s<)}+n3&jR?CRocpAa;xi&b}v#%CUBnL zt5(15#5~~-L2xVB#ywYMoG#bEidpvzzRrs`ECg)TpXYUntnhS_^_u&uUKfgMRDq1q zL%)>M7yn3e?9FHY7ssJv>geEWON3YZ=yA4>TjP}Z)RSK`yPD2Pbd2_p zh;~PWps3)}4W3k5uA8}*^`PnO3RcjXOrG_}h@O#P0ciOsuY<}~Po##pn%f{nwImOs z1ijH1c~!U55&W@i%0qw~B-DgQ=;dkE-lx5y@!5do`pMpqIY94OY0F#bG}=MGG>V=7 zJyq^|hg`!_`ZO)qV0Jn=`r%>;&Hfz|me{%jH z4#bl5q)J~Ee#H0R_wwnz|2I!{2bcxX>8d4V#IV{NK*AM(asQPD8TUGk#z{OxOPw*L zl+Z8Q>1ZD-E(YMMH6mf+XbaGP+5Bklt2xMJ@Bh3AURg~7S-pASnvg+6FCk3s^uRXj zj?@C=&Y0aJ=}%+UpT>*|fCCT|!LXe9jhw)p^f5iWO%+jUZN5OSfZ3S!vA_a1lO6Wc zN9BpS*BURlJlgvn7ainMUc?_+F17TGbNNoPbz-0YW#XAbSZ(`3pWb0t**Db?+@L;6 z1$yqHW}{yi65Ylsi;BkL5qgO3RnkNE`ykVW9z9#_SIbN9*&iIbPz-)1O#^(P)f~mi zcfi%wQ)(fE9>A&?P+e~Uz+~qN`XR(pc&oseN*TQC2d?77pD*x7NUr=;3g8|ni zzrO!qDfIFf)OwIGFv5F9wVX(pOp}ng$L)tz{I|0}Ch?(24+VxS+zlM`}P6AAAMQ zI=DCD5LyY(5cIE;uH49!>vX%Db>`WlV|vgZwngA7e^jXvVL$;m|4< zl7Jib7r%D3YOhr9l*V2JKMO{@9lD|(113T&+h}r&k0RVe7=MWkL|a5)9y8mt()?6$ zRejzjZ^1@dy9N`NRYZfd(BqBzl-SH7E;+>vem4F@&_}{MGGKjY93eR=`77j?--nT{ zZ%+c`hZuUIm(`X9R=bA#&ga{A2!Rz6hueEAA2GL=M}F{<;d)Dl&tECZ_3-%uSW&#d zpWNxy(^6Qy;`fgXSD86l65i`3W}fud@53$vO{-1=V$}OxH|G3n^%aXdsQm}GREy<<^h@>D3SF?4)6Um_P4-2=&7dQ;&*^L%(q_&wjdji@7 z)B(`2^E-&I;+|37Eise-6cxOJe0Al4rgb$b+hy;HQI0Q2o9nQ;$uu2iIsd)Y$zt`< zmuQ{X@r2I=n|eZ`>FeII(3+M@;^${VJmZx;QE7oVP#h5kAzLXPvtBRb{C7He%t3hZ zIfq)8I0rETO|JRyg_{=8w%6q_b29{WJ5aC%^|C(L{_|j~yCI8r(BX-HqtQlv#VnhXf6et7 zx6hKid}u)&>4$&-ata(NjI?(xM1hPqBY=Q!Mm(dC{Hfy5(}1V$(x3xrKOc;b6di@Y zv0p(5&rUkexV_)8x^v$e{IS|J*hnczu^9jH>DQ-^SFo8X5ez|~z^#LtmYC|iKy@?? z5~Y?PB*vh0d;QT^k#VTcX(iy6nbGsQpwTx)ZyM9V6xiM1xd}_%%U=={S>M;|(3iiZ zv65%1pcyke;VGUwEq-f#;|B>o2RnRFIsLfM5;*yjaU)^)oA7(2(|CGU@4S7i#C&3Yho~y zg~ngO!?j59*SQZ}qRc|o{f;F`94!$7YMn=V#P8zx#@xWG?a#YimIXzeu#s8^_UI1R4Xr0e5aUlFFIhv__GP|ubw_cglc{8g2-o{d0 zJ7}y05nrep;2_mT{TVN{47H2e4!+DIy&jvbWfCe^k4iUrC~7p05a-E_EO@lKi6lce zQM_9@Hnw~sEnIo{frl>@iG-n0>6&(2%vdpYK<0l4)wK0*-n^ug=`i&{$xbx}7ZBPq z94Q}6l=x$@-DqJR1TB|0Co8Tbi#t5D#=8Vt+@5a<-2lv?tP{TXAnI+dP(F}Pe8Czu zuDbsUJYGyCz&r1`y*cN2@@;FYC(@6?43H#_dGGqh+(tj{1{t}$EP{swAf52>*UOd5 z%-Q^pORGQ$fgoekPJ-0WZxchBEtMdFPRhwsi-8NUbPz@sFi5%PejO`LO9Xruu9lCE zGg4|8z~1H=-1YLp8FWWir*p)qaP%`Ew1mZC1$!bi!gVOYyWDYv&*$1u1ixm@q4`Id z>+9YGYoUMy^A}~t+R_+csE35NJpczL85DBT_c>GO@DPzR^ml0;h9hL~F2go7Qb1(u z9*45gv4-akG0kAjy+4&%cR%ep*LSI_iR~Bz^pB?ptfj`E)05tg z=bXKbfdmxU=5b_zs$2MVATzA#J5v-LuS;3x-BI$cWTcG%&~~O7I`OBn7Jm!Z5+}4V z<<;aM@H=CW6euGM672_bm1veyPR3(9F&PkHxXY_Gxb0G-3^*-Xaj5tZ38%S$rsfyy z!X?tmc}lzue@=aV_k3`eI@Z40Drv3hUXIBewg%F=eYTtq=86pIrevK*?z5Do?9|h3 zNKMp|#|2ByHcW)$#=x#MwoBuxRf zOizCQ6a&S#yaoJCK1LrM#WGc%ebABfEF6fAlbje3cnDvxK}@Nq{0&5V;!sol{0%O&UV(u* zRK=H3D19iRENj+F@~yvV8*~Lv1|=z@W)GrLr9J3QYo%?sCuGR(H&B0}5A$V?vnUf-so@+BTADi~b{TmfxL6_FI zf66#e1MA8igh-m!DIZ_JM^u>Y8FK&?b)srXa$YD{RMcND@V%S3Jy`OO>0PZI+}(zs zt)sn9<{;3lZGPCWZPfji50Ab$=BR>#S3;r&#*!5RXJT^svuFV zf?YpA()(gbKnC7_bxX$^)Nrz}`G_lI!o?AdcmIU!O`pU0~z4tcXAaR-=Io zRe=oIs$IWYi0s2!gRh#c!!I>yGL55J*h)BwX7iUmv#D^V(U?vQREt0176O}>7=JxW z8MInf6m0X7<^pl3skCXr2v69bwVl2R70O1(Imeqi8bb+CKK|!W{TAj)O zgH%&Dxtf{=rjSk!bh9ipJnu+drSa1^!G`abKxpN3V!7{Mpw&j4 z-QG5Eg)a};A$4{)2dNCt$GiXM#H*FGPQk=g3GvrOCrXgZ#Z%!N(8x8i!ue4^>(K1b z&|kfJ_t_Qmw~g;DujP)Hgf=9z{KXCEs-0*5GV$I9KW&oG0DfR1JL#~z+bPpv$^J6U znp{`jGC)!rJJ+4=3)v4HV5+QI6yh2jd9ZkpEy&g|dJYs)3;*9v{2cECSw47(oZp$; z)Oyr;GmyZ|Ez3L{;pa<4I#GZ#a-tatR($H8BM-O2(gs7js`@@hoGBRj!=ST~<95b2 zTS1J|89n;;2LEmF3yXh0am5=O=b(xI>x%cLUDFN^3CRDq6ThSO#uqZ>y#JzYNj5rq zRzRh71M&7_?aeLTT^mCE(;y7(#2c)fnfP;Ez-I!tvz^I}`U=fcUO0YN$~POoJ={$+ z{2nl&Kvyw=t4rcQxusi!RGnPVi5#EIpj}gBM80eav<(A}rT?LAn4}Uk3b;4;z~Ebv z(dg_aM&tfg*2MUat(V)6+)bQlv?iY_AQ1S!{#EGTH>h69A(nt1{qI6w`SduK1)5*z zzX)A##C5+6Y#@@ejq<-~TXOo2o-Vk(GU8vf%}xIi@2Ud(qkkv#tB>d~%h3Gj{zd3a z`JLk0F1`dXzjNRWxxh@9aqK32 z=}cA6iQSPE06I(oe5qJLb@h=4Qs}>p=Y7Lj>TVXuJQcpVtUnA*JosNHu5ybvM}d9o z-%fmsPH7pK5q9c-op@gOItQ5e?SF6E2(yZ~fQ9I|c6NJsB8d`h5VT80e;>(9(!!#G z&cud;eeQJld*mya%Zg8%Aa!B>RF<0pMjodWAf+KLfH~Z7w*c|0l}fj`#taZAyVAea zHXYsXH*W%E{RYkry8A79MfYqWZyB8QR#%)CFjpQ9^8#<`3s<($P^8V&2Zt5V592bc zl&h-11Sr^>+FKiF0cY3MQVBcMz|(X5>cFM%1^w&q+}Q&pLvel6ClytoRn3CZ?&}NlK2S&>K&G3Jz7N%QO?lmU4fanHQs2-0ToE#UQ#N$U%jduxkiZ)e zVHWp4^?h&I9v#G#ddU*YDB)x_KV88FvScP`OzRuPupaO!7W?nuzXSsBH8JV0iKx!s z6GQy~sijw-qXg|c)+NfWKcK4ZT+z!T$ibzskFDkfs=@l#FtYZNifTgf{@&0t)Qy!@ z*3gD_)7rUt8C-hHTlar# zqBzy*giY?b3a*8KLoP}7NjeKjpfXV5i#>EiUqy{wsPO+@%W9qw=f^!~YdJEQI}O&7 z7Q9F=oT6oH`;ukbtGn;-f6~qjuLJcIEE~s`qRoK>#N;~_PV)*wbv_=zW52%(N)8e^ z6tUyJlx)|gWkA{@w7d?}ilt!gIj4Wm{5xnd?&E)Qw7&uXd{L;*a{ll^+LO_EFVOJA zU8?!?%M{a4tNY z`cMdZ80bGOB2I-AG$JWO6Y>Z+!5Q>&yqWzZ+s=`_@gK+Uy{quz$$Mqc=`F?Q!z~Dw z$sO3!2#c0zw(E{#*nrIIwu4+7m3sL)`Ce=rwCutzt9^o)U^i0mQ8`JU=&!JR{o)S| zAd%#&&?@j^%l8+VDJGp_20>V2D#8ND?7{G z8a3{lJx#&H4s=@n>_&13_JA0323hZNeA^Z|G;Fo!Dh>fx7YtO7!7*I22m#e|D&Oih zr#>cw?>$X{D5m|j&!57(@7tnd%w=YMPQO5o#CYd=3L2C&Mx)a$*;LXl{Gg;WZl!%r!=pLAw!MF?gAr>P zRrZ)7>?RH&@x!TuQRF1u|IevRg^JW(WW(Bh3QZ9F+DdtRx2F>{w6gpIQVE+j*z~s| zWdyCHin?f+8(EKBs|Zwtx&pTMQl4y3db2kuQu*yTuz#Be3|adkWVyHi)tPT}ci^}y4A@;aV15d3Gh>Cf9;CX(dx4Z`?Cs*x1xeq7l0cVQ z`-#gn5yaWHBK9-YBbpkGxNt!IZ@+*p(LuPk%CQ{O0D5R|rSsyeNZD)+4Eq3xLK7Wl zsu?56n-DKSbTLtzE>wzb2j#hzDp&S4#)RomfuC-0u<>5+j{eFv&JltSN4occyx3LG zi+ieIYZuxL=`Vnt7`|W+w$Qld zgKAn34r<8X`|eKu)1t9O_)<#%KEXFbooev_l0c%Q+j?9btp^4^+7#exW~ioxM*^p|n5lM?|EOk?3GAPE(X4i7 zsNCpZhKKuHvZKU*8J^VGhVjHR!*lmNUe_~7xbkPCn*jv`O5QXryTX-ouw78EMQ2>x zPEtSp(RQd!9efCf*Gqk3ZXtZyBvyy#Sm(<3%0CDXh*;Rr z9l(%f{Vnji{R=3z)%DCCrh*(I+%* z0@&*|GT>})wr3c-(O87i$yP7rgqP?j>NOwySS-}})=Nca55NnuO-FhIHJH^WP_bYo zchjsl1eD~q3)zQPAm?zV-d{PQb}j$r0%T?1O1tLH2LXi-ynlUn0H5{JVdfqUZR}$* zKvMTzXK{i{EExzBj0JGJ=gC#u7N-9AL~r^EfFWKH4r5J?u95XmelrczXUC@B%M})Q zJdveFFI^F0P4IQF)KaB}pD4RDoh4-f7W-g0SKGanM8pqNC-n?us`LUBAy13XW>9a z9{(lqi>@=TnBmTgniI$~IrA-N=sI$%9zaLY{|rTxDq!A4hG%Y0ROSQS+Z-_va%M%A zKeFvu`}zO0qy>xJNwqb9ErHTakTt$R9J4~@RezFZI~L*lsT8pbDlal?o;mt6FkwLFl;yEFeg zfBO7dl;@d{@*V4+%7I^m{PiSSl=h_ZU$KMgYxqakim#N=JT+9E`I*2vPAfzHnEFpa z!L#*o+@M@GK`fDgKwD-)K^W!yZM+ntTdRz*QeWTYtqfOvsL5&mB%k1ADK_^T0-pm( z23#H)xBABq{T}NGKs&AALO!&Ga-ooIzdRJe>m)&uHmMHVdG9q2$Wa>tD(my4IfP^d zoY;g$B@aHIzXA@)p*$TP7r^C72Eb$Dn5loAQyK;Xz`q{QG~(M4B|r(qAfx34QusXp zHQRg-u6e@I3;sD}$FEl)0*wb0i7|#rbWY7Xw#~fxy?ck57KPyNup_FyWD-k$k_{dXw$19XD*`^j@#YtCtE|PztT) zipsZr8YV^xE8SU?CapvoAi{|EO6=1hf-oi&vn}bfPQ9@#uTIS@_9^Wb;KcbTxJQkG z9FU-|+@z=5Vb{m){6VP$*-{fAnK%|ZCq!O9`FiW;v>L{fJ|Dt>H*46bkhMU$(IU5- znJa6QztlgeOSrQ84=`h0ure`kBIQ8{Bvj>*o;%la`ZW5OG42sLU_c+#paB`1_Zjs; z!TCQ2^zy$Ch#ZXuo|6eXEBN?|P3XBH@mCKbv2ts(bv1QZ6fGhPhtT}g7)PQ0Sv3e( zLgIb84}jYh!gc{7i`BDb6|B5luq3k*{@+J%-YAg9`Zlq!#Z(rEbX^pRT%O;6RTX7$MqKQz^bVXIAKE^B4Uf6EUO%5{1n${NF%TX&Y*V} z(9tZC7UwGWvBo*jA7x<)b5`{A8hIv6m++I+^`(SYxhs%xCUv{Al@+NbP!CN=nL6p>w1U?;g z8m_uwLUhiO3qITwF^W;bV5oUy>oS@%D{7R{`q2T>P_vome>rS4%g{l;yghd zMFzfi1wL@h>ne|dcX=lpUuW1tM-3gb3<&UgS9W{Y!XB5rcWv%I%tV zPXAGp;Bc)Uu$!YFaX1?aUb0l?p44PXm+U)b{Q5-&dA@NGEJi}TY1hA)A!Y!Z$zW#y z7>7@L-)E+#0Xc;`E!>;H1!2y9w7>Cyh?2zy3X94sUR*!FgoZ{oCP{1jvL`dxT_ z(2nRm;^M5V<Z$07%dEDJ$**v@FZ!P|Df?WsR78If3cim(3y z=xg!K$k$#gj4r^ppPZk$qoljC3_g}RISp!`#T!7QO;gfaz?mDFQ@iv*xWL&)Li&!; zMWJ!g90zmYh(5Wf9w_IdnDzsF1hTZoy1=wy)^~qIU(Xc;Fh#~SLlS%b9(WPzVRIqRUAR8V#hWhE$WNkESd8|qw{2%JlmomdFc{UEfKiUMECagP8k{+ zW{Zl6o%k52E&B*fmXs+JBqxFlJdZTfsMJtRT3jKPCg`Xz9v843RM{@GYe?La_lp_@ z*p*R|ph03U$Ra#Ubyb|m6MZ}3W^@4RWs}a!dXI~TxQ9GbJ&+Rxolcr7zJMkH*e4Td zen*{t<<0G!zDv!{;A6IUs%?Pq}e(lT}0$r(SR^>*rA8s|9?!4+JE}FO~y}YmIB% z3#-4Us}+F{=emF%GzNpTta|RzEnT-DjI|S~qI%(?kp_C9*#E@t6+_5uF+B>ERLXb0 zF&A?SsNy+!+I+u|qfh(U(z&-XAkx1nUXDq`8ukcK+|#lF3e zp9uxGVdKNn4R>#*LDo>Oa6MBgMt8N1pCF8iO&lDT^r(5lte`K()vgzrHj#S|Coz~5 zDeHQ*f6P)s{OVQu4y!M2vDAOs=z4y?92bchIe5Cphr*x0XH0{m0*miZT|X|V0(lR? zmAgD>Eq4jUkx^DYBIV?L_%Ibrx@GY3J@AcoccG~u zLb7isTz{JK+HeF*6gng^xBA8urB3r0b#gQ-yaKNT2XJICn0SB?a?(XYia{^za^~U} z5O{$oV0GNHCEH*eA@iq%UJN?}by|3xU+8}nj_`l&cY651=&JMj7@K~Tltb$K1^%qA zUBKq98wuDP>O!oy{?>oTIXXC4Rt4s#bd7lgd$M8rr>sSYV{Am~{ilk=?{{xw;4XF6 z-EH8Y$qc${Ra`X}HfJ;QD6M1r)(?#A zgUx9D>vF_q2OeqHo)pLi8B2NZ7=Ul}Dc-f39BtGf^Mx zmLjpovb)F_gu?+o!EknjOf#JYnPOz$MS8tr69_I-`P4>6D5WF{lDgqUJ+2LPHWe9VK;y7%fCMGpB*HX^(}Vgfq6W?yCr zdl71_dSJ$-9!+uT-3oo&@>?rF>jT7s9=IaWWWnu8WGZNei6P#?A$V0JB72OqSR!fd zZkVN#^bj{oi-;ST;qYx6-!zTcEs;c@W4+u{*TN!`O`t@%DDJ&yBmMa+aPiAkX4|K^ zh$LcPkr7%y3qYNBT8O!}4QkWXdO$Of+Xf$lBdXYiB;Fx9c%VB;*m1td1;99z5-XqHECxqYOR?XOrZgxZOXYH(?)Q>^%?Ps8R`gzb@r0k}nZgk% zEq7HC(*UN#ztwSN4?fuhc4lL4_xV8KNs>|jK+TKv#~AqQ{Z*3vK$%Z@rvCTj-3*2N zEA@+H*lS|0o+!28Nk#1#QhLY)pLBBg-(^S7^`}SA%bAZnT8j)NqcHDk8i!8f-sQw25Ga)mf zCO+VVySoG+xu9#_{{ZCJ{U!!%9B2%(eyHRyKPEh(V*Cx-|89m6ynPnBjg-is^Ts>E zgTt2~_U(sXH!#OPp81zwCbT#&&f+X^x9lxDWyzsB4gH}B11j*8&t4j~(!@FY_(Zqd zC5Cj?wr%Zt@RHd!HL4a{|Msf?+WQPPSY1$n??N!%BylqoO7Fsg2u{f6!m9QT=Gp@e zkix;=bfwCSZ~P8_NOm_&syYI1IfEk{p_}Y+N7q+26dh`bF)Mj@5f*n1M|`jSb*Yxq z0mY~AXe!t%y?cs0c&4Fm@SNGkoIW$liO!J;z$WerqXIXyDn04_vuI_=k#Pc2qH6(j zRM;?9NeNA}W>h<913~KCe5jI$OfN~Klu|OtdbN5m2%h+PpwpsJpP^NQn0mR%#cA4% zwyK{jMVv@v$df1{FP*c~vs;js|t z>ktqASkG}C7Z$Mvmn^hlj`8=+`$d#ZaaW#YwwS$xportv4I+t&S#iRvh#XI$Mqyu5Iwr~UZN^n6G;^EcG!AO_C9-2Dw;FjZDC8|D<5w=rF2!9>t)s#!V1&ZSv9) zE4elfvBc&Oi0=)zb)^O&PEJfzYvT%tpiLeZ-MjQNlyMA|004!QqI;Y7nf<&#oW%u(n z=H`r~1ZCq-tlkF*4^>iGf~I0-&e7Mef%S+nbuDOgwR}sIa#hOIGt6fOEmYFsx~D}K zDI@hgv58Vu)0P_qJ5NDqXulH@_X3zxM8FVHDvN8{QXl+a9 zox0QpQ^M-I;z;d{Owedv;jG!>C8_%I^hleQ)8~}9FburDFXII*Ezp3eAOK(cFhqrn zJj;Z;P6n`Mw|h2_6W1{(;1JECxqc_hWbcO3eZ7i9frqg&tFUtHe@dwjTqzzwLBU1f z$MczR!Z2?Q10mWVw0*_bTf!m173Q-L()KF4AGR-r@Ya3WR*`AWG~o~UF4Lij{1j- zCZ~OedM@RMv0rK6rByMh$yZX1cE=X#IZ1tzD(C0&i3y~RJfC6k;;xU|lzsFpVnV}M zY1MzoF=_R`lA7O4F>{ppZtms?kF+q8tUMn8v`sP zj(x39Eiy@}c;^N?QQZa%)#RJNd#lB5J2$z@wG#GmXUS){s&&MtRaRYvJv_?iE(bbY zxN_utwz0D@!xD-Uen|}9^a9A=I7~6K=7L2euJJeMu@l=%Gt~6_n}}3iZM4iHl~)_v zDoH#VUF&JS2VV^2XpvFc>Yze0)KcAxp>$G^I=I<}#9+2fxK*;30fI8LdPnvg*i&QD zG53$(edRfSyqbGmqHoqb?NmzR1*6 z1)^@uR@OPk9Yx8=NBI6&c8vvxjf@-q8>6e(kyOoxNf7q&W z1uKDpPhQ@O@z~?C$^%P;LXE%scrQR`w>{AP6Xk4^vr)<4juf9Fx7b5Ii%e~S{S(De({EEkGx7jtRCgvMpH>^TA`ek6b)Xo??$Mr7!-hPDouGp=g-f8aGayt< z`+9+nucVL|8nz*uetO9mg)c?BdXE#<+K{kh#?*hkpXNX!;K3oi(s_vD%4eHb@kAWb zA>Z8VTdu5K@Mr+N`67aAMa&F?J>J5;>}oFW-EwFwH;k;^CR+M*3+=g;DNL#m>(J!$ ztf2*mkO}k4z52&Dp&j6ud)x?0D2fGu%IVg)oh_NHTTWUuXACn4VB>Ti%e#SH)#yr` zJ@4Vf@Tf`*UE+BTwi3IeM)yps9><)@Kz{B4P63lXH18JBuf1GNyH*e+d4D=9vGbiWMzB>vO+{hDDPMTJWUWu^)t4>-0In!y9dN`^nf5^TQ&Z;fQ-J z&1MEQAzLDpkx6FhG@z|1EPuf=aO}2ecF8R1Bv)87TBw!aalf?pQ(MnxwlpYtxAk5s zKYfGqZre|jEjzDtTs`HhFu$9aBrh4L?qcn4(h?L^!pKk&XdBMXKX;tY+IUH&rlmQ) zpTlO+>G7P1IUmgZJO0Hk+W-T4m^D@-boX<)S+K|gax8!|JBZ!5HBlLGSA`7)+lZfp zeW0qLJPFF<;-%lCAGK)C80a?_VBVuSBJ8g_K4>a#=vV8vWpIW?mhvNANm+%vsGc$8 zG146r;Bc|Mm-m?g&KNnXC>>}Sou`GUY|HcGqOIjb%MoR4dW~V5VX^GpNaEQ~u52Aj zl4uy0REI~0;3Vr98=neB#3aUcoDl9!=|EFcehI^Y);hmL>?9Q<#PSWWFI(GM4zm~xdo*d6LsbegsHmw}8Q@4KCwmc%T-`==*#Rv0 z*kYY9g~?tJ7x1fJb3jwo(dp`GgMk5^xY*>IoQ1qpG$UKqh{oB<%oMV)2PoO{9_NO}*UC(5Qv0 zkiCR5NuU97UZYrbzbQc?p%K|-R_DO-?c&goQ^st%j5OSXuN^Jo7VoH1+*>2+1ynsG zw%FN_JV!(&b_X`tdRD&|4CJwj1*Wjy#0#hp<_{~M6t;0R&Y8ZISkZw7tcG%RM>pt} zcNa%Z)`FHDcT&%5{VvHM5C2V0P4y$-poN!n&+Ykzg?W|Bv0vBH%p7u9rQLg6<;9t} zpFzAw!snm&ss75S~ns?uySB z$bXg3Tco0l@Q}}Aw*_ai-0K)(k;M+GxXUck#frr3G;O3L3N>n3S>jWabk0^@ zFn#If?VROK?6PjQ%U_ANe`YgG{+Z3NBHI|GyL~GTz<=P>++nXwSr2?;Baq+`qPTuL zwh0~{0hpV2uIL}8NL}qjl;Uttopt|8lXM4D}!T?y-LjA+TC5*wLO*QO&810p=T51@PQQMQ34*4dm@RDd+1VoF5z^Oufe6tQJR3d0^v$+vG=bb9^Dwo5H2@imm6C}F(@ddRi!7$ zmx6QxH5pk26V0Gwe5cf}d%vh6KFL;P7X8fy2y#t-hGjL6@rZ$qM}^uUEmU}kgvOtJ z`c#_E*L?&&w=_xBZxBp1R`N6Ls@WAhf!U`4&#Mf$&VPo;I)1b*k77946_K^c$N-t9 zK1X%nu0|yh;P)lX8HV>aw4%&FcJ@vtQI-uLE32M6%Q3h1hN1=jlJH1&Q7g#K@&*IG z%&0xbM{HZhaSyY*L5sr4xB}hOXY`iAFdP1q*dohY0uU%hI#z=6_RS&(;fCWfd{khg z_D4^u5CWJgg}r#A%lB>Ub0lKiGw{_DP(c4P33yD(m3${upoc{$*7V>&M%QftdLUZ?;4as6HiDtf|n0a8>LHl#=I9=7a;G zNGwKPf%wNe4=c*_g+PKZSN9)mcJGToVL+1qKKP3;hwTs~#WPv+@Icm}ZI847&`}sf zZe{>jm~fd5gQ0aiJtE-bMbc-Re*4n!g`7#W!)%F=K$Sc@)O9<|b^D`LC-rZGi|8O{ ztFIkp5`YUGQ$XSv&nJD$>#SVlzf+X}Q}R|k-<0(mh>u+HmERf2NCuD}tOw{U_F$@k z(ATF#&Vh^zqkAFIN^&N3P`N)XdI3~o@gXV33-Gqsjj;f>nwSi6WrFo4f4pW1oAv zU;oCq@7;07IRCXhsJ-`EYp%6s_`YwNxg+T7T~NwDT^{!8H7Xa&Vszj1%r4>s3X$Y^lr3-U8H(|U;fg%v**WG68HK_p%B!0 zL8i2vw5Qa2@1wp}pHy}kXK|;O4@6jk;4`=&xju8j+$3%VkOg61mjQ&y>C>f~CvDS= zF2C}_KaFX)urVZof(>($ytKDyoayLwT?Vxvq{7C@mUaVyp}GU|r)+pr`obE`}FoDf(9b3k9{Xql1ru`WnF<9zTS9{ zG7d!n=2`yo&bj-+A0sh>6K!GruC*2QQ0WO6ypl^XCaAt6JO56;A{`1Y6-?D~@K0M8GR_oH_aw!H0iB z)OoLfc-Zb0S#NQroaOxC<_Vd`rD;S^j7!DmGVsa)G+c+P9I+_jO1nxgvbaNWcR;r%I!T+5vM5cvZ;6s)1yf=^X9<|5W=ivZ;C74yJITRDh8l-{OcHfpS!&G|@)%JS zPzzeX%Ti*3Jr+mn)7l2J+E%K7wlXJ5J7-3JQI%x zzG$rXwglS*P{YWq=9opz&)4`ax|ED}+55G-%+I&&ZAXyuIL~cE65PR;aYy7u~h9&z9vt8_|w zC%cU_1_F%lLAa_UbN4G?ML*i?0FZc(1)TzNd>W0Ie+dEmkyictX>iKxV7!mm*-sSp zXuwyC1$~l5* zKc#ct?;-h*d>C%c9pMBs-ner=?J7=pK>913_CJ|74=$;)>}v;qlT@~M7AH2geHA)rT+7woeTh6uw3+yb`{dOaIDSimd&D`M5)uve3GrgbTU&U~HLit1 z;c9h|YpzdfJ10$APX6Lb-rPua`Dw_V$NYdjQIX3Ua-+F}mR^_|g3LIXMrs^&3(Sw} zC`dKke)ArPo&?%qN0DGKfbJ zoC)#}KAP06!3`kLG!)G)8~f~)-5VU5Aw$;n_T2FOG!=_usRy5ZeEYa}n$$ZoOntF> zhU-vjwpGIwaF8J)G3nO3a*K07sYH!}go5W|I><}AF6qz4!vN;PWA#MCl=z;CQBa|!3p`veH(+SdIcA0If8&Oy~WDL#= zWFK@X4g!ZoXE2TQOaXT_?hgy8P8cu>19mEKZtX1$jle>*fAU4fM{G@w_{0R+U8`i7 zt$U=O;9VsSEWw36mu@}{i2;~S_Pb9gr=vl|ezVyT)LOfWQ{0d$ewaup6ROh#gr!qq z2eTYguL6CuV{pbkhb`im+gd~a>NE+JYV&3UNi0#s<)#qQb+!_;O{iD3V7{zU<;IWS zK)j6VG-ad%5?kw^oEE4Ij_QeiEDlx|tp(;|!L1T!9t&k58)NEYb}I7XooHhI-n%Dr zKjL>=e{UqAO9qZ=D$rAgj%aR9V4|*slO7R1WLkE5J{*py{d~&xe+S|a4*&L1Wb{AY=pAD7xs`yDNY2hh3=b2S*50O^pgkp>lZ3eS((} zg?Tt4AaJf^8;$w;JDG7IeEd|J z4#7=17xr)p;-3zXm;j*NkSTdRHzNT8EaMgA!Hd4y$a)UpBmM<~_(5?jyjpdf+WSe) z{1wF{4nWN5DNOVC4G10Dzd~mzV#EJ^EKK=My}mhy|Z?8*|>pMW)Z`+t)?0 zhu^)7DfojLr@~{TzzO|sLDG|iTXI!m8qlLe~6y+_hE3x)u77==?05Z>dpdK zJZZqKUl=Mnwd=f=Ixo7DZwU}Kk@&j~QASg+j;$&|kMy?9FLK^as)cLthddK-fSLOb zSkWTZ!>*~bzzKu#h#=C$d3_#veZcC;2(ZT<*D(xQ@Y0h6!zG@QC~TY>C0f(LfQdWw zx__i_H=`DXTolo_uPZaQf_~&y5Xuo)t`9=>S@^n;yY}U2gY0O8?8y&CsqkpelR>Je zH;|Rl@j3YHR&f=a%h1$wK48;RBAxF){r)lAh5NpUQPZIM92ykD%Tv?RWFJ*jaOB+{ zD1AhGF?8Y*{mRhb;6Vc%&Sfxy5{veLD8KZ3HA_!?=tH=LzRrLk!oR*pRyJRa6nK!( zl{9alNae)hQx#=NW^(Cz2!@qKklm@o+#>I>#0Yb;%>jxI-g=aF_9=w>S3gbI1!gE+ zMOoo_N>S%=4FS*ULTyGI#S{zycF6BTSnLJTzB&0FagAF9H`e7C@?BSzr75%uPKDkc zjR_617o~Od*Mx(@6rp?uiiUemjSK(2C<|G8o_0tg@aFq>WQ-BcnOta)SE|&h#I$Jb zX%B-$Av`i4gE}zla+TFAr8S&h~b45b3tcl$p@`X;( z^Tx5mR-Ec>bBpD;i~z`$+JRZinb6E~n!rb|mf(c%qDKw!@MIX#`1{M!qHa{n-JL^> z$}tiSuD@K9$G6^?BO&)VHR^>!kKrj7Ng-&Mda8&=l}8piZ8M`LIOI1dVL}39L1RKe zFifJ1K*{s8Q!u25#}~nh+-F-`bKyYqd%Eil9D*rB0{g#N6Oqd5Nl-IsWCb%wFDx3d zH77pz#JF^e{BTQPrdH)z~c>JMNFk<=ibRtXiZOM<@+L*EbzB$V(RGG22{Bq zDKGMT!mxbK&?A{Tz8ww@kJ!6)cM;r zsT`cXW(IWSb6^IZ`9&T#Pd+nuDbj}xP>t|G{?Z82*axyhkjK-&iVS5H_`c`iNr?(g z9YuD|t-oCpr^4rqkHHLjzzn93o%*mh_eS-I;ho<$=3g7ZFB>y!05LXU#%$Lb%7HoKYgD){VGyqt?; z(-ia^9v{534>=j=vp&ruPX3e2)vs%PABK*}Bz!35D{&n=Qtt6V+Y>>H(`MoErWI$~ z_QT(sqt8=$Cnzx+htIEA!blPTv|UKEaqiIWb2x$W3LKzIys*(^^AWR7< z1p|53g3y?5uk5@TJFW|(pS==T@#ogDMmn}^9o4iJzK8zikkh@H@whM^ofXN45} zKxn(*9KI?$SZaCGh4NPL^zs07=_t|trDSZU@$N=*uL|{ zYRCJycj?>(-Z(63kGVI$KHB0a1o%8?21JnUWF#Iycd3A2O#ugxNdgTy(RcwtTCT$; zUYz@Qun3P&Gv1p2Xx|us&naL2aDRNQq)Alo-$x}Y+i)}>dhBlogu|i+(8{U@Oe+NA zD3MN{|1ZKso73!wFwtwd0?1bFig`The{VKLLoU0!a7XVqJERESAk60>Z;9(wOiCK{ z`_cNiAk}-ZxNBL$`w0`?49a4%Y#8D)YXF6x1vFv)pea2tk{{vPfG=p-N*71KF&{@< zZD>K;4HCtay@!`ucjp^Fv?LoiQfGtEgu|FE1R_snq`@nL#mUXuiW+U+v*co4_Ey}Bo{tJrVEEEzRS4%S5BdfOqt(UZDT;{^%8=(o z7<0Ib@wNSIJXCdvCJ~WCkOONd8I9!o_Un&ZTfh@P^QO}2oXmwcgVzj{Yc}i}%Nx1* z1lacLP2+I<{UMA9$y7DV0}cCjXP3oC0j%5omE^T>`nx2kd96WWF9FyS1XG`1(ZFJl zY;V|k0@cqiiNvP=T^zm&;QCSU17(5?bP11UgHQkqh9+8%cQhN=93u-I|l;(F*@( zo`{~JjAb!%sa-p5Z^qM&qbUYEye{{KE)jOe28Ej`nRn^p-8t6f?4dLVUghjlnplz6 zM1m{La}kvE*kkZZwcnF1OPybr<#frl3z7#e?Z)iWO&5netu(MnWRdg@2|4XS6AGyV zAcwr~R$b$s7!Aq<`7hizTzjuU$PA3L@E~7PvM&<(=f@xCpSzk}@GV6-Cb4OI@8}~^?0#W^(MuyYDDrrACm>d#NQA%v@}D< zD5uYmdn#%7@XnMh*jD?E&PIc5z=9bC!)^Ze;f^fw z$X?ZSj^?cFD>%Wu3hkIHg(NkEMt}@*|G`bX3FJU8f-GFrqt8<?7%^``_Q?BgaOX%zYDZv*=MOhz-3A%@SSbx_DwhDujNpvYUrsM^dM9qG9a` z$w`nF!s8JhJJ4IxKylQ2?}gTmAd?GK;wt`erefL zVz84vIbFm|*d(Qx#^H3}!UVcFI9#l}bLY(b!@$93hXWaV&$IWw5?^RLNN+u(^Y4Sy zfI&An(7W!N>@#9rdZ{~zUwzHmDZ!5)k7;@jkWK5@Ip9(Zhq*+->!Qat>nR#`7Z|y&(MG zpN7VV63`3D zV0c3J>US)_|6RL}D-4fRKhL<-%ES1iot*8@ zoqnMsChb$-dwt%3ehmVuI1UA`j>FIubQ=CC-6*+$Lkl@V+5XgS40K(MN|8LH zojt1ZIqN%8jhZkmj(-? z7g;b8Kr%w)3V9mJTwa2MWtR~ctwE4TG~PmJH_i4yyP1amuTl_MNR*#_F4+=6CksNQ z=XoDmVr@YYbQ;>Ii$m?Kp}qks+z7cf6$C@;m%f9{ixVRHnGc-t0zQBuG`P_zfp!e| zuJ-=xA00#+zI&_!dFJh9=aH&@gi<*IWxaKdcIX}O9NhAj*nh9OAw_s85I4H?#B)aX z+Xk#=HwZ{R2S%)eMl6Se<(17d8U|iCbA+n@ux>@W{|k`O((!nZ?`b1Mc=&5@pBd(@ zndj5Tjh`)2NMI#gHlQro)q=+Zaf{#muH7wUK0(+vkBDe|f>Z+Z+ousGzoG_I0HI>_C@M3182 zv1d`n23Obsw#0Lq9fwBc-%{SIg^Om9Xg<8s!M8pN8a&T|C3*qA&aSt92Ye+vP*t+u zMYH%N3zT#I*_|zp&4KV`8kBz|KxVb<$p>bu%Qn!0_SovPeVORZ)Iy7v1dLoGc*G?R zlM9L&j;?#hO>&FPTYy1>(ml-KL3T`OcC10^#HV;##rI-0r$cXo#z1OM#-TLzD5lr1 z5Rl8ER9?aT(I1IQo9PoFdLj8Y`5Z2#D}u!Iz#%QP$#Qw? zhz&@@6B=$$fE+7X&oZ!qyCHtzIMigsjZ<*az zgm05Rz49x0P|Xuqr`;@^CaBkwShB z)s$=Bb)s*WfDCefrGL7044#;T>{TU?ct8;GCW%V09<-&1MmMd6dt^h23QvA4(WJ(! z@SW<-O|weJ#A@i)LYZs)*JZVTetamzT3|~2cv0zt&{+4S^)-!pl9l27PfV@fxTAry7S=zuVEw;A5C^~2?v)5y&Fx2`W|k2)Cgbh>UqHDRi#57Aq(eB{ zTIu7C=u&H|C+tNrj2!GYGX2A=*Da__Sj8`JUtS7+Cy%0%Zg#LLwNj8WSv%X^ z_Oo{OTx$3R(dp$rH9FQf1{0|X5CkoyGP4yy%S{3Xt`HPDuD|1)0{ML@I6h^76J8j@ zu%K#vj^+Txt{HAxITVLSG-Z>tb)Y~H$Nah~?y7upjTkxyK(qhYQEm$xmO4uK!O1_unUk2fBeB;KZg=g0 znLTzYLXv@a_$TM7I*xzBRybCW5FY#y z&c(4nKoY4^h<|~DfMo9*ZIBy<+$N;6yFeYnJ^RZshW|-Cv5VQv9j5{nu76}t5P)2x zx_=HbF7SgKnG2?+pk2v>&cX5oa4_yyOxh1SIHid8j0WK*24NWw4CZLnt809ee-jnm z(tOLZx|8G8u@(&p#NeG%mXhAa6nppx@y^7pyR%RMhGjfC!sLC620a)k{MyUuqFO+b zLS)05dq$9P*$~|HBG)siPm6p?oD>ZWioUp+Us!vDFe3>Lr)m-f32z69-hpF0S=(kg z&lMf*=W7R#Zr!=QfUdi7pBCb#i{I@#a^7$$CW)gYr$40Sf8HX*Pw{R#hF*Ym?~cST zNo!=BMG=1))0TN>I;uBzNB4zTfcd`hL}zbs3%cI#Q!~=Jbf>C|hsVzHiNpK@XoCR5 zKVzEcB7n#b;jTWEm_N9i;_l9^^Pbn)Qnp0BZ(NysuR#3J{+^n0h#8j>YuVjLn!N(i ze;NS)2m_j6AEYD&0om*Yj|h z-)a}53jYY@?t_4Ik$6|@d)<-3aRtdgoYRPAvEh+wzs@a|@)V>OyGfbNt-)6`T1nA% zxx6tEL4f-d-Fr~R0*Yz9kQ)*ZzlI!HBhUw4<~qSmOW|MLBP%*}u_KOm8hU3*Avq!_ z!buMloRGcr^|Q#-z^dBQy2}IIpWZ=snHdx=xR7K`QC{5O2Q2pReJv#?!X)AZL{9bQ zhbc4sc#PE4saeDup}tpL^k@w_gQtPy$=LewZRqlA$Y@-hl=+)hNGdo|wX>xFLl{6Z z9Kew)n)RpA9rQh_(-<(P#r=(_zmOeS!2U_fqB3dD4t z04UnENOWs{=-%-NTF!28%AC#J$`B!R$N|2;;r`I7;Rz!q-v0LFQ&Q}?$=1keK!ucE zR06f^xuJVW0w$<*P1eLWeM8dT^2`q8V^bkbaY-y}+b0rFA#$vh9MS9(tzXk$1%ZI-*_ekyRfX2;plkd@L!uf>6oXl|ICn+PUEcir#C}4 zT83~wTWb!UaK@)0cs^(pA5J3$N;A=W1kPwe33MoafK;bwhYUNJ6D4|WaBnkL5o9!O zJ*@gV=J%dPsWb;n*fi$XL%>Quy!+nNgvoVCU|rh3=F7)`Nj^)wiC)$_3IckV0^O7O z2vlTfHpZ$;2-&97>!RM0h^R_%UT{RhhAgV-D-gaiFRw&yPDF511_GE(irC&n;Q0fW zUfVp3#_?0^kf5^Xy0T$|bj>sE);X3^B$I+0<38-?HU#OV^Prq@Cr%7Nf&z3f7Vp*=X|(u5dSW2`zOXSRn%?2H zC{EFHu@4H6c&c<6!*TF@oJG)778u5bO$oy#q_05L4dyESe zL=u%2z3Ewy2m?R@UoFY5I9`v53cjGk_0G9hC!PUHWWei5vzkH-3ZQys{7yVP1U(lg z(F}fdTuHY{7paNNFHlMPLx=)b4U?B@%FQP?fXhscghT6vJOy-$YjK~9v$-Q29_)Od zQHsKCK@Yk|1_Gs5c5hiB5|k51@ObE`*cZ#vyoYA30b-!jCge_l=6j?R?#0r#s1iu~ zgU=Om+_Npb$D_5IO-&lUy<6-C?9hC`ogvq_e3o6|g&EM-F=h@j{{fkFTLovoLzBZ2 z2fx*bb30!i2Bv_p>Z{9GQTiL2*SRYDgW}p0b_?#?^5U@twBzA#)XvnyyJ~^+Tl}E4 z<+?=9*pQ9B11PLs|%@ammIALiU8+^FEXznPe`49YcK3a?BmD0KOlL_^AB z#lEmO(scuR^W+<%(6*56?XL}QJ>}lG)d4%#qKa;^SqUillS}Eo!J70$ZbcYnTqDus zcQ`0zS*Gdig6&u#Fk%^ zJ&3>e@gi)3P1AdPFWO9Zi_apVET~ONA*p|G{~f**e+_}cLw(j^;xRd7z4bEuSNE)4 z0;#loXvRS*+4(K{jg9-EJzV|E6nxk^kMObCV;(e2JM|SkGY~s_lPNTq93q{1-yBAD zzoq0i#o5K$x6<{yctVV7ZvD{$kW2R(q1Q3RKoa~Rs2JX%%!iAp_z%0G%D z@|D9R*T(1`My2nQjK3m5(Sh$8LgaB{&*<*#WGnPvj&bw zbg}(5B)`qDt?bvo%66hxh`Dq6hB0yb;#jG#z>JrQhJkoR#Kiky2${~)@1vlY<#o-Z zuGvMEKq9qvXy$p^x%Z9dPm#6GS*)UFw(g0MdHV<_*3sXkCO&X=FPT(w(*+lo?G9Jm zIK7(0C6Xs=CvG3EcH3o-I(^0*JwWrmdED2Oj{AsnMxfWzdg5rs^ix-}3RyeIS8m#8 z-TWkgtK;+r&4zyB*;lva+;aq}qFYV?dGjNU_!IGU>#w1xWPf^6q@XFiE`IBt(fu+F zT0S=IFl{^@7TxejAV@^8KiHW&5m=VD`-x2BMQhEc-(ug`yQMkPn|Jz5p)@oupL~X= zc$l7T7lSbauCnBE;)_~cQjQ4dX4-R>W{V=x@0j)e@N+y?7u`v2h7UPddo2*=>TiZI-d|6`m@xSm#*?wGcON@_|h^o z)_Zjqf!;Rwe12UXagsTfr}_{i!rVM4Wl>lBIA{Y%?~fVl*;t`2RS3Z4aqTIQB8g%n z(Z12Q4?|soopT#Pi2^3AiW#;jdb3W1fRcoA?N{9>wb7;cd{B`LrE{*alqBj6Icx)T zSMi;`NNSd_Ye$$#fFl2hnnz4;8p8bL8;V~sm>ca3E6GMXcO=F1P9T_~(`aydrnfjx z$+cVO))Q+`TYc9dZMZqFRPf&XGnFAd29uDae-ZD`nMafyc=Y;@CHd`Z0%Fd2DS9Q|PzPAh$j=319k z!Li397&P4z-DcuYwOJ}tK5Thv_9Ircw56TRXAw{|IssqwR9ag4RGr3Emlm19sL zzDns#3~In3v57C|8qb$QzTxJ{*L)g{O}8&b++kK6Ka`#B7=wQ^k8b0lBQC~Za5z6s z?>I&lnu!a>^qy;>a{9b@JWqcF9TkOpB!$(@vMA4Qk4M*zg!Wro{+Ow69~)g+P7MTo zoaOe=x&2j7ub+Tz`;k0N- z-7uhiHdW2jL9VX70#A__ncdXEM@^l4anX>10kdICPR^ELv{*r1$32C(5y`iM5B4q7 zQnFz2v>{4YI+q=;&^u4RLAM9{p!R(K5q!i{vP!Pz16DG%=X!7km3D2L=ZRaWk~-V3w{D z>E(mBGDb}{EkV|g^ZaFzZhfN7pdRtzkj6D)vSKlk5L7k@C!b#(b?}HDyHre&PVONe zZfU|kp)T3=C*kBLZmLJb?+XY9p+g>6J$A9^`*hU96`dtU$dfbr} zihu}GS=N%0z3Ifm``50%)b-QES=W<~H-~AK?k4MTh!XdIuHzw2(}BvrXWb)z`$MMh zKEWdkO8StmG<>1|#o3es=;k~FuL_$Fo#_&rQNf{^_#?jOHUu|1(2T}Y`t>UP7&uf( ze1Y0M&R+en4Gx|EVj{zX-vgE;s^rq@qL@^VIxbJ3P#d6!04fMV4Dzk0N_C4(#BRC* z4g;3DR+1-&e}KAcC7PJifaO4RUgM?o%m}_iZ(;F{l`31-sa@|^X_xjf`tg*U>KInU z=W=|YSFF5H(+OOoJ5gjvb{L`vR7XC8A}cp>HMx9ufC`&O(zcUdUn@mUIA zlBnKZupvG|CKt@YHRpTeO1&5sn{|9%-vQkxy43ziN1jT-)>0~c9j(s)jfZy~fB?-`0GKMU>`UIL5$4hs*#|5+lj9XZn^OC*Du=x0w9V?$%e)S}Gs_koEyju|~YXiwfYFm8vsvfrv-fdLNH-L1f{n4zUL| zSIL-gno@*izU{tO?uJ)6inh}d~*Ur!Uy9zNLyrf2qW#GRzj3LJw3l7usDSC zjoovAX-cJ?j&o9Jd-=N2a!xt9dh~?1m*hl3OO-XTq}Mt@Wl3y@qd7vcz@08uu0gLU z4rzgQt0Ksb@_m>t-y@2)^JwbhPq})un285?lbLt$#NQepswKx8Ph|#^F`7w`hCx+p zxQAVHhS`e3dZ~(WKgZ?n{Sl?=)tHiZj4QAEAfpF?c8|OK7~Fl?gg*$!-6NO$Y%0hz`aT}M>bR_QZ>Up zMe;$}qIrVo>8s4zR@)58>5C`#?oT9_|MOP64WzpLT*1 zLeoP!NK}IM-{AofwWbHBs7($qamV!Ss0Pv=nzuH@ptg>6fvOLlP zUmhhq^AD;7x;b8p1eyT4yqLO@-rzac4Y{z2QZusA_Z7Brk|yQk+#yISEX@ZwN>Os+ z3{>1<^vc6IuGb`Yv|S)diBFifft9?f%!+Qjn z5F4=<{W7ErdB3PzP#%X&UVn|^y!H=_-p+kdN0or2t*9p+$TKYI<9KzR#s%Yvq8`w* z60@$>3C1UMsubwqa8ok*^G)` zl0yd-{66t?R#rjj@qN>Dwjwmee9ORqLM!GwwLwa4Mm;jmkX9iKQlRWNdK@DN57Uk@ ze`a_!Xv?+I>Dw7wqp>^K{X;EC`W;D&!b9CSh>>4(dc}JSpCn{;IE=YEpCI4+uRnr+ z@X(^XC?VlH?<8C%`7`0`P>Nuxe|ygFe?Klq_`8JV^#4BZ*U9-mH-FdNM52g@C=-t2 zR19Hlpa=@!CH5m-@1fH`S5?~U`pOG$WjtS6_@+SKi2v3z$Y}ged)ah%CJOVl9o@uW zCaPBS)(JqXKba3OJ`7mG@Fr#Uzh$i;v2uON@9c6m=(>twu#>>0o`!T5(%$Z&fMXf7 ztP%b9mNiUMwDxn5Clxjq{#jnqjT%Cr=l^Db?HIzV@LO%Q2_&g^7LH;t2L^y;&UOv2 zT|omclCXz+H2;2Gj{@iLpM7L*P1TxS-g6^pMo58)Hk#n z{zI!7q$^FzL`y^(h~-s`GhZSk0Fs3tR5c^A&+FR&t9%X(O&tK8w%)u7#N1*4;YFv& zTu9A`9p|RGu@_V7FtB%^{M-po5Ti`{D~{?}gn|F>-DZ*j)|dhvQ{VoN8qVNwt$)3F z!9bu!|570bn(S1ltsqILRS;k%+f0Glu>vU%=X6honbz)Hncut1n7l-bO>r@C>kH6c72ZKgQ_BA7wD3OO1E< zSF3=SNlP|GGGH2l(&CAuhcp~jjl~KZau236-9vaDzuzps&08!V;WHX@p!Mnv;+CaD zJ|EA|D@v1WHYI)A85`xyZ7svu5Lw>rZ8ayAV2m*jvd)Xot|D&YtRlk<4l*XQR*_)% zj(=N`$7&HKUVs^X^W_EiH~#%)<{!4VuehYGZ#tyVNzd?O$&@a#93e)b zDd>5WgNWci{Lw;!#aUnYUVLBSX}TcV)oa1Wkett?M*7eybvwR5Q&ZDZ@B8L+gA(_E zfPg1&)g6!WpLTb5mk`(=pSsJ*$;s2EYf!c0-0RWN+djU&1qamS{1%w7D>D^E`CSzYzJGP(Tz{rifBhMk8=x@7`g66@>h z(>unuZcKT8=waLMQC(RnEhbXfdn-@phIX~E#;wvR&ncms&PP``xVU z7?|ne;xg?c9q5>ulR0)_$OxM=gCB}OhWGn8L#Yh)HY~7{wc{_wc2!Ugrr*S~e4nz} z_~Q@YKV~s^v-Gez($T{%h04$6Bk{NSjJW^x2s8z?sGdqTuJy%|>5frwswV>`H1jZZ z=C7|&L^1Bs##My(zY$@)E58rZ@7X%9MwsWH9}?U|DkPYIH(|3}7!%U-)WzB^-He#n z{o7g~f0Lz|6`~r69~L*Qy@Ntl%sUv= z`k8AKhI)dSel`uK$A($c={Q_3<{sTIbAcvfMh0r@;CDap9$}zOC%D2-{Q8+(!IYE& zSkspCpKcN6YF6I%3-3>ZA$&{YIANd%XdZrXB@9$z<5|nnuHTIc{-%$wq^wL*K>Tt* zz=asTO1?gkrS)~0-pAeld0xkK$3{ne$deQp&NEik)*`Eu{^!*(;ny?9IXgQaGd4CJ zSY7pWI#$RTd^R{KDQRwN%m2;DNcwI}ithuwiP!A>v0uj`K{|hp;#=U6Cxz#h%b60t z-@vo1rrQkuy7DIcaapyfmN!(bfimoi3;vT44hx|XUV)D}f diff --git a/nebula-exchange/doc-2.0/CN/parameter-reference/.ex-ug-paras-nebulagraph.md b/nebula-exchange/doc-2.0/CN/parameter-reference/.ex-ug-paras-nebulagraph.md deleted file mode 100644 index e43298a..0000000 --- a/nebula-exchange/doc-2.0/CN/parameter-reference/.ex-ug-paras-nebulagraph.md +++ /dev/null @@ -1,16 +0,0 @@ -# Nebula Graph 相关参数 - -下表列出在使用 Exchange 导入数据时您需要设置的 Nebula Graph 相关参数。实际应用时的参数设置,参考不同来源数据的 [操作示例](../use-exchange/ex-ug-import-from-neo4j.md)。 - -| 参数 | 默认值 | 数据类型 | 是否必需 | 说明 | -| :--- | :--- | :--- | :--- | :--- | -| `nebula.address.graph` | 无 | `list[string]` | 是 | Nebula Graph 图数据库 Graph 服务的地址列表。如果有多个地址,以英文逗号(,)分隔。格式为 `"ip1:port","ip2:port","ip3:port"`。 | -| `nebula.address.meta` | 无 | `list[string]` | 是 | Nebula Graph 图数据库 Meta 服务的地址列表。如果有多个地址,以英文逗号(,)分隔。格式为 `"ip1:port","ip2:port","ip3:port"`。 | -| `nebula.user` | `user` | `string` | 是 | 数据库用户名,默认为 `user` 。如果 Nebula Graph 启用了身份认证:
                                          - 如果未创建不同用户,使用 `root` 。
                                          - 如果已经创建了不同的用户并且分配了指定空间的角色,则使用对该空间拥有写操作权限的用户。 | -| `nebula.pswd` | `password` | `string` | 是 | 数据库用户名对应的密码,默认 `user` 的密码为 `password` 。如果 Nebula Graph 启用了身份认证:
                                          - 使用 `root` 时,密码为 `nebula` 。
                                          - 使用其他用户账号时,设置账号对应的密码。 | -| `nebula.space` | 无 | `string` | 是 | 导入数据对应的图空间(Space)名称。 | -| `nebula.connection.timeout` | 3000 | `int` | 否 | Thrift 连接的超时时间,单位为 ms。 | -| `nebula.connection.retry` | 3 | `int` | 否 | Thrift 连接重试次数。 | -| `nebula.execution.retry` | 3 | `int` | 否 | nGQL 语句执行重试次数。 | -| `nebula.error.max` | 32 | `int` | 否 | 指定导入过程中的最大失败次数。当失败次数达到最大值时,提交的 Spark 作业将自动停止。 | -| `nebula.error.output` | 无 | `string` | 是 | 在 Nebula Graph 服务器上指定输出错误信息的日志路径。您可以在这个文件里查看发生的所有错误信息。 | diff --git a/nebula-exchange/doc-2.0/CN/parameter-reference/.ex-ug-paras-neo4j.md b/nebula-exchange/doc-2.0/CN/parameter-reference/.ex-ug-paras-neo4j.md deleted file mode 100644 index fef818a..0000000 --- a/nebula-exchange/doc-2.0/CN/parameter-reference/.ex-ug-paras-neo4j.md +++ /dev/null @@ -1,36 +0,0 @@ -# Neo4j 数据源相关参数 - -如果要导入的数据来源为 Neo4j,您可能需要配置以下参数。 - -| 参数 | 默认值 | 数据类型 | 是否必需 | 说明 | -| :--- | :--- | :--- | :--- | :--- | -| `tags.name` | 无 | `string` | 是 | 设置为 Nebula Graph 中的标签名称。 | -| `tags.type.source` | 无 | `string` | 是 | 指定标签源数据的格式。设置为 `neo4j`。 | -| `tags.type.sink` | 无 | `string` | 是 | 指定标签源数据导入 Nebula Graph 的方式。可以设置为:
                                          - `client`:以客户端形式导入
                                          - `sst`:以 SST 文件格式导入 | -| `tags.server` | 无 | `string` | 是 | 设置 Neo4j 数据库服务器地址,格式必须为 `bolt://:7687` 。 | -| `tags.user` | 无 | `string` | 是 | Neo4j 数据库登录账号。 | -| `tags.password` | 无 | `string` | 是 | Neo4j 数据库账号登录密码。 | -| `tags.encription` | `false` | `string` | 否 | 传输是否加密,默认值为 `false`,表示不加密。设置为 `true` 时,表示加密。 | -| `tags.database` | 无 | `string` | 否 | 设置源数据所在 Neo4j 数据库的名称。如果您使用 Community Edition Neo4j,不支持这个参数。 | -| `tags.exec` | 无 | `string` | 是 | 写入 Cypher 语句,从 Neo4j 数据库中检索打了某种标签的点的属性,并指定别名。Cypher 语句不能以英文分号(`;`)结尾。
                                          例如,写入 Cypher 语句 `match (n:label) return n.neo4j-field-0 as neo4j-field-0, n.neo4j-field-1 as neo4j-field-1 order by (n.neo4j-field-0)`。| -| `tags.fields` | 无 | `list[string]` | 是 | 指定源数据中与 Nebula Graph 标签对应的属性名称。以列表形式列出,多个属性名称之间以英文逗号(`,`)隔开。列出的属性名称必须与 `tags.exec` 中列出的属性名称保持一致。 | -| `tags.nebula.fields` | 无 | `list[string]` | 是 | 指定 Nebula Graph Schema 中标签对应的属性名称。以列表形式列出。与 `tags.fields` 列表中的属性名称一一对应,形成映射关系。多个属性名称之间以英文逗号(`,`)隔开。 | -| `tags.vertex`
                                          或者
                                          tags {
                                              vertex {
                                                   field: [name]
                                                   policy: "hash"
                                              }
                                          }
                                          | 无 | `string` | 是 | 将源数据中某个属性的值作为 Nebula Graph 点 VID 的来源。
                                          如果属性为 `int` 或者 `long` 类型,使用 `tags.vertex: [field name]` 设置 VID 列。
                                          如果不是上述类型的属性,您可以通过 `tags.vertex.field` 和 `tags.vertex.policy`  对 VID 进行预处理。其中,`tags.vertex.policy` 可以设置为 `"hash"`。 | -| `tags.batch` | 256 | `int` | 是 | 单次写入 Nebula Graph 的点数据量。 | -| `tags.partition` | 32 | `int` | 是 | Spark 的分区数量。 | -| `tags.check_point_path` | 无 | `string` | 否 | 设置保存导入进度信息的目录,用于断点续传。如果未设置,表示不启用断点续传。 | -| `edges.name` | 无 | `string` | 是 | 指定 Nebula Graph 中的边类型名称。 | -| `edges.type.source` | 无 | `string` | 是 | 指定源数据格式,设置为 neo4j。 | -| `edges.type.sink` | 无 | `string` | 是 | 指定边数据导入 Nebula Graph 的方式。可以设置为:
                                          - `client`:以客户端形式导入
                                          - `sst`:以 SST 文件格式导入
                                          | -| `edges.server` | 无 | `string` | 是 | 指定 Neo4j 数据库服务器地址,格式必须为 `bolt://:7687` 。 | -| `edges.user` | 无 | `string` | 是 | 指定 Neo4j 数据库登录账号。 | -| `edges.password` | 无 | `string` | 是 | 指定 Neo4j 数据库账号登录密码。 | -| `edges.exec` | 无 | `string` | 是 | 写入 Cypher 语句,表示从 Neo4j 数据库中查询关系属性。Cypher 语句不能以英文分号(`;`)结尾。
                                          例如,写入 Cypher 语句 `match (a:vertex_label)-[r:edge_label]->(b:vertex_label) return a.neo4j-source-field, b.neo4j-target-field, r.neo4j-field-0 as neo4j-field-0, r.neo4j-field-1 as neo4j-field-1 order by id(r)`。 | -| `edges.fields` | 无 | `list[string]` | 是 | 指定源数据中与 Nebula Graph 边类型对应的属性名称。以列表形式列出,多个属性名称之间以英文逗号(`,`)隔开。列出的属性名称必须与 `edges.exec` 中列出的属性名称保持一致。 | -| `edges.nebula.fields` | 无 | `list[string]` | 是 | Nebula Graph Schema 中边类型对应的属性名称。以列表形式列出,与 `edges.fields` 列表中的属性名称一一对应,形成映射关系。多个属性名称之间以英文逗号(`,`)隔开。 | -| `edges.source`
                                          或者 
                                          edges: {
                                              source: {
                                                  field: [name]
                                                  policy:   "hash" 
                                              }
                                          }
                                          | 无 | `string` | 否 | 指定源数据中某个属性,将它的值用作 Nebula Graph 边的起始点 VID。
                                          如果是上述类型的属性,使用 `edges.source = field` 设置起始点 VID 列。
                                          如果不是上述类型的属性,您可以通过 `edges.source.field` 和 `edges.source.policy`  对 VID 进行预处理,即使用 `hash()`函数处理属性名称,生成的数值用作 VID。其中,`edges.source.policy` 可以设置为 `"hash"`。 | -| `edges.target`
                                          或者
                                          edges: {
                                              target: {
                                                  field: [name]
                                                  policy: "hash"   
                                              }
                                          }
                                          | 无 | `string` | 否 | 指定源数据中某个属性,将它的值用作 Nebula Graph 边的目标点 VID。必须为 `int` 或 `long` 类型的属性。
                                          如果属性为 `int` 或者 `long` 类型,使用 `edges.target: [field name]` 设置目标点 VID 列。
                                          如果不是上述类型的属性,您可以通过 `edges.target.field` 和 `edges.target.policy`  对 VID 进行预处理。其中,`edges.target.policy` 设置为 `"hash"`。 | -| `edges.ranking` | 无 | `string` | 否 | 将源数据中某一列数据作为 Nebula Graph 中边的 Rank 值。 | -| `edges.batch` | 256 | `int` | 是 | 单次写入 Nebula Graph 的边数据量。 | -| `edges.partition` | 32 | `int` | 是 | Spark 的分区数量。 | -| `edges.check_point_path` | 无 | `string` | 否 | 设置保存导入进度信息的目录,用于断点续传。如果未设置,表示不启用断点续传。 | diff --git a/nebula-exchange/doc-2.0/CN/parameter-reference/.ex-ug-paras-spark.md b/nebula-exchange/doc-2.0/CN/parameter-reference/.ex-ug-paras-spark.md deleted file mode 100644 index a5e26e9..0000000 --- a/nebula-exchange/doc-2.0/CN/parameter-reference/.ex-ug-paras-spark.md +++ /dev/null @@ -1,10 +0,0 @@ -# Spark 参数 - -在使用 Exchange 导入数据时,您可以根据需要设置 Spark 参数,详细信息的 Spark 参数信息,参考[《Apache Spark 文档》](https://spark.apache.org/docs/latest/configuration.html#application-properties "点击前往 Apache Spark 文档")。下表仅提供部分参数的配置说明。实际应用时的参数设置,参考不同来源数据的 [操作示例](../use-exchange/ex-ug-import-from-neo4j.md)。 - -| 参数 | 默认值 | 数据类型 | 是否必需 | 说明 | -| :--- | :--- | :--- | :--- | :--- | -| `spark.app.name` | Spark Writer | `string` | 否 | Spark Driver Program 名称。 | -| `spark.driver.cores` | 1 | `int` | 否 | Driver 进程的核数,仅适用于集群模式。 | -| `spark.driver.maxResultSize` | 1G | `string` | 否 | 每个 Spark 操作(例如收集)中所有分区的序列化结果的上限(以字节为单位)。最小值为 1M,设为 0 则表示无限制上限。 | -| `spark.cores.max` | 无 | `int` | 否 | 当以“粗粒度”共享模式在独立部署集群或 Mesos 集群上运行时,跨集群(而非从每台计算机)请求应用程序的最大 CPU 核数。如果未设置,则默认值为 Spark 的独立集群管理器上的 `spark.deploy.defaultCores` 或 Mesos 上的 infinite(所有可用的内核)。 | diff --git a/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-para-import-command.md b/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-para-import-command.md deleted file mode 100644 index 90be03f..0000000 --- a/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-para-import-command.md +++ /dev/null @@ -1,19 +0,0 @@ -# 导入命令参数 - -完成配置文件修改后,可以运行以下命令将指定来源的数据导入Nebula Graph数据库。 - -```bash -/bin/spark-submit --master "local" --class com.vesoft.nebula.exchange.Exchange -c -``` - -> **说明**:JAR文件版本号以您实际编译得到的JAR文件名称为准。 - -下表列出了命令的相关参数。 - -| 参数 | 是否必需 | 默认值 | 说明 | -| :--- | :--- | :--- | :--- | -| `--class`  | 是 | 无 | 指定驱动的主类。 | -| `--master`  | 是 | 无 | 指定Spark集群中master进程的URL。详情请参见[master-urls](https://spark.apache.org/docs/latest/submitting-applications.html#master-urls "点击前往 Apache Spark 文档")。 | -| `-c`  / `--config`  | 是 | 无 | 指定配置文件的路径。 | -| `-h`  / `--hive`  | 否 | `false` | 添加这个参数表示支持从Hive中导入数据。 | -| `-D`  / `--dry`  | 否 | `false` | 添加这个参数表示检查配置文件的格式是否符合要求,但不会校验`tags`和`edges`的配置项是否正确。正式导入数据时不能添加这个参数。 | diff --git a/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-parameter.md b/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-parameter.md deleted file mode 100644 index 622be3c..0000000 --- a/nebula-exchange/doc-2.0/CN/parameter-reference/ex-ug-parameter.md +++ /dev/null @@ -1,168 +0,0 @@ -# 配置说明 - -本文介绍使用Nebula Exchange时如何修改配置文件[`application.conf`](https://github.com/vesoft-inc/nebula-spark-utils/blob/master/nebula-exchange/src/main/resources/application.conf)。 - -修改配置文件之前,建议您根据数据源复制并修改文件名称,便于区分。例如数据源为CSV文件,可以复制为`csv_application.conf`。 - -配置文件的内容主要分为如下几类: - -- Spark相关配置 - -- Hive配置(可选) - -- Nebula Graph相关配置 - -- 点配置 - -- 边配置 - -## Spark相关配置 - -本文只列出部分Spark参数,更多参数请参见[官方文档](https://spark.apache.org/docs/latest/configuration.html#application-properties)。 - -|参数|数据类型|默认值|是否必须|说明| -|:---|:---|:---|:---|:---| -|`spark.app.name`|string|`Nebula Exchange 2.0`|否|Spark驱动程序名称。| -|`spark.driver.cores`|int|`1`|否|驱动程序使用的CPU核数,仅适用于集群模式。| -|`spark.driver.maxResultSize`|string|`1G`|否|单个Spark操作(例如collect)时,所有分区的序列化结果的总大小限制(字节为单位)。最小值为1M,0表示无限制。| -|`spark.executor.memory`|string|`1G`|否|Spark驱动程序使用的内存量,可以指定单位,例如512M、1G。| -|`spark.cores.max`|int|`16`|否|当驱动程序以“粗粒度”共享模式在独立部署集群或Mesos集群上运行时,跨集群(而非从每台计算机)请求应用程序的最大CPU核数。如果未设置,则值为Spark的独立集群管理器上的`spark.deploy.defaultCores`或Mesos上的infinite(所有可用的内核)。| - -## Hive配置(可选) - -如果Spark和Hive部署在不同集群,才需要配置连接Hive的参数,否则请忽略这些配置。 - -|参数|数据类型|默认值|是否必须|说明| -|:---|:---|:---|:---|:---| -|`hive.warehouse`|string|-|是|HDFS中的warehouse路径。用双引号括起路径,以`hdfs://`开头。| -|`hive.connectionURL`|string|-|是|JDBC连接的URL。例如`"jdbc:mysql://127.0.0.1:3306/hive_spark?characterEncoding=UTF-8"`。| -|`hive.connectionDriverName`|string|`"com.mysql.jdbc.Driver"`|是|驱动名称。| -|`hive.connectionUserName`|list\[string\]|-|是|连接的用户名。| -|`hive.connectionPassword`|list\[string\]|-|是|用户名对应的密码。| - -## Nebula Graph相关配置 - -|参数|数据类型|默认值|是否必须|说明| -|:---|:---|:---|:---|:---| -|`nebula.address.graph`|list\[string\]|`["127.0.0.1:9669"]`|是|所有Graph服务的地址,包括IP和端口,多个地址用英文逗号(,)分隔。格式为`["ip1:port1","ip2:port2","ip3:port3"]`。| -|`nebula.address.meta`|list\[string\]|`["127.0.0.1:9559"]`|是|所有Meta服务的地址,包括IP和端口,多个地址用英文逗号(,)分隔。格式为`["ip1:port1","ip2:port2","ip3:port3"]`。| -|`nebula.user`|string|-|是|拥有Nebula Graph写权限的用户名。| -|`nebula.pswd`|string|-|是|用户名对应的密码。| -|`nebula.space`|string|-|是|需要导入数据的的图空间名称。| -|`nebula.path.local`|string|`"/tmp"`|否|(TODO:coding)导入SST文件时需要设置本地SST文件路径。| -|`nebula.path.remote`|string|`"/sst"`|否|(TODO:coding)导入SST文件时需要设置远端SST文件路径。| -|`nebula.path.hdfs.namenode`|string|`"hdfs://name_node:9000"`|否|(TODO:coding)导入SST文件时需要设置HDFS的namenode。| -|`nebula.connection.timeout`|int|`3000`|否|Thrift连接的超时时间,单位为 ms。| -|`nebula.connection.retry`|int|`3`|否|Thrift连接重试次数。| -|`nebula.execution.retry`|int|`3`|否|nGQL语句执行重试次数。| -|`nebula.error.max`|int|`32`|否|导入过程中的最大失败次数。当失败次数达到最大值时,提交的Spark作业将自动停止。| -|`nebula.error.output`|string|`/tmp/errors`|否|输出错误日志的路径。错误日志保存执行失败的nGQL语句。| -|`nebula.rate.limit`|int|`1024`|否|导入数据时令牌桶的令牌数量限制。| -|`nebula.rate.timeout`|int|`1000`|否|令牌桶中拿取令牌的超时时间,单位:毫秒。| - -## 点配置 - -对于不同的数据源,点的配置也有所不同,有很多通用参数,也有部分特有参数,配置时需要配置通用参数和不同数据源的特有参数。 - -### 通用参数 - -|参数|数据类型|默认值|是否必须|说明| -|:---|:---|:---|:---|:---| -|`tags.name`|string|-|是|Nebula Graph中定义的标签名称。| -|`tags.type.source`|string|-|是|指定数据源。例如`csv`。| -|`tags.type.sink`|string|`client`|是|指定导入方式,可选值为`client`和`SST`(暂不支持)。| -|`tags.fields`|list\[string\]|-|是|属性对应的列的表头或列名。如果有表头或列名,请直接使用该名称。如果CSV文件没有表头,用`[_c0, _c1, _c2]`的形式表示第一列、第二列、第三列,以此类推。| -|`tags.nebula.fields`|list\[string\]|-|是|Nebula Graph中定义的属性名称,顺序必须和`tags.fields`一一对应。例如`[_c1, _c2]`对应`[name, age]`,表示第二列为属性name的值,第三列为属性age的值。| -|`tags.vertex.field`|string|-|是|点ID的列。例如CSV文件没有表头时,可以用`_c0`表示第一列的值作为点ID。| -|`tags.batch`|int|`256`|是|单批次写入Nebula Graph的最大点数量。| -|`tags.partition`|int|`32`|是|Spark分片数量。| - -### Parquet/JSON/ORC源特有参数 - -|参数|数据类型|默认值|是否必须|说明| -|:---|:---|:---|:---|:---| -|`tags.path`|string|-|是|HDFS中点数据文件的路径。用双引号括起路径,以`hdfs://`开头。| - -### CSV源特有参数 - -|参数|数据类型|默认值|是否必须|说明| -|:---|:---|:---|:---|:---| -|`tags.path`|string|-|是|HDFS中点数据文件的路径。用双引号括起路径,以`hdfs://`开头。| -|`tags.separator`|string|`,`|是|分隔符。默认值为英文逗号(,)。| -|`tags.header`|bool|`true`|是|文件是否有表头。| - -### Hive源特有参数 - -|参数|数据类型|默认值|是否必须|说明| -|:---|:---|:---|:---|:---| -|`tags.exec`|string|-|是|查询数据源的语句。例如`select name,age from mooc.users`。| - -### Neo4j源特有参数 - -|参数|数据类型|默认值|是否必须|说明| -|:---|:---|:---|:---|:---| -|`tags.exec`|string|-|是|查询数据源的语句。例如`match (n:label) return n.neo4j-field-0`。| -|`tags.server`|string|`"bolt://127.0.0.1:7687"`|是|Neo4j服务器地址。| -|`tags.user`|string|-|是|拥有读取权限的Neo4j用户名。| -|`tags.password`|string|-|是|用户名对应密码。| -|`tags.database`|string|-|是|Neo4j中保存源数据的数据库名。| -|`tags.check_point_path`|string|`/tmp/test`|否|设置保存导入进度信息的目录,用于断点续传。如果未设置,表示不启用断点续传。| - -### MySQL源特有参数 - -|参数|数据类型|默认值|是否必须|说明| -|:---|:---|:---|:---|:---| -|`tags.host`|string|-|是|MySQL服务器地址。| -|`tags.port`|string|-|是|MySQL服务器端口。| -|`tags.database`|string|-|是|数据库名称。| -|`tags.table`|string|-|是|需要作为数据源的表名称。| -|`tags.user`|string|-|是|拥有读取权限的MySQL用户名。| -|`tags.password`|string|-|是|用户名对应密码。| -|`tags.sentence`|string|-|是|查询数据源的语句。例如`"select teamid, name from basketball.team order by teamid;"`。| - -### Hbase源特有参数 - -|参数|数据类型|默认值|是否必须|说明| -|:---|:---|:---|:---|:---| -|`tags.host`|string|`127.0.0.1`|是|Hbase服务器地址。| -|`tags.port`|string|`2181`|是|Hbase服务器端口。| -|`tags.table`|string|-|是|需要作为数据源的表名称。| -|`tags.columnFamily`|string|-|是|表所属的列族(column family)。| - -### Pulsar源特有参数 - -|参数|数据类型|默认值|是否必须|说明| -|:---|:---|:---|:---|:---| -|`tags.service`|string|`"pulsar://localhost:6650"`|是|Pulsar服务器地址。| -|`tags.admin`|string|`"http://localhost:8081"`|是|连接pulsar的admin.url。| -|`tags.options.`|string|-|是|Pulsar的选项,可以从`topic`、`topics`和`topicsPattern`选择一个进行配置。| -|`tags.interval.seconds`|int|`10`|是|读取消息的间隔。单位:秒。| - -### Kafka源特有参数 - -|参数|数据类型|默认值|是否必须|说明| -|:---|:---|:---|:---|:---| -|`tags.service`|string|-|是|Kafka服务器地址。| -|`tags.topic`|string|-|是|消息类别。| -|`tags.interval.seconds`|int|`10`|是|读取消息的间隔。单位:秒。| - -## 边配置 - -对于不同的数据源,边的配置也有所不同,有很多通用参数,也有部分特有参数,配置时需要配置通用参数和不同数据源的特有参数。 - -边配置的不同数据源特有参数请参见上方点配置内的特有参数介绍,注意区分tags和edges即可。 - -### 通用参数 - -|参数|数据类型|默认值|是否必须|说明| -|:---|:---|:---|:---|:---| -|`edges.name`| string|-|是|Nebula Graph中定义的边类型名称。| -|`edges.type.source`|string|-|是|指定数据源。例如`csv`。| -|`edges.type.sink`|string|`client`|是|指定导入方式,可选值为`client`和`SST`(暂不支持)。| -|`edges.fields`|list\[string\]|-|是|属性对应的列的表头或列名。如果有表头或列名,请直接使用该名称。如果CSV文件没有表头,用`[_c0, _c1, _c2]`的形式表示第一列、第二列、第三列,以此类推。| -|`edges.nebula.fields`|list\[string\]|-|是|Nebula Graph中定义的属性名称,顺序必须和`edges.fields`一一对应。例如`[_c2, _c3]`对应`[start_year, end_year]`,表示第三列为开始年份的值,第四列为结束年份的值。| -|`edges.source.field`|string|-|是|边的起始点的列。例如`_c0`表示第一列的值作为边的起始点。| -|`edges.target.field`|string|-|是|边的目的点的列。例如`_c1`表示第二列的值作为边的目的点。| -|`edges.ranking`|int|-|否|rank值的列。没有指定时,默认所有rank值为`0`。| -|`edges.batch`|int|`256`|是|单批次写入Nebula Graph的最大边数量。| -|`edges.partition`|int|`32`|是|Spark分片数量。| \ No newline at end of file diff --git a/nebula-exchange/doc-2.0/CN/use-exchange/.ex-ug-import-from-sst.md b/nebula-exchange/doc-2.0/CN/use-exchange/.ex-ug-import-from-sst.md deleted file mode 100644 index b614862..0000000 --- a/nebula-exchange/doc-2.0/CN/use-exchange/.ex-ug-import-from-sst.md +++ /dev/null @@ -1,98 +0,0 @@ -# 导入 SST 文件 - -Nebula Exchange 能将不同来源的数据转换成 SST 文件后再导入 Nebula Graph 数据库中。本文描述 Exchange 将源数据转换为 SST 文件并导入 Nebula Graph 的实现原理,并提供示例说明如何修改配置文件完成 SST 文件导入操作。 - -> **说明**:仅 Linux 系统支持导入 SST 文件。 - -## 实现方法 - -Nebula Graph 底层使用 RocksDB 作为键值型存储引擎。RocksDB 是基于磁盘的存储引擎,数据以 Sorted String Table(SSTable)格式存放。SSTable 是一个内部包含了任意长度、排好序的键值对 <key,value> 集合的文件,用于高效地存储大量的键值型数据。 - -RocksDB 提供了一系列 API 用于创建及导入 SST 文件,有助于您快速导入海量数据。 - -处理 SST 文件的整个过程主要由 Exchange 的 Reader、sstProcessor 和 sstWriter 完成。整个数据处理过程如下所示: - -1. Exchange 的 Reader 从数据源中读取数据。 - -2. sstProcessor 按照 Nebula Graph 要求的格式生成 SST 文件,存储到本地,并上传到 HDFS。SST 文件主要包含点和边两类数据,其中, - - - 表示点的键包括:分区信息、点 ID(VID)、标签类型信息和标签版本信息。 - - 表示边的键包括:分区信息、起点和终点 ID(`rsc_vid` 和 `dst_vid`)、边类型信息、边排序信息和边版本信息。 - - 对应的值主要包含各个属性键值对序列化信息。 - -3. SstFileWriter 创建 SST 文件:Exchange 会创建一个 SstFileWriter 对象,然后打开一个文件并插入数据。生成 SST 文件时,行数据必须严格按照增序进行写入。 - -4. 生成 SST 文件之后,RocksDB 通过 `IngestExternalFile()` 方法将 SST 文件导入到 Nebula Graph 之中。例如: - - ``` - IngestExternalFileOptions ifo; - // Ingest the 2 passed SST files into the DB - Status s = db_->IngestExternalFile({"/home/usr/file1.sst", "/home/usr/file2.sst"}, ifo); - if (!s.ok()) { - printf("Error while adding file %s and %s, Error %s\n", - file_path1.c_str(), file_path2.c_str(), s.ToString().c_str()); - return 1; - } - ``` - - 调用 `IngestExternalFile()` 方法时,RocksDB 默认会将文件拷贝到数据目录,并且阻塞 RocksDB 写入操作。如果 SST 文件中的键范围覆盖了 Memtable 键的范围,则将 Memtable 落盘(flush)到硬盘。将 SST 文件放置在 LSM 树最优位置后,为文件分配一个全局序列号,并打开写操作。 - -## 使用示例 - -不同来源的数据,导入 Nebula Graph 的操作与客户端形式导入操作基本相同,但是有以下差异: - -- 环境里必须部署 HDFS。 -- 在配置文件中,必须做以下修改: - - 源数据的标签和边类型配置:`tags.type.sink` 和 `edges.type.sink` 必须配置为 `sst`。 - - Nebula Graph 相关配置里,需要添加 Nebula Graph 数据库 Meta 服务的 IP 地址和端口,并添加 SST 文件在本地和 HDFS 的存储路径。 - - ```conf - # Nebula Graph 相关配置 - nebula: { - address: { - # 添加 Nebula Graph 数据库 Graph 服务的 IP 地址和端口 - graph: ["127.0.0.1:3699"] - # 添加 Nebula Graph 数据库 Meta 服务的 IP 地址和端口 - meta:["127.0.0.1:45500"] - } - user: user - pswd: password - space: test - path:{ - # 指定 SST 文件保存到本地的路径 - local:/Users/example/path - # 指定上传 SST 文件的 HDFS 路径 - remote:/example/ - } - - connection { - timeout: 3000 - retry: 3 - } - - execution { - retry: 3 - } - - error: { - max: 32 - output: /tmp/errors - } - - rate: { - limit: 64M - timeout: 1000 - } - } - ``` - -详细描述请参考不同数据源的操作示例: - -- [导入 Neo4j 数据](ex-ug-import-from-neo4j.md) -- [导入 Hive 数据](ex-ug-import-hive.md) -- [导入 CSV 文件数据](ex-ug-import-from-csv.md) -- [导入 JSON 文件数据](ex-ug-import-json.md) -- 导入 HBase 数据[doc_TODO] -- 导入 Hive 数据[doc_TODO] -- 导入 Kafka 数据[doc_TODO] -- 导入 MySQL 数据[doc_TODO] diff --git a/nebula-exchange/doc-2.0/CN/use-exchange/.ex-ug-import-steps.md b/nebula-exchange/doc-2.0/CN/use-exchange/.ex-ug-import-steps.md deleted file mode 100644 index 44f3c89..0000000 --- a/nebula-exchange/doc-2.0/CN/use-exchange/.ex-ug-import-steps.md +++ /dev/null @@ -1,55 +0,0 @@ -# 导入数据步骤 - -本文介绍如何使用Exchange从指定的数据源导入数据到Nebula Graph。 - -## 前提条件 - -- 已经[安装部署Nebula Graph](https://docs.nebula-graph.com.cn/2.0/4.deployment-and-installation/2.compile-and-install-nebula-graph/2.install-nebula-graph-by-rpm-or-deb/)并获取如下信息: - - - Graph服务和Meta服务的的IP地址和端口。 - - - 拥有Nebula Graph写权限的用户名和密码。 - -- 已经编译Exchange。详情请参见[编译Exchange](../ex-ug-compile.md)。 - -- 已经安装Spark。 - -- 了解Nebula Graph中创建Schema的信息,包括标签和边类型的名称、属性等。 - -## 操作步骤 - -按以下步骤将不同来源的数据导入Nebula Graph数据库。 - -1. 在Nebula Graph中创建数据模型,包括图空间和Schema。 - -2. (可选)处理源数据。例如,在导入Neo4j数据时,为提高导出速度,在Neo4j数据库中为指定的标签属性创建索引。 - -3. 分别修改Spark、Nebula Graph以及点和边数据的配置文件。 - - > **说明**:编译Exchange后,进入`nebula-java/tools/exchange`目录,您可以参考`target/classes/server_application.conf`文件修改配置文件。 - -4. 导入数据至Nebula Graph。 - -5. 验证导入数据的完整性。 - -6. (可选)在Nebula Graph中重建索引。 - -关于详细操作步骤,根据数据来源不同,您可以参见如下文档: - -- [导入Neo4j数据](ex-ug-import-neo4j.md) - -- [导入Hive数据](ex-ug-import-hive.md) - -- [导入CSV文件数据](ex-ug-import-from-csv.md) - -- [导入JSON文件数据](ex-ug-import-json.md) - -- [导入Parquet文件数据](ex-ug-import-parquet.md) - -- [导入ORC文件数据](ex-ug-import-orc.md) - - - diff --git a/nebula-exchange/doc-2.0/EN/ex-ug-toc.md b/nebula-exchange/doc-2.0/EN/ex-ug-toc.md deleted file mode 100644 index d274290..0000000 --- a/nebula-exchange/doc-2.0/EN/ex-ug-toc.md +++ /dev/null @@ -1,25 +0,0 @@ -# Nebula Exchange v2.x User Guide - -- About Nebula Exchange - - [What is Nebula Exchange](about-exchange/ex-ug-what-is-exchange.md) - - [Limitations](about-exchange/ex-ug-limitations.md) - - [Glossary](about-exchange/ex-ug-terms.md) - - [FAQ](about-exchange/ex-ug-faq.md) -- [Compile Exchange](ex-ug-compile.md) -- Use Exchange - - [Use Exchange](use-exchange/ex-ug-import-steps.md) - - [Import data from CSV files](use-exchange/ex-ug-import-from-csv.md) - - [Import data from JSON files](use-exchange/ex-ug-import-json.md) - - [Import data from Hive](use-exchange/ex-ug-import-hive.md) - - [Import data from Apache Parquet][DOC_TODO] - - [Import data from Apache ORC][DOC_TODO] - - [Import data from Neo4j][DOC_TODO] - - [Import data from HBase][DOC_TODO] - - [Import data from MySQL][DOC_TODO] - - [Import data from Kafka][DOC_TODO] - - [Import data from Pulsar][DOC_TODO] - - [Import SST files][DOC_TODO] -- Parameter reference - - [Spark related parameters](parameter-reference/ex-ug-paras-spark.md) - - [Nebula Graph related parameters](parameter-reference/ex-ug-paras-nebulagraph.md) - - [Import command parameters](parameter-reference/ex-ug-para-import-command.md) diff --git a/nebula-exchange/doc-2.0/EN/figs/ex-ug-001.png b/nebula-exchange/doc-2.0/EN/figs/ex-ug-001.png deleted file mode 100644 index 0e57d6f37d403a85e59ae6b842c289fbaa8ff791..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151025 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≫nKt| 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

                                          +
                                          English |
                                          中文 +