0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.netbeans.modules.visualweb.designer.markup;
0043:
0044: import org.netbeans.modules.visualweb.api.insync.InSyncService;
0045: import com.sun.rave.designtime.markup.MarkupDesignBean;
0046: import java.lang.ref.WeakReference;
0047: import java.util.Map;
0048: import java.util.WeakHashMap;
0049: import javax.xml.parsers.DocumentBuilder;
0050: import javax.xml.parsers.ParserConfigurationException;
0051: import org.apache.batik.css.engine.CSSStylableElement;
0052: import org.apache.batik.css.engine.StyleMap;
0053: import org.apache.xerces.dom.DocumentImpl;
0054: import org.netbeans.modules.visualweb.designer.html.HtmlAttribute;
0055: import org.netbeans.modules.visualweb.designer.html.HtmlTag;
0056: import org.w3c.dom.Document;
0057: import org.w3c.dom.Element;
0058: import org.w3c.dom.Node;
0059: import org.w3c.dom.NodeList;
0060: import org.w3c.dom.Text;
0061:
0062: /**
0063: * Impl of the <code>MarkupService</code>.
0064: * <p>
0065: * Note: Do not use this from other modules, use <code>MarkupService</code>
0066: * This won't be public.
0067: * </p>
0068: *
0069: * @author Peter Zavadsky
0070: */
0071: public final class MarkupServiceImpl {
0072:
0073: // private static final String KEY_JSPX = "vwpJspx"; // NOI18N
0074:
0075: // private static final String KEY_STYLE_MAP = "vwpStyleMap"; // NOI18N
0076:
0077: // private static final String KEY_STYLE_PARENT = "vwpStyleParent"; // NOI18N
0078:
0079: // private static final String KEY_RENDERED_TEXT = "vwpRenderedText"; // NOI18N
0080:
0081: // private static final String KEY_SOURCE_TEXT = "vwpSourceText"; // NOI18N
0082:
0083: // private static final String KEY_RENDERED_ELEMENT = "vwpRenderedElement"; // NOI18N
0084:
0085: // private static final String KEY_SOURCE_ELEMENT="vwpSourceElement"; // NOI18N
0086:
0087: private MarkupServiceImpl() {
0088: }
0089:
0090: // public static String expandHtmlEntities(String html, boolean warn, Node node) {
0091: // FileObject fileObject = null;
0092: // int lineNumber = -1;
0093: // if (node != null) {
0094: // if (node.getNodeType() == Node.TEXT_NODE) {
0095: // node = node.getParentNode();
0096: // }
0097: //
0098: // Element element = InSyncService.getProvider().getCorrespondingSourceElement((Element)node);
0099: //
0100: // if (element != null) {
0101: // Document doc = element.getOwnerDocument();
0102: // // <markup_separation>
0103: //// MarkupUnit unit = doc.getMarkup();
0104: //// if (unit != null) {
0105: //// fileObject = unit.getFileObject();
0106: //// lineNumber = unit.computeLine(element);
0107: //// }
0108: // // ====
0109: // fileObject = InSyncService.getProvider().getFileObject(doc);
0110: // lineNumber = InSyncService.getProvider().computeLine(doc, element);
0111: // // </markup_seaparation>
0112: // }
0113: // }
0114: //
0115: // return Entities.getExpandedString(html, warn, fileObject, lineNumber);
0116: // }
0117: //
0118: // public static int getUnexpandedOffset(String unexpanded, int expandedOffset) {
0119: // return Entities.getUnexpandedOffset(unexpanded, expandedOffset);
0120: // }
0121: //
0122: // public static int getExpandedOffset(String unexpanded, int unexpandedOffset) {
0123: // return Entities.getExpandedOffset(unexpanded, unexpandedOffset);
0124: // }
0125:
0126: // public static XhtmlElement getCorrespondingSourceElement(XhtmlElement element) {
0127: // return MarkupUtilities.getCorrespondingSourceElement(element);
0128: // }
0129:
0130: // // <utilities methods>
0131: // public static URL getCascadedXMLBase(Element elt) {
0132: // return MarkupUtilities.getCascadedXMLBase(elt);
0133: // }
0134:
0135: // XXX From org.netbeans.modules.visualweb.insync.Util.
0136: // /**
0137: // * Given an element which may be in a rendered DocumentFragment, return the corresponding JSF
0138: // * element in the source.
0139: // */
0140: // public static Element getCorrespondingSourceElement(Element element) {
0141: // return MarkupUtilities.getCorrespondingSourceElement(element);
0142: // }
0143: //
0144: //
0145: // // <markup_separation> copied from insync/Util
0146: // // XXX This should be separate utility api, openide extension or what.
0147: // /**
0148: // * Show the given line in a particular file.
0149: // *
0150: // * @param filename The full path to the file
0151: // * @param lineno The line number
0152: // * @param openFirst Usually you'll want to pass false. When set to true, this will first open
0153: // * the file, then request the given line number; this works around certain bugs for
0154: // * some editor types like CSS files.
0155: // */
0156: // public static void show(String filename, int lineno, int column, boolean openFirst) {
0157: // MarkupUtilities.show(filename, lineno, column, openFirst);
0158: // }
0159: //
0160: // /**
0161: // * Show the given line in a particular file.
0162: // *
0163: // * @param fileObject The FileObject for the file
0164: // * @param lineno The line number
0165: // * @param openFirst Usually you'll want to pass false. When set to true, this will first open
0166: // * the file, then request the given line number; this works around certain bugs for
0167: // * some editor types like CSS files.
0168: // */
0169: // public static void show(FileObject fileObject, int lineno, int column,
0170: // boolean openFirst) {
0171: // MarkupUtilities.show(fileObject, lineno, column, openFirst);
0172: // }
0173:
0174: // // <markup_separation> moved from insync/MarkupUnit
0175: // /** Convert the given URL to a path: decode spaces from %20's, etc.
0176: // * If the url does not begin with "file:" it will not do anything.
0177: // * @todo Find a better home for this method
0178: // */
0179: // public static String fromURL(String url) {
0180: // return MarkupUtilities.fromURL(url);
0181: // }
0182: // // </markup_separation>
0183:
0184: // <error_handling> Moved from RaveDocument.
0185: // XXX These methods are suspicoius, they deal with openide output window.
0186: // // and there may not be any knowing about it from this impls.
0187: // /** Clear document related errors.
0188: // * @param delayed When set, don't actually clear the errors right now;
0189: // * it clears the errors next time another error is added. */
0190: // public static void clearErrors(boolean delayed) {
0191: // MarkupUtilities.clearErrors(delayed);
0192: // }
0193:
0194: // /**
0195: // * Display the given error message to the user. The optional listener argument
0196: // * (pass in null if not applicable) will make the line hyperlinked and the
0197: // * listener is invoked to process any user clicks.
0198: // * @param message The string to be displayed to the user
0199: // * @param listener null, or a listener to be notified when the user clicks
0200: // * the linked message
0201: // */
0202: // public static void displayError(String message, OutputListener listener) {
0203: // MarkupUtilities.displayError(message, listener);
0204: // }
0205:
0206: // /**
0207: // * Cause the panel/window within which errors are displayed to come to the front if possible.
0208: // *
0209: // */
0210: // public static void selectErrors() {
0211: // MarkupUtilities.selectErrors();
0212: // }
0213: //
0214: // public static void displayError(String message) {
0215: // MarkupUtilities.displayError(message);
0216: // }
0217: //
0218: // public static void displayErrorForLocation(String message, Object location, int line, int column) {
0219: // MarkupUtilities.displayErrorForLocation(message, location, line, column);
0220: // }
0221: //
0222: // public static void displayErrorForFileObject(String message, FileObject fileObject, int line, int column) {
0223: // MarkupUtilities.displayErrorForFileObject(message, fileObject, line, column);
0224: // }
0225: //
0226: // /** Given a general location object provided from the CSS parser,
0227: // * compute the correct file name to use.
0228: // */
0229: // public static String computeFilename(Object location) {
0230: // return MarkupUtilities.computeFilename(location);
0231: // }
0232: // /** Given a general location object provided from the CSS parser,
0233: // * compute the correct line number to use.
0234: // */
0235: // public static int computeLineNumber(Object location, int line) {
0236: // return MarkupUtilities.computeLineNumber(location, line);
0237: // }
0238: // </error_handling>
0239:
0240: // // XXX Moved from DesignerService.
0241: // /**
0242: // * Return an InputStream for the given CSS URI, if the corresponding CSS
0243: // * file is open and edited. Otherwise return null.
0244: // *
0245: // * @param uri The URI to the CSS file. <b>MUST</b> be an absolute file url!
0246: // * @return An InputStream for the live edited CSS
0247: // */
0248: // public static InputStream getOpenCssStream(String uriString) {
0249: // return MarkupUtilities.getOpenCssStream(uriString);
0250: // }
0251: // // </utilities methods>
0252:
0253: // <separation of models> moved from designer/FacesSupport
0254: // /**
0255: // * Generate the html string from the given node. This will return
0256: // * an empty string unless the Node is an Element or a DocumentFragment
0257: // * or a Document.
0258: // */
0259: // public static String getHtmlStream(Node node) {
0260: // if (node.getNodeType() == Node.ELEMENT_NODE) {
0261: // return getHtmlStream((Element)node);
0262: // } else if (node.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {
0263: // return getHtmlStream((DocumentFragment)node);
0264: // } else if (node.getNodeType() == Node.DOCUMENT_NODE) {
0265: // return getHtmlStream((org.w3c.dom.Document)node);
0266: // } else if ((node.getNodeType() == Node.TEXT_NODE) ||
0267: // (node.getNodeType() == Node.CDATA_SECTION_NODE)) {
0268: // return node.getNodeValue();
0269: // } else {
0270: // return "";
0271: // }
0272: // }
0273: //
0274: // /** Generate the html string from the given element */
0275: // public static String getHtmlStream(Element element) {
0276: // StringWriter w = new StringWriter(); // XXX initial size?
0277: // OutputFormat format = new OutputFormat(element.getOwnerDocument(), null, true); // default enc, do-indent
0278: // format.setLineWidth(160);
0279: // format.setIndent(4);
0280: //
0281: // JspxSerializer serializer = new JspxSerializer(w, format);
0282: //
0283: // try {
0284: // serializer.serialize(element);
0285: // } catch (java.io.IOException ex) {
0286: // ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
0287: // }
0288: //
0289: // return w.getBuffer().toString();
0290: // }
0291: //
0292: // /** Generate the html string from the given element. Does formatting. */
0293: // public static String getHtmlStream(org.w3c.dom.Document document) {
0294: // StringWriter w = new StringWriter(); // XXX initial size?
0295: // OutputFormat format = new OutputFormat(document, null, true); // default enc, do-indent
0296: // format.setLineWidth(160);
0297: // format.setIndent(4);
0298: //
0299: // JspxSerializer serializer = new JspxSerializer(w, format);
0300: //
0301: // try {
0302: // serializer.serialize(document);
0303: // } catch (java.io.IOException ex) {
0304: // ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
0305: // }
0306: //
0307: // return w.getBuffer().toString();
0308: // }
0309: //
0310: // /** Generate the html string from the given document fragment */
0311: // public static String getHtmlStream(DocumentFragment df) {
0312: // OutputFormat format = new OutputFormat(df.getOwnerDocument()); // default enc, do-indent
0313: // format.setLineWidth(160);
0314: // format.setIndent(4);
0315: //
0316: // StringWriter w = new StringWriter(); // XXX initial size?
0317: // JspxSerializer serializer = new JspxSerializer(w, format);
0318: //
0319: // try {
0320: // serializer.serialize(df);
0321: // } catch (java.io.IOException ex) {
0322: // ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
0323: // }
0324: //
0325: // return w.getBuffer().toString();
0326: // }
0327: // </separation of models> moved from designer/FacesSupport
0328:
0329: public static DocumentBuilder createRaveSourceDocumentBuilder(
0330: boolean useCss) throws ParserConfigurationException {
0331: return RaveDocumentBuilderFactory.newDocumentBuilder(useCss,
0332: true);
0333: }
0334:
0335: public static DocumentBuilder createRaveRenderedDocumentBuilder(
0336: boolean useCss) throws ParserConfigurationException {
0337: return RaveDocumentBuilderFactory.newDocumentBuilder(useCss,
0338: false);
0339: }
0340:
0341: // Moved from RaveDocument.
0342: /**
0343: * Given two matching node trees where one represents a tree of
0344: * nodes rendered from the other, update the source and render references
0345: * in the nodes such that the "src" tree is marked as the source nodes
0346: * for "dst".
0347: */
0348: public static void markRendered(Node src, Node dst) {
0349: // if (src instanceof RaveElement) {
0350: // assert dst instanceof RaveElement;
0351: // RaveElement srcElement = (RaveElement)src;
0352: // RaveElement dstElement = (RaveElement)dst;
0353: //// srcElement.source = null;
0354: //// dstElement.source = srcElement;
0355: // dstElement.setSource(srcElement);
0356: // } else if (src instanceof RaveText) {
0357: // assert dst instanceof RaveText;
0358: // RaveText srcText = (RaveText)src;
0359: // RaveText dstText = (RaveText)dst;
0360: //// srcText.source = null;
0361: //// dstText.source = srcText;
0362: // dstText.setSource(srcText);
0363: // }
0364: // if (src instanceof RaveSourceElement) {
0365: if (src instanceof Element
0366: && src.getOwnerDocument() instanceof RaveSourceDocument) {
0367: // assert dst instanceof RaveRenderedElement;
0368: // RaveSourceElement srcElement = (RaveSourceElement)src;
0369: // RaveRenderedElement dstElement = (RaveRenderedElement)dst;
0370: Element srcElement = (Element) src;
0371: Element dstElement = (Element) dst;
0372: // srcElement.source = null;
0373: // dstElement.source = srcElement;
0374: // dstElement.linkToSourceElement(srcElement);
0375: linkToSourceElement(dstElement, srcElement);
0376: // } else if (src instanceof RaveSourceText) {
0377: } else if (src instanceof Text
0378: && src.getOwnerDocument() instanceof RaveSourceDocument) {
0379: // assert dst instanceof RaveRenderedText;
0380: // RaveSourceText srcText = (RaveSourceText)src;
0381: // RaveRenderedText dstText = (RaveRenderedText)dst;
0382: Text srcText = (Text) src;
0383: Text dstText = (Text) dst;
0384: // srcText.source = null;
0385: // dstText.source = srcText;
0386: // dstText.linkToSourceText(srcText);
0387: linkToSourceText(dstText, srcText);
0388: }
0389:
0390: NodeList srcChildren = src.getChildNodes();
0391: NodeList dstChildren = dst.getChildNodes();
0392: int len = srcChildren.getLength();
0393: assert dstChildren.getLength() == len;
0394:
0395: for (int i = 0; i < len; i++) {
0396: markRendered(srcChildren.item(i), dstChildren.item(i));
0397: }
0398: }
0399:
0400: public static void markRenderedNodes(Element parent, Node node) {
0401: // RaveElement element;
0402: // if (node instanceof RaveElement) {
0403: // element = (RaveElement)node;
0404: // RaveRenderedElement element;
0405: Element element;
0406: // if (node instanceof RaveRenderedElement) {
0407: // element = (RaveRenderedElement)node;
0408: if (node instanceof Element
0409: && node.getOwnerDocument() instanceof RaveRenderedDocument) {
0410: element = (Element) node;
0411: } else {
0412: element = null;
0413: }
0414:
0415: // We work our way right to left, bottom to top, to ensure that
0416: // the last setJsp call made for a particular jsp node will be the
0417: // leftmost, topmost rendered node for that jsp element.
0418: NodeList nl = node.getChildNodes();
0419:
0420: for (int n = nl.getLength(), i = n - 1; i >= 0; i--) {
0421: markRenderedNodes(element, nl.item(i));
0422: }
0423:
0424: // if (node instanceof RaveRenderNode) {
0425: // RaveRenderNode rn = (RaveRenderNode)node;
0426:
0427: // if (node instanceof RaveElementImpl || node instanceof RaveTextImpl) {
0428: // if (node instanceof RaveRenderedElementImpl || node instanceof RaveRenderedTextImpl) {
0429: if (node != null
0430: && node.getOwnerDocument() instanceof RaveRenderedDocument) {
0431:
0432: if (element != null) {
0433: // if ((parent != null) && (parent.getDesignBean() == element.getDesignBean())) {
0434: MarkupDesignBean markupDesignBean = InSyncService
0435: .getProvider().getMarkupDesignBeanForElement(
0436: element);
0437: MarkupDesignBean parentMarkupDesignBean = parent == null ? null
0438: : InSyncService.getProvider()
0439: .getMarkupDesignBeanForElement(parent);
0440: if (markupDesignBean == parentMarkupDesignBean) {
0441: // element.linkToSourceElement(null);
0442: linkToSourceElement(element, null);
0443: // } else if (element.getDesignBean() != null) {
0444: // element.setSource((RaveElement)element.getDesignBean().getElement());
0445: } else if (markupDesignBean != null) {
0446: // element.setSource((RaveElement)InSyncService.getProvider().getMarkupDesignBeanForElement(element).getElement());
0447: // #6455709 Some strange class cast exception, couldn't reproduce, needs to be tested more carefully.
0448: Element elem = markupDesignBean.getElement();
0449: // if (elem instanceof RaveSourceElement) {
0450: if (elem != null
0451: && elem.getOwnerDocument() instanceof RaveSourceDocument) {
0452: // element.linkToSourceElement((RaveSourceElement)elem);
0453: linkToSourceElement(element, elem);
0454: } else {
0455: // XXX Log a problem?
0456: // element.linkToSourceElement(null);
0457: linkToSourceElement(element, null);
0458: }
0459: } else {
0460: // rn.markRendered();
0461: // if (node instanceof RaveElementImpl) {
0462: // ((RaveElementImpl)node).markRendered();
0463: // } else if (node instanceof RaveTextImpl) {
0464: // ((RaveTextImpl)node).markRendered();
0465: // }
0466: }
0467: } else {
0468: // rn.markRendered();
0469: // if (node instanceof RaveElementImpl) {
0470: // ((RaveElementImpl)node).markRendered();
0471: // } else if (node instanceof RaveTextImpl) {
0472: // ((RaveTextImpl)node).markRendered();
0473: // }
0474: }
0475: }
0476: }
0477:
0478: public static void markJspxSource(Node n) {
0479: // if (n instanceof RaveRenderNode) {
0480: // ((RaveRenderNode)n).setJspx(true);
0481: // }
0482: // if (n instanceof RaveElementImpl) {
0483: // ((RaveElementImpl)n).setJspx(true);
0484: // } else if (n instanceof RaveTextImpl) {
0485: // ((RaveTextImpl)n).setJspx(true);
0486: // }
0487: // if (n instanceof AbstractRaveElement) {
0488: // ((AbstractRaveElement)n).setJspx(true);
0489: // } else if (n instanceof AbstractRaveText) {
0490: // ((AbstractRaveText)n).setJspx(true);
0491: // }
0492: setJspxNode(n, true);
0493:
0494: NodeList list = n.getChildNodes();
0495: int len = list.getLength();
0496:
0497: for (int i = 0; i < len; i++) {
0498: markJspxSource(list.item(i));
0499: }
0500: }
0501:
0502: public static void setInputEncodingForDocument(Document document,
0503: String inputEncoding) {
0504: if (document instanceof DocumentImpl) {
0505: ((DocumentImpl) document).setInputEncoding(inputEncoding);
0506: }
0507: }
0508:
0509: public static String getStyleText(Element e) {
0510: String text = "";
0511: Node n = e.getFirstChild();
0512: if (n != null) {
0513: StringBuffer sb = new StringBuffer();
0514: while (n != null) {
0515: if (n.getNodeType() == Node.CDATA_SECTION_NODE
0516: // Unlike javascript, where the first line in a comment should be treated
0517: // as a comment, the browsers seem to treat all comment text as style rules
0518: || n.getNodeType() == Node.COMMENT_NODE
0519:
0520: || n.getNodeType() == Node.TEXT_NODE)
0521: // XXX should pick up comments contents too!!
0522: sb.append(n.getNodeValue());
0523: n = n.getNextSibling();
0524: }
0525: text = sb.toString();
0526: // Strip out comments?
0527: }
0528: return text;
0529: }
0530:
0531: // XXX From org.netbeans.modules.visualweb.insync.Util.
0532: public static Element getCorrespondingSourceElement(Element elem) {
0533: // if (!(elem instanceof RaveElement)) {
0534: // if (!(elem instanceof RaveElementImpl)) {
0535: // if (!(elem instanceof RaveRenderedElementImpl)) {
0536: if (!(elem != null && elem.getOwnerDocument() instanceof RaveRenderedDocument)) {
0537: return elem;
0538: }
0539:
0540: // RaveElement element = (RaveElement)elem;
0541: // RaveElementImpl element = (RaveElementImpl)elem;
0542: // RaveRenderedElementImpl element = (RaveRenderedElementImpl)elem;
0543: Element element = elem;
0544:
0545: // if (!element.isRendered()) {
0546: // return element;
0547: // }
0548:
0549: org.w3c.dom.Node node = element;
0550: while (node != null) {
0551: // if (node instanceof RaveElement) {
0552: // RaveElement xel = (RaveElement)node;
0553: // if (node instanceof RaveElementImpl) {
0554: // RaveElementImpl xel = (RaveElementImpl)node;
0555: // if (xel.isRendered()) {
0556: // RaveElement src = xel.getSource();
0557: // if (src != null) {
0558: // if (node instanceof RaveRenderedElementImpl) {
0559: if (node instanceof Element
0560: && node.getOwnerDocument() instanceof RaveRenderedDocument) {
0561: // RaveRenderedElementImpl xel = (RaveRenderedElementImpl)node;
0562: Element xel = (Element) node;
0563: // if (xel.isRendered()) {
0564: // RaveSourceElement src = xel.getSourceElement();
0565: Element src = getSourceElement(xel);
0566: if (src != null) {
0567: return src;
0568: }
0569: // }
0570: }
0571: node = node.getParentNode();
0572: }
0573:
0574: // return element.getSourceElement();
0575: // return element.getSourceElement();
0576: return getSourceElement(element);
0577: }
0578:
0579: // /** Returns true if the node is rendered.
0580: // * By "is rendered" I mean that the position points to a node
0581: // * in a renderer-hierarchy DOM (such as HTML rendered from JSF components).
0582: // */
0583: // public static boolean isRenderedNode(Node node) {
0584: //// if (node instanceof RaveRenderNode) {
0585: //// return ((RaveRenderNode)node).isRendered();
0586: //// }
0587: //// if (node instanceof RaveElementImpl) {
0588: //// return ((RaveElementImpl)node).isRendered();
0589: //// } else if (node instanceof RaveTextImpl) {
0590: //// return ((RaveTextImpl)node).isRendered();
0591: //// }
0592: //// if (node instanceof AbstractRaveElement) {
0593: //// return ((AbstractRaveElement)node).isRendered();
0594: //// } else if (node instanceof AbstractRaveText) {
0595: //// return ((AbstractRaveText)node).isRendered();
0596: //// }
0597: // if (node instanceof RaveRenderedElement) {
0598: // return true;
0599: // } else if (node instanceof RaveRenderedText) {
0600: // return true;
0601: // }
0602: // return false;
0603: // }
0604:
0605: private static final Map<Node, Boolean> node2jspx = new WeakHashMap<Node, Boolean>(
0606: 200);
0607:
0608: public static boolean isJspxNode(Node node) {
0609: // if (node instanceof RaveRenderNode) {
0610: // return ((RaveRenderNode)node).isJspx();
0611: // }
0612: // if (node instanceof RaveElementImpl) {
0613: // return ((RaveElementImpl)node).isJspx();
0614: // } else if (node instanceof RaveTextImpl) {
0615: // return ((RaveTextImpl)node).isJspx();
0616: // }
0617: // if (node instanceof AbstractRaveElement) {
0618: // return ((AbstractRaveElement)node).isJspx();
0619: // } else if (node instanceof AbstractRaveText) {
0620: // return ((AbstractRaveText)node).isJspx();
0621: // }
0622: // return false;
0623: // Boolean b = node == null ? null : (Boolean)node.getUserData(KEY_JSPX);
0624: Boolean b = node2jspx.get(node);
0625: return b == null ? false : b.booleanValue();
0626: }
0627:
0628: public static void setJspxNode(Node node, boolean jspx) {
0629: // if (node instanceof RaveRenderNode) {
0630: // ((RaveRenderNode)node).setJspx(jspx);
0631: // }
0632: // if (node instanceof RaveElementImpl) {
0633: // ((RaveElementImpl)node).setJspx(jspx);
0634: // } else if (node instanceof RaveTextImpl) {
0635: // ((RaveTextImpl)node).setJspx(jspx);
0636: // }
0637: // if (node instanceof AbstractRaveElement) {
0638: // ((AbstractRaveElement)node).setJspx(jspx);
0639: // } else if (node instanceof AbstractRaveText) {
0640: // ((AbstractRaveText)node).setJspx(jspx);
0641: // }
0642: if (node == null) {
0643: return;
0644: }
0645: // node.setUserData(KEY_JSPX, Boolean.valueOf(jspx), JspxDataHandler.getDefault());
0646: node2jspx.put(node, Boolean.valueOf(jspx));
0647: }
0648:
0649: public static Node getRenderedNodeForNode(Node node) {
0650: // if (node instanceof RaveRenderNode) {
0651: // return ((RaveRenderNode)node).getRenderedNode();
0652: // }
0653: // if (node instanceof RaveElementImpl) {
0654: // return ((RaveElementImpl)node).getRenderedNode();
0655: // } else if (node instanceof RaveTextImpl) {
0656: // return ((RaveTextImpl)node).getRenderedNode();
0657: // }
0658: // if (node instanceof RaveSourceElement) {
0659: if (node instanceof Element
0660: && node.getOwnerDocument() instanceof RaveSourceDocument) {
0661: // return ((RaveSourceElement)node).getRenderedElement();
0662: return getRenderedElement((Element) node);
0663: // } else if (node instanceof RaveSourceText) {
0664: } else if (node instanceof Text
0665: && node.getOwnerDocument() instanceof RaveSourceDocument) {
0666: // return ((RaveSourceText)node).getRenderedText();
0667: return getRenderedText((Text) node);
0668: // } else if (node instanceof RaveRenderedElement
0669: // || node instanceof RaveRenderedText) { // XXX
0670: } else if (node != null
0671: && node.getOwnerDocument() instanceof RaveRenderedDocument) {
0672: return node;
0673: }
0674:
0675: return null;
0676: }
0677:
0678: public static Node getSourceNodeForNode(Node node) {
0679: // if (node instanceof RaveRenderNode) {
0680: // return ((RaveRenderNode)node).getSourceNode();
0681: // }
0682: // if (node instanceof RaveElementImpl) {
0683: // return ((RaveElementImpl)node).getSourceNode();
0684: // } else if (node instanceof RaveTextImpl) {
0685: // return ((RaveTextImpl)node).getSourceNode();
0686: // }
0687: // if (node instanceof RaveRenderedElement) {
0688: if (node instanceof Element
0689: && node.getOwnerDocument() instanceof RaveRenderedDocument) {
0690: // return ((RaveRenderedElement)node).getSourceElement();
0691: return getSourceElement((Element) node);
0692: // } else if (node instanceof RaveRenderedText) {
0693: } else if (node instanceof Text
0694: && node.getOwnerDocument() instanceof RaveRenderedDocument) {
0695: // return ((RaveRenderedText)node).getSourceText();
0696: return getSourceText((Text) node);
0697: // } else if (node instanceof RaveSourceElement
0698: // || node instanceof RaveSourceText) { // XXX
0699: } else if (node != null
0700: && node.getOwnerDocument() instanceof RaveSourceDocument) {
0701: return node;
0702: }
0703: return null;
0704: }
0705:
0706: public static Element getRenderedElementForElement(Element element) {
0707: // if (element instanceof RaveElement) {
0708: // return ((RaveElement)element).getRendered();
0709: // }
0710: // if (element instanceof RaveSourceElement) {
0711: if (element != null
0712: && element.getOwnerDocument() instanceof RaveSourceDocument) {
0713: // return ((RaveSourceElement)element).getRenderedElement();
0714: return getRenderedElement(element);
0715: // } else if (element instanceof RaveRenderedElement) { // XXX
0716: } else if (element != null
0717: && element.getOwnerDocument() instanceof RaveRenderedDocument) {
0718: return element;
0719: }
0720: return null;
0721: }
0722:
0723: public static void setRenderedElementForElement(Element element,
0724: Element renderedElement) {
0725: // if (element instanceof RaveElement) {
0726: // ((RaveElement)element).setRendered((RaveElement)renderedElement);
0727: // }
0728: // if (element instanceof RaveSourceElement) {
0729: if (element != null
0730: && element.getOwnerDocument() instanceof RaveSourceDocument) {
0731: // ((RaveSourceElement)element).linkToRenderedElement((RaveRenderedElement)renderedElement);
0732: linkToRenderedElement(element, renderedElement);
0733: }
0734: }
0735:
0736: public static Element getSourceElementForElement(Element element) {
0737: // if (element instanceof RaveElement) {
0738: // return ((RaveElement)element).getSource();
0739: // }
0740: // if (element instanceof RaveRenderedElement) {
0741: if (element != null
0742: && element.getOwnerDocument() instanceof RaveRenderedDocument) {
0743: // return ((RaveRenderedElement)element).getSourceElement();
0744: return getSourceElement(element);
0745: // } else if (element instanceof RaveSourceElement) { // XXX
0746: } else if (element != null
0747: && element.getOwnerDocument() instanceof RaveSourceDocument) { // XXX
0748: return element;
0749: }
0750: return null;
0751: }
0752:
0753: public static Text getRenderedTextForText(Text text) {
0754: // if (text instanceof RaveText) {
0755: // return ((RaveText)text).getRendered();
0756: // }
0757: // if (text instanceof RaveSourceText) {
0758: if (text != null
0759: && text.getOwnerDocument() instanceof RaveSourceDocument) {
0760: // return ((RaveSourceText)text).getRenderedText();
0761: return getRenderedText(text);
0762: // } else if (text instanceof RaveRenderedText) { // XXX
0763: } else if (text != null
0764: && text.getOwnerDocument() instanceof RaveRenderedDocument) {
0765: return text;
0766: }
0767: return null;
0768: }
0769:
0770: public static Text getSourceTextForText(Text text) {
0771: // if (text instanceof RaveText) {
0772: // return ((RaveText)text).getSource();
0773: // }
0774: // if (text instanceof RaveRenderedText) {
0775: if (text != null
0776: && text.getOwnerDocument() instanceof RaveRenderedDocument) {
0777: // return ((RaveRenderedText)text).getSourceText();
0778: return getSourceText(text);
0779: // } else if (text instanceof RaveSourceText) { // XXX
0780: } else if (text != null
0781: && text.getOwnerDocument() instanceof RaveSourceDocument) {
0782: return text;
0783: }
0784: return null;
0785: }
0786:
0787: public static void setSourceTextForText(Text text, Text sourceText) {
0788: // if (text instanceof RaveText) {
0789: // ((RaveText)text).setSource((RaveText)sourceText);
0790: // }
0791: // if (text instanceof RaveRenderedText) {
0792: if (text != null
0793: && text.getOwnerDocument() instanceof RaveRenderedDocument) {
0794: // ((RaveRenderedText)text).linkToSourceText((RaveSourceText)sourceText);
0795: linkToSourceText(text, sourceText);
0796: }
0797: }
0798:
0799: public static Element getTBodyElementForTableElement(
0800: Element tableElement) {
0801: // if (tableElement instanceof RaveRenderedTableElement) {
0802: // ((RaveRenderedTableElement)tableElement).getTbody();
0803: // } else if (tableElement instanceof RaveSourceTableElement) {
0804: // return ((RaveSourceTableElement)tableElement).getTbody();
0805: // }
0806: if (tableElement instanceof RaveTableElement) {
0807: return ((RaveTableElement) tableElement).getTbody();
0808: }
0809: return null;
0810: }
0811:
0812: private static final Map<Element, StyleMap> element2styleMap = new WeakHashMap<Element, StyleMap>(
0813: 200);
0814:
0815: static void setElementStyleMap(Element element, StyleMap styleMap) {
0816: if (element == null) {
0817: return;
0818: }
0819: // element.setUserData(KEY_STYLE_MAP, styleMap, StyleMapDataHandler.getDefault());
0820: element2styleMap.put(element, styleMap);
0821: }
0822:
0823: static StyleMap getElementStyleMap(Element element) {
0824: if (element == null) {
0825: return null;
0826: }
0827: // return (StyleMap)element.getUserData(KEY_STYLE_MAP);
0828: return element2styleMap.get(element);
0829: }
0830:
0831: private static final Map<Element, WeakReference<CSSStylableElement>> element2cssStylableElement = new WeakHashMap<Element, WeakReference<CSSStylableElement>>(
0832: 200);
0833:
0834: static void setElementStyleParent(Element element,
0835: CSSStylableElement styleParent) {
0836: if (element == null) {
0837: return;
0838: }
0839: // element.setUserData(KEY_STYLE_PARENT, styleParent, StyleParentDataHandler.getDefault());
0840: element2cssStylableElement.put(element,
0841: new WeakReference<CSSStylableElement>(styleParent));
0842: }
0843:
0844: static CSSStylableElement getElementStyleParent(Element element) {
0845: if (element == null) {
0846: return null;
0847: }
0848: // return (CSSStylableElement)element.getUserData(KEY_STYLE_PARENT);
0849: WeakReference<CSSStylableElement> wRef = element2cssStylableElement
0850: .get(element);
0851: return wRef == null ? null : wRef.get();
0852: }
0853:
0854: static boolean isElementPseudoInstanceOf(Element element,
0855: String pseudoClass) {
0856: if (element == null) {
0857: return false;
0858: }
0859:
0860: if (pseudoClass.equals("first-child")) {
0861: Node n = element.getPreviousSibling();
0862:
0863: while ((n != null)
0864: && (n.getNodeType() != Node.ELEMENT_NODE)) {
0865: n = n.getPreviousSibling();
0866: }
0867:
0868: return n == null;
0869: } else if (pseudoClass.equals("link")) {
0870: Node n = element;
0871: String a = HtmlTag.A.toString();
0872:
0873: while (n != null) {
0874: if ((n.getNodeType() == Node.ELEMENT_NODE)
0875: && n.getNodeName().equals(a)) {
0876: // Only a link if the href attribute is set!
0877: if (((Element) n).hasAttribute(HtmlAttribute.HREF)) {
0878: return true;
0879: }
0880: }
0881:
0882: n = n.getParentNode();
0883: }
0884:
0885: return false;
0886: }
0887:
0888: return false;
0889: }
0890:
0891: private static final Map<Text, WeakReference<Text>> sourceText2renderedText = new WeakHashMap<Text, WeakReference<Text>>(
0892: 200);
0893:
0894: static void setRenderedText(Text text, Text renderedText) {
0895: if (text == null) {
0896: return;
0897: }
0898: // text.setUserData(KEY_RENDERED_TEXT, renderedText, RenderedTextDataHandler.getDefault());
0899: sourceText2renderedText.put(text, new WeakReference<Text>(
0900: renderedText));
0901: }
0902:
0903: static Text getRenderedText(Text text) {
0904: if (text == null) {
0905: return null;
0906: }
0907: // return (Text)text.getUserData(KEY_RENDERED_TEXT);
0908: WeakReference<Text> wRef = sourceText2renderedText.get(text);
0909: return wRef == null ? null : wRef.get();
0910: }
0911:
0912: private static final Map<Text, WeakReference<Text>> renderedText2sourceText = new WeakHashMap<Text, WeakReference<Text>>(
0913: 200);
0914:
0915: static void setSourceText(Text text, Text sourceText) {
0916: if (text == null) {
0917: return;
0918: }
0919: // text.setUserData(KEY_SOURCE_TEXT, sourceText, SourceTextDataHandler.getDefault());
0920: renderedText2sourceText.put(text, new WeakReference<Text>(
0921: sourceText));
0922: }
0923:
0924: static Text getSourceText(Text text) {
0925: if (text == null) {
0926: return null;
0927: }
0928: // return (Text)text.getUserData(KEY_SOURCE_TEXT);
0929: WeakReference<Text> wRef = renderedText2sourceText.get(text);
0930: return wRef == null ? null : wRef.get();
0931: }
0932:
0933: static void linkToSourceText(Text text, Text sourceText) {
0934: setSourceText(text, sourceText);
0935:
0936: // if (sourceText != null) {
0937: //// ((RaveTextImpl) alternate).rendered = false;
0938: //// ((RaveTextImpl) alternate).alternate = this;
0939: //// ((RaveSourceTextImpl)sourceText).setRenderedText(this);
0940: // }
0941: setRenderedText(sourceText, text);
0942: }
0943:
0944: private static final Map<Element, WeakReference<Element>> sourceElement2renderedElement = new WeakHashMap<Element, WeakReference<Element>>(
0945: 200);
0946:
0947: static void setRenderedElement(Element element,
0948: Element renderedElement) {
0949: if (element == null) {
0950: return;
0951: }
0952: // element.setUserData(KEY_RENDERED_ELEMENT, renderedElement, RenderedElementDataHandler.getDefault());
0953: sourceElement2renderedElement.put(element,
0954: new WeakReference<Element>(renderedElement));
0955: }
0956:
0957: static Element getRenderedElement(Element element) {
0958: if (element == null) {
0959: return null;
0960: }
0961: // return (Element)element.getUserData(KEY_RENDERED_ELEMENT);
0962: WeakReference<Element> wRef = sourceElement2renderedElement
0963: .get(element);
0964: return wRef == null ? null : wRef.get();
0965: }
0966:
0967: static void linkToRenderedElement(Element element,
0968: Element renderedElement) {
0969: setRenderedElement(element, renderedElement);
0970:
0971: // if (renderedElement != null) {
0972: //// ((RaveElementImpl)alternate).rendered = true;
0973: //// ((RaveElementImpl)alternate).alternate = this;
0974: //// ((RaveRenderedElementImpl)renderedElement).setSourceElement(element);
0975: // }
0976: setSourceElement(renderedElement, element);
0977: }
0978:
0979: private static final Map<Element, WeakReference<Element>> renderedElement2sourceElement = new WeakHashMap<Element, WeakReference<Element>>(
0980: 200);
0981:
0982: static void setSourceElement(Element element, Element sourceElement) {
0983: if (element == null) {
0984: return;
0985: }
0986: // element.setUserData(KEY_SOURCE_ELEMENT, sourceElement, SourceElementDataHandler.getDefault());
0987: renderedElement2sourceElement.put(element, new WeakReference(
0988: sourceElement));
0989: }
0990:
0991: static Element getSourceElement(Element element) {
0992: if (element == null) {
0993: return null;
0994: }
0995: // return (Element)element.getUserData(KEY_SOURCE_ELEMENT);
0996: WeakReference<Element> wRef = renderedElement2sourceElement
0997: .get(element);
0998: return wRef == null ? null : wRef.get();
0999: }
1000:
1001: static void linkToSourceElement(Element element,
1002: Element sourceElement) {
1003: setSourceElement(element, sourceElement);
1004:
1005: // // Don't store references to invisible markup (<script>, <style>, <input hidden>)
1006: // if (sourceElement != null) {
1007: // // XXX Original code
1008: // // Make the source have a render reference to this element too, unless
1009: // // we know it's a nonvisual element that I'll never need a reference from.
1010: // // (And because some components can render script or style tags at the top
1011: // // level next to the bean render, it's important not to clobber the render
1012: // // pointer here.)
1013: // String name = element == null ? "" : element.getTagName(); // NOI18N
1014: //
1015: // char first = name.length() > 0 ? name.charAt(0) : '0';
1016: //
1017: // if (!(((first == 's') && (name.equals(HtmlTag.SCRIPT.name) || name.equals(HtmlTag.STYLE.name)))
1018: // || ((first == 'i') && (name.equals(HtmlTag.INPUT.name))
1019: // && element.getAttribute(HtmlAttribute.TYPE).equals("hidden")))) { // NOI18N
1020: //// ((RaveElementImpl)alternate).rendered = false;
1021: //// ((RaveElementImpl)alternate).alternate = this;
1022: //// ((RaveSourceElementImpl)sourceElement).setRenderedElement(this);
1023: // setRenderedElement(sourceElement, element);
1024: // }
1025: // }
1026: // XXX Original code
1027: // Make the source have a render reference to this element too, unless
1028: // we know it's a nonvisual element that I'll never need a reference from.
1029: // (And because some components can render script or style tags at the top
1030: // level next to the bean render, it's important not to clobber the render
1031: // pointer here.)
1032: if (element != null) {
1033: String name = element.getTagName(); // NOI18N
1034: char first = name.charAt(0);
1035: if (((first == 's') && (name.equals(HtmlTag.SCRIPT.name) || name
1036: .equals(HtmlTag.STYLE.name))) // NOI18N
1037: || ((first == 'i')
1038: && (name.equals(HtmlTag.INPUT.name)) && element
1039: .getAttribute(HtmlAttribute.TYPE).equals(
1040: "hidden"))) { // NOI18N
1041: // Don't store references to invisible markup (<script>, <style>, <input hidden>)
1042: return;
1043: }
1044: }
1045:
1046: setRenderedElement(sourceElement, element);
1047: }
1048:
1049: // private static class JspxDataHandler implements UserDataHandler {
1050: // private static final JspxDataHandler INSTANCE = new JspxDataHandler();
1051: //
1052: // public static JspxDataHandler getDefault() {
1053: // return INSTANCE;
1054: // }
1055: //
1056: // public void handle(short operation, String key, Object data, Node src, Node dst) {
1057: // // No op.
1058: // }
1059: // } // End of JspxDataHandler.
1060:
1061: // private static class StyleMapDataHandler implements UserDataHandler {
1062: // private static final StyleMapDataHandler INSTANCE = new StyleMapDataHandler();
1063: //
1064: // public static StyleMapDataHandler getDefault() {
1065: // return INSTANCE;
1066: // }
1067: //
1068: // public void handle(short operation, String key, Object data, Node src, Node dst) {
1069: // // No op.
1070: // }
1071: // } // End of StyleMapDataHandler.
1072:
1073: // private static class StyleParentDataHandler implements UserDataHandler {
1074: // private static final StyleParentDataHandler INSTANCE = new StyleParentDataHandler();
1075: //
1076: // public static StyleParentDataHandler getDefault() {
1077: // return INSTANCE;
1078: // }
1079: //
1080: // public void handle(short operation, String key, Object data, Node src, Node dst) {
1081: // // No op.
1082: // }
1083: // } // End of StyleParentDataHandler.
1084:
1085: // private static class RenderedTextDataHandler implements UserDataHandler {
1086: // private static final RenderedTextDataHandler INSTANCE = new RenderedTextDataHandler();
1087: //
1088: // public static RenderedTextDataHandler getDefault() {
1089: // return INSTANCE;
1090: // }
1091: //
1092: // public void handle(short operation, String key, Object data, Node src, Node dst) {
1093: // // No op.
1094: // }
1095: // } // End of RenderedTextDataHandler.
1096:
1097: // private static class SourceTextDataHandler implements UserDataHandler {
1098: // private static final SourceTextDataHandler INSTANCE = new SourceTextDataHandler();
1099: //
1100: // public static SourceTextDataHandler getDefault() {
1101: // return INSTANCE;
1102: // }
1103: //
1104: // public void handle(short operation, String key, Object data, Node src, Node dst) {
1105: // // No op.
1106: // }
1107: //
1108: // } // End of SourceTextDataHandler.
1109:
1110: // private static class RenderedElementDataHandler implements UserDataHandler {
1111: // private static final RenderedElementDataHandler INSTANCE = new RenderedElementDataHandler();
1112: //
1113: // public static RenderedElementDataHandler getDefault() {
1114: // return INSTANCE;
1115: // }
1116: //
1117: // public void handle(short operation, String key, Object data, Node src, Node dst) {
1118: // // No op.
1119: // // TODO Make the copying here instead of AbstractRaveElement.copyFrom.
1120: // }
1121: // } // End of RenderedElementDataHandler.
1122:
1123: // private static class SourceElementDataHandler implements UserDataHandler {
1124: // private static final SourceElementDataHandler INSTANCE = new SourceElementDataHandler();
1125: //
1126: // public static SourceElementDataHandler getDefault() {
1127: // return INSTANCE;
1128: // }
1129: //
1130: // public void handle(short operation, String key, Object data, Node src, Node dst) {
1131: // // No op.
1132: // // TODO Make the copying here instead of AbstractRaveElement.copyFrom.
1133: // }
1134: // } // End of SourceElementDataHandler.
1135: }
|