You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ml...@apache.org on 2006/07/31 16:08:55 UTC

svn commit: r427121 [9/29] - in /incubator/harmony/enhanced/classlib/trunk/modules/swing: make/ src/main/java/common/javax/swing/ src/main/java/common/javax/swing/text/ src/main/java/common/javax/swing/text/html/ src/main/java/common/javax/swing/text/h...

Added: incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/TableTagView.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/TableTagView.java?rev=427121&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/TableTagView.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/TableTagView.java Mon Jul 31 07:08:47 2006
@@ -0,0 +1,514 @@
+/*
+ *  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Vadim L. Bogdanov
+ * @version $Revision$
+ */
+package javax.swing.text.html;
+
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.util.BitSet;
+
+import javax.swing.SizeRequirements;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentEvent.ElementChange;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BoxView;
+import javax.swing.text.Element;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.View;
+import javax.swing.text.ViewFactory;
+import javax.swing.text.html.CSS.FloatValue;
+
+import org.apache.harmony.x.swing.Utilities;
+
+class TableTagView extends BlockView implements ViewFactory {
+    private int[] columnWidths = new int[5];
+    private AttributeSet cachedAttributes;
+    private boolean areColumnSizeRequirementsValid;
+    private SizeRequirements[] columnSizeRequirements = new SizeRequirements[5];
+
+    private class TableRowView extends BlockView {
+        private BitSet isColumnOccupied = new BitSet(16);
+
+        public TableRowView(final Element elem) {
+            super(elem, X_AXIS);
+        }
+
+        protected SizeRequirements calculateMajorAxisRequirements(final int axis,
+                final SizeRequirements r) {
+            SizeRequirements size = r == null ? new SizeRequirements() : r;
+            SizeRequirements[] widths = calculateColumnSizeRequirements();
+            size.minimum = 0;
+            size.preferred = 0;
+            for (int i = 0; i < getColumnCount(); i++) {
+                size.minimum += widths[i].minimum;
+                size.preferred += widths[i].preferred;
+                size.maximum = Utilities.safeIntSum(size.maximum, widths[i].maximum);
+            }
+            return size;
+        }
+
+        protected SizeRequirements calculateMinorAxisRequirements(
+                int axis, SizeRequirements r) {
+            SizeRequirements size = super.calculateMinorAxisRequirements(axis, r);
+            size.maximum = size.preferred;
+            return size;
+        }
+
+        protected void layoutMajorAxis(final int targetSpan, final int axis,
+                                       final int[] offsets, final int[] spans) {
+            int[] widths = getColumnWidths();
+
+            int currentOffset = 0;
+            int widthsIndex = 0;
+            for (int i = 0; i < spans.length; i++) {
+                // take row spans of cells on previous rows into account
+                for (int j = 0; isColumnOccupied.get(widthsIndex + j); j++) {
+                    currentOffset += widths[widthsIndex + j];
+                    widthsIndex++;
+                }
+
+                offsets[i] = currentOffset;
+                int colSpan = getColumnSpan(i);
+                spans[i] = 0;
+                for (int j = 0; j < colSpan; j++) {
+                    spans[i] += widths[widthsIndex + j];
+                }
+                widthsIndex += colSpan;
+                currentOffset += spans[i];
+            }
+        }
+
+        protected void layoutMinorAxis(int targetSpan, int axis,
+                                       int[] offsets, int[] spans) {
+            for (int viewIndex = 0; viewIndex < getViewCount(); viewIndex++) {
+                int rowSpan = getRowSpan(getView(viewIndex));
+                offsets[viewIndex] = 0;
+                if (rowSpan == 1) {
+                    spans[viewIndex] = (int)getView(viewIndex).getPreferredSpan(axis);
+                } else {
+                    spans[viewIndex] = targetSpan;
+                }
+            }
+        }
+
+        public int getColumnSpan(final int viewIndex) {
+            String strSpan = (String)getView(viewIndex).getElement().getAttributes()
+                .getAttribute(HTML.Attribute.COLSPAN);
+            return strSpan == null ? 1 : Integer.parseInt(strSpan);
+        }
+
+        public int getMaxRowSpan() {
+            int maxRowSpan = 1;
+            for (int viewIndex = 0; viewIndex < getViewCount(); viewIndex++) {
+                maxRowSpan = Math.max(maxRowSpan, getRowSpan(getView(viewIndex)));
+            }
+
+            return maxRowSpan;
+        }
+
+        private int getRowSpan(final View v) {
+            String strSpan = (String)v.getElement().getAttributes()
+                .getAttribute(HTML.Attribute.ROWSPAN);
+            return strSpan == null ? 1 : Integer.parseInt(strSpan);
+        }
+
+        public int getColumnCount() {
+            int count = 0;
+            for (int i = 0; i < getViewCount(); i++) {
+                count += getColumnSpan(i);
+            }
+            count += isColumnOccupied.cardinality();
+            return count;
+        }
+
+        public void setColumnOccupied(final int column) {
+            isColumnOccupied.set(column);
+        }
+
+        public boolean isColumnOccupied(final int column) {
+            return isColumnOccupied.get(column);
+        }
+
+        public int[] updateRowMarkup(final int[] prevRowRowSpans) {
+            isColumnOccupied.clear();
+
+            int col = 0;
+            int[] spans = prevRowRowSpans;
+            for (int viewIndex = 0; viewIndex < getViewCount(); viewIndex++) {
+                spans = enshureCapacity(spans, col + 1);
+                boolean occupied = spans[col] > 0;
+                if (occupied) {
+                    setColumnOccupied(col);
+                    spans[col]--;
+                } else {
+                    int rowSpan = getRowSpan(getView(viewIndex));
+                    int colSpan = getColumnSpan(viewIndex);
+                    enshureCapacity(spans, col + colSpan);
+                    for (; colSpan > 0; colSpan--) {
+                        if (rowSpan > 1) {
+                            spans[col] = rowSpan - 1;
+                        }
+                    }
+                }
+
+                col++;
+            }
+
+            return spans;
+        }
+
+        private int[] enshureCapacity(final int[] arr, final int len) {
+            if (len > arr.length) {
+                int[] newArr = new int[len + 16];
+                System.arraycopy(arr, 0, newArr, 0, arr.length);
+                return newArr;
+            }
+            return arr;
+        }
+    }
+
+    private class TableCellView extends BlockView {
+        private AttributeSet attrs;
+
+        public TableCellView(final Element elem) {
+            super(elem, Y_AXIS);
+        }
+
+        public AttributeSet getAttributes() {
+            if (attrs == null) {
+                attrs = new CompositeAttributeSet(
+                    super.getAttributes(), getAdditionalCellAttrs());
+            }
+            return attrs;
+        }
+
+        public void changedUpdate(final DocumentEvent e, final Shape s,
+                                  final ViewFactory f) {
+            attrs = null;
+            super.changedUpdate(e, s, f);
+        }
+    }
+
+    // THEAD, TFOOT, TBODY are not supported
+    private static class RowViewIterator {
+        private View currentParent;
+        private TableRowView currentRowView;
+        private int currentIndex;
+
+        public RowViewIterator(final View root) {
+            currentParent = root;
+            next();
+        }
+
+        public boolean isValid() {
+            return currentRowView != null;
+        }
+
+         public void next() {
+            while (currentIndex < currentParent.getViewCount()) {
+                if (currentParent.getView(currentIndex) instanceof TableRowView) {
+                    currentRowView = (TableRowView)currentParent.getView(currentIndex);
+                    currentIndex++;
+                    return;
+                }
+                currentIndex++;
+            }
+
+            if (currentIndex >= currentParent.getViewCount()) {
+                currentRowView = null;
+            }
+        }
+
+        public TableRowView getView() {
+            return currentRowView;
+        }
+    }
+
+    public TableTagView(final Element elem) {
+        super(elem, Y_AXIS);
+    }
+
+    public View create(final Element elem) {
+        HTML.Tag tag = HTMLEditorKit.getHTMLTagByElement(elem);
+
+        if (HTML.Tag.TR.equals(tag)) {
+            return createTableRow(elem);
+        } else if (HTML.Tag.TD.equals(tag) || HTML.Tag.TH.equals(tag)) {
+            return createTableCell(elem);
+        } else if (HTML.Tag.CAPTION.equals(tag)) {
+            return new BlockView(elem, BlockView.Y_AXIS);
+        } else if (HTML.Tag.COLGROUP.equals(tag)) {
+            return new InvisibleTagView(elem);
+        } else if (HTML.Tag.COL.equals(tag)) {
+            return new InvisibleTagView(elem);
+        }
+
+        return super.getViewFactory().create(elem);
+    }
+
+    public void changedUpdate(final DocumentEvent e, final Shape s,
+                              final ViewFactory f) {
+        cachedAttributes = null;
+        super.changedUpdate(e, s, f);
+    }
+
+    public AttributeSet getAttributes() {
+        if (cachedAttributes == null) {
+            cachedAttributes = new CompositeAttributeSet(
+                super.getAttributes(), getAdditionalTableAttrs());
+        }
+
+        return cachedAttributes;
+    }
+
+    public ViewFactory getViewFactory() {
+        return this;
+    }
+
+    public void preferenceChanged(View child, boolean width, boolean height) {
+        areColumnSizeRequirementsValid = false;
+
+        super.preferenceChanged(this, width, height);
+
+        for (int i = 0; i < getViewCount(); i++) {
+            if (getView(i) instanceof BoxView) {
+                ((BoxView)getView(i)).layoutChanged(X_AXIS);
+            }
+        }
+    }
+
+    protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets, int[] spans) {
+        super.layoutMajorAxis(targetSpan, axis, offsets, spans);
+        int row = 0;
+
+        for (RowViewIterator rowIt = new RowViewIterator(this); rowIt.isValid();
+                rowIt.next()) {
+            int maxRowSpan = rowIt.getView().getMaxRowSpan();
+            maxRowSpan = Math.min(maxRowSpan - 1, spans.length - row);
+            for (; maxRowSpan > 0; maxRowSpan--) {
+                spans[row] += spans[row + maxRowSpan];
+            }
+
+            row++;
+        }
+    }
+
+    protected void forwardUpdate(ElementChange change, DocumentEvent event, Shape shape, ViewFactory factory) {
+        boolean xValid = isLayoutValid(X_AXIS);
+
+        super.forwardUpdate(change, event, shape, factory);
+
+        if (xValid && !isLayoutValid(X_AXIS)) {
+            Rectangle rc = shape.getBounds();
+            getContainer().repaint(rc.x, rc.y, ((BoxView)getParent()).getWidth(), rc.height);
+        }
+    }
+
+    protected TableRowView createTableRow(final Element elem) {
+        return new TableRowView(elem);
+    }
+
+    protected TableCellView createTableCell(final Element elem) {
+        return new TableCellView(elem);
+    }
+
+    protected SizeRequirements calculateMajorAxisRequirements(
+            final int axis, final SizeRequirements r) {
+        SizeRequirements size = super.calculateMajorAxisRequirements(axis, r);
+        size.maximum = size.preferred;
+        return size;
+    }
+
+    protected SizeRequirements calculateMinorAxisRequirements(
+            final int axis, final SizeRequirements r) {
+        areColumnSizeRequirementsValid = isLayoutValid(X_AXIS);
+        SizeRequirements size = super.calculateMinorAxisRequirements(axis, r);
+        size.maximum = size.preferred;
+        return size;
+    }
+
+    int getCaptionHeight() {
+        View captionView = getView(0);
+        if (captionView != null && HTML.Tag.CAPTION.equals
+                (HTMLEditorKit.getHTMLTagByElement(captionView.getElement()))) {
+            return (int)captionView.getPreferredSpan(Y_AXIS);
+        }
+        return 0;
+    }
+
+    private int getColumnCount() {
+        if (!areColumnSizeRequirementsValid) {
+            updateRowViewColumnOccupied();
+        }
+
+        int count = 0;
+        for (RowViewIterator rowIt = new RowViewIterator(this);
+                rowIt.isValid(); rowIt.next()) {
+            count = Math.max(count, rowIt.getView().getColumnCount());
+        }
+        return count;
+    }
+
+    private void updateRowViewColumnOccupied() {
+        int[] rowSpans = new int[1];
+
+        for (RowViewIterator rowIt = new RowViewIterator(this); rowIt.isValid();
+                rowIt.next()) {
+            rowSpans = rowIt.getView().updateRowMarkup(rowSpans);
+        }
+    }
+
+    /*
+     * This function is based on the autolayout algorithm described here:
+     * http://www.w3.org/TR/html4/appendix/notes.html#h-B.5.2
+     */
+    private int[] getColumnWidths() {
+//        if (isLayoutValid(X_AXIS)) {
+//            return columnWidths;
+//        }
+
+        int columnCount = getColumnCount();
+        if (columnCount > columnWidths.length) {
+            columnWidths = new int[columnCount];
+        }
+
+        SizeRequirements[] sizes = calculateColumnSizeRequirements();
+        int minTableWidth = 0;
+        int maxTableWidth = 0;
+        for (int col = 0; col < getColumnCount(); col++) {
+            columnWidths[col] = sizes[col].minimum;
+            minTableWidth += columnWidths[col];
+            maxTableWidth += sizes[col].maximum;
+        }
+
+        int delta = maxTableWidth - minTableWidth;
+
+        if (delta > 0) {
+            for (int col = 0; col < getColumnCount(); col++) {
+                columnWidths[col] += (double)(sizes[col].maximum - columnWidths[col])
+                    / (double)delta
+                    * (double)(getWidth() - minTableWidth);
+            }
+        }
+
+        return columnWidths;
+    }
+
+    private SizeRequirements[] calculateColumnSizeRequirements() {
+        if (areColumnSizeRequirementsValid) {
+            return columnSizeRequirements;
+        }
+
+        int columnCount = getColumnCount();
+        if (columnSizeRequirements.length < columnCount) {
+            SizeRequirements[] oldSizeReqs = columnSizeRequirements;
+            columnSizeRequirements = new SizeRequirements[columnCount];
+            System.arraycopy(oldSizeReqs, 0, columnSizeRequirements, 0,
+                             oldSizeReqs.length);
+        }
+
+        for (int col = 0; col < columnCount; col++) {
+            if (columnSizeRequirements[col] == null) {
+                columnSizeRequirements[col] = new SizeRequirements();
+            } else {
+                columnSizeRequirements[col].minimum = 0;
+                columnSizeRequirements[col].maximum = 0;
+                columnSizeRequirements[col].preferred = 0;
+            }
+        }
+
+        for (RowViewIterator rowIt = new RowViewIterator(this); rowIt.isValid(); rowIt.next()) {
+            int spansCount = 0;
+            TableRowView rowView = rowIt.getView();
+            for (int col = 0; col < rowView.getViewCount(); col++) {
+                while (rowView.isColumnOccupied(col + spansCount)) {
+                    spansCount++;
+                }
+                int colSpan = rowView.getColumnSpan(col);
+                for (int i = 0; i < colSpan; i++) {
+                    joinSizeRequirements(columnSizeRequirements[col + spansCount + i],
+                        (int)rowView.getView(col).getMinimumSpan(X_AXIS) / colSpan,
+                        (int)rowView.getView(col).getPreferredSpan(X_AXIS) / colSpan,
+                        (int)rowView.getView(col).getMaximumSpan(X_AXIS) / colSpan);
+                }
+                spansCount += colSpan - 1;
+            }
+        }
+
+        areColumnSizeRequirementsValid = true;
+        return columnSizeRequirements;
+    }
+
+    private void joinSizeRequirements(final SizeRequirements size, final int min,
+                                      final int pref, final int max) {
+        size.minimum = Math.max(size.minimum, min);
+        size.preferred = Math.max(size.preferred, pref);
+
+        if (size.maximum > 0) {
+            size.maximum = Math.min(size.maximum, max);
+        } else {
+            size.maximum = Math.max(size.maximum, max);
+        }
+        // getColumnWidths() fails without this
+        size.maximum = Math.min(size.maximum, Short.MAX_VALUE);
+    }
+
+    private Object getCellSpacingAttr() {
+        Object cellSpacing = getElement().getAttributes()
+            .getAttribute(HTML.Attribute.CELLSPACING);
+        if (cellSpacing == null) {
+            cellSpacing = "1";
+        }
+        return FloatValue.factory.toCSS(Float.valueOf((String)cellSpacing));
+    }
+
+    private AttributeSet getAdditionalCellAttrs() {
+        SimpleAttributeSet attrs = new SimpleAttributeSet();
+
+        Object v = getCellSpacingAttr();
+        if (v != null) {
+            attrs.addAttribute(CSS.Attribute.MARGIN_LEFT, v);
+            attrs.addAttribute(CSS.Attribute.MARGIN_TOP, v);
+        }
+
+        v = getElement().getAttributes().getAttribute(HTML.Attribute.BORDER);
+        if (v != null) {
+            getStyleSheet().addCSSAttribute(attrs, CSS.Attribute.BORDER, "inset 1px");
+        }
+        return attrs;
+    }
+
+    private AttributeSet getAdditionalTableAttrs() {
+        SimpleAttributeSet attrs = new SimpleAttributeSet();
+
+        Object v = getCellSpacingAttr();
+        if (v != null) {
+            attrs.addAttribute(CSS.Attribute.PADDING_RIGHT, v);
+            attrs.addAttribute(CSS.Attribute.PADDING_BOTTOM, v);
+        }
+
+        v = getElement().getAttributes().getAttribute(HTML.Attribute.BORDER);
+        if (v instanceof String) {
+            String strValue = (String)v;
+            getStyleSheet().addCSSAttribute(attrs, CSS.Attribute.BORDER,
+                                            "inset " + strValue + "pt");
+        }
+        return attrs;
+    }
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/TagIterator.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/TagIterator.java?rev=427121&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/TagIterator.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/TagIterator.java Mon Jul 31 07:08:47 2006
@@ -0,0 +1,70 @@
+/*
+ *  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+* @author Alexander T. Simbirtsev
+* @version $Revision$
+*/
+package javax.swing.text.html;
+
+import javax.swing.text.AttributeSet;
+import javax.swing.text.Document;
+import javax.swing.text.Element;
+import javax.swing.text.ElementIterator;
+import javax.swing.text.html.HTML.Tag;
+import javax.swing.text.html.HTMLDocument.Iterator;
+
+class TagIterator extends Iterator {
+
+    private final Tag tag;
+    private final ElementIterator it;
+    private Element current;
+
+    public TagIterator(final Tag tag, final Document document) {
+        this.tag = tag;
+        it = new ElementIterator(document);
+        next();
+    }
+
+    public AttributeSet getAttributes() {
+        return (current != null) ? current.getAttributes() : null;
+    }
+
+    public int getEndOffset() {
+        return (current != null) ? current.getEndOffset() : -1;
+    }
+
+    public int getStartOffset() {
+        return (current != null) ? current.getStartOffset() : -1;
+    }
+
+    public Tag getTag() {
+        return tag;
+    }
+
+    public boolean isValid() {
+        return (current != null);
+    }
+
+    public void next() {
+        current = it.next();
+        while (current != null) {
+            if (tag.toString().equals(current.getName())) {
+                break;
+            }
+            current = it.next();
+        }
+    }
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/ViewAttributeSet.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/ViewAttributeSet.java?rev=427121&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/ViewAttributeSet.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/ViewAttributeSet.java Mon Jul 31 07:08:47 2006
@@ -0,0 +1,98 @@
+/*
+ *  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Alexey A. Ivanov
+ * @version $Revision$
+ */
+package javax.swing.text.html;
+
+import javax.swing.text.AttributeSet;
+import javax.swing.text.Element;
+import javax.swing.text.View;
+import javax.swing.text.html.CSS.RelativeValueResolver;
+
+class ViewAttributeSet extends CompositeAttributeSet {
+    final View view;
+
+    ViewAttributeSet(final StyleSheet ss, final View view) {
+        super(calculateElementAttr(ss, view),
+              calculateCSSRules(ss, view));
+        this.view = view;
+    }
+
+    public AttributeSet getResolveParent() {
+        final View parent = view.getParent();
+        return parent != null ? parent.getAttributes() : null;
+    }
+
+    public Object getAttribute(final Object key) {
+        if (key == ResolveAttribute) {
+            return getResolveParent();
+        }
+
+        Object result = getElementAttr().getAttribute(key);
+        if (result != null) {
+            return result;
+        }
+
+        if (getCssRules().getAttributeCount() > 0) {
+            result =
+                ((CascadedStyle)getCssRules()).getAttribute(key, view.getElement());
+            if (result != null) {
+                return result;
+            }
+        }
+
+        final AttributeSet resolver = getResolveParent();
+        if (resolver == null) {
+            return null;
+        }
+
+        if (key instanceof CSS.Attribute) {
+            CSS.Attribute cssKey = (CSS.Attribute)key;
+            if (cssKey.isInherited()) {
+                result = resolver.getAttribute(key);
+                if (result instanceof RelativeValueResolver) {
+                    return ((RelativeValueResolver)result)
+                           .getComputedValue(view.getParent());
+                }
+                return result;
+            }
+            return null;
+        }
+        return resolver.getAttribute(key);
+    }
+
+    private static AttributeSet calculateElementAttr(final StyleSheet ss,
+                                                     final View view) {
+        final Element element = view.getElement();
+        return ss.translateHTMLToCSS(element.getAttributes());
+    }
+
+    private static AttributeSet calculateCSSRules(final StyleSheet ss,
+                                                  final View view) {
+        HTML.Tag tag = SelectorMatcher.getTag(view.getElement());
+        return tag != null ? ss.getRule(tag, view.getElement()) : ss.getEmptySet();
+    }
+
+    private AttributeSet getElementAttr() {
+        return getPrimarySet();
+    }
+
+    private AttributeSet getCssRules() {
+        return getSecondarySet();
+    }
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/default.css
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/default.css?rev=427121&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/default.css (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/default.css Mon Jul 31 07:08:47 2006
@@ -0,0 +1,88 @@
+/*
+  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+*/
+/*
+ * @author Vadim L. Bogdanov, Alexey A. Ivanov
+ * @version $Revision$
+ */
+
+body { 
+    font-family: serif;
+    font-size: 14pt;
+    padding: 0.5em;
+}
+
+h1, h2, h3, h4, h5, h6, p {
+    margin-top: 0.75em;
+}
+
+h1 {
+    font-size: x-large;
+    font-weight: bold;
+}
+
+h2 {
+    font-size: large;
+    font-weight: bold;
+}
+
+h3 {
+    font-weight: bold;
+}
+
+b, strong {
+    font-weight: bolder;
+}
+
+i, em {
+	font-style: italic;
+}
+
+ol {
+    list-style-type: decimal;
+    padding-left: 40px;
+    margin-top: 0.25em;
+}
+
+ul {
+    list-style-type: disc;
+    padding-left: 40px;
+    margin-top: 0.25em;
+}
+
+a {
+    color: blue;
+    text-decoration: underline
+}
+
+code, tt, pre, kbd {
+	font-family: monospace;
+}
+
+th {
+    font-weight: bold;
+}
+
+td, th {
+    padding: 1px 2px;
+}
+
+small {
+    font-size: smaller;
+}
+
+big {
+    font-size: larger;
+}
\ No newline at end of file

Added: incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/AttributeList.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/AttributeList.java?rev=427121&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/AttributeList.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/AttributeList.java Mon Jul 31 07:08:47 2006
@@ -0,0 +1,188 @@
+/*
+ *  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Evgeniya G. Maenkova
+ * @version $Revision$
+ */
+package javax.swing.text.html.parser;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Vector;
+
+public final class AttributeList implements DTDConstants, Serializable {
+    public String name;
+
+    public int type;
+
+    public Vector values;
+
+    public int modifier;
+
+    public String value;
+
+    public AttributeList next;
+    //TODO It need check type FIXED, IMPLIED, REQUIRED?
+    public AttributeList(final String name,
+                         final int type,
+                         final int modifier,
+                         final String value,
+                         final Vector values,
+                         final AttributeList next) {
+        this.name = name;
+        this.type = type;
+        this.modifier = modifier;
+        this.value = value;
+        this.values = values;
+        this.next = next;
+    }
+
+    public static String type2name(final int type) {
+        init();
+        return type < names.length ? names[type] : null;
+    }
+
+    public static int name2type(final String name) {
+        init();
+        for (int i = 0; i < names.length; i++) {
+                if (name.equals(names[i])) {
+                    return i;
+                }
+        }
+        return 1;
+    }
+
+    static int nameToModifier(final String name) {
+        if ("#IMPLIED".equals(name)) {
+            return DTDConstants.IMPLIED;
+        } else if ("#REQUIRED".equals(name)) {
+            return DTDConstants.REQUIRED;
+        } else if ("#FIXED".equals(name)) {
+            return DTDConstants.FIXED;
+        } else {
+            return DTDConstants.DEFAULT;
+        }
+    }
+
+    static String modifierToName(final int modifier) {
+        if (modifier == DTDConstants.IMPLIED) {
+            return "#IMPLIED";
+        } else if (modifier == DTDConstants.REQUIRED) {
+            return "#REQUIRED";
+        } else if (modifier == DTDConstants.FIXED) {
+            return "#FIXED";
+        } else {
+            return "#DEFAULT";
+        }
+    }
+
+    public AttributeList(final String name) {
+        this.name = name;
+    }
+
+
+    AttributeList() {
+    }
+
+    public String toString() {
+        return "AttributeList["
+               + "name=" + name + ", "
+               + "type=" + type + ", "
+               + "modifier=" + modifier + ", "
+               + "value=" + value + ", "
+               + "values=" + values + ", "
+               + "next=" + next + "]";
+    }
+
+    final String paramString() {
+        //name type modifier,next.name next.type next.modifier
+        String name = this.name;
+        String type = values == null ? type2name(this.type) : valuesToString();
+        String modifier = modifierToName(this.modifier);
+        modifier = "#DEFAULT".equals(modifier) ? value : modifier;
+        String result = name + " " + type + " " + modifier;
+        return next == null ? result : result + "," + next.paramString();
+    }
+
+    final String valuesToString() {
+        if (values != null) {
+            String result = "";
+            for (int i = 0; i < values.size(); i++) {
+                result += "|" + values.get(i);
+            }
+            return result.substring(1, result.length());
+        }
+        return null;
+    }
+
+    public AttributeList getNext() {
+        return next;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public Enumeration getValues() {
+        return values.elements();
+    }
+
+    public int getModifier() {
+        return modifier;
+    }
+
+    public int getType() {
+        return type;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    private static String[] names;
+
+    private static void init() {
+        if (names == null) {
+            names = new String[] {null,
+                                  "CDATA",
+                                  "ENTITY",
+                                  "ENTITIES",
+                                  "ID",
+                                  "IDREF",
+                                  "IDREFS",
+                                  "NAME",
+                                  "NAMES",
+                                  "NMTOKEN",
+                                  "NMTOKENS",
+                                  "NOTATION",
+                                  "NUMBER",
+                                  "NUMBERS",
+                                  "NUTOKEN",
+                                  "NUTOKENS"
+                                  };
+        }
+    }
+
+    //TODO correct a bit: Do we check an instance or just equals?
+    final boolean containsValue(final String value) {
+        if (value == this.value) {
+            return true;
+        }
+
+        return values.contains(value);
+    }
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/ContentModel.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/ContentModel.java?rev=427121&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/ContentModel.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/ContentModel.java Mon Jul 31 07:08:47 2006
@@ -0,0 +1,340 @@
+/*
+ *  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Evgeniya G. Maenkova
+ * @version $Revision$
+ */
+package javax.swing.text.html.parser;
+
+import java.io.Serializable;
+import java.util.Vector;
+
+/**
+ *
+ * Element's content representation. That's unary or binary expression.
+ * Operands can be null (matched with null object), instance of Element,
+ * instance of ContentType.
+ * Valid operations can be unary operations (types):
+ * 1)'+' - (e+) - e must occur one or more times;
+ * 2)'*' - (e*) - e must occur zero or more times;
+ * 3)'?' - (e?) - e must occur zero or one time;
+ * 4)(0) - (e) - e must occur one time only
+ * and binary operations (types):
+ * 1)'|' - (e1|e2) means either e1 or e2 must occur, but not both;
+ * 2)',' - (e1,e2) means both A and B must occur, in that order;
+ * 3)'&' - (e1 & e2) means both e1 and e2 must occur, in any order *
+ * (Operation interpretation corresponds to HTML 4.01 Specification (3.3.3))
+ * As content model is using for dtd presentation here is some ambiguity
+ * what null object can be matched with. So null shouldn't be passed to
+ * constructor.
+ *    No resursion is allowed.
+ *    Content, next, type fields has the following limitation:
+ *    1) if type is one from {'+', '*', '?'} content hasn't to be null;
+ *    2) if type is one from {'|', ',', '&'} content and next have not to be
+ *       null;
+ *    3) content can be null if and only if type is 0;
+ *    4) content can be null, instance of Element or instance of ContentModel;
+ *    5) type can be one from the following '*', '+', '?', '|', '&', ','.
+ */
+
+public final class ContentModel implements Serializable {
+    public int type;
+
+    public Object content;
+
+    public ContentModel next;
+
+    private static final char DEFAULT_TYPE = 0;
+    private static final char PLUS_TYPE = '+';
+    private static final char STAR_TYPE = '*';
+    private static final char QUESTION_TYPE = '?';
+    private static final char LINE_TYPE = '|';
+    private static final char COMMA_TYPE = ',';
+    private static final char AMPER_TYPE = '&';
+
+    /**
+     * @throws IllegalArgumentException in the following cases:
+     * 2) content model isn't instance of Element or Content Model
+     *    (in particular, content equals to null);
+     * 3) types isn't binary type mentioned above;
+     * 4) next equals to null.
+     */
+    public ContentModel(final int type,
+                        final Object content,
+                        final ContentModel next) {
+         checkBinaryType(type);
+         checkObjectParameter(content);
+         checkObjectParameter(next);
+         this.type = type;
+         this.content = content;
+         this.next = next;
+    }
+
+    /**
+     * @throws IllegalArgumentException in the following cases:
+     * 1) type isn't unary type;
+     * 2) next equals to null
+     */
+
+    public ContentModel(final int type,
+                        final ContentModel content) {
+        checkObjectParameter(content);
+        checkUnaryType(type);
+        this.type = type;
+        this.content = content;
+    }
+
+    /**
+     * That content model will be mathed with exactly one element.
+     * Type will be 0.
+     * Element can be equals to null. in such case contentModel will be matched
+     * with an empty input stream.
+     */
+    public ContentModel(final Element element) {
+        content = element;
+    }
+
+    public ContentModel() {
+    }
+
+    public String toString() {
+        if (type == DEFAULT_TYPE) {
+            return content == null ? "null" : ((Element)content).getName();
+        } else if (isUnaryType(type)) {
+            ContentModel content = (ContentModel)this.content;
+            boolean need = !(content.content instanceof Element
+               && isExtUnaryType(content.type));
+            return getBracket("(", need) + content.toString()
+                + getBracket(")", need) + (char)type;
+        } else {
+           String contentToString = content instanceof Element
+               ? ((Element)content).getName() : content.toString();
+           boolean needLeft = (content instanceof ContentModel)
+              && ((ContentModel)content).type != type
+              && isBinaryType(((ContentModel)content).type);
+           boolean needRight = next != null && next.type != type
+               && isBinaryType(next.type);
+           return getBracket("(", needLeft) + contentToString
+               + getBracket(")", needLeft)
+               + (char) type
+               + getBracket("(", needRight) + next + getBracket(")", needRight);
+        }
+    }
+
+    private String getBracket(final String s, final boolean need) {
+        return need ? s : "";
+    }
+
+    /**
+     *
+     * @return first Element from 'next' contentModel. if type equals one of
+     * unary operations that'll be null.
+     */
+    public Element first() {
+        return isExtUnaryType(type) || next == null ? null
+                : next.getFirstElement();
+    }
+
+    private Element getFirstElement() {
+
+        if (content == null) {
+            return null;
+        }
+        return content instanceof Element ? (Element)content
+                : ((ContentModel)content).getFirstElement();
+    }
+
+
+    /**
+     * @return
+     * 1) Returns true if token is null or equals to content or this content
+     *    model equals to token;
+     * 2) if type equals to 0 return true if token equals to content and false
+     *    otherwise;
+     * 3) If type is one from the unary types returns false if token isn't
+     *    istance of Element or ContentModel. Otherwise, returns true if and
+     *    only if one of the following conditions is true:
+     *    a) content is instance of Element, token is instance of Element and
+     *       token equals to content
+     *    b) content is instance of ContentModel, token is instance of Element
+     *       and content.first(token) returns true;
+     *    c) content is instance of Element and token is instance of
+     *       ContentModel, token.type equals to 0 and content equals to
+     *       token.content;
+     *    d) content is instance of ContentModel, token is instance of
+     *       ContentModel and content.first(token) returns true;
+     * 4) If type is one from binary types then:
+     *    a) if content instance of Element and content equals to token returns
+     *       true;
+     *    b) if content instance of ContentModel and content.first(token)
+     *       equals to true, then returns true
+     *    c) if content.first(token) equals to true returns true;
+     *    d) if type equals to ',' returns true if and only if content is
+     *       instance of ContentModel and content.empty() && next.first(token)
+     *       equals to true.
+     *    e) if type equals to '| or '&' returns next.first(token).
+     *
+     */
+
+    public boolean first(final Object token) {
+        if (token == null || token.equals(content) || equals(token)) {
+            return true;
+        }
+        if (type == DEFAULT_TYPE) {
+            return token.equals(content);
+        } else if (isUnaryType(type)) {
+            return canBeFirstInContent(token);
+        } else if (isBinaryType(type)) {
+            boolean contentIsModel = content instanceof ContentModel;
+            boolean contentIsElement = content instanceof Element;
+            if ((contentIsModel && ((ContentModel)content).first(token))
+                || (contentIsElement && content.equals(token))) {
+                return true;
+            }
+            switch (type) {
+            case COMMA_TYPE:
+                return  (contentIsModel && ((ContentModel)content).empty())
+                    && next.first(token);
+            case LINE_TYPE:
+            case AMPER_TYPE:
+                return next.first(token);
+            default:
+                return false;
+            }
+        } else  {
+            return false;
+        }
+    }
+
+    private boolean canBeFirstInContent(final Object token) {
+        boolean contentIsElement = contentIsElement();
+        boolean tokenIsElement = token instanceof Element;
+        boolean tokenIsModel = token instanceof ContentModel;
+        if (!tokenIsElement && !tokenIsModel) {
+            return false;
+        }
+
+        boolean contentIsModel = !contentIsElement;
+        return (contentIsElement && tokenIsElement && token.equals(content))
+           || (contentIsModel && tokenIsElement
+               && ((ContentModel)content).first(token))
+           || (contentIsElement && tokenIsModel
+               && ((ContentModel)token).type == 0
+               && content.equals(((ContentModel)token).content))
+           || (contentIsModel && tokenIsModel
+               && ((ContentModel)content).first(token));
+
+    }
+
+
+    /**
+     * Adds all elements of this contentModel to elemVec ignoring operations
+     * between elements. For instance, for ((a+)| ((b*),(c?))) elements a,b,c
+     * will be added to the elemVec.
+     * It supposes that elemVec isn't null.
+     * If content is null, nothing will be added to elemVec.
+     */
+
+    public void getElements(final Vector elemVec) {
+        if (content instanceof Element) {
+            elemVec.add(content);
+        } else if (content != null) {
+            ((ContentModel)content).getElements(elemVec);
+        }
+        if (next != null) {
+            next.getElements(elemVec);
+        }
+    }
+
+    /**
+     * @return: true if and only if some of the conditions is true:
+     * 1)type equals to 0 and content equals to null;
+     * 2)type equals to '*' or '?';
+     * 3)if type equals to '|' one of the following conditions is true:
+     *    a) content is instance of ContentModel and could match an empty input
+     *       stream;
+     *    b) next could match an empty input stream;
+     * 4)if type equals to ',' or '&' both conditions are true:
+     *    a) content is instance of ContentModel and could match an empty input
+     *       stream;
+     *    b) next could match an empty input stream;
+     */
+    public boolean empty() {
+        switch (type) {
+        case DEFAULT_TYPE:
+            return content == null;
+        case STAR_TYPE:
+        case QUESTION_TYPE:
+            return true;
+        case PLUS_TYPE:
+            return false;
+        case LINE_TYPE:
+            return (!contentIsElement() && ((ContentModel)content).empty())
+            || next.empty();
+        case AMPER_TYPE:
+        case COMMA_TYPE:
+            return !contentIsElement() && ((ContentModel)content).empty()
+            && next.empty();
+        default:
+            return false;
+        }
+    }
+
+    private boolean isUnaryType(final int type) {
+        return type == STAR_TYPE || type == PLUS_TYPE || type == QUESTION_TYPE;
+    }
+
+    private boolean isExtUnaryType(final int type) {
+        return isUnaryType(type) || type == DEFAULT_TYPE;
+    }
+
+    private boolean isBinaryType(final int type) {
+        return type == LINE_TYPE || type == COMMA_TYPE || type == AMPER_TYPE;
+    }
+
+    private void checkBinaryType(final int type) {
+        if (!isBinaryType(type)) {
+            throw new IllegalArgumentException("Illegal type, must be "
+                                               + COMMA_TYPE + ", "
+                                               + LINE_TYPE + ", "
+                                               + AMPER_TYPE + "");
+        }
+    }
+
+    private void checkUnaryType(final int type) {
+        if (!isUnaryType(type)) {
+            throw new IllegalArgumentException("Illegal type, must be "
+                                               + STAR_TYPE + ", "
+                                               + PLUS_TYPE + ", "
+                                               + QUESTION_TYPE + "");
+        }
+    }
+
+    private void checkObjectParameter(final Object object) {
+        if (!(object instanceof Element || object instanceof ContentModel)) {
+            throw new IllegalArgumentException("Object have to be instance "
+                    + "of Element or ContentModel and not null");
+        }
+    }
+
+    private boolean contentIsElement() {
+        return isElement(content);
+    }
+
+    private boolean isElement(final Object obj) {
+        return obj instanceof Element;
+    }
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DTD.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DTD.java?rev=427121&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DTD.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DTD.java Mon Jul 31 07:08:47 2006
@@ -0,0 +1,382 @@
+/*
+ *  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Evgeniya G. Maenkova
+ * @version $Revision$
+ */
+package javax.swing.text.html.parser;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.BitSet;
+import java.util.Hashtable;
+import java.util.Vector;
+
+public class DTD implements DTDConstants {
+    public static final int FILE_VERSION = 1;
+
+    public String name;
+
+    public Vector elements = new Vector();
+
+    public Hashtable elementHash = new Hashtable();
+    public Hashtable entityHash = new Hashtable();
+
+    public final Element pcdata;
+    public final Element html;
+    public final Element meta;
+    public final Element base;
+    public final Element isindex;
+    public final Element head;
+    public final Element body;
+    public final Element applet;
+    public final Element param;
+    public final Element p;
+    public final Element title;
+
+    private static final Hashtable dtdHash = new Hashtable();
+
+    private static final String pattern = "(\\|)+";
+
+    /**
+     * Created DTD will not be pushed to DTD hash.
+     * @throws IllegalArgumentException if name equals to null
+     */
+    public static DTD getDTD(final String name) throws IOException {
+        checkName(name);
+        String key = name.toLowerCase();
+        Object dtd = dtdHash.get(key);
+        return dtd == null ? new DTD(name.toLowerCase()) : (DTD)dtd;
+    }
+
+    /**
+     *
+     * @throws IllegalArgumentException if dtd or name equal to null
+     */
+    public static void putDTDHash(final String name,
+                                  final DTD dtd) {
+        checkName(name);
+        checkValue(dtd);
+        dtdHash.put(name.toLowerCase(), dtd);
+    }
+
+    private static void checkName(final String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("Name must be not null");
+        }
+    }
+
+    private static void checkValue(final DTD dtd) {
+        if (dtd == null) {
+            throw new IllegalArgumentException("DTD must be not null");
+        }
+    }
+
+
+    protected DTD(final String name) {
+        //TODO may be it need change the order
+        this.name = name;
+
+        pcdata = createDefaultElement(HTMLConstants.PCDATA_ELEMENT_NAME, 0);
+        putElement(pcdata);
+
+        html = createDefaultElement(HTMLConstants.HTML_ELEMENT_NAME, 1);
+        putElement(html);
+
+        meta = createDefaultElement(HTMLConstants.META_ELEMENT_NAME, 2);
+        putElement(meta);
+
+        base = createDefaultElement(HTMLConstants.BASE_ELEMENT_NAME, 3);
+        putElement(base);
+
+        isindex = createDefaultElement(HTMLConstants.ISINDEX_ELEMENT_NAME, 4);
+        putElement(isindex);
+
+        head = createDefaultElement(HTMLConstants.HEAD_ELEMENT_NAME, 5);
+        putElement(head);
+
+        body = createDefaultElement(HTMLConstants.BODY_ELEMENT_NAME, 6);
+        putElement(body);
+
+        applet = createDefaultElement(HTMLConstants.APPLET_ELEMENT_NAME, 7);
+        putElement(applet);
+
+        param = createDefaultElement(HTMLConstants.PARAM_ELEMENT_NAME, 8);
+        putElement(param);
+
+        p = createDefaultElement(HTMLConstants.P_ELEMENT_NAME, 9);
+        putElement(p);
+
+        title = createDefaultElement(HTMLConstants.TITLE_ELEMENT_NAME, 10);
+        putElement(title);
+
+        putElement(createDefaultElement(HTMLConstants.STYLE_ELEMENT_NAME, 11));
+        putElement(createDefaultElement(HTMLConstants.LINK_ELEMENT_NAME, 12));
+        putElement(new Element(13, HTMLConstants.UNKNOWN_ELEMENT_NAME, false,
+                               true, null, null, EMPTY, null, null, null));
+
+        entityHash.put(HTMLConstants.SPACE_ENTITY_NAME,
+                       createDefaultEntity(HTMLConstants.SPACE_ENTITY_NAME,
+                                           " "));
+        entityHash.put(HTMLConstants.RS_ENTITY_NAME,
+                       createDefaultEntity(HTMLConstants.RS_ENTITY_NAME,
+                                           "\n"));
+        entityHash.put(HTMLConstants.RE_ENTITY_NAME,
+                       createDefaultEntity(HTMLConstants.RE_ENTITY_NAME,
+                                           "\r"));
+    }
+
+    private void putElement(final Element element) {
+        elements.add(element);
+        elementHash.put(element.getName(), element);
+    }
+
+
+    private Element createDefaultElement(final String name,
+                                         final int index) {
+        return new Element(index, name, false, false, null, null,
+                           ANY, null, null, null);
+    }
+
+    private Entity createDefaultEntity(final String name,
+                                       final String data) {
+        return new Entity(name, 0, data, true, false);
+    }
+
+    public void read(final DataInputStream stream) throws IOException {
+        ObjectInputStream is = new ObjectInputStream(stream);
+        try {
+            elementHash = (Hashtable)is.readObject();
+            elements = (Vector)is.readObject();
+            int size = is.readInt();
+            for (int i = 0; i < size; i ++) {
+                String name = (String)is.readObject();
+                int data = is.readInt();
+                DTDUtilities.handleEntity(this, name, data);
+            }
+            is.close();
+            updateFields();
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public String toString() {
+        return name;
+    }
+
+    protected ContentModel defContentModel(final int type,
+                                           final Object content,
+                                           final ContentModel next) {
+        return new ContentModel(type, content, next);
+    }
+
+    /**
+     *
+     * @param values attributes split by '|'
+     */
+    protected AttributeList defAttributeList(final String name,
+                                             final int type,
+                                             final int modifier,
+                                             final String value,
+                                             final String values,
+                                             final AttributeList next) {
+
+        return new AttributeList(name, type, modifier, value,
+                                 createAttributeNamesVector(values), next);
+    }
+
+    private Vector createAttributeNamesVector(final String values) {
+        if (values == null) {
+            return null;
+        }
+        Vector result = new Vector();
+        String[] tokens = values.split(pattern);
+        for (int i = 0; i < tokens.length; i++) {
+            String token = tokens[i];
+            if (!"".equals(token)) {
+               result.add(token);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * If element exists but doesn't correspond to this parameters, it will be
+     * updated.
+     */
+    protected Element defElement(final String name,
+                                 final int type,
+                                 final boolean oStart,
+                                 final boolean oEnd,
+                                 final ContentModel content,
+                                 final String[] exclusions,
+                                 final String[] inclusions,
+                                 final AttributeList atts) {
+        return defineElement(name, type, oStart, oEnd, content,
+                             createBitSetByStrings(exclusions),
+                             createBitSetByStrings(inclusions),
+                             atts);
+
+    }
+
+    private BitSet createBitSetByStrings(final String[] names) {
+        if (names == null) {
+            return null;
+        }
+        BitSet result = new BitSet();
+        for (int i = 0; i < names.length; i++) {
+            Element elem = (Element)elementHash.get(names[i]);
+            if (elem != null) {
+                result.set(elem.getIndex());
+            }
+        }
+
+        return result;
+    }
+
+    protected Entity defEntity(final String name,
+                               final int type,
+                               final String str) {
+        return defineEntity(name, type, str == null ? null : str.toCharArray());
+    }
+
+    public Entity defEntity(final String name,
+                            final int type,
+                            final int ch) {
+        return defineEntity(name, type, new char[] {(char)ch});
+    }
+
+    /**
+     * Updated attributes of corresponding element, if this one exists.
+     * Otherwise, new elements are created with these attributes and put to
+     * elementsHash.
+     */
+    public void defineAttributes(final String name,
+                                 final AttributeList atts) {
+        Object obj = elementHash.get(name);
+        Element elem;
+        if (obj == null) {
+            elem = createDefaultElement(name, elements.size());
+            putElement(elem);
+        } else {
+            elem = (Element)obj;
+        }
+        elem.atts = atts;
+    }
+
+    /**
+     * If element exists but doesn't correspond to this parameters, it will be
+     * updated.
+     */
+    public Element defineElement(final String name,
+                                 final int type,
+                                 final boolean omitStart,
+                                 final boolean omitEnd,
+                                 final ContentModel contentModel,
+                                 final BitSet exclusions,
+                                 final BitSet inclusions,
+                                 final AttributeList atts) {
+        Object obj = elementHash.get(name);
+        Element result;
+        if (obj == null) {
+            result = new Element(elements.size(), name, omitStart, omitEnd,
+                                 exclusions, inclusions, type, contentModel,
+                                 atts, null);
+            putElement(result);
+        } else {
+            result = (Element)obj;
+            result.updateElement(result.index, name, omitStart, omitEnd,
+                                 exclusions, inclusions, type, contentModel,
+                                 atts, null);
+        }
+        return result;
+    }
+
+    /**
+     * If entity with this name exists, it will not be updated.
+     */
+    public Entity defineEntity(final String name,
+                               final int type,
+                               final char[] data) {
+        Object obj = entityHash.get(name);
+        Entity result;
+        if (obj == null) {
+            result = new Entity(name, type, data);
+            entityHash.put(name, result);
+        } else {
+            result = (Entity)obj;
+        }
+        return result;
+    }
+
+    /**
+     *
+     * @return if index < 0 or elements.size() <= index returns null.
+     */
+    public Element getElement(final int index) {
+        return index >= 0 && index < elements.size() ? (Element)
+                elements.get(index) : null;
+    }
+
+    public Element getElement(final String name) {
+        Object obj = elementHash.get(name);
+        if (obj != null) {
+            return (Element)obj;
+        }
+        Element element = createDefaultElement(name, elements.size());
+        putElement(element);
+        return element;
+    }
+
+    public Entity getEntity(final int index) {
+        return null;
+    }
+
+    public Entity getEntity(final String name) {
+        return (Entity)entityHash.get(name);
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    private void replace(final Element elem) {
+        elementHash.put(elem.name, elem);
+        int index = elem.getIndex();
+        elements.setElementAt(elem, index);
+    }
+
+    private void updateField(final Element elem) {
+        elem.updateElement(getElement(elem.getName()));
+        replace(elem);
+    }
+
+    private void updateFields() {
+        updateField(pcdata);
+        updateField(html);
+        updateField(meta);
+        updateField(base);
+        updateField(isindex);
+        updateField(head);
+        updateField(body);
+        updateField(applet);
+        updateField(param);
+        updateField(p);
+        updateField(title);
+    }
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DTDConstants.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DTDConstants.java?rev=427121&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DTDConstants.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DTDConstants.java Mon Jul 31 07:08:47 2006
@@ -0,0 +1,93 @@
+/*
+ *  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Evgeniya G. Maenkova
+ * @version $Revision$
+ */
+package javax.swing.text.html.parser;
+
+public interface DTDConstants {
+    int CDATA = 1;
+
+    int ENTITY = 2;
+
+    int ENTITIES = 3;
+
+    int ID = 4;
+
+    int IDREF = 5;
+
+    int IDREFS = 6;
+
+    int NAME = 7;
+
+    int NAMES = 8;
+
+    int NMTOKEN = 9;
+
+    int NMTOKENS = 10;
+
+    int NOTATION = 11;
+
+    int NUMBER = 12;
+
+    int NUMBERS = 13;
+
+    int NUTOKEN = 14;
+
+    int NUTOKENS = 15;
+
+    int RCDATA = 16;
+
+    int EMPTY = 17;
+
+    int MODEL = 18;
+
+    int ANY = 19;
+
+    int FIXED = 1;
+
+    int REQUIRED = 2;
+
+    int CURRENT = 3;
+
+    int CONREF = 4;
+
+    int IMPLIED = 5;
+
+    int PUBLIC = 10;
+
+    int SDATA = 11;
+
+    int PI = 12;
+
+    int STARTTAG = 13;
+
+    int ENDTAG = 14;
+
+    int MS = 15;
+
+    int MD = 16;
+
+    int SYSTEM = 17;
+
+    int GENERAL = 65536;
+
+    int DEFAULT = 131072;
+
+    int PARAMETER = 262144;
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DTDUtilities.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DTDUtilities.java?rev=427121&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DTDUtilities.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DTDUtilities.java Mon Jul 31 07:08:47 2006
@@ -0,0 +1,261 @@
+/*
+ *  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Evgeniya G. Maenkova
+ * @version $Revision$
+ */
+package javax.swing.text.html.parser;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+class DTDUtilities implements DTDConstants {
+    static final String SPLIT_PATTERN = "\\|";
+    static final String REPLACE_PATTERN = " |\\(|\\)";
+    static void putAttribute(final Hashtable atts,
+                             final String name,
+                             final String value) {
+        if (name.indexOf("|") >= 0) {
+           String[] names = replaceAndSplit(name);
+           for (int i = 0; i < names.length; i++) {
+               putAttribute(atts, names[i], value);
+           }
+        } else {
+            atts.put(name, value);
+        }
+    };
+
+    static String[] replaceAndSplit(final String s) {
+        return s.replaceAll(REPLACE_PATTERN, "").split(SPLIT_PATTERN);
+    }
+
+    static void handleElement(final Object obj,
+                              final String name,
+                              final String descr,
+                              final Hashtable attrTable) {
+        //For testing
+        if (obj instanceof Hashtable) {
+            ((Hashtable)obj).put(name, descr);
+            return;
+        }
+        DTD dtd = (DTD)obj;
+        if (name.indexOf("|") >= 0) {
+            String[] names = replaceAndSplit(name);
+            for (int i = 0; i < names.length; i++) {
+                handleElement(dtd, names[i], descr, attrTable);
+            }
+         } else {
+             String[] splDescr = splitElementDescr(descr);
+             boolean oStart = isOmitTag(splDescr[0], true);
+             boolean oEnd = isOmitTag(splDescr[0], false);
+             ContentModel contentModel = createContentModel(dtd, splDescr[1]);
+             String[] exclusions = splitString(splDescr[2]);
+             String[] inclusions = splitString(splDescr[3]);
+             AttributeList atts =
+                 createAttributeList(dtd, (String)attrTable.get(name));
+             int type = getType(oEnd, splDescr[1]);
+             dtd.defElement(name, type, oStart, oEnd, contentModel,
+                            exclusions, inclusions, atts);
+        }
+    };
+
+    static int getType(final boolean oEnd, final String descr) {
+        if (descr.startsWith("EMPTY") && oEnd) {
+            return EMPTY;
+        } else if (descr.startsWith("CDATA")) {
+            return CDATA;
+        } else {
+            return MODEL;
+        }
+    }
+
+    static boolean isOmitTag(final String descr, final boolean isStart) {
+        return descr.charAt(isStart ? 0 : 2) == 'O';
+    }
+
+    static void handleEntity(final DTD dtd, final String name,
+                              final int value) {
+        Entity entity = new Entity(name, (char)value);
+        dtd.entityHash.put(name, entity);
+        dtd.entityHash.put(new Integer(value), entity);
+    }
+
+    static AttributeList createAttributeList(final DTD dtd, final String spec) {
+        String[] specs = spec.replaceAll("( )+", " ")
+            .replaceAll("( )*\\|( )*", "|").split(" ");
+        AttributeList result = null;
+        String values = "";
+        int modifier = 0;
+        for (int i = specs.length - 3; i >= 0; i -= 3) {
+            modifier = AttributeList.nameToModifier(specs[i + 2]);
+            values = specs[i + 1];
+            values = values.indexOf(")") >= 0
+               ? values.replaceAll("\\(|\\)", "") : null;
+            result = dtd.defAttributeList(specs[i + 0],
+                                      AttributeList.name2type(specs[i + 1]),
+                                      modifier,
+                                      modifier == DEFAULT ? specs[i + 2] : null,
+                                      values,
+                                      result);
+
+        }
+        return result;
+    }
+
+
+    static String[] splitString(final String s) {
+        return s == null ? null : s.split("\\|");
+    }
+
+    static boolean isBalanced(final String s) {
+        int count = 0;
+        for (int i = 0; i < s.length(); i++) {
+            char ch = s.charAt(i);
+            if (ch == ')' && count < 0) {
+                count++;
+            } else if (ch == '(') {
+                count--;
+            }
+        }
+        return count == 0;
+    }
+
+    static ContentModel createContentModel(final DTD dtd, final String descr) {
+        if (descr.startsWith("EMPTY") || descr.startsWith("CDATA")) {
+            return null;
+        }
+        int length = descr.length();
+        if (descr.matches("([a-zA-Z]|[0-9]|#)+")) {
+            return new ContentModel((Element)dtd.elementHash.get(descr));
+        } else if (descr.matches("\\((.)*\\)")
+                   && isBalanced(descr.substring(1, length - 1))) {
+            return createContentModel(dtd,
+                                      descr.substring(1, length - 1));
+        } else if (descr.matches("\\((.)+\\)[+*?]")
+                   || descr.matches("([a-zA-Z]|[0-9]|#)+[+|*|?]")) {
+            int index = length - 1;
+            return
+               new ContentModel(descr.charAt(index),
+                                createContentModel(dtd,
+                                                   descr.substring(0, index)));
+        } else {
+            int count = 0;
+            char ch = 0;
+            for (int i = descr.length() - 1; i >= 0; i--) {
+                ch = descr.charAt(i);
+                if ("|,&".indexOf(ch) >= 0 && count == 0) {
+                    count = i;
+                    break;
+                } else if (ch == ')') {
+                    count++;
+                } else if (ch == '(') {
+                    count--;
+                }
+
+            }
+            return
+               new ContentModel(ch,
+                               createContentModel(dtd,
+                                                  descr.substring(0, count)),
+                               createContentModel(dtd,
+                                                  descr.substring(count + 1,
+                                                                  length)));
+        }
+    }
+
+    static String[] splitElementDescr(final String descr) {
+        String tags = descr.substring(0, 3);
+        String allContent = descr.substring(4, descr.length());
+        allContent = allContent.replaceAll("( )+", "");
+        int incIndex = allContent.indexOf("+(");
+        int excIndex = allContent.indexOf("-(");
+        String content = "";
+        String exc = null;
+        String inc = null;
+
+        if (incIndex >= 0 && excIndex >= 0) {
+            if (incIndex > excIndex) {
+                inc = allContent.substring(incIndex, excIndex);
+                exc = allContent.substring(excIndex, allContent.length());
+                content = allContent.substring(0, incIndex);
+            } else {
+                inc = allContent.substring(excIndex, incIndex);
+                exc = allContent.substring(incIndex, allContent.length());
+                content = allContent.substring(0, excIndex);
+            }
+        } else if (incIndex >= 0) {
+            inc = allContent.substring(incIndex, allContent.length());
+            content = allContent.substring(0, incIndex);
+        } else if (excIndex >= 0) {
+            exc = allContent.substring(excIndex, allContent.length());
+            content = allContent.substring(0, excIndex);
+        } else {
+            content = allContent;
+        }
+        inc = inc == null ? null : inc.substring(2, inc.length() - 1);
+        exc = exc == null ? null : exc.substring(2, exc.length() - 1);
+        return new String[]{tags, content, exc, inc};
+    }
+
+
+    static void initDTD(final DTD dtd) {
+        EntitiesHandler.initEntitiesCreation(dtd);
+        ElementsHandler.initAttributes();
+        putAllElementsIntoHash(dtd);
+        ElementsHandler.initElementsCreation(dtd);
+    }
+
+    static void putAllElementsIntoHash(final DTD dtd) {
+        Iterator iter = ElementsHandler.atts.keySet().iterator();
+        while (iter.hasNext()) {
+            String name = (String)iter.next();
+            dtd.defElement(name, EMPTY, false, false, null, null, null, null);
+        }
+        dtd.defElement("#PCDATA", EMPTY, false, false, null, null, null, null);
+    }
+    //TODO Probably, don't suplicate information in elements vector
+    static void createBinaryDTD(final String fileName) {
+        try {
+           ObjectOutputStream os = new ObjectOutputStream(
+                                   new FileOutputStream(fileName));
+           DTD dtd = new DTD("tmp");
+           initDTD(dtd);
+           os.writeObject(dtd.elementHash);
+           os.writeObject(dtd.elements);
+           int size = dtd.entityHash.size();
+           os.writeInt((size - 3)/2);
+           Iterator iter = dtd.entityHash.keySet().iterator();
+           while (iter.hasNext()) {
+               Object key = iter.next();
+               if (key instanceof String
+                   && !key.equals("#SPACE")
+                   && !key.equals("#RS")
+                   && !key.equals("#RE")) {
+                   Entity entity = (Entity)dtd.entityHash.get(key);
+                   os.writeObject(key);
+                   os.writeInt(entity.data[0]);
+               }
+           }
+           os.flush();
+           os.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+}

Added: incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DocumentParser.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DocumentParser.java?rev=427121&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DocumentParser.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/DocumentParser.java Mon Jul 31 07:08:47 2006
@@ -0,0 +1,76 @@
+/*
+ *  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Evgeniya G. Maenkova
+ * @version $Revision$
+ */
+package javax.swing.text.html.parser;
+
+import java.io.IOException;
+import java.io.Reader;
+import javax.swing.text.ChangedCharSetException;
+import javax.swing.text.html.HTMLEditorKit;
+
+public class DocumentParser extends Parser {
+
+    public DocumentParser(final DTD a0) {
+        super(a0);
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+
+    protected void handleError(final int a0, final String a1) {
+        throw new UnsupportedOperationException("Not implemented");
+
+    }
+
+
+    protected void handleText(final char[] a0) {
+        throw new UnsupportedOperationException("Not implemented");
+
+    }
+
+
+    protected void handleEndTag(final TagElement a0) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+
+    protected void handleEmptyTag(final TagElement a0) throws ChangedCharSetException {
+        throw new UnsupportedOperationException("Not implemented");
+
+    }
+
+
+    protected void handleComment(final char[] a0) {
+        throw new UnsupportedOperationException("Not implemented");
+
+    }
+
+
+    protected void handleStartTag(final TagElement a0) {
+        throw new UnsupportedOperationException("Not implemented");
+
+    }
+
+
+    public void parse(final Reader a0, final HTMLEditorKit.ParserCallback a1, final boolean a2) throws IOException {
+        throw new UnsupportedOperationException("Not implemented");
+
+    }
+
+}
+

Added: incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/Element.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/Element.java?rev=427121&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/Element.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/swing/src/main/java/common/javax/swing/text/html/parser/Element.java Mon Jul 31 07:08:47 2006
@@ -0,0 +1,197 @@
+/*
+ *  Copyright 2005 - 2006 The Apache Software Software Foundation or its licensors, as applicable.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/**
+ * @author Evgeniya G. Maenkova
+ * @version $Revision$
+ */
+package javax.swing.text.html.parser;
+
+import java.io.Serializable;
+import java.util.BitSet;
+
+public final class Element implements DTDConstants, Serializable {
+    public int index;
+
+    public String name;
+
+    public boolean oStart;
+
+    public boolean oEnd;
+
+    public BitSet inclusions;
+
+    public BitSet exclusions;
+
+    public int type = DTDConstants.ANY;
+
+    public ContentModel content;
+
+    public AttributeList atts;
+
+    public Object data;
+
+    Element(final int index,
+            final String name,
+            final boolean oStart,
+            final boolean oEnd,
+            final BitSet exclusions,
+            final BitSet inclusions,
+            final int type,
+            final ContentModel content,
+            final AttributeList atts,
+            final Object data) {
+        this.index = index;
+        this.name = name;
+        this.oStart = oStart;
+        this.oEnd = oEnd;
+        this.inclusions = inclusions;
+        this.exclusions = exclusions;
+        this.type = type;
+        this.content = content;
+        this.atts = atts;
+        this.data = data;
+    }
+
+    Element() {
+    }
+
+    public static int name2type(final String name) {
+        if (name.equals("ANY")) {
+            return DTDConstants.ANY;
+        } else if (name.equals("CDATA")) {
+            return DTDConstants.CDATA;
+        } else if (name.equals("EMPTY")) {
+            return DTDConstants.EMPTY;
+        } else if (name.equals("RCDATA")) {
+            return DTDConstants.RCDATA;
+        } else {
+            return 0;
+        }
+    }
+
+
+    public AttributeList getAttributeByValue(final String value) {
+        AttributeList currentAtts = this.atts;
+        if (value == null) {
+            return null;
+        }
+        while (currentAtts != null) {
+            if (currentAtts.containsValue(value)) {
+                return currentAtts;
+            }
+            currentAtts = currentAtts.next;
+        }
+        return null;
+    }
+
+    public AttributeList getAttribute(final String name) {
+        AttributeList currentAtts = this.atts;
+        if (name == null) {
+            return null;
+        }
+        while (currentAtts != null) {
+            if (name.equals(currentAtts.getName())) {
+                return currentAtts;
+            }
+            currentAtts = currentAtts.next;
+        }
+        return null;
+    }
+
+    public String toString() {
+        return "javax.swing.text.html.parser.Element["
+               + "index=" + index + ","
+               + "name=" + name + ","
+               + "oStart=" + oStart + ","
+               + "oEnd=" + oEnd + ","
+               + "inclusions=" + inclusions + ","
+               + "exclusions=" + exclusions + ","
+               + "type=" + type + ","
+               + "content=" +  content + ","
+               + "atts=" +  atts + ","
+               + "data=" +  data + "]";
+    }
+
+    public boolean isEmpty() {
+        return type == DTDConstants.EMPTY;
+    }
+
+
+    public int getIndex() {
+        return index;
+    }
+
+
+    public AttributeList getAttributes() {
+        return atts;
+    }
+
+    public ContentModel getContent() {
+        return content;
+    }
+
+    public int getType() {
+        return type;
+    }
+
+    public boolean omitEnd() {
+        return oEnd;
+    }
+
+    public boolean omitStart() {
+        return oStart;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    final void updateElement(final int index,
+                             final String name,
+                             final boolean oStart,
+                             final boolean oEnd,
+                             final BitSet exclusions,
+                             final BitSet inclusions,
+                             final int type,
+                             final ContentModel content,
+                             final AttributeList atts,
+                             final Object data) {
+        this.index = index;
+        this.name = name;
+        this.oStart = oStart;
+        this.oEnd = oEnd;
+        this.inclusions = inclusions;
+        this.exclusions = exclusions;
+        this.type = type;
+        this.content = content;
+        this.atts = atts;
+        this.data = data;
+    }
+
+    final void updateElement(final Element element) {
+        this.index = element.index;
+        this.name = element.name;
+        this.oStart = element.oStart;
+        this.oEnd = element.oEnd;
+        this.inclusions = element.inclusions;
+        this.exclusions = element.exclusions;
+        this.type = element.type;
+        this.content = element.content;
+        this.atts = element.atts;
+        this.data = element.data;
+    }
+}
+