/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2010, 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.display2d.style; import java.util.ArrayList; import java.util.Collection; import org.geotoolkit.display2d.GO2Utilities; import org.geotoolkit.style.StyleConstants; import org.opengis.filter.expression.Expression; import org.opengis.style.AnchorPoint; /** * * @author Johann Sorel (Geomatys) * @module */ public abstract class CachedAnchorPoint{ protected final AnchorPoint styleElement; private final Collection<String> attributs; private CachedAnchorPoint(final AnchorPoint anchor, final Collection<String> attributs) { this.styleElement = anchor; this.attributs = attributs; } /** * @return the original object */ public AnchorPoint getSource(){ return styleElement; } public boolean isStatic(){ return attributs.isEmpty(); } /** * Returns the list of attributs requiered by this style. * This can be used to help caching a light version of the feature. * * @return Collection<String> : all requiered feature attributs name */ public Collection<String> getRequieredAttributsName(final Collection<String> buffer){ if(buffer == null){ return attributs; }else{ buffer.addAll(attributs); return buffer; } } public abstract float[] getValues(Object candidate, float[] buffer); public static CachedAnchorPoint cache(final AnchorPoint anchor){ float cachedX = Float.NaN; float cachedY = Float.NaN; final Collection<String> attributs; if(anchor != null){ attributs = new ArrayList<String>(); final Expression expX = anchor.getAnchorPointX(); final Expression expY = anchor.getAnchorPointY(); if(GO2Utilities.isStatic(expX)){ cachedX = GO2Utilities.evaluate(expX, null, Float.class, 0.5f); }else{ GO2Utilities.getRequieredAttributsName(expX,attributs); } if(GO2Utilities.isStatic(expY)){ cachedY = GO2Utilities.evaluate(expY, null, Float.class, 0.5f); }else{ GO2Utilities.getRequieredAttributsName(expY,attributs); } }else{ attributs = Cache.EMPTY_ATTRIBUTS; //we can cache X and Y with default values cachedX = StyleConstants.DEFAULT_ANCHOR_POINT_Xf; cachedY = StyleConstants.DEFAULT_ANCHOR_POINT_Yf; } if(attributs.isEmpty()){ return new StaticAnchorPoint(anchor, cachedX, cachedY); }else{ return new DynamicAnchorPoint(anchor, cachedX, cachedY,attributs); } } public abstract float getMarginRatio(Object candidate, float coeff); private static final class StaticAnchorPoint extends CachedAnchorPoint{ private final float cachedX; private final float cachedY; public StaticAnchorPoint(final AnchorPoint anchor, final float cachedX, final float cachedY) { super(anchor,Cache.EMPTY_ATTRIBUTS); this.cachedX = cachedX; this.cachedY = cachedY; } @Override public float[] getValues(final Object candidate, final float[] buffer){ if(buffer == null){ return new float[]{cachedX,cachedY}; }else{ buffer[0] = cachedX; buffer[1] = cachedY; return buffer; } } @Override public float getMarginRatio(Object candidate, float coeff) { return Math.max(cachedX, cachedY); } } private static final class DynamicAnchorPoint extends CachedAnchorPoint{ private final float cachedX; private final float cachedY; public DynamicAnchorPoint(final AnchorPoint anchor, final float cachedX, final float cachedY, final Collection<String> attributs) { super(anchor,attributs); this.cachedX = cachedX; this.cachedY = cachedY; } @Override public float[] getValues(final Object candidate, float[] buffer){ if(buffer == null){ buffer = new float[2]; } buffer[0] = evalX(candidate); buffer[1] = evalY(candidate); return buffer; } private float evalX(Object candidate){ if(Float.isNaN(cachedX)){ //if X is null it means it is dynamic final Expression anchorX = styleElement.getAnchorPointX(); return GO2Utilities.evaluate(anchorX, candidate, Float.class, StyleConstants.DEFAULT_ANCHOR_POINT_Xf); } else { return cachedX; } } private float evalY(Object candidate){ if(Float.isNaN(cachedY)){ //if Y is null it means it is dynamic final Expression anchorY = styleElement.getAnchorPointY(); return GO2Utilities.evaluate(anchorY, candidate, Float.class, StyleConstants.DEFAULT_ANCHOR_POINT_Yf); } else { return cachedY; } } @Override public float getMarginRatio(Object candidate, float coeff) { if(candidate==null) return Float.NaN; return Math.max(evalX(candidate), evalY(candidate)); } } }