Skip to content

Commit

Permalink
[HJwIMwqg] Revert "apoc.export.csv.graph incorrectly exports properti…
Browse files Browse the repository at this point in the history
…es with datatype float (#403)"

This reverts commit ae1d8be.
  • Loading branch information
vga91 committed Sep 1, 2023
1 parent ae1d8be commit a3dd62c
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 382 deletions.
2 changes: 1 addition & 1 deletion common/src/main/java/apoc/export/util/BulkImportUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

public class BulkImportUtil {

public static Map<Class<?>, String> allowedMapping = Collections.unmodifiableMap(new HashMap(){{
private static Map<Class<?>, String> allowedMapping = Collections.unmodifiableMap(new HashMap(){{
put(Double.class, "double");
put(Float.class, "float");
put(Integer.class, "int");
Expand Down
14 changes: 2 additions & 12 deletions common/src/main/java/apoc/export/util/MetaInformation.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,10 @@
import java.util.Set;
import java.util.stream.Collectors;

import static apoc.export.util.BulkImportUtil.allowedMapping;
import static apoc.gephi.GephiFormatUtils.getCaption;
import static apoc.meta.tablesforlabels.PropertyTracker.typeMappings;
import static apoc.util.collection.Iterables.stream;
import static java.util.Arrays.asList;
import static org.apache.commons.lang3.ClassUtils.primitiveToWrapper;

/**
* @author mh
Expand Down Expand Up @@ -115,17 +113,9 @@ public static void updateKeyTypes(Map<String, Class> keyTypes, Entity pc) {

public static String typeFor(Class value, Set<String> allowed) {
if (value == void.class) return null; // Is this necessary?
final boolean isArray = value.isArray();
value = isArray ? value.getComponentType() : value;
// csv case
// consistent with https://neo4j.com/docs/operations-manual/current/tools/neo4j-admin/neo4j-admin-import/#import-tool-header-format-properties
if (allowed == null) {
return allowedMapping.getOrDefault( primitiveToWrapper(value), "string" );
}
// graphML case
String name = value.getSimpleName().toLowerCase();
boolean isAllowed = allowed.contains(name);
Types type = Types.of(value);
String name = (value.isArray() ? value.getComponentType() : value).getSimpleName().toLowerCase();
boolean isAllowed = allowed != null && allowed.contains(name);
switch (type) {
case NULL:
return null;
Expand Down
5 changes: 0 additions & 5 deletions common/src/main/resources/manyTypes.csv

This file was deleted.

47 changes: 16 additions & 31 deletions core/src/main/java/apoc/export/csv/CsvFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
Expand Down Expand Up @@ -165,22 +163,15 @@ public String[] writeResultHeader(Result result, CSVWriter out) {
public void writeAll(SubGraph graph, Reporter reporter, ExportConfig config, CSVWriter out) {
Map<String, Class> nodePropTypes = collectPropTypesForNodes(graph, db, config);
Map<String, Class> relPropTypes = collectPropTypesForRelationships(graph, db, config);
List<Map.Entry<String, String>> nodeHeader = generateHeader(nodePropTypes, config.useTypes(), NODE_HEADER_FIXED_COLUMNS);
List<Map.Entry<String, String>> relHeader = generateHeader(relPropTypes, config.useTypes(), REL_HEADER_FIXED_COLUMNS);
List<Map.Entry<String, String>> header = new ArrayList<>(nodeHeader);
List<String> nodeHeader = generateHeader(nodePropTypes, config.useTypes(), NODE_HEADER_FIXED_COLUMNS);
List<String> relHeader = generateHeader(relPropTypes, config.useTypes(), REL_HEADER_FIXED_COLUMNS);
List<String> header = new ArrayList<>(nodeHeader);
header.addAll(relHeader);
out.writeNext(header.stream().map(e -> e.getKey() + e.getValue()).toArray(String[]::new), applyQuotesToAll);
out.writeNext(header.toArray(new String[header.size()]), applyQuotesToAll);
int cols = header.size();

writeNodes(graph, out, reporter, getNamesHeader(nodeHeader, NODE_HEADER_FIXED_COLUMNS.length), cols, config.getBatchSize());
writeRels(graph, out, reporter, getNamesHeader(relHeader, REL_HEADER_FIXED_COLUMNS.length), cols, nodeHeader.size(), config.getBatchSize());
}

private List<String> getNamesHeader(List<Map.Entry<String, String>> header, int length) {
return header.subList(length, header.size())
.stream()
.map(Map.Entry::getKey)
.collect(Collectors.toList());
writeNodes(graph, out, reporter, nodeHeader.subList(NODE_HEADER_FIXED_COLUMNS.length, nodeHeader.size()), cols, config.getBatchSize());
writeRels(graph, out, reporter, relHeader.subList(REL_HEADER_FIXED_COLUMNS.length, relHeader.size()), cols, nodeHeader.size(), config.getBatchSize());
}

private void writeAllBulkImport(SubGraph graph, Reporter reporter, ExportConfig config, ExportFileManager writer) {
Expand Down Expand Up @@ -290,26 +281,20 @@ private void writeRow(ExportConfig config, ExportFileManager writer, Set<String>
}
}

private List<Map.Entry<String, String>> generateHeader(Map<String, Class> propTypes, boolean useTypes, String... starters) {
// we create a List of Entry<PropertyName, PropertyDataType>,
// so that the headers will look like nameProp:typeProp,nameProp2:typeProp2,...
// or, with config `useTypes: false`, like nameProp,nameProp2,...
List<Map.Entry<String, String>> result = Arrays.stream(starters)
.map(item -> {
final String[] split = item.split(":");
// with the config `useTypes: true`, we add `:<typeProp>` to each colum
return new AbstractMap.SimpleEntry<>(split[0], useTypes ? (":" + split[1]) : "");
})
.collect(Collectors.toList());

private List<String> generateHeader(Map<String, Class> propTypes, boolean useTypes, String... starters) {
List<String> result = new ArrayList<>();
if (useTypes) {
Collections.addAll(result, starters);
} else {
result.addAll(Stream.of(starters).map(s -> s.split(":")[0]).collect(Collectors.toList()));
}
result.addAll(propTypes.entrySet().stream()
.map(entry -> {
String type = MetaInformation.typeFor(entry.getValue(), null);
// with the config `useTypes: true`, if the type is not null , we add `:<typeProp>` to each colum
return new AbstractMap.SimpleEntry<>(entry.getKey(),
(type == null || type.equals("string") || !useTypes) ? "" : ":" + type);
return (type == null || type.equals("string") || !useTypes)
? entry.getKey() : entry.getKey() + ":" + type;
})
.sorted(Map.Entry.comparingByKey())
.sorted()
.collect(Collectors.toList()));
return result;
}
Expand Down
Loading

0 comments on commit a3dd62c

Please sign in to comment.