/**
   * 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;
    }
  }
  /**
   * Creates a Collada root for an untyped source. The source must be either a {@link File} or a
   * {@link String} identifying either a file path or a {@link URL}. Null is returned if the source
   * type is not recognized.
   *
   * @param docSource either a {@link File} or a {@link String} identifying a file path or {@link
   *     URL}.
   * @return a new {@link ColladaRoot} for the specified source, or null if the source type is not
   *     supported.
   * @throws IllegalArgumentException if the source is null.
   * @throws IOException if an error occurs while reading the source.
   */
  public static ColladaRoot create(Object docSource) throws IOException {
    if (docSource == null) {
      String message = Logging.getMessage("nullValue.DocumentSourceIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    if (docSource instanceof File) {
      return new ColladaRoot((File) docSource);
    } else if (docSource instanceof URL) {
      return new ColladaRoot((URL) docSource);
    } else if (docSource instanceof String) {
      File file = new File((String) docSource);
      if (file.exists()) return new ColladaRoot(file);

      URL url = WWIO.makeURL(docSource);
      if (url != null) return new ColladaRoot(url);
    } else if (docSource instanceof InputStream) {
      return new ColladaRoot((InputStream) docSource);
    }

    return null;
  }