All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.unlaxer.jaddress.gremlin.GremlinUtil Maven / Gradle / Ivy

package org.unlaxer.jaddress.gremlin;

import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.has;
import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.unlaxer.jaddress.entity.standard.建物階層;
import org.unlaxer.jaddress.entity.standard.郵便番号;
import org.unlaxer.jaddress.entity.standard.階層要素;
import org.unlaxer.jaddress.parser.AddressContext;
import org.unlaxer.jaddress.parser.AddressElement;
import org.unlaxer.jaddress.parser.BlockHierarchyResolver.BlockPatternResolverResult;
import org.unlaxer.jaddress.parser.BuildingHierarchyResolver.BuildingHierarchyResolverResult;
import org.unlaxer.jaddress.parser.BuildingHierarchyResolver2.BuildingHierarchyResolverResult2;
import org.unlaxer.jaddress.parser.CharacterKind;
import org.unlaxer.jaddress.parser.CharacterKinds;
import org.unlaxer.jaddress.parser.SeparatorKind;

public class GremlinUtil {

	private GraphTraversalSource g;

	public GremlinUtil(GraphTraversalSource g) {
		super();
		this.g = g;
	}

	public static enum Edge {
		include
	}

	public static enum Field {
		label, //
		element, //
		value, //
		level, //
		lead, //
		tail,//
	}

	/**
	 * property support array Gremlin = OK (VertexPropertyFeatures) Neo4j = NG
	 * (https://neo4j.com/docs/cypher-manual/current/syntax/values/)
	 * 
	 * 使えても、検索、マージは面倒になる
	 * 
	 * @param addressContext
	 */
	public void create(AddressContext addressContext) {
		List vertexs = new ArrayList<>();
		List needEdges = new ArrayList<>();
		List nodes = convertToNodes(addressContext);

		nodes.forEach(n -> {
			GraphTraversal g0 = g.V().hasLabel(n.label)//
					.has(Field.element.name(), n.element)//
					.has(Field.value.name(), n.value)//
					.has(Field.level.name(), n.level)//
					.has(Field.lead.name(), n.lead)//
					.has(Field.tail.name(), n.tail)//
			;

			Vertex v1;
			if (g0.hasNext()) {
				v1 = g0.next();
				needEdges.add(false);
			} else {
				g0.iterate();
				v1 = g.addV(n.label)//
						.property(Field.element.name(), n.element)//
						.property(Field.value.name(), n.value)//
						.property(Field.level.name(), n.level)//
						.property(Field.lead.name(), n.lead)//
						.property(Field.tail.name(), n.tail)//
						.next();
				needEdges.add(true);
			}
			vertexs.add(v1);
		});

		for (int i = 1; i < vertexs.size(); i++) {
			if (needEdges.get(i - 1) || needEdges.get(i)) {
				g.V(vertexs.get(i - 1)).addE(Edge.include.name()).to(vertexs.get(i)).next();
			}
		}

	}

	private List convertToNodes(AddressContext addressContext) {
		List nodes = new ArrayList<>();
		List labels = new ArrayList<>();

		labels.add(addressContext.zip.hyphonated);
		nodes.add(new NodeElement(addressContext.zip));

		addressContext.results().right.ifPresent(result -> {
			result.get().stream().forEach(as -> {
				as.get().forEach(addressElement -> {
					String value = addressElement.asString();
					if (value != null && !value.isBlank()) {
						labels.add(value);
						nodes.add(new NodeElement(labels, addressElement));
					}
				});
			});
		});

		return nodes;
	}

	@SuppressWarnings("unchecked")
	public BlockPatternResolverResult searchBlockPattern(郵便番号 zip, AddressElement town) {
		BlockPatternResolverResult ret = new BlockPatternResolverResult();

		createGraphTraversal(zip, town).valueMap(Field.element.name(), Field.value.name()).toStream().forEach(map -> {
			String a = (String) ((List) (map.get(Field.element.name()))).get(0);
			String b = (String) ((List) (map.get(Field.value.name()))).get(0);
//			System.out.println(a + "=" + b);
			CharacterKinds cs = new CharacterKinds(CharacterKind.stringAndCharacterKindsOf(b));
			ret.add(階層要素.valueOf(a), cs);
		});

		return ret;
	}

	private GraphTraversal createGraphTraversal(郵便番号 zip, AddressElement town) {
		GraphTraversal t1 = g.V().hasLabel(zip.hyphonated)
				.until(has(Field.value.name(), town.asString()).has(Field.level.name(), town.階層要素().level))
				.repeat(out());

		GraphTraversal t2 = t1.repeat(out()).emit();
		return t2;
	}

	@SuppressWarnings("unchecked")
	public BuildingHierarchyResolverResult2 searchBuildings2(郵便番号 zip, Map<階層要素, AddressElement> addressMap) {
		SortedMap<階層要素, CharacterKinds> ret1 = new TreeMap<>();

		createGraphTraversal(zip, addressMap).valueMap(Field.element.name(), Field.value.name()).toStream()
				.forEach(map -> {
					String a = (String) ((List) (map.get(Field.element.name()))).get(0);
					String b = (String) ((List) (map.get(Field.value.name()))).get(0);
					CharacterKinds cs = new CharacterKinds(CharacterKind.stringAndCharacterKindsOf(b));
					階層要素 k = 階層要素.valueOf(a);
					ret1.put(k, cs);
				});

		Set buildingNames = createGraphTraversal(zip, addressMap).has(Field.level.name(), 9)
				.values(Field.value.name()).toStream().map(e -> (String) e).distinct().collect(Collectors.toSet());

		return new BuildingHierarchyResolverResult2(ret1, buildingNames);
	}

	public AddressElement createAddressElement(String word, 階層要素 _階層要素) {
		return new AddressElement(word, _階層要素, SeparatorKind.domainSpecificSeparator,
				SeparatorKind.domainSpecificSeparator);
	}

	public BuildingHierarchyResolverResult searchBuildings(郵便番号 zip, Map<階層要素, AddressElement> addressMap) {

		Set<階層要素> elements = createGraphTraversal(zip, addressMap).values(Field.element.name()).toStream()
				.map(p -> 階層要素.valueOf((String) p)).distinct().collect(Collectors.toSet());

		Set buildingNames = createGraphTraversal(zip, addressMap).has(Field.level.name(), 9)
				.values(Field.value.name()).toStream().map(e -> (String) e).distinct().collect(Collectors.toSet());

		return new BuildingHierarchyResolverResult(建物階層.from階層要素(elements), buildingNames);
	}

	private GraphTraversal createGraphTraversal(郵便番号 zip, Map<階層要素, AddressElement> addressMap) {
		GraphTraversal t = g.V().hasLabel(zip.hyphonated).out(Edge.include.name());
		階層要素[] keys = new 階層要素[addressMap.size()];
		addressMap.keySet().toArray(keys);

		for (int i = 0; i < addressMap.size(); i++) {
			AddressElement e = addressMap.get(keys[i]);
			t.has(Field.value.name(), e.asString()).has(Field.element.name(), e.階層要素().name());
			if (addressMap.size() - 1 != i) {
				t.out(Edge.include.name());
			}
		}

		t.repeat(out()).emit();
		return t;
	}

	public void truncate() {
		long count = g.V().count().next();
		for (int i = 0; i < count / 1000 + 1; i++) {
			g.V().limit(1000).drop().iterate();
		}
		count = g.E().count().next();
		for (int i = 0; i < count / 1000 + 1; i++) {
			g.E().limit(1000).drop().iterate();
		}
	}

	public Stream searchNextValues(String label) {
		return g.V().hasLabel(label).out(Edge.include.name()).values(Field.value.name()).toStream()
				.map(v -> v.toString()).distinct();
	}

	public String count() {
		return String.format("V=%d, E=%d", g.V().count().next(), g.E().count().next());
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy