/**
   * Resolves a reference to a local element identified by address and identifier, where {@code
   * linkBase} identifies a document, including the current document, and {@code linkRef} is the id
   * of the desired element.
   *
   * <p>If {@code linkBase} refers to a local COLLADA file and {@code linkRef} is non-null, the
   * return value is the element identified by {@code linkRef}. If {@code linkRef} is null, the
   * return value is a parsed {@link ColladaRoot} for the COLLADA file identified by {@code
   * linkBase}. Otherwise, {@code linkBase} is returned.
   *
   * @param linkBase the address of the document containing the requested element.
   * @param linkRef the element's identifier.
   * @return the requested element, or null if the element is not found.
   * @throws IllegalArgumentException if the address is null.
   */
  protected Object resolveLocalReference(String linkBase, String linkRef) {
    if (linkBase == null) {
      String message = Logging.getMessage("nullValue.DocumentSourceIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    try {
      File file = new File(linkBase);

      if (!file.exists()) return null;

      // Determine whether the file is a COLLADA document. If not, just return the file path.
      if (!WWIO.isContentType(file, ColladaConstants.COLLADA_MIME_TYPE))
        return file.toURI().toString();

      // Attempt to open and parse the COLLADA file.
      ColladaRoot refRoot = ColladaRoot.createAndParse(file);
      // An exception is thrown if parsing fails, so no need to check for null.

      // Add the parsed file to the session cache so it doesn't have to be parsed again.
      WorldWind.getSessionCache().put(linkBase, refRoot);

      // Now check the newly opened COLLADA file for the referenced item, if a reference was
      // specified.
      if (linkRef != null) return refRoot.getItemByID(linkRef);
      else return refRoot;
    } catch (Exception e) {
      String message =
          Logging.getMessage("generic.UnableToResolveReference", linkBase + "/" + linkRef);
      Logging.logger().warning(message);
      return null;
    }
  }
  /**
   * Initiates a retrieval of the model referenced by this placemark. Once the resource is retrieved
   * and loaded, this calls <code>{@link #setColladaRoot(ColladaRoot)}</code> to specify this link's
   * new network resource, and sends an <code>
   * {@link gov.nasa.worldwind.avlist.AVKey#RETRIEVAL_STATE_SUCCESSFUL}</code> property change event
   * to this link's property change listeners.
   *
   * <p>This does nothing if this <code>KMLNetworkLink</code> has no <code>KMLLink</code>.
   *
   * @param address the address of the resource to retrieve
   */
  protected void retrieveModel(String address) throws IOException, XMLStreamException {
    Object o = this.parent.getRoot().resolveReference(address);
    if (o == null) return;

    ColladaRoot root = ColladaRoot.createAndParse(o);
    if (root == null) return;

    this.setColladaRoot(root);
    this.resourceRetrievalTime.set(System.currentTimeMillis());
    this.parent.getRoot().requestRedraw();
  }