/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) * * 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.geotools.styling; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.logging.Logger; import org.geotools.feature.NameImpl; import org.geotools.util.SimpleInternationalString; import org.geotools.util.Utilities; import org.opengis.feature.type.Name; import org.opengis.filter.Id; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.Function; import org.opengis.metadata.citation.OnLineResource; import org.opengis.style.FeatureTypeStyle; import org.opengis.style.SemanticType; import org.opengis.style.StyleVisitor; import org.opengis.util.Cloneable; /** * Implementation of Feature Type Style; care is taken to ensure everything * is mutable. * * @author James Macgill * @author Johann Sorel (Geomatys) * * @source $URL$ * @version $Id$ */ public class FeatureTypeStyleImpl implements org.geotools.styling.FeatureTypeStyle, Cloneable { private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.geotools.styling"); private List<Rule> rules = new ArrayList<Rule>(); private Set<SemanticType> semantics = new LinkedHashSet<SemanticType>(); private Id featureInstances = null; private Set<Name> featureTypeNames = new LinkedHashSet<Name>(); private DescriptionImpl description = new DescriptionImpl(); private String name = "name"; private OnLineResource online = null; private Expression transformation; /** * Creates a new instance of FeatureTypeStyleImpl * * @param rules DOCUMENT ME! */ protected FeatureTypeStyleImpl(Rule[] rules) { this(Arrays.asList(rules)); } protected FeatureTypeStyleImpl(List<Rule> arules) { rules = new ArrayList<Rule>(); rules.addAll(arules); } /** * Creates a new instance of FeatureTypeStyleImpl */ protected FeatureTypeStyleImpl() { rules = new ArrayList<Rule>(); } public FeatureTypeStyleImpl(org.opengis.style.FeatureTypeStyle fts){ this.description = new DescriptionImpl( fts.getDescription() ); this.featureInstances = fts.getFeatureInstanceIDs(); this.featureTypeNames = new LinkedHashSet<Name>(fts.featureTypeNames()); this.name = fts.getName(); this.rules = new ArrayList<Rule>(); if( fts.rules() != null ){ for (org.opengis.style.Rule rule : fts.rules()) { rules.add( RuleImpl.cast(rule) ); // need to deep copy? } } this.semantics = new LinkedHashSet<SemanticType>(fts.semanticTypeIdentifiers()); } public List<Rule> rules() { return rules; } @Deprecated public org.geotools.styling.Rule[] getRules() { final org.geotools.styling.Rule[] ret; ret = new org.geotools.styling.Rule[rules.size()]; for(int i=0, n=rules.size(); i<n; i++){ ret[i] = (org.geotools.styling.Rule) rules.get(i); } return ret; } @Deprecated public void setRules(org.geotools.styling.Rule[] newRules) { rules = new ArrayList<Rule>(); rules.addAll(Arrays.asList(newRules)); // fireChanged(); } @Deprecated public void addRule(org.geotools.styling.Rule rule) { rules.add(rule); // fireChildAdded(rule); } public Set<SemanticType> semanticTypeIdentifiers() { return semantics; } @Deprecated public String[] getSemanticTypeIdentifiers() { String[] ids = new String[semantics.size()]; Iterator<SemanticType> types = semantics.iterator(); int i=0; while (types.hasNext()){ ids[i] = types.next().name(); i++; } if(ids.length == 0){ ids = new String[]{SemanticType.ANY.toString()}; } return ids; } @Deprecated public void setSemanticTypeIdentifiers(String[] types) { semantics.clear(); for(String id : types){ SemanticType st = SemanticType.valueOf(id); if(st != null) semantics.add(st); } } public Set<Name> featureTypeNames() { return featureTypeNames; } @Deprecated public String getFeatureTypeName() { if(!featureTypeNames.isEmpty()){ return featureTypeNames.iterator().next().getLocalPart(); }else{ return "Feature"; // this is the deafault value - matches to any feature } } @Deprecated public void setFeatureTypeName(String name) { featureTypeNames.clear(); if (name.equals("feature")) { LOGGER.warning("FeatureTypeStyle with typename 'feature' - " + "did you mean to say 'Feature' (with a capital F) for the 'generic' FeatureType"); } Name featurename = new NameImpl(name); featureTypeNames.add(featurename); } public Id getFeatureInstanceIDs() { return featureInstances; } public Description getDescription() { return description; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Deprecated public String getAbstract() { if( description == null || description.getAbstract() == null){ return null; } return description.getAbstract().toString(); } @Deprecated public void setAbstract(String abstractStr) { description.setAbstract(new SimpleInternationalString(abstractStr)); } @Deprecated public String getTitle() { if( description == null || description.getTitle() == null){ return null; } return description.getTitle().toString(); } @Deprecated public void setTitle(String title) { description.setTitle(new SimpleInternationalString(title)); } public Object accept(StyleVisitor visitor,Object data) { return visitor.visit(this,data); } public void accept(org.geotools.styling.StyleVisitor visitor) { visitor.visit(this); } /** * Creates a deep copy clone of the FeatureTypeStyle. * * @see org.geotools.styling.FeatureTypeStyle#clone() */ public Object clone() { FeatureTypeStyle clone; try { clone = (FeatureTypeStyle) super.clone(); } catch (CloneNotSupportedException e) { throw new AssertionError(e); // this should never happen. } final List<Rule> rulesCopy = new ArrayList<Rule>(); for(Rule rl : rules){ rulesCopy.add( (Rule) ((Cloneable) rl).clone() ); } clone.rules().clear(); ((List<Rule>)clone.rules()).addAll(rulesCopy); clone.featureTypeNames().clear(); clone.featureTypeNames().addAll(featureTypeNames); clone.semanticTypeIdentifiers().clear(); clone.semanticTypeIdentifiers().addAll(semantics); return clone; } /** * Overrides hashCode. * * @return The hashcode. */ public int hashCode() { final int PRIME = 1000003; int result = 0; if (rules != null) { result = (PRIME * result) + rules.hashCode(); } if (featureInstances != null) { result = (PRIME * result) + featureInstances.hashCode(); } if (semantics != null) { result = (PRIME * result) + semantics.hashCode(); } if (featureTypeNames != null) { result = (PRIME * result) + featureTypeNames.hashCode(); } if (name != null) { result = (PRIME * result) + name.hashCode(); } if (description != null) { result = (PRIME * result) + description.hashCode(); } return result; } /** * Compares this FeatureTypeStyleImpl with another. * * <p> * Two FeatureTypeStyles are equal if they contain equal properties and an * equal list of Rules. * </p> * * @param oth The other FeatureTypeStyleImpl to compare with. * * @return True if this and oth are equal. */ public boolean equals(Object oth) { if (this == oth) { return true; } if (oth instanceof FeatureTypeStyleImpl) { FeatureTypeStyleImpl other = (FeatureTypeStyleImpl) oth; return Utilities.equals(name, other.name) && Utilities.equals(description, other.description) && Utilities.equals(rules, other.rules) && Utilities.equals(featureTypeNames, other.featureTypeNames) && Utilities.equals(semantics, other.semantics); } return false; } public String toString() { StringBuffer buf = new StringBuffer(); buf.append( "FeatureTypeStyleImpl"); buf.append( "["); if( name != null ) { buf.append(" name="); buf.append( name ); } else { buf.append( " UNNAMED"); } buf.append( ", "); buf.append( featureTypeNames ); buf.append( ", rules=<"); buf.append( rules.size() ); buf.append( ">" ); if( rules.size() > 0 ){ buf.append( "(" ); buf.append( rules.get(0)); if( rules.size() > 1 ){ buf.append(",..."); } buf.append( ")"); } buf.append("]"); return buf.toString(); } public void setOnlineResource(OnLineResource online) { this.online = online; } public OnLineResource getOnlineResource() { return online; } static FeatureTypeStyleImpl cast(FeatureTypeStyle featureTypeStyle) { if( featureTypeStyle == null){ return null; } else if ( featureTypeStyle instanceof FeatureTypeStyleImpl){ return (FeatureTypeStyleImpl) featureTypeStyle; } else { FeatureTypeStyleImpl copy = new FeatureTypeStyleImpl(); // the above is a deep copy - replace with cast if we can return copy; } } public Expression getTransformation() { return transformation; } public void setTransformation(Expression transformation) { this.transformation = transformation; } }