├── .gitignore
├── .travis.yml
├── FURTHER_EXAMPLES.md
├── README.md
├── pom.xml
└── src
├── main
└── java
│ └── com
│ └── graphaware
│ └── importer
│ ├── BatchImporter.java
│ ├── FileBatchImporter.java
│ ├── cache
│ ├── BaseCaches.java
│ ├── Cache.java
│ ├── Caches.java
│ ├── InjectCache.java
│ ├── MapDBCache.java
│ └── MapDBCaches.java
│ ├── cli
│ ├── BaseCommandLineParser.java
│ ├── CommandLineParser.java
│ ├── CsvCommandLineParser.java
│ ├── DbCommandLineParser.java
│ └── FileCommandLineParser.java
│ ├── config
│ ├── BaseImportConfig.java
│ ├── CsvImportConfig.java
│ ├── DbImportConfig.java
│ ├── FileImportConfig.java
│ └── ImportConfig.java
│ ├── context
│ ├── BaseImportContext.java
│ ├── CacheAwareImportContext.java
│ ├── ImportContext.java
│ └── SimpleImportContext.java
│ ├── data
│ ├── Data.java
│ ├── DynamicData.java
│ ├── access
│ │ ├── BaseTabularDataReader.java
│ │ ├── CacheDataReader.java
│ │ ├── CacheEntryMapper.java
│ │ ├── CsvDataReader.java
│ │ ├── DataAccess.java
│ │ ├── DataReader.java
│ │ ├── DataWriter.java
│ │ ├── DbDataReader.java
│ │ ├── FileDataWriter.java
│ │ ├── QueueDbDataReader.java
│ │ └── TabularDataReader.java
│ └── location
│ │ ├── DataLocator.java
│ │ ├── FileLocator.java
│ │ ├── InputFileLocator.java
│ │ └── SimpleDataLocator.java
│ ├── domain
│ ├── DirectedRelationship.java
│ ├── GenericRelationship.java
│ ├── Neo4jProperty.java
│ ├── Neo4jPropertyContainer.java
│ ├── Neo4jRelationship.java
│ └── UndirectedRelationship.java
│ ├── importer
│ ├── BaseImporter.java
│ ├── Importer.java
│ └── TabularImporter.java
│ ├── inserter
│ └── SynchronizedBatchInserter.java
│ ├── plan
│ ├── DefaultExecutionPlan.java
│ └── ExecutionPlan.java
│ ├── stats
│ ├── LoggingStatisticsCollector.java
│ ├── StatisticsCollector.java
│ └── StopWatch.java
│ └── util
│ ├── BlockingArrayBlockingQueue.java
│ └── ReflectionUtils.java
└── test
├── java
└── com
│ └── graphaware
│ └── importer
│ ├── cache
│ └── CachesTest.java
│ ├── cli
│ └── FileCommandLineParserTest.java
│ ├── domain
│ └── Neo4jPropertyContainerTest.java
│ ├── integration
│ ├── BatchImporterIntegrationTest.java
│ ├── TestBatchImporter.java
│ ├── TestBatchImporter2.java
│ ├── domain
│ │ └── Person.java
│ └── inserter
│ │ ├── FriendsImporter.java
│ │ ├── JobsImporter.java
│ │ ├── LastRoleImporter.java
│ │ ├── LocationImporter.java
│ │ └── PersonImporter.java
│ ├── plan
│ └── DefaultExecutionPlanTest.java
│ └── stats
│ └── StopWatchTest.java
└── resources
├── friends.csv
├── jobs.csv
├── locations.csv
├── log4j.properties
├── logback.xml
├── neo4j.properties
└── people.csv
/.gitignore:
--------------------------------------------------------------------------------
1 | .buildpath
2 | .project
3 | .settings
4 | target/
5 | .idea/
6 | *.class
7 | *.iml
8 | *.iws
9 | *.ipr
10 | *.db
11 | *.log
12 | .DS_Store
13 | .classpath
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 |
3 | jdk:
4 | - oraclejdk8
5 |
6 | sudo: false
7 |
8 | branches:
9 | only:
10 | - master
11 |
12 | after_success:
13 | - echo "ossrh\${env.OSSRH_USER}\${env.OSSRH_PASS}" > ~/settings.xml
14 | - mvn deploy --settings ~/settings.xml
--------------------------------------------------------------------------------
/FURTHER_EXAMPLES.md:
--------------------------------------------------------------------------------
1 | Further Examples
2 | ================
3 |
4 | This document showcases some further examples of reading data from alternate data sources. To successfully set up and customize additional database import tools, the `DataReader`, `ImportConfig` and `CommandLineParser` classes must be implemented.
5 |
6 | # MySQL Data Source
7 |
8 | ### `MySqlDataReader` Implementation
9 |
10 | The following libraries are required for the `DataReader`.
11 |
12 | ```java
13 | import com.graphaware.importer.data.access.QueueDbDataReader;
14 | import org.apache.commons.dbcp2.BasicDataSource;
15 | import org.springframework.jdbc.core.JdbcTemplate;
16 | import javax.sql.DataSource;
17 | ```
18 |
19 | The class itself is similar to that of the Oracle example in [README.md](../master/README.md). `QueueDbDataReader` is still extended although the MySQL JDBC driver is alternatively used. Note that variable `db` is added to represent the name of the database. The variable `prefetchsize` found in the `OracleDataReader` example is defunct in a MySQL environment and is therefore not included.
20 |
21 | ```java
22 | public class MySqlDataReader extends QueueDbDataReader {
23 |
24 | private final String db;
25 | private final int fetchSize;
26 |
27 | public MySqlDataReader(String dbHost, String dbPort, String user, String password, String db, int fetchSize) {
28 | super (dbHost, dbPort, user, password);
29 | this.db = db;
30 | this.fetchSize = fetchSize;
31 | try {
32 | Class.forName("com.mysql.jdbc.Driver");
33 | } catch (ClassNotFoundException e) {
34 | e.printStackTrace();
35 | }
36 | }
37 |
38 | @Override
39 | protected String getDriverClassName() {
40 | return "com.mysql.jdbc.Driver";
41 | }
42 |
43 | @Override
44 | protected String getUrl(String host, String port) {
45 | return "jdbc:mysql://" + host + ":" + port + "/" + db;
46 | }
47 |
48 | @Override
49 | protected void additionalConfig(JdbcTemplate template) {
50 | template.setFetchSize(fetchSize);
51 | }
52 |
53 | @Override
54 | protected void additionalConfig(DataSource dataSource) {
55 | ((BasicDataSource) dataSource).setInitialSize(1000);
56 | }
57 | }
58 | ```
59 |
60 | ### `MySqlImportConfig` Implementation
61 |
62 | The following libraries are required for the `ImportConfig`.
63 |
64 | ```java
65 | import com.graphaware.importer.config.DbImportConfig;
66 | import com.graphaware.importer.data.access.DataReader;
67 | ```
68 |
69 | Again, the class dismissed the `prefetchsize` variable found in the `OracleDataReader` example. The `db` database name variable is added in a similar way.
70 |
71 | ```java
72 | public class MySqlImportConfig extends DbImportConfig {
73 |
74 | private final String db;
75 | private final int fetchSize;
76 |
77 | public MySqlImportConfig(String graphDir, String outputDir, String props, String dbHost, String dbPort, String user, String password, String db, int fetchSize) {
78 | super(graphDir, outputDir, props, dbHost, dbPort, user, password);
79 | this.db = db;
80 | this.fetchSize = fetchSize;
81 | }
82 |
83 | @Override
84 | public DataReader createReader() {
85 | return new MySqlDataReader(getDbHost(), getDbPort(), getUser(), getPassword(), getDb(), fetchSize);
86 | }
87 |
88 | public String getDb() {
89 | return this.db;
90 | }
91 | }
92 | ```
93 |
94 | ### `MySqlCommandLineParser` Implementation
95 |
96 | The following libraries are required for the `CommandLineParser`.
97 |
98 | ```java
99 | import com.graphaware.importer.cli.DbCommandLineParser;
100 | import org.apache.commons.cli.CommandLine;
101 | import org.apache.commons.cli.Option;
102 | import org.apache.commons.cli.Options;
103 | import org.apache.commons.cli.ParseException;
104 | ```
105 |
106 | The `CommandLineParser` is the first point of interaction between user input and the program. It therefore has been slightly modified to idiomatically interpret a MySQL data source.
107 |
108 | ```java
109 | public class MySqlCommandLineParser extends DbCommandLineParser {
110 |
111 | @Override
112 | protected MySqlImportConfig doProduceConfig(CommandLine line, String graphDir, String outputDir, String props, String host, String port, String user, String password) throws ParseException {
113 | String db = String.valueOf(getOptionalValue(line, "db", ""));
114 | int fetchSize = Integer.valueOf(getOptionalValue(line, "fs", "10000"));
115 |
116 | return new MySqlImportConfig(graphDir, outputDir, props, host, port, user, password, db, fetchSize);
117 | }
118 |
119 | @Override
120 | protected void addOptions(Options options) {
121 | super.addOptions(options);
122 | options.addOption(new Option("db", "db", true, "database name"));
123 | options.addOption(new Option("fs", "fetchSize", true, "JDBC driver row fetch size (default 10000)"));
124 | }
125 | }
126 | ```
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 | 4.0.0
18 |
19 |
20 | com.graphaware.neo4j
21 | module-parent
22 | 2.3.3.37
23 |
24 |
25 | programmatic-importer
26 | 2.3.3.37.4-SNAPSHOT
27 |
28 | GraphAware Programmatic Neo4j Importer
29 | Importer high-performance multi-threaded initial data load into Neo4j from CSV/SQL with custom logic
30 | http://graphaware.com
31 |
32 |
33 |
34 | GNU General Public License, version 3
35 | http://www.gnu.org/licenses/gpl-3.0.txt
36 | repo
37 |
38 |
39 |
40 |
41 | scm:git:git@github.com:graphaware/neo4j-importer.git
42 | scm:git:git@github.com:graphaware/neo4j-importer.git
43 | git@github.com:graphaware/neo4j-importer.git
44 | HEAD
45 |
46 |
47 |
48 |
49 | bachmanm
50 | Michal Bachman
51 | neo4j-importer@graphaware.com
52 |
53 |
54 |
55 |
56 | https://travis-ci.org/graphaware/neo4j-importer
57 | Travis CI
58 |
59 |
60 | 2015
61 |
62 |
63 | GitHub
64 | https://github.com/graphaware/neo4j-importer/issues
65 |
66 |
67 |
68 | Graph Aware Limited
69 | http://graphaware.com
70 |
71 |
72 |
73 |
74 |
75 |
76 | org.neo4j
77 | neo4j
78 | compile
79 |
80 |
81 |
82 | commons-io
83 | commons-io
84 | compile
85 |
86 |
87 |
88 | com.graphaware.neo4j
89 | runtime
90 | test
91 |
92 |
93 |
94 | ch.qos.logback
95 | logback-classic
96 | compile
97 | 1.1.5
98 |
99 |
100 |
101 | org.springframework
102 | spring-orm
103 | ${spring.version}
104 | compile
105 |
106 |
107 |
108 | org.apache.commons
109 | commons-dbcp2
110 | 2.0.1
111 | compile
112 |
113 |
114 |
115 | commons-cli
116 | commons-cli
117 | 1.2
118 | compile
119 |
120 |
121 |
122 | com.graphaware.neo4j
123 | tests
124 |
125 |
126 |
127 | org.apache.commons
128 | commons-csv
129 | 1.1
130 |
131 |
132 |
133 | org.mapdb
134 | mapdb
135 | 3.0.2
136 | compile
137 |
138 |
139 |
140 | com.google.guava
141 | guava
142 | compile
143 |
144 |
145 |
146 |
147 |
148 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/FileBatchImporter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer;
17 |
18 | import com.graphaware.importer.cli.CommandLineParser;
19 | import com.graphaware.importer.cli.CsvCommandLineParser;
20 | import com.graphaware.importer.config.FileImportConfig;
21 | import com.graphaware.importer.data.Data;
22 | import com.graphaware.importer.data.DynamicData;
23 | import com.graphaware.importer.data.location.DataLocator;
24 | import com.graphaware.importer.data.location.InputFileLocator;
25 | import com.graphaware.importer.importer.Importer;
26 |
27 | import java.util.HashSet;
28 | import java.util.Map;
29 | import java.util.Set;
30 |
31 | /**
32 | * {@link com.graphaware.importer.BatchImporter} for file-based imports.
33 | */
34 | public abstract class FileBatchImporter extends BatchImporter {
35 |
36 | /**
37 | * {@inheritDoc}
38 | */
39 | @Override
40 | protected CommandLineParser commandLineParser() {
41 | return new CsvCommandLineParser();
42 | }
43 |
44 | /**
45 | * {@inheritDoc}
46 | */
47 | @Override
48 | protected DataLocator createInputDataLocator(FileImportConfig config) {
49 | return new InputFileLocator(config.getInputDir(), input());
50 | }
51 |
52 | /**
53 | * Get input data to logical file name mapping.
54 | *
55 | * @return mapping. One-to-one mapping of all importers' input data names by default.
56 | */
57 | protected Map input() {
58 | Set inputs = new HashSet<>();
59 |
60 | for (Importer importer : importers()) {
61 | inputs.add(importer.inputData().name());
62 | }
63 |
64 | return DynamicData.oneToOne(inputs.toArray(new String[inputs.size()]));
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/cache/BaseCaches.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.cache;
17 |
18 | import com.graphaware.importer.importer.Importer;
19 | import com.graphaware.importer.util.ReflectionUtils;
20 | import org.slf4j.Logger;
21 | import org.slf4j.LoggerFactory;
22 | import org.springframework.util.Assert;
23 |
24 | import java.lang.reflect.Field;
25 | import java.util.*;
26 |
27 | /**
28 | * Abstract base-class for {@link com.graphaware.importer.cache.Caches} implementations.
29 | */
30 | public abstract class BaseCaches implements Caches {
31 |
32 | private static final Logger LOG = LoggerFactory.getLogger(BaseCaches.class);
33 |
34 | private final Map caches = new HashMap<>();
35 |
36 | /**
37 | * {@inheritDoc}
38 | */
39 | @Override
40 | public void createCache(String cacheName, Class> keyType, Class> valueType) {
41 | Assert.hasLength(cacheName);
42 | Assert.notNull(keyType);
43 | Assert.notNull(valueType);
44 |
45 | if (caches.containsKey(cacheName)) {
46 | throw new IllegalStateException("Cache " + cacheName + " has already been created");
47 | }
48 |
49 | caches.put(cacheName, doCreateCache(cacheName, keyType, valueType));
50 | }
51 |
52 | /**
53 | * Create a cache.
54 | *
55 | * @param cacheName name of the cache. Never null or empty.
56 | * @param keyType Java type of the key stored in the cache. Never null.
57 | * @param valueType Java type of the value stored in the cache. Typically a {@link java.lang.Long}. Never null.
58 | */
59 | public abstract Cache doCreateCache(String cacheName, Class> keyType, Class> valueType);
60 |
61 | /**
62 | * {@inheritDoc}
63 | */
64 | @Override
65 | public Cache getCache(String cacheName) {
66 | Assert.hasLength(cacheName);
67 |
68 | if (!caches.containsKey(cacheName)) {
69 | throw new IllegalStateException("Cache " + cacheName + " has not been created");
70 | }
71 |
72 | return caches.get(cacheName);
73 | }
74 |
75 | /**
76 | * {@inheritDoc}
77 | */
78 | @Override
79 | public void inject(Importer importer) {
80 | Assert.notNull(importer);
81 |
82 | for (Field field : ReflectionUtils.getAllFields(importer.getClass())) {
83 | if (field.getAnnotation(InjectCache.class) != null) {
84 | field.setAccessible(true);
85 | try {
86 | field.set(importer, getCache(field.getAnnotation(InjectCache.class).name()));
87 | } catch (IllegalAccessException e) {
88 | throw new RuntimeException(e);
89 | }
90 | }
91 | }
92 | }
93 |
94 | /**
95 | * {@inheritDoc}
96 | */
97 | @Override
98 | public void cleanup(Collection unfinished) {
99 | Assert.notNull(unfinished);
100 |
101 | if (unfinished.isEmpty()) {
102 | LOG.info("No need to clear caches, the import is finished.");
103 | return;
104 | }
105 |
106 | Set neededCaches = new HashSet<>();
107 | for (Importer importer : unfinished) {
108 | neededCaches.addAll(neededCaches(importer));
109 | }
110 |
111 | boolean cacheCleared = false;
112 |
113 | for (String candidate : caches.keySet()) {
114 | if (!neededCaches.contains(candidate) && !getCache(candidate).isEmpty()) {
115 | LOG.info("Clearing cache: " + candidate);
116 | getCache(candidate).clear();
117 | cacheCleared = true;
118 | }
119 | }
120 |
121 | if (cacheCleared) {
122 | compact();
123 | }
124 | }
125 |
126 | /**
127 | * Compact caches after some of them have been cleared, if needed. No-op by default.
128 | */
129 | protected void compact() {
130 |
131 | }
132 |
133 | /**
134 | * {@inheritDoc}
135 | */
136 | @Override
137 | public Set neededCaches(Importer importer) {
138 | Assert.notNull(importer);
139 |
140 | Set result = new HashSet<>();
141 |
142 | for (Field field : ReflectionUtils.getAllFields(importer.getClass())) {
143 | if (field.getAnnotation(InjectCache.class) != null) {
144 | result.add(field.getAnnotation(InjectCache.class).name());
145 | }
146 | }
147 |
148 | return result;
149 | }
150 |
151 | /**
152 | * {@inheritDoc}
153 | */
154 | @Override
155 | public Set createdCaches(Importer importer) {
156 | Assert.notNull(importer);
157 |
158 | Set result = new HashSet<>();
159 |
160 | for (Field field : ReflectionUtils.getAllFields(importer.getClass())) {
161 | if (field.getAnnotation(InjectCache.class) != null && field.getAnnotation(InjectCache.class).creator()) {
162 | result.add(field.getAnnotation(InjectCache.class).name());
163 | }
164 | }
165 |
166 | return result;
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/cache/Cache.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.cache;
17 |
18 | import java.util.Map;
19 | import java.util.Set;
20 |
21 | /**
22 | * A cache, like a {@link java.util.Map} with {@link #get(Object)} and {@link #containsKey(Object)} supporting null keys,
23 | * returning null and false, respectively.
24 | *
25 | * Caches are needed to map identifiers from custom data sources to Neo4j node IDs assigned to the nodes upon insertion.
26 | *
27 | * @param key type.
28 | * @param value type.
29 | */
30 | public interface Cache {
31 |
32 | int size();
33 |
34 | boolean isEmpty();
35 |
36 | boolean containsKey(K key);
37 |
38 | V get(K key);
39 |
40 | void put(K key, V value);
41 |
42 | void clear();
43 |
44 | Set> entrySet();
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/cache/Caches.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.cache;
17 |
18 | import com.graphaware.importer.importer.Importer;
19 |
20 | import java.util.Collection;
21 | import java.util.Set;
22 |
23 | /**
24 | * {@link com.graphaware.importer.cache.Cache}s used by all {@link com.graphaware.importer.importer.Importer}s.
25 | */
26 | public interface Caches {
27 |
28 | /**
29 | * Create a cache. Cache has to be created before it can be used and cache names must be unique.
30 | *
31 | * @param cacheName name of the cache. Must not be null or empty and must be unique.
32 | * @param keyType Java type of the key stored in the cache. Must not be null.
33 | * @param valueType Java type of the value stored in the cache. Typically a {@link java.lang.Long}. Must not be null.
34 | * @throws java.lang.IllegalStateException in case a cache with the given name already exists.
35 | */
36 | void createCache(String cacheName, Class> keyType, Class> valueType);
37 |
38 | /**
39 | * Get cache with the given name.
40 | *
41 | * @param cacheName name of the cache to locate. Must not be null or empty.
42 | * @return cache, never null.
43 | * @throws java.lang.IllegalStateException in case no such cache exists.
44 | */
45 | Cache getCache(String cacheName);
46 |
47 | /**
48 | * Get names of caches needed by the given inserter.
49 | * Found from {@link com.graphaware.importer.cache.InjectCache} annotations on fields.
50 | *
51 | * @param importer for which to find needed caches. Must not be null.
52 | * @return names of caches needed by the inserter.
53 | */
54 | Set neededCaches(Importer importer);
55 |
56 | /**
57 | * Get names of caches created by the given inserter.
58 | * Found from {@link com.graphaware.importer.cache.InjectCache} annotations on fields,
59 | * where {@link InjectCache#creator()} equals true.
60 | *
61 | * @param importer for which to find created caches. Must not be null.
62 | * @return names of created by the inserter.
63 | */
64 | Set createdCaches(Importer importer);
65 |
66 | /**
67 | * Inject the right caches to the given inserter. Will populate fields annotated with
68 | * {@link com.graphaware.importer.cache.InjectCache}.
69 | *
70 | * @param importer to inject caches to. Must not be null.
71 | */
72 | void inject(Importer importer);
73 |
74 | /**
75 | * Cleanup caches that will no longer be used.
76 | *
77 | * @param unfinished inserters that are not yet finished. Must not be null.
78 | */
79 | void cleanup(Collection unfinished);
80 |
81 | /**
82 | * Destroy all caches.
83 | */
84 | void destroy();
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/cache/InjectCache.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.cache;
17 |
18 | import java.lang.annotation.Documented;
19 | import java.lang.annotation.Retention;
20 | import java.lang.annotation.Target;
21 |
22 | import static java.lang.annotation.ElementType.FIELD;
23 | import static java.lang.annotation.RetentionPolicy.RUNTIME;
24 |
25 | /**
26 | * An annotation indicating that a field should have a named cache injected.
27 | */
28 | @Target({FIELD})
29 | @Retention(RUNTIME)
30 | @Documented
31 | public @interface InjectCache {
32 |
33 | /**
34 | * @return Name of the cache to inject.
35 | */
36 | String name();
37 |
38 | /**
39 | * @return Whether the class whose field is annotated is the creator of the cache.
40 | */
41 | boolean creator() default false;
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/cache/MapDBCache.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.cache;
17 |
18 | import org.mapdb.DB;
19 | import org.mapdb.Serializer;
20 |
21 | import java.util.Map;
22 | import java.util.Set;
23 |
24 | /**
25 | * {@link com.graphaware.importer.cache.Cache} backed by {@link org.mapdb.DB}.
26 | *
27 | * @param key type.
28 | * @param value type.
29 | */
30 | public class MapDBCache implements Cache {
31 |
32 | private final Map map;
33 |
34 | public MapDBCache(DB db, String name, Serializer keySerializer, Serializer valueSerializer) {
35 | map = db.hashMap(name).keySerializer(keySerializer).valueSerializer(valueSerializer).create();
36 | }
37 |
38 | @Override
39 | public int size() {
40 | return map.size();
41 | }
42 |
43 | @Override
44 | public boolean isEmpty() {
45 | return map.isEmpty();
46 | }
47 |
48 | @Override
49 | public boolean containsKey(K key) {
50 | return map.containsKey(key);
51 | }
52 |
53 | @Override
54 | public V get(K key) {
55 | return map.get(key);
56 | }
57 |
58 | @Override
59 | public void put(K key, V value) {
60 | map.put(key, value);
61 | }
62 |
63 | @Override
64 | public void clear() {
65 | map.clear();
66 | }
67 |
68 | @Override
69 | public Set> entrySet() {
70 | return map.entrySet();
71 | }
72 | }
73 |
74 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/cache/MapDBCaches.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.cache;
17 |
18 | import com.graphaware.importer.config.ImportConfig;
19 | import org.mapdb.DB;
20 | import org.mapdb.DBMaker;
21 | import org.mapdb.Serializer;
22 | import org.springframework.util.Assert;
23 |
24 | /**
25 | * {@link com.graphaware.importer.cache.Caches} of type {@link com.graphaware.importer.cache.MapDBCache}.
26 | */
27 | public class MapDBCaches extends BaseCaches {
28 |
29 | private final DB db;
30 |
31 | public MapDBCaches(ImportConfig config) {
32 | db = DBMaker
33 | .fileDB(config.getCacheFile())
34 | .fileMmapEnable()
35 | .fileMmapEnableIfSupported()
36 | .fileMmapPreclearDisable()
37 | .cleanerHackEnable()
38 | .fileDeleteAfterClose()
39 | .closeOnJvmShutdown()
40 | .make();
41 | }
42 |
43 | /**
44 | * {@inheritDoc}
45 | */
46 | @Override
47 | public final Cache doCreateCache(String cacheName, Class> keyType, Class> valueType) {
48 | return doCreateCache(db, cacheName, keyType, valueType);
49 | }
50 |
51 | /**
52 | * Create a cache backed by the given {@link org.mapdb.DB}.
53 | *
54 | * @param db backing the new cache.
55 | * @param cacheName name of the cache.
56 | * @param keyType Java type of the key stored in the cache.
57 | * @param valueType Java type of the value stored in the cache. Typically a {@link java.lang.Long}.
58 | * @return cache.
59 | */
60 | protected MapDBCache doCreateCache(DB db, String cacheName, Class> keyType, Class> valueType) {
61 | return new MapDBCache(db, cacheName, getSerializer(keyType), getSerializer(valueType));
62 | }
63 |
64 | /**
65 | * {@inheritDoc}
66 | */
67 | @Override
68 | public void destroy() {
69 | db.close();
70 | }
71 |
72 | /**
73 | * Resolve a serializer for a given key or value type.
74 | *
75 | * @param type type. Must not be null.
76 | * @return serializer for the given type.
77 | */
78 | protected Serializer> getSerializer(Class> type) {
79 | Assert.notNull(type);
80 |
81 | if (String.class.isAssignableFrom(type)) {
82 | return Serializer.STRING;
83 | }
84 |
85 | if (Long.class.isAssignableFrom(type)) {
86 | return Serializer.LONG;
87 | }
88 |
89 | if (Integer.class.isAssignableFrom(type)) {
90 | return Serializer.INTEGER;
91 | }
92 |
93 | return defaultSerializer(type);
94 | }
95 |
96 | /**
97 | * Get a serializer for a type, for which a serializer hasn't been resolved by {@link #getSerializer(Class)}.
98 | *
99 | * @param type type. Never null.
100 | * @return serializer for the given type.
101 | */
102 | protected Serializer> defaultSerializer(Class> type) {
103 | Assert.notNull(type);
104 |
105 | return Serializer.JAVA;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/cli/BaseCommandLineParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.cli;
17 |
18 | import com.graphaware.importer.config.ImportConfig;
19 | import org.apache.commons.cli.*;
20 | import org.slf4j.Logger;
21 | import org.slf4j.LoggerFactory;
22 |
23 | /**
24 | * Abstract base-class for implementations of {@link com.graphaware.importer.cli.CommandLineParser}.
25 | *
26 | * @param type of the produced config.
27 | */
28 | public abstract class BaseCommandLineParser implements CommandLineParser {
29 |
30 | private static final Logger LOG = LoggerFactory.getLogger(BaseCommandLineParser.class);
31 |
32 | /**
33 | * {@inheritDoc}
34 | */
35 | @Override
36 | public final T parseArgs(String[] args) {
37 | Options options = produceOptions();
38 |
39 | try {
40 | return produceConfig(args, options);
41 | } catch (ParseException exp) {
42 | System.err.println("Parsing failed. Reason: " + exp.getMessage());
43 | HelpFormatter formatter = new HelpFormatter();
44 | formatter.printHelp("importer", options);
45 | return null;
46 | }
47 | }
48 |
49 | private T produceConfig(String[] args, Options options) throws ParseException {
50 | CommandLine line = new BasicParser().parse(options, args);
51 |
52 | String graphDir = getMandatoryValue(line, "g");
53 | String outputDir = getMandatoryValue(line, "o");
54 | String props = getMandatoryValue(line, "r");
55 | String cacheFile = getMandatoryValue(line, "c");
56 |
57 | LOG.info("Producing import config:");
58 | LOG.info("\tGraph: " + graphDir);
59 | LOG.info("\tOutput: " + outputDir);
60 | LOG.info("\tProps: " + props);
61 | LOG.info("\tCache File: " + cacheFile);
62 |
63 | return doProduceConfig(line, graphDir, outputDir, props, cacheFile);
64 | }
65 |
66 | /**
67 | * Produce a config.
68 | *
69 | * @param line the command line.
70 | * @param graphDir graph directory, already extracted from the command line.
71 | * @param outputDir output directory, already extracted from the command line.
72 | * @param props path to Neo4j properties, already extracted from the command line.
73 | * @return import configuration.
74 | * @throws ParseException
75 | */
76 | protected abstract T doProduceConfig(CommandLine line, String graphDir, String outputDir, String props, String cacheFile) throws ParseException;
77 |
78 | /**
79 | * Produce default/essential options.
80 | *
81 | * @return command line options.
82 | */
83 | private Options produceOptions() {
84 | Options options = new Options();
85 | options.addOption(new Option("g", "graph", true, "use given directory to output the graph"));
86 | options.addOption(new Option("o", "output", true, "use given directory to output auxiliary files, such as statistics"));
87 | options.addOption(new Option("r", "properties", true, "use given file as neo4j properties"));
88 | options.addOption(new Option("c", "cachefile", true, "use given file as temporary cache on disk"));
89 |
90 | addOptions(options);
91 |
92 | return options;
93 | }
94 |
95 | /**
96 | * Add extra options to the default ones. No-op by default, intended to be overridden.
97 | *
98 | * @param options default options.
99 | */
100 | protected void addOptions(Options options) {
101 |
102 | }
103 |
104 | /**
105 | * Convenience method for getting an optional command line value.
106 | *
107 | * @param line command line.
108 | * @param opt option.
109 | * @param defaultValue if the option isn't present.
110 | * @return value.
111 | */
112 | protected final String getOptionalValue(CommandLine line, String opt, String defaultValue) {
113 | return line.getOptionValue(opt, defaultValue);
114 | }
115 |
116 | /**
117 | * Convenience method for getting a mandatory command line value.
118 | *
119 | * @param line command line.
120 | * @param opt option.
121 | * @return value.
122 | * @throws org.apache.commons.cli.ParseException if the option is missing.
123 | */
124 | protected final String getMandatoryValue(CommandLine line, String opt) throws ParseException {
125 | String result = line.getOptionValue(opt);
126 | if (result == null) {
127 | throw new ParseException("Missing option: " + opt);
128 | }
129 | return result;
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/cli/CommandLineParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.cli;
17 |
18 | import com.graphaware.importer.config.ImportConfig;
19 |
20 | /**
21 | * A parser of command line arguments, producing an {@link ImportConfig}.
22 | *
23 | * @param type of the produced config.
24 | */
25 | public interface CommandLineParser {
26 |
27 | /**
28 | * Produce an {@link ImportConfig} from command line arguments.
29 | *
30 | * @param args args.
31 | * @return import context. null if the config could not be produced for whatever reason.
32 | */
33 | T parseArgs(String[] args);
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/cli/CsvCommandLineParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.cli;
17 |
18 | import com.graphaware.importer.config.CsvImportConfig;
19 | import com.graphaware.importer.config.FileImportConfig;
20 | import org.apache.commons.cli.CommandLine;
21 |
22 | /**
23 | * Implementation of {@link com.graphaware.importer.cli.CommandLineParser} for CSV imports.
24 | */
25 | public class CsvCommandLineParser extends FileCommandLineParser {
26 |
27 | /**
28 | * {@inheritDoc}
29 | */
30 | @Override
31 | protected FileImportConfig doProduceConfig(CommandLine line, String graphDir, String outputDir, String props, String cacheFile, String inputDir) {
32 | return new CsvImportConfig(graphDir, outputDir, props, cacheFile, inputDir);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/cli/DbCommandLineParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.cli;
17 |
18 | import com.graphaware.importer.config.DbImportConfig;
19 | import org.apache.commons.cli.CommandLine;
20 | import org.apache.commons.cli.Option;
21 | import org.apache.commons.cli.Options;
22 | import org.apache.commons.cli.ParseException;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * Implementation of {@link com.graphaware.importer.cli.CommandLineParser} for database imports.
28 | */
29 | public abstract class DbCommandLineParser extends BaseCommandLineParser {
30 |
31 | private static final Logger LOG = LoggerFactory.getLogger(DbCommandLineParser.class);
32 |
33 | /**
34 | * {@inheritDoc}
35 | */
36 | @Override
37 | protected DbImportConfig doProduceConfig(CommandLine line, String graphDir, String outputDir, String props, String cacheFile) throws ParseException {
38 | String host = getMandatoryValue(line, "h");
39 | String port = getMandatoryValue(line, "t");
40 | String user = getMandatoryValue(line, "u");
41 | String password = getMandatoryValue(line, "p");
42 |
43 | LOG.info("\tHost:" + host);
44 | LOG.info("\tPort:" + port);
45 | LOG.info("\tUsername:" + user);
46 | LOG.info("\tPassword: **********");
47 |
48 | return doProduceConfig(line, graphDir, outputDir, props, cacheFile, host, port, user, password);
49 | }
50 |
51 | /**
52 | * Produce a config.
53 | *
54 | * @param line the command line.
55 | * @param graphDir graph directory, already extracted from the command line.
56 | * @param outputDir output directory, already extracted from the command line.
57 | * @param props path to Neo4j properties, already extracted from the command line.
58 | * @param host db host, already extracted from the command line.
59 | * @param port db port, already extracted from the command line.
60 | * @param user db user, already extracted from the command line.
61 | * @param password db password, already extracted from the command line.
62 | * @return import configuration.
63 | * @throws ParseException
64 | */
65 | protected abstract DbImportConfig doProduceConfig(CommandLine line, String graphDir, String outputDir, String props, String cacheFile, String host, String port, String user, String password) throws ParseException;
66 |
67 | /**
68 | * {@inheritDoc}
69 | */
70 | @Override
71 | protected void addOptions(Options options) {
72 | super.addOptions(options);
73 |
74 | options.addOption(new Option("h", "host", true, "database host"));
75 | options.addOption(new Option("t", "port", true, "database port"));
76 | options.addOption(new Option("u", "username", true, "database username"));
77 | options.addOption(new Option("p", "password", true, "database encrypted password"));
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/cli/FileCommandLineParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.cli;
17 |
18 | import com.graphaware.importer.config.FileImportConfig;
19 | import org.apache.commons.cli.CommandLine;
20 | import org.apache.commons.cli.Option;
21 | import org.apache.commons.cli.Options;
22 | import org.apache.commons.cli.ParseException;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | /**
27 | * Implementation of {@link com.graphaware.importer.cli.CommandLineParser} for file imports.
28 | */
29 | public abstract class FileCommandLineParser extends BaseCommandLineParser {
30 |
31 | private static final Logger LOG = LoggerFactory.getLogger(FileCommandLineParser.class);
32 |
33 | /**
34 | * {@inheritDoc}
35 | */
36 | @Override
37 | protected T doProduceConfig(CommandLine line, String graphDir, String outputDir, String props, String cacheFile) throws ParseException {
38 | String inputDir = getMandatoryValue(line, "i");
39 | LOG.info("\tInput: " + inputDir);
40 |
41 | return doProduceConfig(line, graphDir, outputDir, props, cacheFile, inputDir);
42 | }
43 |
44 | /**
45 | * Produce a config.
46 | *
47 | * @param line the command line.
48 | * @param graphDir graph directory, already extracted from the command line.
49 | * @param outputDir output directory, already extracted from the command line.
50 | * @param props path to Neo4j properties, already extracted from the command line.
51 | * @param inputDir directory for input files, already extracted from the command line.
52 | * @return import configuration.
53 | */
54 | protected abstract T doProduceConfig(CommandLine line, String graphDir, String outputDir, String props, String cacheFile, String inputDir);
55 |
56 | /**
57 | * {@inheritDoc}
58 | */
59 | @Override
60 | protected void addOptions(Options options) {
61 | options.addOption(new Option("i", "input", true, "use given directory to find input files"));
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/config/BaseImportConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.config;
17 |
18 | import com.graphaware.importer.data.access.DataReader;
19 | import org.springframework.util.Assert;
20 |
21 | /**
22 | * Base-class for {@link com.graphaware.importer.config.ImportConfig} implementations.
23 | */
24 | public abstract class BaseImportConfig implements ImportConfig {
25 |
26 | private final String graphDir;
27 | private final String outputDir;
28 | private final String props;
29 | private final String cacheFile;
30 |
31 | /**
32 | * Construct a new config.
33 | *
34 | * @param graphDir directory where the database will be stored. Must not be null or empty.
35 | * @param outputDir directory where other files produced by the import will be stored. Must not be null or empty.
36 | * @param props path to Neo4j properties used during the import. Must not be null or empty.
37 | * @param cacheFile full path to file on disk that will be used as a cache.
38 | */
39 | protected BaseImportConfig(String graphDir, String outputDir, String props, String cacheFile) {
40 | Assert.hasLength(graphDir);
41 | Assert.hasLength(outputDir);
42 | Assert.hasLength(props);
43 | Assert.hasLength(cacheFile);
44 |
45 | this.graphDir = graphDir;
46 | this.outputDir = outputDir;
47 | this.props = props;
48 | this.cacheFile = cacheFile;
49 | }
50 |
51 | /**
52 | * {@inheritDoc}
53 | */
54 | @Override
55 | public String getGraphDir() {
56 | return graphDir;
57 | }
58 |
59 | /**
60 | * {@inheritDoc}
61 | */
62 | @Override
63 | public String getOutputDir() {
64 | return outputDir;
65 | }
66 |
67 | /**
68 | * {@inheritDoc}
69 | */
70 | @Override
71 | public String getProps() {
72 | return props;
73 | }
74 |
75 | /**
76 | * {@inheritDoc}
77 | */
78 | @Override
79 | public String getCacheFile() {
80 | return cacheFile;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/config/CsvImportConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.config;
17 |
18 | import com.graphaware.importer.data.access.CsvDataReader;
19 | import com.graphaware.importer.data.access.DataReader;
20 |
21 | /**
22 | * {@link com.graphaware.importer.config.ImportConfig} implementation for CSV file-based import.
23 | */
24 | public class CsvImportConfig extends FileImportConfig {
25 |
26 | private final char delimiter;
27 | private final char quote;
28 |
29 | /**
30 | * Construct a new config.
31 | *
32 | * @param graphDir directory where the database will be stored. Must not be null or empty.
33 | * @param outputDir directory where other files produced by the import will be stored. Must not be null or empty.
34 | * @param props path to Neo4j properties used during the import. Must not be null or empty.
35 | * @param cacheFile full path to file on disk that will be used as a cache.
36 | * @param inputDir directory where input files will be searched. Must not be null or empty.
37 | * @param delimiter CSV file delimiter.
38 | * @param quote CSV file quote character.
39 | */
40 | public CsvImportConfig(String graphDir, String outputDir, String props, String cacheFile, String inputDir, char delimiter, char quote) {
41 | super(graphDir, outputDir, props, cacheFile, inputDir);
42 | this.delimiter = delimiter;
43 | this.quote = quote;
44 | }
45 |
46 | /**
47 | * Construct a new config with comma as delimiter and a double quote as quote.
48 | *
49 | * @param graphDir directory where the database will be stored. Must not be null or empty.
50 | * @param outputDir directory where other files produced by the import will be stored. Must not be null or empty.
51 | * @param props path to Neo4j properties used during the import. Must not be null or empty.
52 | * @param cacheFile full path to file on disk that will be used as a cache.
53 | * @param inputDir directory where input files will be searched. Must not be null or empty.
54 | */
55 | public CsvImportConfig(String graphDir, String outputDir, String props, String cacheFile, String inputDir) {
56 | this(graphDir, outputDir, props, cacheFile, inputDir, ',', '\"');
57 | }
58 |
59 | /**
60 | * {@inheritDoc}
61 | */
62 | @Override
63 | public DataReader createReader() {
64 | return new CsvDataReader(delimiter, quote);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/config/DbImportConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.config;
17 |
18 | /**
19 | * Base class for {@link com.graphaware.importer.config.ImportConfig} implementations for database-based import.
20 | */
21 | public abstract class DbImportConfig extends BaseImportConfig {
22 |
23 | private final String dbHost;
24 | private final String dbPort;
25 | private final String user;
26 | private final String password;
27 |
28 | protected DbImportConfig(String graphDir, String outputDir, String props, String cacheFile, String dbHost, String dbPort, String user, String password) {
29 | super(graphDir, outputDir, props, cacheFile);
30 | this.dbHost = dbHost;
31 | this.dbPort = dbPort;
32 | this.user = user;
33 | this.password = password;
34 | }
35 |
36 | public String getDbHost() {
37 | return dbHost;
38 | }
39 |
40 | public String getDbPort() {
41 | return dbPort;
42 | }
43 |
44 | public String getUser() {
45 | return user;
46 | }
47 |
48 | public String getPassword() {
49 | return password;
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/config/FileImportConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.config;
17 |
18 | /**
19 | * Base class for {@link com.graphaware.importer.config.ImportConfig} implementations for file-based import.
20 | */
21 | public abstract class FileImportConfig extends BaseImportConfig {
22 |
23 | private final String inputDir;
24 |
25 | /**
26 | * Construct a new config.
27 | *
28 | * @param graphDir directory where the database will be stored. Must not be null or empty.
29 | * @param outputDir directory where other files produced by the import will be stored. Must not be null or empty.
30 | * @param props path to Neo4j properties used during the import. Must not be null or empty.
31 | * @param cacheFile full path to file on disk that will be used as a cache.
32 | * @param inputDir directory where the input files will be read from.
33 | */
34 | protected FileImportConfig(String graphDir, String outputDir, String props, String cacheFile, String inputDir) {
35 | super(graphDir, outputDir, props, cacheFile);
36 | this.inputDir = inputDir;
37 | }
38 |
39 | public String getInputDir() {
40 | return inputDir;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/config/ImportConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.config;
17 |
18 | import com.graphaware.importer.data.access.DataReader;
19 |
20 | /**
21 | * Configuration of an import.
22 | */
23 | public interface ImportConfig {
24 |
25 | /**
26 | * @return directory where the database will be stored.
27 | */
28 | String getGraphDir();
29 |
30 | /**
31 | * @return directory where other files produced by the import will be stored.
32 | */
33 | String getOutputDir();
34 |
35 | /**
36 | * @return path to Neo4j properties used during the import.
37 | */
38 | String getProps();
39 |
40 | /**
41 | * Get the data reader that will provide data for this import.
42 | *
43 | * @return data reader.
44 | */
45 | DataReader createReader();
46 |
47 | /**
48 | * Get full path to the file on disk that will be used as cache.
49 | *
50 | * @return path to file.
51 | */
52 | String getCacheFile();
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/context/BaseImportContext.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.context;
17 |
18 | import com.graphaware.importer.config.ImportConfig;
19 | import com.graphaware.importer.inserter.SynchronizedBatchInserter;
20 | import com.graphaware.importer.stats.LoggingStatisticsCollector;
21 | import com.graphaware.importer.stats.StatisticsCollector;
22 | import org.neo4j.index.impl.lucene.LuceneBatchInserterIndexProviderNewImpl;
23 | import org.neo4j.unsafe.batchinsert.BatchInserter;
24 | import org.neo4j.unsafe.batchinsert.BatchInserterIndexProvider;
25 | import org.neo4j.unsafe.batchinsert.BatchInserters;
26 | import org.slf4j.Logger;
27 | import org.slf4j.LoggerFactory;
28 | import org.springframework.core.io.ClassPathResource;
29 | import org.springframework.util.Assert;
30 |
31 | import java.io.File;
32 | import java.io.IOException;
33 | import java.util.HashMap;
34 | import java.util.Map;
35 | import java.util.Properties;
36 | import java.util.concurrent.Executors;
37 | import java.util.concurrent.ScheduledExecutorService;
38 | import java.util.concurrent.TimeUnit;
39 |
40 | /**
41 | * Bare-bones base-class for {@link ImportContext} implementations.
42 | */
43 | abstract class BaseImportContext implements ImportContext {
44 |
45 | private static final Logger LOG = LoggerFactory.getLogger(BaseImportContext.class);
46 |
47 | protected final ImportConfig config;
48 |
49 | private BatchInserter inserter;
50 | private BatchInserterIndexProvider indexProvider;
51 |
52 | /**
53 | * Create a new import context with the given config.
54 | *
55 | * @param config import config. Must not be null.
56 | */
57 | public BaseImportContext(ImportConfig config) {
58 | Assert.notNull(config);
59 |
60 | this.config = config;
61 | }
62 |
63 | /**
64 | * {@inheritDoc}
65 | */
66 | @Override
67 | public final BatchInserter inserter() {
68 | return inserter;
69 | }
70 |
71 | /**
72 | * {@inheritDoc}
73 | */
74 | @Override
75 | public final BatchInserterIndexProvider indexProvider() {
76 | return indexProvider;
77 | }
78 |
79 | /**
80 | * {@inheritDoc}
81 | */
82 | @Override
83 | public final void essentialBootstrap() {
84 | inserter = createBatchInserter();
85 | indexProvider = createIndexProvider();
86 | }
87 |
88 | /**
89 | * {@inheritDoc}
90 | */
91 | @Override
92 | public final void fullBootstrap() {
93 | preBootstrap();
94 |
95 | essentialBootstrap();
96 |
97 | postBootstrap();
98 | }
99 |
100 | /**
101 | * Perform preliminary actions before context bootstrapping. No-op by default, intended to be overridden.
102 | */
103 | protected void preBootstrap() {
104 | }
105 |
106 | /**
107 | * Perform additional context bootstrapping. No-op by default, intended to be overridden.
108 | */
109 | protected void postBootstrap() {
110 | }
111 |
112 | /**
113 | * {@inheritDoc}
114 | */
115 | @Override
116 | public final void check() {
117 | doCheck();
118 | }
119 |
120 | /**
121 | * Perform additional checks. No-op by default, intended to be overridden.
122 | *
123 | * @throws java.lang.IllegalStateException if not OK.
124 | */
125 | protected void doCheck() {
126 | }
127 |
128 | /**
129 | * {@inheritDoc}
130 | */
131 | @Override
132 | public StatisticsCollector createStatistics(String name) {
133 | return new LoggingStatisticsCollector(name);
134 | }
135 |
136 | /**
137 | * {@inheritDoc}
138 | */
139 | @Override
140 | public final void shutdown() {
141 | ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
142 | executor.scheduleAtFixedRate(new Runnable() {
143 | @Override
144 | public void run() {
145 | LOG.info("I am still alive!");
146 | }
147 | }, 1, 1, TimeUnit.MINUTES);
148 |
149 | preShutdown();
150 |
151 | indexProvider().shutdown();
152 |
153 | inserter().shutdown();
154 |
155 | postShutdown();
156 |
157 | executor.shutdownNow();
158 | }
159 |
160 | /**
161 | * Perform actions before the context is shutdown. No-op by default, intended to be overridden.
162 | */
163 | protected void preShutdown() {
164 | }
165 |
166 | /**
167 | * Perform actions after the context has been shutdown. No-op by default, intended to be overridden.
168 | *
169 | * Note that by this time, you should only perform logging and the like, everything else in the context (especially inserters and index providers) has been shut down!
170 | */
171 | protected void postShutdown() {
172 | }
173 |
174 | /**
175 | * Create a {@link org.neo4j.unsafe.batchinsert.BatchInserter}.
176 | *
177 | * @return batch inserter.
178 | */
179 | protected final BatchInserter createBatchInserter() {
180 | try {
181 | return new SynchronizedBatchInserter(BatchInserters.inserter(new File(config.getGraphDir()), new HashMap((Map) getProperties())));
182 | } catch (IOException e) {
183 | throw new RuntimeException(e);
184 | }
185 | }
186 |
187 | /**
188 | * Get the properties passed in to the batch inserter.
189 | *
190 | * @return properties.
191 | */
192 | protected Properties getProperties() {
193 | final Properties properties = new Properties();
194 | try {
195 | properties.load(new ClassPathResource(config.getProps()).getInputStream());
196 | } catch (IOException e) {
197 | LOG.warn("Could not read properties");
198 | throw new RuntimeException(e);
199 | }
200 | return properties;
201 | }
202 |
203 | /**
204 | * Create a {@link org.neo4j.unsafe.batchinsert.BatchInserterIndexProvider}.
205 | *
206 | * @return index provider.
207 | */
208 | protected final BatchInserterIndexProvider createIndexProvider() {
209 | return new LuceneBatchInserterIndexProviderNewImpl(((SynchronizedBatchInserter) inserter).getBatchInserter());
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/context/CacheAwareImportContext.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.context;
17 |
18 | import com.graphaware.importer.cache.Caches;
19 | import com.graphaware.importer.config.ImportConfig;
20 | import com.graphaware.importer.data.Data;
21 | import com.graphaware.importer.data.access.CacheDataReader;
22 | import com.graphaware.importer.data.access.CacheEntryMapper;
23 | import com.graphaware.importer.data.access.DataReader;
24 | import com.graphaware.importer.data.location.DataLocator;
25 | import org.springframework.util.Assert;
26 |
27 | import java.util.Map;
28 |
29 | /**
30 | * {@link com.graphaware.importer.context.ImportContext} useful for imports where {@link Caches} themselves can serve
31 | * as data input. In such cases, a {@link com.graphaware.importer.data.location.DataLocator} for the cached data needs
32 | * to be provided to the constructor, along with a {@link java.util.Map} of {@link com.graphaware.importer.data.access.CacheEntryMapper}s.
33 | */
34 | public class CacheAwareImportContext extends SimpleImportContext {
35 |
36 | private final DataLocator cacheInputLocator;
37 | private final Map cacheEntryMappers;
38 |
39 | /**
40 | * Create a new context.
41 | *
42 | * @param config import config.
43 | * @param caches caches to be used throughout the import.
44 | * @param inputLocator component capable of locating input data.
45 | * @param outputLocator component capable of locating (creating) output data.
46 | * @param cacheInputLocator component capable of locating cached input data. Must not be null.
47 | * @param cacheEntryMappers mapper for cached data as if they were columns. Must not be null.
48 | */
49 | public CacheAwareImportContext(ImportConfig config, Caches caches, DataLocator inputLocator, DataLocator outputLocator, DataLocator cacheInputLocator, Map cacheEntryMappers) {
50 | super(config, caches, inputLocator, outputLocator);
51 | Assert.notNull(cacheInputLocator);
52 | Assert.notNull(cacheEntryMappers);
53 | this.cacheInputLocator = cacheInputLocator;
54 | this.cacheEntryMappers = cacheEntryMappers;
55 | }
56 |
57 | /**
58 | * {@inheritDoc}
59 | */
60 | @Override
61 | protected DataReader doCreateReader(Data data) {
62 | if (cacheInputLocator.canLocate(data)) {
63 | return new CacheDataReader(caches(), cacheEntryMappers);
64 | }
65 |
66 | return super.doCreateReader(data);
67 | }
68 |
69 | /**
70 | * {@inheritDoc}
71 | */
72 | @Override
73 | protected String locate(Data data) {
74 | if (cacheInputLocator.canLocate(data)) {
75 | return cacheInputLocator.locate(data);
76 | }
77 |
78 | return super.locate(data);
79 | }
80 |
81 | /**
82 | * {@inheritDoc}
83 | */
84 | @Override
85 | protected void doCheck() {
86 | super.doCheck();
87 |
88 | cacheInputLocator.check();
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/context/ImportContext.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.context;
17 |
18 | import com.graphaware.importer.cache.Caches;
19 | import com.graphaware.importer.data.Data;
20 | import com.graphaware.importer.data.access.DataReader;
21 | import com.graphaware.importer.stats.StatisticsCollector;
22 | import org.neo4j.unsafe.batchinsert.BatchInserter;
23 | import org.neo4j.unsafe.batchinsert.BatchInserterIndexProvider;
24 |
25 | /**
26 | * Context for an import.
27 | */
28 | public interface ImportContext {
29 |
30 | /**
31 | * Perform essential bootstrap of the context, i.e., create {@link org.neo4j.unsafe.batchinsert.BatchInserter} and
32 | * {@link org.neo4j.unsafe.batchinsert.BatchInserterIndexProvider}.
33 | */
34 | void essentialBootstrap();
35 |
36 | /**
37 | * Bootstrap the context, i.e. prepare for import.
38 | */
39 | void fullBootstrap();
40 |
41 | /**
42 | * Check that the context is OK.
43 | *
44 | * @throws java.lang.IllegalStateException if not OK.
45 | */
46 | void check();
47 |
48 | /**
49 | * Create a new statistics collector for stats with the given name.
50 | *
51 | * @param name stats name. Must not be null or empty.
52 | * @return collector.
53 | */
54 | StatisticsCollector createStatistics(String name);
55 |
56 | /**
57 | * Get caches used throughout the import.
58 | *
59 | * @return caches.
60 | */
61 | Caches caches();
62 |
63 | /**
64 | * Get the batch inserter associated with this import.
65 | *
66 | * @return batch inserter.
67 | */
68 | BatchInserter inserter();
69 |
70 | /**
71 | * Get the index provider associated with this import.
72 | *
73 | * @return batch inserter index provider.
74 | */
75 | BatchInserterIndexProvider indexProvider();
76 |
77 | /**
78 | * Create a reader for the given data.
79 | *
80 | * @param data for which to create a reader. Must not be null.
81 | * @return data reader. Null if no data reader for given input data can be created.
82 | */
83 | DataReader createReader(Data data);
84 |
85 | /**
86 | * Shutdown the context after import has finished.
87 | */
88 | void shutdown();
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/context/SimpleImportContext.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.context;
17 |
18 | import com.graphaware.importer.cache.Caches;
19 | import com.graphaware.importer.config.ImportConfig;
20 | import com.graphaware.importer.data.Data;
21 | import com.graphaware.importer.data.access.DataReader;
22 | import com.graphaware.importer.data.location.DataLocator;
23 | import org.apache.commons.io.FileUtils;
24 | import org.slf4j.Logger;
25 | import org.slf4j.LoggerFactory;
26 | import org.springframework.util.Assert;
27 |
28 | import java.io.File;
29 | import java.io.IOException;
30 |
31 | /**
32 | * Simplest usable {@link com.graphaware.importer.context.ImportContext} that is aware of caches and I/O.
33 | */
34 | public class SimpleImportContext extends BaseImportContext {
35 |
36 | private static final Logger LOG = LoggerFactory.getLogger(SimpleImportContext.class);
37 |
38 | private final Caches caches;
39 | private final DataLocator inputLocator;
40 | private final DataLocator outputLocator;
41 |
42 | /**
43 | * Create a new context.
44 | *
45 | * @param config import config. Must not be null.
46 | * @param caches caches to be used throughout the import. Must not be null.
47 | * @param inputLocator component capable of locating input data. Must not be null.
48 | * @param outputLocator component capable of locating (creating) output data. Must not be null.
49 | */
50 | public SimpleImportContext(ImportConfig config, Caches caches, DataLocator inputLocator, DataLocator outputLocator) {
51 | super(config);
52 | this.caches = caches;
53 | this.inputLocator = inputLocator;
54 | this.outputLocator = outputLocator;
55 | }
56 |
57 | /**
58 | * {@inheritDoc}
59 | */
60 | @Override
61 | public final Caches caches() {
62 | return caches;
63 | }
64 |
65 | /**
66 | * {@inheritDoc}
67 | */
68 | @Override
69 | public final DataReader createReader(Data data) {
70 | Assert.notNull(data);
71 |
72 | DataReader dataReader = doCreateReader(data);
73 | dataReader.initialize();
74 | dataReader.read(locate(data), data.name());
75 | return dataReader;
76 | }
77 |
78 | /**
79 | * Create a brand new data reader.
80 | *
81 | * @param data for which to create a reader. Never null.
82 | * @return data reader.
83 | */
84 | protected DataReader doCreateReader(Data data) {
85 | return config.createReader();
86 | }
87 |
88 | /**
89 | * Locate data.
90 | *
91 | * @param data to locate.
92 | * @return logical data location.
93 | */
94 | protected String locate(Data data) {
95 | return inputLocator.locate(data);
96 | }
97 |
98 | /**
99 | * {@inheritDoc}
100 | */
101 | @Override
102 | protected void preBootstrap() {
103 | super.preBootstrap();
104 |
105 | deleteGraphDirectory();
106 | }
107 |
108 | /**
109 | * {@inheritDoc}
110 | */
111 | @Override
112 | protected void doCheck() {
113 | super.doCheck();
114 |
115 | inputLocator.check();
116 | outputLocator.check();
117 | }
118 |
119 | /**
120 | * Delete the directory (if exists) where the resulting graph will be stored after the import.
121 | */
122 | protected void deleteGraphDirectory() {
123 | try {
124 | LOG.info("Deleting " + config.getGraphDir() + "...");
125 | FileUtils.deleteDirectory(new File(config.getGraphDir()));
126 | } catch (IOException e) {
127 | LOG.warn("Could not delete graph directory", e);
128 | throw new RuntimeException(e);
129 | }
130 | }
131 |
132 | protected DataLocator getInputLocator() {
133 | return inputLocator;
134 | }
135 |
136 | protected DataLocator getOutputLocator() {
137 | return outputLocator;
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/data/Data.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.data;
17 |
18 | /**
19 | * Input or output data for importer.
20 | */
21 | public interface Data {
22 |
23 | /**
24 | * @return name of the data.
25 | */
26 | String name();
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/data/DynamicData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.data;
17 |
18 | import org.springframework.util.Assert;
19 |
20 | import java.util.HashMap;
21 | import java.util.Map;
22 |
23 | /**
24 | * Named {@link com.graphaware.importer.data.Data} programmatically created on-the-fly.
25 | */
26 | public class DynamicData implements Data {
27 |
28 | private final String name;
29 |
30 | /**
31 | * Create new data.
32 | *
33 | * @param name name of the data. Must not be null or empty.
34 | * @return data object.
35 | */
36 | public static Data withName(final String name) {
37 | return new DynamicData(name);
38 | }
39 |
40 | /**
41 | * Create a one-to-one {@link com.graphaware.importer.data.Data} to name map. Convenient when data names and logical
42 | * (file) names of the data is the same.
43 | *
44 | * @param names of data.
45 | * @return map of data-name pairs (where the name of the data in the key and the value are the same).
46 | */
47 | public static Map oneToOne(String... names) {
48 | Map result = new HashMap<>();
49 | for (String name : names) {
50 | result.put(withName(name), name);
51 | }
52 | return result;
53 | }
54 |
55 | /**
56 | * Create new data.
57 | *
58 | * @param name name of the data. Must not be null or empty.
59 | */
60 | protected DynamicData(String name) {
61 | Assert.hasLength(name);
62 |
63 | this.name = name;
64 | }
65 |
66 | /**
67 | * {@inheritDoc}
68 | */
69 | @Override
70 | public String name() {
71 | return name;
72 | }
73 |
74 | /**
75 | * {@inheritDoc}
76 | */
77 | @Override
78 | public boolean equals(Object o) {
79 | if (this == o) return true;
80 | if (o == null || getClass() != o.getClass()) return false;
81 |
82 | DynamicData dynamicData = (DynamicData) o;
83 |
84 | if (!name.equals(dynamicData.name)) return false;
85 |
86 | return true;
87 | }
88 |
89 | /**
90 | * {@inheritDoc}
91 | */
92 | @Override
93 | public int hashCode() {
94 | return name.hashCode();
95 | }
96 |
97 | /**
98 | * {@inheritDoc}
99 | */
100 | @Override
101 | public String toString() {
102 | return name;
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/data/access/BaseTabularDataReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.data.access;
17 |
18 | import org.slf4j.Logger;
19 | import org.slf4j.LoggerFactory;
20 | import org.springframework.util.StringUtils;
21 |
22 | import java.text.ParseException;
23 | import java.text.SimpleDateFormat;
24 | import java.util.TimeZone;
25 |
26 | /**
27 | * Abstract base-class for {@link TabularDataReader} implementations.
28 | */
29 | public abstract class BaseTabularDataReader implements TabularDataReader {
30 |
31 | private static final Logger LOG = LoggerFactory.getLogger(BaseTabularDataReader.class);
32 |
33 | protected SimpleDateFormat dateFormat;
34 |
35 | /**
36 | * {@inheritDoc}
37 | */
38 | @Override
39 | public void initialize() {
40 | this.dateFormat = dateFormat();
41 | }
42 |
43 | /**
44 | * Create a date format for date conversions.
45 | *
46 | * @return date format. By default, it is "dd/MM/yyyy" in GMT+1. Override for different format.
47 | */
48 | protected SimpleDateFormat dateFormat() {
49 | SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
50 | format.setTimeZone(TimeZone.getTimeZone("GMT+1"));
51 | return format;
52 | }
53 |
54 | /**
55 | * {@inheritDoc}
56 | */
57 | @Override
58 | public Long readLong(String columnName) {
59 | String value = readStringForConversion(columnName);
60 |
61 | if (value == null) {
62 | return null;
63 | }
64 |
65 | try {
66 | return Long.parseLong(value);
67 | } catch (NumberFormatException e) {
68 | LOG.warn("Value " + value + " in column " + columnName + " is not a long");
69 | return null;
70 | }
71 | }
72 |
73 | /**
74 | * {@inheritDoc}
75 | */
76 | @Override
77 | public Integer readInt(String columnName) {
78 | String value = readStringForConversion(columnName);
79 |
80 | if (value == null) {
81 | return null;
82 | }
83 |
84 | try {
85 | return Integer.parseInt(value);
86 | } catch (NumberFormatException e) {
87 | LOG.warn("Value " + value + " in column " + columnName + " is not an int");
88 | return null;
89 | }
90 | }
91 |
92 | /**
93 | * {@inheritDoc}
94 | */
95 | @Override
96 | public Long readDate(String columnName) {
97 | String value = readStringForConversion(columnName);
98 |
99 | if (value == null) {
100 | return null;
101 | }
102 |
103 | try {
104 | return dateFormat.parse(value).getTime();
105 | } catch (ParseException e) {
106 | LOG.warn("Value " + value + " in column " + columnName + " is not a date");
107 | return null;
108 | }
109 | }
110 |
111 | /**
112 | * {@inheritDoc}
113 | */
114 | @Override
115 | public final String readObject(String columnName) {
116 | return doReadObject(columnName);
117 | }
118 |
119 | /**
120 | * Read a String that is intended to be converted to another type.
121 | *
122 | * @param columnName column name.
123 | * @return the String, or null if the value was null, or an empty String.
124 | */
125 | protected final String readStringForConversion(String columnName) {
126 | String value = doReadObject(columnName);
127 |
128 | if (value == null) {
129 | return null;
130 | }
131 |
132 | if (StringUtils.isEmpty(value.trim())) {
133 | return null;
134 | }
135 |
136 | return value.trim();
137 | }
138 |
139 | /**
140 | * Read a String from a column.
141 | *
142 | * @param columnName column name.
143 | * @return String, can be null.
144 | */
145 | protected abstract String doReadObject(String columnName);
146 | }
147 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/data/access/CacheDataReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.data.access;
17 |
18 | import com.graphaware.importer.cache.Caches;
19 | import org.springframework.util.Assert;
20 |
21 | import java.util.Iterator;
22 | import java.util.Map;
23 |
24 | /**
25 | * A {@link com.graphaware.importer.data.access.TabularDataReader} that reads data from a {@link com.graphaware.importer.cache.Cache}.
26 | */
27 | public class CacheDataReader implements TabularDataReader {
28 |
29 | private final Caches caches;
30 | private final Map mappers;
31 | private Iterator entryIterator;
32 | private Map.Entry entry;
33 | private CacheEntryMapper mapper;
34 | private int entryNumber = 0;
35 |
36 | /**
37 | * Create a new reader.
38 | *
39 | * @param caches to read from. Must not be null.
40 | * @param mappers of cached data to "columns". Must not be null.
41 | */
42 | public CacheDataReader(Caches caches, Map mappers) {
43 | Assert.notNull(caches);
44 | Assert.notNull(mappers);
45 |
46 | this.caches = caches;
47 | this.mappers = mappers;
48 | }
49 |
50 | /**
51 | * {@inheritDoc}
52 | */
53 | @Override
54 | public void initialize() {
55 | //no-op
56 | }
57 |
58 | /**
59 | * {@inheritDoc}
60 | */
61 | @Override
62 | public void read(String connectionString, String hint) {
63 | if (entryIterator != null || entry != null) {
64 | throw new IllegalStateException("Previous reader hasn't been closed");
65 | }
66 | entryIterator = caches.getCache(connectionString).entrySet().iterator();
67 | mapper = mappers.get(connectionString);
68 | }
69 |
70 | /**
71 | * {@inheritDoc}
72 | */
73 | @Override
74 | public void close() {
75 | entryIterator = null;
76 | entry = null;
77 | entryNumber = 0;
78 | }
79 |
80 | /**
81 | * {@inheritDoc}
82 | */
83 | @Override
84 | public Long readLong(String columnName) {
85 | Long value = (Long) mapper.getValue(entry, columnName);
86 |
87 | if (value == null) {
88 | return null;
89 | }
90 |
91 | return value;
92 | }
93 |
94 | /**
95 | * {@inheritDoc}
96 | */
97 | @Override
98 | public Integer readInt(String columnName) {
99 | Integer value = (Integer) mapper.getValue(entry, columnName);
100 |
101 | if (value == null) {
102 | return null;
103 | }
104 |
105 | return value;
106 | }
107 |
108 | /**
109 | * {@inheritDoc}
110 | */
111 | @Override
112 | public Long readDate(String columnName) {
113 | throw new UnsupportedOperationException("Not yet implemented"); //probably never needed
114 | }
115 |
116 | /**
117 | * {@inheritDoc}
118 | */
119 | @Override
120 | public String readObject(String columnName) {
121 | String value = (String) mapper.getValue(entry, columnName);
122 |
123 | if (value == null) {
124 | return null;
125 | }
126 |
127 | return value;
128 | }
129 |
130 | /**
131 | * {@inheritDoc}
132 | */
133 | @Override
134 | public int getRow() {
135 | return entryNumber;
136 | }
137 |
138 | /**
139 | * {@inheritDoc}
140 | */
141 | @Override
142 | public boolean readRecord() {
143 | if (!entryIterator.hasNext()) {
144 | return false;
145 | }
146 |
147 | entry = entryIterator.next();
148 | entryNumber++;
149 |
150 | return true;
151 | }
152 |
153 | /**
154 | * {@inheritDoc}
155 | */
156 | @Override
157 | public String getRawRecord() {
158 | return entry.toString();
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/data/access/CacheEntryMapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.data.access;
17 |
18 | import java.util.Map;
19 |
20 | /**
21 | * A component that maps a {@link com.graphaware.importer.cache.Cache} entry into a Java object as if it was read from
22 | * a tabular source.
23 | */
24 | public interface CacheEntryMapper {
25 |
26 | /**
27 | * Get a cached value.
28 | *
29 | * @param entry cache entry. Must not be null.
30 | * @param columnName name of the "column" (as if reading from a tabular source). Must not be null.
31 | * @return mapped value.
32 | */
33 | Object getValue(Map.Entry entry, String columnName);
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/data/access/CsvDataReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.data.access;
17 |
18 | import org.apache.commons.csv.CSVFormat;
19 | import org.apache.commons.csv.CSVRecord;
20 |
21 | import java.io.FileReader;
22 | import java.io.IOException;
23 | import java.io.Reader;
24 | import java.util.Iterator;
25 |
26 | /**
27 | * {@link TabularDataReader} for CSV files.
28 | */
29 | public class CsvDataReader extends BaseTabularDataReader {
30 |
31 | private Iterator records;
32 | private CSVRecord record;
33 | private Reader in;
34 |
35 | private final char delimiter;
36 | private final char quote;
37 |
38 | /**
39 | * Create a new reader.
40 | *
41 | * @param delimiter delimiter.
42 | * @param quote quote character.
43 | */
44 | public CsvDataReader(char delimiter, char quote) {
45 | this.delimiter = delimiter;
46 | this.quote = quote;
47 | }
48 |
49 | /**
50 | * {@inheritDoc}
51 | */
52 | @Override
53 | public void read(String connectionString, String hint) {
54 | if (records != null) {
55 | throw new IllegalStateException("Previous reader hasn't been closed");
56 | }
57 |
58 | try {
59 | in = new FileReader(connectionString);
60 | records = CSVFormat.DEFAULT
61 | .withDelimiter(delimiter)
62 | .withQuote(quote)
63 | .withHeader()
64 | .parse(in).iterator();
65 |
66 | } catch (Exception e) {
67 | throw new RuntimeException(e);
68 | }
69 | }
70 |
71 | /**
72 | * {@inheritDoc}
73 | */
74 | @Override
75 | public void close() {
76 | try {
77 | in.close();
78 | } catch (IOException e) {
79 | throw new RuntimeException(e);
80 | }
81 |
82 | in = null;
83 | records = null;
84 | record = null;
85 | }
86 |
87 | /**
88 | * {@inheritDoc}
89 | */
90 | @Override
91 | protected String doReadObject(String columnName) {
92 | String s = record.get(columnName);
93 |
94 | if (s != null) {
95 | s = s.replaceAll(System.getProperty("line.separator"), "").trim();
96 | }
97 |
98 | return s;
99 | }
100 |
101 | /**
102 | * {@inheritDoc}
103 | */
104 | @Override
105 | public int getRow() {
106 | return Long.valueOf(record.getRecordNumber()).intValue();
107 | }
108 |
109 | /**
110 | * {@inheritDoc}
111 | */
112 | @Override
113 | public boolean readRecord() {
114 | if (!records.hasNext()) {
115 | return false;
116 | }
117 | record = records.next();
118 |
119 | return true;
120 | }
121 |
122 | /**
123 | * {@inheritDoc}
124 | */
125 | @Override
126 | public String getRawRecord() {
127 | return record.toString();
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/data/access/DataAccess.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.data.access;
17 |
18 | /**
19 | * A component accessing data.
20 | */
21 | public interface DataAccess extends AutoCloseable {
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/data/access/DataReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.data.access;
17 |
18 | /**
19 | * A reader of data. Does not have to be (and usually isn't) thread-safe. Therefore, this class should be accessed
20 | * in a single thread.
21 | *
22 | * @param type of object that is retrieved from cells.
23 | */
24 | public interface DataReader extends DataAccess {
25 |
26 | /**
27 | * Initialize the reader.
28 | */
29 | void initialize();
30 |
31 | /**
32 | * Open the reader.
33 | *
34 | * @param connectionString identification of the data source (e.g. SQL query, file name, etc.)
35 | * @param hint human-readable representation of the connection for naming threads, logging, etc.
36 | */
37 | void read(String connectionString, String hint);
38 |
39 | /**
40 | * Close the reader and release all resources.
41 | *
42 | * {@inheritDoc}
43 | */
44 | @Override
45 | void close();
46 |
47 | /**
48 | * Read an object from a column (family,...).
49 | *
50 | * @param columnName name of the column.
51 | * @return an object.
52 | */
53 | O readObject(String columnName);
54 |
55 | /**
56 | * Get current row number.
57 | *
58 | * @return current row number.
59 | */
60 | int getRow();
61 |
62 | /**
63 | * Read the next record, i.e. advance the cursor by 1.
64 | *
65 | * @return true iff there was a next record.
66 | */
67 | boolean readRecord();
68 |
69 | /**
70 | * Get the current record in its raw form.
71 | *
72 | * @return raw record.
73 | */
74 | String getRawRecord();
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/data/access/DataWriter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.data.access;
17 |
18 | /**
19 | * A data writer.
20 | */
21 | public interface DataWriter extends DataAccess {
22 |
23 | /**
24 | * Append a string to the writer.
25 | *
26 | * @param s to append. Must not be null.
27 | * @return this instance.
28 | */
29 | DataWriter append(String s);
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/data/access/DbDataReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.data.access;
17 |
18 | import org.apache.commons.dbcp2.BasicDataSource;
19 | import org.springframework.jdbc.core.JdbcTemplate;
20 | import org.springframework.util.Assert;
21 |
22 | import javax.sql.DataSource;
23 |
24 | /**
25 | * {@link com.graphaware.importer.data.access.TabularDataReader} for databases.
26 | */
27 | public abstract class DbDataReader extends BaseTabularDataReader {
28 |
29 | private final String dbHost;
30 | private final String dbPort;
31 | private final String user;
32 | private final String password;
33 | protected JdbcTemplate jdbcTemplate;
34 |
35 | /**
36 | * Construct a new reader.
37 | *
38 | * @param dbHost db host. Must not be null or empty.
39 | * @param dbPort db port. Must not be null or empty.
40 | * @param user db user. Must not be null.
41 | * @param password db password. Must not be null.
42 | */
43 | public DbDataReader(String dbHost, String dbPort, String user, String password) {
44 | Assert.hasLength(dbHost);
45 | Assert.hasLength(dbPort);
46 | Assert.notNull(user);
47 | Assert.notNull(password);
48 |
49 | this.dbHost = dbHost;
50 | this.dbPort = dbPort;
51 | this.user = user;
52 | this.password = password;
53 | }
54 |
55 | /**
56 | * {@inheritDoc}
57 | */
58 | @Override
59 | public void initialize() {
60 | super.initialize();
61 | this.jdbcTemplate = createJdbcTemplate();
62 | }
63 |
64 | /**
65 | * Create a {@link org.springframework.jdbc.core.JdbcTemplate} used for talking to the database.
66 | *
67 | * @return jdbc template.
68 | */
69 | protected JdbcTemplate createJdbcTemplate() {
70 | DataSource dataSource = createDataSource();
71 |
72 | JdbcTemplate result = new JdbcTemplate(dataSource);
73 |
74 | additionalConfig(result);
75 |
76 | return result;
77 | }
78 |
79 | /**
80 | * Create a {@link javax.sql.DataSource} used for talking to the database.
81 | *
82 | * @return data source.
83 | */
84 | protected DataSource createDataSource() {
85 | BasicDataSource dataSource = new BasicDataSource();
86 |
87 | dataSource.setUrl(getUrl(dbHost, dbPort));
88 | dataSource.setUsername(user);
89 | dataSource.setPassword(password);
90 | dataSource.setDefaultReadOnly(true);
91 | dataSource.setDefaultAutoCommit(false);
92 |
93 | dataSource.setDriverClassName(getDriverClassName());
94 |
95 | additionalConfig(dataSource);
96 |
97 | return dataSource;
98 | }
99 |
100 | /**
101 | * Perform additional configuration on the JDBC template. No-op by default, to be overridden.
102 | *
103 | * @param template to perform additional config on.
104 | */
105 | protected void additionalConfig(JdbcTemplate template) {
106 | }
107 |
108 | /**
109 | * Perform additional configuration on the data source. No-op by default, to be overridden.
110 | *
111 | * @param dataSource to perform additional config on.
112 | */
113 | protected void additionalConfig(DataSource dataSource) {
114 | }
115 |
116 | /**
117 | * Get the class name of the JDBC driver. Must be present on the classpath.
118 | *
119 | * @return driver name.
120 | */
121 | protected abstract String getDriverClassName();
122 |
123 | /**
124 | * Create the JDBC connection string (url).
125 | *
126 | * @param host host to connect to.
127 | * @param port port to connect on.
128 | * @return JDBC connection string.
129 | */
130 | protected abstract String getUrl(String host, String port);
131 | }
132 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/data/access/FileDataWriter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.data.access;
17 |
18 | import java.io.FileWriter;
19 | import java.io.IOException;
20 |
21 | /**
22 | * A {@link com.graphaware.importer.data.access.DataWriter} that extends a {@link java.io.FileWriter}.
23 | */
24 | public class FileDataWriter extends FileWriter implements DataWriter {
25 |
26 | private final String fileName;
27 |
28 | /**
29 | * Constructs a FileWriter object given a file name.
30 | *
31 | * @param fileName String The system-dependent filename. Must not be null.
32 | * @throws IOException if the named file exists but is a directory rather
33 | * than a regular file, does not exist but cannot be
34 | * created, or cannot be opened for any other reason
35 | */
36 | public FileDataWriter(String fileName) throws IOException {
37 | super(fileName);
38 | this.fileName = fileName;
39 | }
40 |
41 | /**
42 | * {@inheritDoc}
43 | *
44 | * Translates {@link java.io.IOException} to {@link java.lang.RuntimeException}.
45 | */
46 | @Override
47 | public DataWriter append(String s) {
48 | try {
49 | super.append(s);
50 | } catch (IOException e) {
51 | throw new RuntimeException(e);
52 | }
53 |
54 | return this;
55 | }
56 |
57 | /**
58 | * {@inheritDoc}
59 | */
60 | @Override
61 | public String toString() {
62 | return "FileDataWriter to " + fileName;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/com/graphaware/importer/data/access/QueueDbDataReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013-2016 GraphAware
3 | *
4 | * This file is part of the GraphAware Framework.
5 | *
6 | * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms
7 | * of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
8 | * or (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 | * See the GNU General Public License for more details. You should have received a copy of the
13 | * GNU General Public License along with this program. If not, see .
14 | */
15 |
16 | package com.graphaware.importer.data.access;
17 |
18 | import org.slf4j.Logger;
19 | import org.slf4j.LoggerFactory;
20 | import org.springframework.dao.DataAccessException;
21 | import org.springframework.jdbc.core.ResultSetExtractor;
22 |
23 | import java.sql.ResultSet;
24 | import java.sql.ResultSetMetaData;
25 | import java.sql.SQLException;
26 | import java.util.Calendar;
27 | import java.util.Date;
28 | import java.util.HashMap;
29 | import java.util.Map;
30 | import java.util.concurrent.ArrayBlockingQueue;
31 | import java.util.concurrent.BlockingQueue;
32 | import java.util.concurrent.TimeUnit;
33 |
34 | /**
35 | * {@link com.graphaware.importer.data.access.DbDataReader} that uses a queue to temporally decouple reading from the
36 | * database and processing the records.
37 | *
38 | * One thread fills the queue with records, another thread reads from the queue. The queue is blocking. This means if it
39 | * is full, the database reading thread will block on insert. If it is empty, calls to {@link #readRecord()} will block.
40 | */
41 | public abstract class QueueDbDataReader extends DbDataReader {
42 |
43 | private static final Logger LOG = LoggerFactory.getLogger(QueueDbDataReader.class);
44 | public static final String ROW = "row";
45 |
46 | private volatile BlockingQueue