/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
* (C) 2009, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotoolkit.filter;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import org.geotoolkit.filter.binding.Binding;
import org.geotoolkit.filter.binding.Bindings;
import org.opengis.filter.FilterVisitor;
import org.opengis.filter.Id;
import org.opengis.filter.identity.Identifier;
import org.apache.sis.internal.feature.AttributeConvention;
/**
* Immutable id filter.
* This implementation assume Object ids have a 1=1 relation with Identifier and
* that both are unique within this filter.
*
* @author Johann Sorel (Geomatys)
* @module
*/
public class DefaultId implements Id,Serializable{
private static final String XPATH_ID = AttributeConvention.IDENTIFIER_PROPERTY.toString();
private final DualKeyMap keys = new DualKeyMap();
public DefaultId( final Set<? extends Identifier> ids ) {
for(Identifier id : ids){
keys.put(id.getID(), id);
}
}
/**
* {@inheritDoc }
*/
@Override
public Set<Object> getIDs() {
return keys.keySet();
}
/**
* {@inheritDoc }
*/
@Override
public Set<Identifier> getIdentifiers() {
return new HashSet<Identifier>(keys.values());
}
/**
* {@inheritDoc }
*/
@Override
public boolean evaluate(final Object object) {
if (object == null) {
return false;
}
final Binding binding = Bindings.getBinding(object.getClass(), XPATH_ID);
if (binding == null) {
return false;
}
return keys.containsKey(binding.get(object, XPATH_ID, null));
}
/**
* {@inheritDoc }
*/
@Override
public Object accept(final FilterVisitor visitor, final Object extraData) {
return visitor.visit(this, extraData);
}
/**
* {@inheritDoc }
*/
@Override
public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final DefaultId other = (DefaultId) obj;
if (this.keys != other.keys && (this.keys == null || !this.keys.equals(other.keys))) {
return false;
}
return true;
}
/**
* {@inheritDoc }
*/
@Override
public int hashCode() {
int hash = 7;
hash = 59 * hash + (this.keys != null ? this.keys.hashCode() : 0);
return hash;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Filter ID :");
for(final Object key : keys.keySet()){
sb.append(key.toString()).append(", ");
}
return sb.toString();
}
/**
* Take advantage of the fact that both ObjectId and Identifier are unique and
* ObjectId is an attribut of Identifier.
* This special map act like a double key map and so benefit all the performance
* of hashmap.
*/
private static class DualKeyMap extends HashMap<Object,Identifier>{
@Override
public boolean containsValue(final Object value) {
if(value instanceof Identifier){
Identifier ident = (Identifier) value;
return containsKey(ident.getID());
}else{
return false;
}
}
}
}