/* Copyright 2008-2010 Gephi Authors : Martin Škurla Website : http://www.gephi.org This file is part of Gephi. Gephi is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Gephi 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with Gephi. If not, see <http://www.gnu.org/licenses/>. */ package org.gephi.neo4j.plugin.impl; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.gephi.neo4j.plugin.api.FilterDescription; import org.gephi.neo4j.plugin.api.FilterOperator; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Path; import org.neo4j.helpers.Predicate; /** * * @author Martin Škurla */ class NodeReturnFilter implements Predicate<Path> { private final Map<PropertyParsingKey, Object> mapper; private final Set<PropertyParsingKey> notParsableProperties; private final Collection<FilterDescription> filterDescriptions; private final boolean restrictMode; private final boolean matchCase; NodeReturnFilter(Collection<FilterDescription> filterDescriptions, boolean restrictMode, boolean matchCase) { this.filterDescriptions = filterDescriptions; this.restrictMode = restrictMode; this.matchCase = matchCase; this.mapper = new HashMap<PropertyParsingKey, Object>(); this.notParsableProperties = new HashSet<PropertyParsingKey>(); } @Override public boolean accept(Path path) { return accept(path.endNode()); } public boolean accept(Node node) { for (FilterDescription filterDescription : filterDescriptions) { if (node.hasProperty(filterDescription.getPropertyKey())) { Object nodePropertyValue = node.getProperty(filterDescription.getPropertyKey()); boolean isValid = doValidation(nodePropertyValue, filterDescription.getOperator(), filterDescription.getPropertyValue()); if (isValid == false) { return false; } } else { return !restrictMode; } } return true; } @SuppressWarnings("unchecked") private <T> T parseValue(String expectedValue, Class<T> finalType) throws NotParsableException { PropertyParsingKey key = new PropertyParsingKey(expectedValue, finalType); if (notParsableProperties.contains(key)) { throw new NotParsableException(); } Object parsedValue = mapper.get(key); if (parsedValue == null) { try { parsedValue = TypeHelper.parseFromString(expectedValue, finalType); mapper.put(key, parsedValue); return (T) parsedValue; } catch (NotParsableException npe) { notParsableProperties.add(key); throw npe; } } throw new AssertionError(); } private boolean doValidation(Object nodePropertyValue, FilterOperator operator, String expectedValue) { try { if (TypeHelper.isWholeNumber(nodePropertyValue)) { return operator.executeOnWholeNumbers((Number) nodePropertyValue, parseValue(expectedValue, Long.class)); } else if (TypeHelper.isRealNumber(nodePropertyValue)) { return operator.executeOnRealNumbers((Number) nodePropertyValue, parseValue(expectedValue, Double.class)); } else if (TypeHelper.isBoolean(nodePropertyValue)) { return operator.executeOnBooleans((Boolean) nodePropertyValue, parseValue(expectedValue, Boolean.class)); } else if (TypeHelper.isCharacter(nodePropertyValue)) { return operator.executeOnCharacters((Character) nodePropertyValue, parseValue(expectedValue, Character.class), matchCase); } else if (TypeHelper.isArray(nodePropertyValue)) { if (TypeHelper.isWholeNumberArray(nodePropertyValue)) { return operator.executeOnWholeNumberArrays(nodePropertyValue, parseValue(expectedValue, Long[].class)); } else if (TypeHelper.isRealNumberArray(nodePropertyValue)) { return operator.executeOnRealNumberArrays(nodePropertyValue, parseValue(expectedValue, Double[].class)); } else if (TypeHelper.isBooleanArray(nodePropertyValue)) { return operator.executeOnBooleanArrays(nodePropertyValue, parseValue(expectedValue, Boolean[].class)); } else if (TypeHelper.isCharacterArray(nodePropertyValue)) { return operator.executeOnCharacterArrays(nodePropertyValue, parseValue(expectedValue, Character[].class), matchCase); } else if (TypeHelper.isStringArray(nodePropertyValue)) { return operator.executeOnStringArrays(nodePropertyValue, parseValue(expectedValue, String[].class), matchCase); } else { throw new AssertionError(); } } else if (TypeHelper.isString(nodePropertyValue)) { return operator.executeOnStrings((String) nodePropertyValue, expectedValue, matchCase); } else { throw new AssertionError(); } } catch (NotParsableException npe) { return false; } } private static class PropertyParsingKey { private final String textValue; private final Class<?> finalType; PropertyParsingKey(String textValue, Class<?> finalType) { this.textValue = textValue; this.finalType = finalType; } @Override public boolean equals(Object o) { if (!(o instanceof PropertyParsingKey)) { return false; } PropertyParsingKey key = (PropertyParsingKey) o; return this.finalType == key.finalType || this.textValue.equals(key.textValue); } @Override public int hashCode() { return textValue.hashCode() + finalType.hashCode(); } } }