Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8282222

Make DOM collections (e.g.: `NodeList`, etc.) extend `java.lang.Iterable`

XMLWordPrintable

      A DESCRIPTION OF THE PROBLEM :
      Summary
      -------

      Make DOM collections (e.g.: `NodeList`, etc.) extend `java.lang.Iterable`.

      Problem
      -------

      The DOM collections, that is DOM interfaces with an indexed property getter and a length accessor, are based off the IDL specified in the old DOM specification.
      Modern WebIDL defines that the ECMAScript bindings for such interfaces have the `%Symbol.iterator%` property, the Java equivalent of which is `java.lang.Iterable`.

      Solution
      --------

      Make the following DOM collection interfaces extend `java.lang.Iterable` with the `T` type parameter being set to the return type of the `item(int)` method:

      - `org.w3c.dom.DOMImplementationList`
      - `org.w3c.dom.DOMStringList`
      - `org.w3c.dom.NamedNodeMap`
      - `org.w3c.dom.NodeList`
      - `org.w3c.dom.css.CSSRuleList`
      - `org.w3c.dom.css.CSSStyleDeclaration`
      - `org.w3c.dom.css.CSSValueList`
      - `org.w3c.dom.stylesheets.MediaList`
      - `org.w3c.dom.stylesheets.StyleSheetList`

      The interfaces should also provide a default implementation for backwards compatibility.

      Specification
      -------------

      `jdk.xml.internal.DefaultDOMIterator`:
      ```diff
      +package jdk.xml.internal;
      +
      +import java.util.Iterator;
      +import java.util.NoSuchElementException;
      +import java.util.function.IntFunction;
      +import java.util.function.IntSupplier;
      +
      +public final class DefaultDOMIterator<T> implements Iterator<T> {
      +
      + private final IntFunction<T> itemGetter;
      + private final IntSupplier lengthGetter;
      +
      + private int currentIndex = 0;
      +
      + private DefaultDOMIterator(IntFunction<T> itemGetter, IntSupplier lengthGetter) {
      + this.itemGetter = itemGetter;
      + this.lengthGetter = lengthGetter;
      + }
      +
      + public static <T> DefaultDOMIterator<T> of(IntFunction<T> itemGetter, IntSupplier lengthGetter) {
      + return new DefaultDOMIterator<>(itemGetter, lengthGetter);
      + }
      +
      + @Override
      + public boolean hasNext() {
      + return currentIndex < lengthGetter.getAsInt();
      + }
      +
      + @Override
      + public T next() {
      + if (currentIndex >= lengthGetter.getAsInt()) {
      + throw new NoSuchElementException();
      + }
      +
      + return itemGetter.apply(currentIndex++);
      + }
      +}
      ```

      `org.w3c.dom.DOMImplementationList`:
      ```diff
      @@ -50,7 +54,7 @@ package org.w3c.dom;
        * <p>See also the <a href='http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407&#39;&gt;Document Object Model (DOM) Level 3 Core Specification</a>.
        * @since 1.5, DOM Level 3
        */
      -public interface DOMImplementationList {
      +public interface DOMImplementationList extends Iterable<DOMImplementation> {
           /**
            * Returns the <code>index</code>th item in the collection. If
            * <code>index</code> is greater than or equal to the number of
      @@ -69,4 +73,8 @@ public interface DOMImplementationList {
            */
           public int getLength();
       
      + @Override
      + public default Iterator<DOMImplementation> iterator() {
      + return DefaultDOMIterator.of(this::item, this::getLength);
      + }
       }
      ```

      `org.w3c.dom.DOMStringList`:
      ```diff
      @@ -50,7 +54,7 @@ package org.w3c.dom;
        * <p>See also the <a href='http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407&#39;&gt;Document Object Model (DOM) Level 3 Core Specification</a>.
        * @since 1.5, DOM Level 3
        */
      -public interface DOMStringList {
      +public interface DOMStringList extends Iterable<String> {
           /**
            * Returns the <code>index</code>th item in the collection. If
            * <code>index</code> is greater than or equal to the number of
      @@ -76,4 +80,8 @@ public interface DOMStringList {
            */
           public boolean contains(String str);
       
      + @Override
      + public default Iterator<String> iterator() {
      + return DefaultDOMIterator.of(this::item, this::getLength);
      + }
       }
      ```

      `org.w3c.dom.NamedNodeMap`:
      ```diff
      @@ -53,7 +57,7 @@ package org.w3c.dom;
        * <p><code>NamedNodeMap</code> objects in the DOM are live.
        * <p>See also the <a href='http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407&#39;&gt;Document Object Model (DOM) Level 3 Core Specification</a>.
        */
      -public interface NamedNodeMap {
      +public interface NamedNodeMap extends Iterable<Node> {
           /**
            * Retrieves a node specified by name.
            * @param name The <code>nodeName</code> of a node to retrieve.
      @@ -209,4 +213,8 @@ public interface NamedNodeMap {
                                         String localName)
                                         throws DOMException;
       
      + @Override
      + public default Iterator<Node> iterator() {
      + return DefaultDOMIterator.of(this::item, this::getLength);
      + }
       }
      ```

      `org.w3c.NodeList`:
      ```diff
      @@ -49,7 +53,7 @@ package org.w3c.dom;
        * index, starting from 0.
        * <p>See also the <a href='http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407&#39;&gt;Document Object Model (DOM) Level 3 Core Specification</a>.
        */
      -public interface NodeList {
      +public interface NodeList extends Iterable<Node> {
           /**
            * Returns the <code>index</code>th item in the collection. If
            * <code>index</code> is greater than or equal to the number of nodes in
      @@ -67,4 +71,8 @@ public interface NodeList {
            */
           public int getLength();
       
      + @Override
      + public default Iterator<Node> iterator() {
      + return DefaultDOMIterator.of(this::item, this::getLength);
      + }
       }
      ```

      `org.w3c.dom.css.CSSRuleList`:
      ```diff
      @@ -49,7 +53,7 @@ package org.w3c.dom.css;
        * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Style-20001113&#39;&gt;Document Object Model (DOM) Level 2 Style Specification</a>.
        * @since 1.4, DOM Level 2
        */
      -public interface CSSRuleList {
      +public interface CSSRuleList extends Iterable<CSSRule> {
           /**
            * The number of <code>CSSRules</code> in the list. The range of valid
            * child rule indices is <code>0</code> to <code>length-1</code>
      @@ -69,4 +73,8 @@ public interface CSSRuleList {
            */
           public CSSRule item(int index);
       
      + @Override
      + public default Iterator<CSSRule> iterator() {
      + return DefaultDOMIterator.of(this::item, this::getLength);
      + }
       }
      ```

      `org.w3c.dom.css.CSSStyleDeclaration`:
      ```diff
      @@ -62,7 +65,7 @@ package org.w3c.dom.css;
        * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Style-20001113&#39;&gt;Document Object Model (DOM) Level 2 Style Specification</a>.
        * @since 1.4, DOM Level 2
        */
      -public interface CSSStyleDeclaration {
      +public interface CSSStyleDeclaration extends Iterable<String> {
           /**
            * The parsable textual representation of the declaration block
            * (excluding the surrounding curly braces). Setting this attribute will
      @@ -188,4 +191,8 @@ public interface CSSStyleDeclaration {
            */
           public CSSRule getParentRule();
       
      + @Override
      + public default Iterator<String> iterator() {
      + return DefaultDOMIterator.of(this::item, this::getLength);
      + }
       }
      ```

      `org.w3c.dom.css.CSSValueList`:
      ```diff
      @@ -52,7 +56,7 @@ package org.w3c.dom.css;
        * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Style-20001113&#39;&gt;Document Object Model (DOM) Level 2 Style Specification</a>.
        * @since 1.4, DOM Level 2
        */
      -public interface CSSValueList extends CSSValue {
      +public interface CSSValueList extends CSSValue, Iterable<CSSValue> {
           /**
            * The number of <code>CSSValues</code> in the list. The range of valid
            * values of the indices is <code>0</code> to <code>length-1</code>
      @@ -72,4 +76,8 @@ public interface CSSValueList extends CSSValue {
            */
           public CSSValue item(int index);
       
      + @Override
      + public default Iterator<CSSValue> iterator() {
      + return DefaultDOMIterator.of(this::item, this::getLength);
      + }
       }
      ```

      `org.w3c.dom.stylesheets.MediaList`:
      ```diff
      @@ -53,7 +56,7 @@ package org.w3c.dom.stylesheets;
        * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Style-20001113&#39;&gt;Document Object Model (DOM) Level 2 Style Specification</a>.
        * @since 1.4, DOM Level 2
        */
      -public interface MediaList {
      +public interface MediaList extends Iterable<String> {
           /**
            * The parsable textual representation of the media list. This is a
            * comma-separated list of media.
      @@ -111,4 +114,8 @@ public interface MediaList {
           public void appendMedium(String newMedium)
                                    throws DOMException;
       
      + @Override
      + public default Iterator<String> iterator() {
      + return DefaultDOMIterator.of(this::item, this::getLength);
      + }
       }
      ```

      `org.w3c.dom.stylesheets.StyleSheetList`:
      ```diff
      @@ -49,7 +53,7 @@ package org.w3c.dom.stylesheets;
        * <p>See also the <a href='http://www.w3.org/TR/2000/REC-DOM-Level-2-Style-20001113&#39;&gt;Document Object Model (DOM) Level 2 Style Specification</a>.
        * @since 1.4, DOM Level 2
        */
      -public interface StyleSheetList {
      +public interface StyleSheetList extends Iterable<StyleSheet> {
           /**
            * The number of <code>StyleSheets</code> in the list. The range of valid
            * child stylesheet indices is <code>0</code> to <code>length-1</code>
      @@ -68,4 +72,8 @@ public interface StyleSheetList {
            */
           public StyleSheet item(int index);
       
      + @Override
      + public default Iterator<StyleSheet> iterator() {
      + return DefaultDOMIterator.of(this::item, this::getLength);
      + }
       }
      ```


            joehw Joe Wang
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: