/** * This file is part of d:swarm graph extension. * * d:swarm graph extension is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * d:swarm graph extension is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with d:swarm graph extension. If not, see <http://www.gnu.org/licenses/>. */ package org.dswarm.graph.delta.match; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import org.neo4j.graphdb.GraphDatabaseService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.dswarm.graph.DMPGraphException; import org.dswarm.graph.delta.DeltaState; import org.dswarm.graph.delta.match.mark.Marker; /** * @author tgaengler * @param <ENTITY> */ public abstract class Matcher<ENTITY> implements MatchResultSet<ENTITY> { private static final Logger LOG = LoggerFactory.getLogger(Matcher.class); protected Set<String> matches; protected boolean matchesCalculated = false; protected final Optional<Map<String, ENTITY>> existingEntities; protected final Optional<Map<String, ENTITY>> newEntities; protected final GraphDatabaseService existingResourceDB; protected final GraphDatabaseService newResourceDB; protected final String prefixedExistingResourceURI; protected final String prefixedNewResourceURI; protected final Marker<ENTITY> marker; public Matcher(final Optional<? extends Collection<ENTITY>> existingEntitiesArg, final Optional<? extends Collection<ENTITY>> newEntitiesArg, final GraphDatabaseService existingResourceDBArg, final GraphDatabaseService newResourceDBArg, final String prefixedExistingResourceURIArg, final String prefixedNewResourceURIArg, final Marker<ENTITY> markerArg) throws DMPGraphException { existingResourceDB = existingResourceDBArg; newResourceDB = newResourceDBArg; prefixedExistingResourceURI = prefixedExistingResourceURIArg; prefixedNewResourceURI = prefixedNewResourceURIArg; marker = markerArg; if (existingEntitiesArg.isPresent()) { existingEntities = Optional.ofNullable(generateHashes(existingEntitiesArg.get(), existingResourceDB)); } else { existingEntities = Optional.empty(); } if (newEntitiesArg.isPresent()) { newEntities = Optional.ofNullable(generateHashes(newEntitiesArg.get(), newResourceDB)); } else { newEntities = Optional.empty(); } } protected abstract Map<String, ENTITY> generateHashes(final Collection<ENTITY> entities, final GraphDatabaseService resourceDB) throws DMPGraphException; @Override public void match() throws DMPGraphException { getMatches(); markMatchedPaths(); } public Optional<? extends Collection<ENTITY>> getExistingEntitiesNonMatches() { return getNonMatches(existingEntities); } public Optional<? extends Collection<ENTITY>> getNewEntitiesNonMatches() { return getNonMatches(newEntities); } protected Optional<? extends Collection<String>> getMatches() { calculateMatches(); return Optional.ofNullable(matches); } protected Optional<Map<String, ENTITY>> getExistingEntities() { return existingEntities; } protected Optional<Map<String, ENTITY>> getNewEntities() { return newEntities; } protected Optional<? extends Collection<ENTITY>> getMatches(final Optional<Map<String, ENTITY>> entityMap) { if (matches == null || matches.isEmpty()) { return Optional.empty(); } if (!entityMap.isPresent()) { return Optional.empty(); } final List<ENTITY> entities = new ArrayList<>(); for (final String match : matches) { if (entityMap.get().containsKey(match)) { entities.add(entityMap.get().get(match)); } } return Optional.ofNullable(entities); } protected void calculateMatches() { if (!matchesCalculated) { matches = new HashSet<>(); if (existingEntities.isPresent() && newEntities.isPresent()) { for (final String hash : existingEntities.get().keySet()) { if (newEntities.get().containsKey(hash)) { matches.add(hash); } } } Matcher.LOG.debug("'{}' matches", matches.size()); matchesCalculated = true; } } protected Optional<? extends Collection<ENTITY>> getNonMatches(final Optional<Map<String, ENTITY>> entityMap) { if (matches == null || matches.isEmpty()) { if (!entityMap.isPresent()) { return Optional.empty(); } return Optional.of(entityMap.get().values()); } if (!entityMap.isPresent()) { return Optional.empty(); } final List<ENTITY> valueEntities = new ArrayList<>(); for (final Map.Entry<String, ENTITY> entityEntry : entityMap.get().entrySet()) { if (!matches.contains(entityEntry.getKey())) { valueEntities.add(entityEntry.getValue()); } } return Optional.of(valueEntities); } protected void markMatchedPaths() throws DMPGraphException { Matcher.LOG.debug("mark matched paths in existing resource (exact matches)"); markPaths(getMatches(existingEntities), DeltaState.ExactMatch, existingResourceDB, prefixedExistingResourceURI); Matcher.LOG.debug("mark matched paths in new resource (exact matches)"); markPaths(getMatches(newEntities), DeltaState.ExactMatch, newResourceDB, prefixedNewResourceURI); } protected void markPaths(final Optional<? extends Collection<ENTITY>> entities, final DeltaState deltaState, final GraphDatabaseService graphDB, final String prefixedResourceURI) throws DMPGraphException { if (entities.isPresent()) { marker.markPaths(entities.get(), deltaState, graphDB, prefixedResourceURI); } } }