All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gov.nasa.worldwind.ogc.kml.KMLAbstractFeature Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2012 United States Government as represented by the Administrator of the
 * National Aeronautics and Space Administration.
 * All Rights Reserved.
 */

package gov.nasa.worldwind.ogc.kml;

import gov.nasa.worldwind.event.Message;
import gov.nasa.worldwind.ogc.kml.impl.*;
import gov.nasa.worldwind.render.*;
import gov.nasa.worldwind.util.*;
import gov.nasa.worldwind.util.xml.XMLEventParserContext;
import gov.nasa.worldwind.util.xml.atom.*;
import gov.nasa.worldwind.util.xml.xal.XALAddressDetails;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
import java.util.*;

/**
 * Represents the KML Feature element and provides access to its contents.
 * 

* KMLAbstractFeature implements the KMLRenderable interface, but does not actually render * anything. Subclasses should override the methods {@link #doPreRender(gov.nasa.worldwind.ogc.kml.impl.KMLTraversalContext, * gov.nasa.worldwind.render.DrawContext)} and {@link #doRender(gov.nasa.worldwind.ogc.kml.impl.KMLTraversalContext, * gov.nasa.worldwind.render.DrawContext)} to render their contents. If the visibility property is * set to false, this does not call doPreRender and doRender during rendering. * * @author tag * @version $Id: KMLAbstractFeature.java 1171 2013-02-11 21:45:02Z dcollins $ */ public abstract class KMLAbstractFeature extends KMLAbstractObject implements KMLRenderable { /** The style selectors specified in the KML Feature element. Is empty if no selectors were specified. */ protected List styleSelectors = new ArrayList(); /** * The visibility flag for the feature. This field is determined from the visibility element of the KML feature * initially, but the client may set it directly, in which case it may then differ from the visibility field in the * fields table. */ protected Boolean visibility; // may be different from the visibility field if application has set it explicitly /** The region specified in the KML Feature element. Is null if no region was specified. */ protected KMLRegion region; /** A balloon explicitly associated with this feature by the client. This is not a KML field of the Feature element. */ protected Balloon balloon; // not a KML schema field, merely a convenience field of this class /** * Construct an instance. * * @param namespaceURI the qualifying namespace URI. May be null to indicate no namespace qualification. */ protected KMLAbstractFeature(String namespaceURI) { super(namespaceURI); } @Override protected void doAddEventContent(Object o, XMLEventParserContext ctx, XMLEvent event, Object... args) throws XMLStreamException { if (o instanceof KMLAbstractView) this.setView((KMLAbstractView) o); else if (o instanceof KMLAbstractTimePrimitive) this.setTimePrimitive((KMLAbstractTimePrimitive) o); else if (o instanceof KMLAbstractStyleSelector) this.addStyleSelector((KMLAbstractStyleSelector) o); else if (o instanceof KMLRegion) this.setRegion((KMLRegion) o); else if (o instanceof Boolean && event.asStartElement().getName().getLocalPart().equalsIgnoreCase("visibility")) this.setVisibility((Boolean) o); else super.doAddEventContent(o, ctx, event, args); } public String getName() { return (String) this.getField("name"); } /** * Indicates whether this KMLAbstractFeature is enabled for rendering. This returns null * if no visibility is specified. This indicates the default visibility of true should be used. * * @return true or null to draw feature shape, otherwise false. The default * value is true. * * @see #setVisibility(Boolean) */ public Boolean getVisibility() { return this.visibility; } /** * Specifies whether this KMLAbstractFeature is enabled for rendering. * * @param visibility true or null to draw this feature, otherwise false. The * default value is true. * * @see #getVisibility() */ public void setVisibility(Boolean visibility) { this.visibility = visibility; } public Boolean getOpen() { return (Boolean) this.getField("open"); } public AtomPerson getAuthor() { return (AtomPerson) this.getField("author"); } public AtomLink getLink() { return (AtomLink) this.getField("link"); } public String getAddress() { return (String) this.getField("address"); } public XALAddressDetails getAddressDetails() { return (XALAddressDetails) this.getField("AddressDetails"); } public String getPhoneNumber() { return (String) this.getField("phoneNumber"); } public Object getSnippet() { Object o = this.getField("snippet"); if (o != null) return o; return this.getField("Snippet"); } public String getSnippetText() { Object o = this.getField("snippet"); if (o != null) return ((String) o).trim(); KMLSnippet snippet = (KMLSnippet) this.getSnippet(); if (snippet != null && snippet.getCharacters() != null) return snippet.getCharacters().trim(); // trim because string parser might not have parsed it return null; } public String getDescription() { return (String) this.getField("description"); } protected void setView(KMLAbstractView o) { this.setField("AbstractView", o); } public KMLAbstractView getView() { return (KMLAbstractView) this.getField("AbstractView"); } protected void setTimePrimitive(KMLAbstractTimePrimitive o) { this.setField("AbstractTimePrimitive", o); } public KMLAbstractTimePrimitive getTimePrimitive() { return (KMLAbstractTimePrimitive) this.getField("AbstractTimePrimitive"); } public KMLStyleUrl getStyleUrl() { return (KMLStyleUrl) this.getField("styleUrl"); } protected void addStyleSelector(KMLAbstractStyleSelector o) { this.styleSelectors.add(o); } public List getStyleSelectors() { return this.styleSelectors; } public boolean hasStyleSelectors() { return this.getStyleSelectors() != null && this.getStyleSelectors().size() > 0; } public boolean hasStyle() { return this.hasStyleSelectors() || this.getStyleUrl() != null; } public KMLRegion getRegion() { return this.region; } protected void setRegion(KMLRegion region) { this.region = region; } public KMLExtendedData getExtendedData() { return (KMLExtendedData) this.getField("ExtendedData"); } /** * Set the balloon associated with this feature. *

* Note: Balloon is not a field in the KML Feature element. It's a direct field of this class and enables the client * to associate a balloon with the feature. * * @param balloon New balloon. */ public void setBalloon(Balloon balloon) { this.balloon = balloon; } /** * Get the balloon associated with this feature, if any. * * @return The balloon associated with the feature. Returns null if there is no associated balloon. */ public Balloon getBalloon() { return this.balloon; } /** {@inheritDoc} */ public void preRender(KMLTraversalContext tc, DrawContext dc) { if (tc == null) { String message = Logging.getMessage("nullValue.TraversalContextIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (dc == null) { String message = Logging.getMessage("nullValue.DrawContextIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (!this.isFeatureActive(tc, dc)) return; this.doPreRender(tc, dc); } /** {@inheritDoc} */ public void render(KMLTraversalContext tc, DrawContext dc) { if (tc == null) { String message = Logging.getMessage("nullValue.TraversalContextIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (dc == null) { String message = Logging.getMessage("nullValue.DrawContextIsNull"); Logging.logger().severe(message); throw new IllegalArgumentException(message); } if (!this.isFeatureActive(tc, dc)) return; this.doRender(tc, dc); } /** * Indicates whether this KMLAbstractFeature is active and should be rendered on the specified * DrawContext. This returns true if the following conditions are all true: *

*

  • This feature's visibility is unspecified (null) or is set to * true.
  • This feature as no Region and does not inherit a Region from an ancestor, or its * Region is active for the specified DrawContext.
*

* If this feature has no Region, this inherits the Region of its nearest ancestor by using the Region on the top of * the KML traversal context's region stack (if any). If there is no ancestor Region this feature is assumed to be * the DrawContext's view and is rendered according to its visibility flag. A Region is * considered active if it is visible, and the DrawContext meets the Region's level of detail * criteria. * * @param tc the current KML traversal context. Specifies an inherited Region (if any) and a detail hint. * @param dc the current draw context. Used to determine whether this feature's Region is active. * * @return true if this feature should be rendered, otherwise false. */ protected boolean isFeatureActive(KMLTraversalContext tc, DrawContext dc) { if (this.getVisibility() != null && !this.getVisibility()) return false; KMLRegion region = this.getRegion(); if (region == null) region = tc.peekRegion(); return region == null || region.isActive(tc, dc); } /** * Called from preRender if this KMLAbstractFeature's visibility is not set * to false. Subclasses should override this method to pre-render their content. * * @param tc the current KML traversal context. * @param dc the current draw context. */ protected void doPreRender(KMLTraversalContext tc, DrawContext dc) { // Subclasses override to implement render behavior. } /** * Called from render if this KMLAbstractFeature's visibility is not set to * false. Subclasses should override this method to render their content. * * @param tc the current KML traversal context. * @param dc the current draw context. */ protected void doRender(KMLTraversalContext tc, DrawContext dc) { // Subclasses override to implement render behavior. } /** * Draws the {@link gov.nasa.worldwind.render.Balloon} associated with this KML feature. This does * nothing if there is no Balloon associated with this feature. * * @param tc the current KML traversal context. * @param dc the current draw context. */ @SuppressWarnings({"UnusedDeclaration"}) protected void renderBalloon(KMLTraversalContext tc, DrawContext dc) { if (this.getBalloon() != null) this.getBalloon().render(dc); } /** * Obtains the effective values for a specified sub-style (IconStyle, ListStyle, etc.) and state * (normal or highlight). The returned style is the result of merging values from this feature * instance's style selectors and its styleUrl, if any, with precedence given to style selectors. *

* A remote styleUrl that has not yet been resolved is not included in the result. In this case the returned * sub-style is marked with the value {@link gov.nasa.worldwind.avlist.AVKey#UNRESOLVED}. The same is true when a * StyleMap style selector contains a reference to an external Style and that reference has not been resolved. * * @param styleState the style mode, either \"normal\" or \"highlight\". * @param subStyle an instance of the sub-style desired, such as {@link gov.nasa.worldwind.ogc.kml.KMLIconStyle}. * The effective sub-style values are accumulated and merged into this instance. The instance * should not be one from within the KML document because its values are overridden and augmented; * it's just an independent variable in which to return the merged attribute values. For * convenience, the instance specified is returned as the return value of this method. * * @return the sub-style values for the specified type and state. The reference returned is the one passed in as the * subStyle argument. */ public KMLAbstractSubStyle getSubStyle(KMLAbstractSubStyle subStyle, String styleState) { return KMLAbstractStyleSelector.mergeSubStyles(this.getStyleUrl(), this.getStyleSelectors(), styleState, subStyle); } @Override public void applyChange(KMLAbstractObject sourceValues) { if (!(sourceValues instanceof KMLAbstractFeature)) { String message = Logging.getMessage("KML.InvalidElementType", sourceValues.getClass().getName()); Logging.logger().warning(message); throw new IllegalArgumentException(message); } super.applyChange(sourceValues); KMLAbstractFeature sourceFeature = (KMLAbstractFeature) sourceValues; if (sourceValues.hasField("visibility")) this.setVisibility((Boolean) sourceFeature.getField("visibility")); if (sourceFeature.getRegion() != null) this.setRegion(sourceFeature.getRegion()); if (sourceFeature.getStyleSelectors() != null && sourceFeature.getStyleSelectors().size() > 0) { this.mergeStyleSelectors(sourceFeature); this.onChange(new Message(KMLAbstractObject.MSG_STYLE_CHANGED, this)); } } /** * Merge a list of incoming style selectors with the current list. If an incoming selector has the same ID as an * existing one, replace the existing one, otherwise just add the incoming one. * * @param sourceFeature the incoming style selectors. */ protected void mergeStyleSelectors(KMLAbstractFeature sourceFeature) { // Make a copy of the existing list so we can modify it as we traverse the copy. List styleSelectorsCopy = new ArrayList(this.getStyleSelectors().size()); styleSelectorsCopy.addAll(this.getStyleSelectors()); for (KMLAbstractStyleSelector sourceSelector : sourceFeature.getStyleSelectors()) { String id = sourceSelector.getId(); if (!WWUtil.isEmpty(id)) { for (KMLAbstractStyleSelector existingSelector : styleSelectorsCopy) { String currentId = existingSelector.getId(); if (!WWUtil.isEmpty(currentId) && currentId.equals(id)) { this.getStyleSelectors().remove(existingSelector); } } } this.getStyleSelectors().add(sourceSelector); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy