/*
* $Id: CSSStyleSheetImpl.java,v 1.2 2008/03/26 02:17:24 sdanig Exp $
*
* CSS Parser Project
*
* Copyright (C) 1999-2005 David Schweinsberg. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* To contact the authors of the library:
*
* http://cssparser.sourceforge.net/
* mailto:davidsch@users.sourceforge.net
*/
package com.steadystate.css.dom;
import java.io.IOException;
import java.io.Serializable;
import java.io.StringReader;
import org.w3c.dom.DOMException;
import org.w3c.dom.Node;
import org.w3c.dom.stylesheets.MediaList;
import org.w3c.dom.stylesheets.StyleSheet;
import org.w3c.dom.css.CSSImportRule;
import org.w3c.dom.css.CSSRule;
import org.w3c.dom.css.CSSRuleList;
import org.w3c.dom.css.CSSStyleSheet;
import org.w3c.css.sac.CSSException;
import org.w3c.css.sac.InputSource;
import org.w3c.css.sac.SACMediaList;
import com.steadystate.css.parser.CSSOMParser;
import com.steadystate.css.parser.SACParserCSS2;
/**
* Implementation of {@link CSSStyleSheet}.
*
* @author <a href="mailto:davidsch@users.sourceforge.net">David Schweinsberg</a>
* @version $Id: CSSStyleSheetImpl.java,v 1.2 2008/03/26 02:17:24 sdanig Exp $
*/
public class CSSStyleSheetImpl implements CSSStyleSheet, Serializable {
private static final long serialVersionUID = -2300541300646796363L;
private boolean disabled = false;
private Node ownerNode = null;
private StyleSheet parentStyleSheet = null;
private String href = null;
private String title = null;
private MediaList media = null;
private CSSRule ownerRule = null;
private boolean readOnly = false;
private CSSRuleList cssRules = null;
private String baseUri;
public void setMedia(MediaList media)
{
this.media = media;
}
private String getBaseUri()
{
return this.baseUri;
}
public void setBaseUri(String baseUri)
{
this.baseUri = baseUri;
}
public CSSStyleSheetImpl() {
}
public String getType() {
return "text/css";
}
public boolean getDisabled() {
return this.disabled;
}
/**
* We will need to respond more fully if a stylesheet is disabled, probably
* by generating an event for the main application.
*/
public void setDisabled(boolean disabled) {
this.disabled = disabled;
}
public Node getOwnerNode() {
return this.ownerNode;
}
public StyleSheet getParentStyleSheet() {
return this.parentStyleSheet;
}
public String getHref() {
return this.href;
}
public String getTitle() {
return this.title;
}
public MediaList getMedia() {
return this.media;
}
public CSSRule getOwnerRule() {
return this.ownerRule;
}
public CSSRuleList getCssRules() {
if (this.cssRules == null)
{
this.cssRules = new CSSRuleListImpl();
}
return this.cssRules;
}
public int insertRule(String rule, int index) throws DOMException {
if (this.readOnly) {
throw new DOMExceptionImpl(
DOMException.NO_MODIFICATION_ALLOWED_ERR,
DOMExceptionImpl.READ_ONLY_STYLE_SHEET);
}
try {
InputSource is = new InputSource(new StringReader(rule));
CSSOMParser parser = new CSSOMParser();
parser.setParentStyleSheet(this);
CSSRule r = parser.parseRule(is);
if (getCssRules().getLength() > 0) {
// We need to check that this type of rule can legally go into
// the requested position.
int msg = -1;
if (r.getType() == CSSRule.CHARSET_RULE) {
// Index must be 0, and there can be only one charset rule
if (index != 0) {
msg = DOMExceptionImpl.CHARSET_NOT_FIRST;
} else if (getCssRules().item(0).getType()
== CSSRule.CHARSET_RULE) {
msg = DOMExceptionImpl.CHARSET_NOT_UNIQUE;
}
} else if (r.getType() == CSSRule.IMPORT_RULE) {
// Import rules must preceed all other rules (except
// charset rules)
if (index <= getCssRules().getLength()) {
for (int i = 0; i < index; i++) {
int rt = getCssRules().item(i).getType();
if ((rt != CSSRule.CHARSET_RULE)
|| (rt != CSSRule.IMPORT_RULE)) {
msg = DOMExceptionImpl.IMPORT_NOT_FIRST;
break;
}
}
}
}
if (msg > -1) {
throw new DOMExceptionImpl(
DOMException.HIERARCHY_REQUEST_ERR,
msg);
}
}
// Insert the rule into the list of rules
((CSSRuleListImpl)getCssRules()).insert(r, index);
} catch (ArrayIndexOutOfBoundsException e) {
throw new DOMExceptionImpl(
DOMException.INDEX_SIZE_ERR,
DOMExceptionImpl.ARRAY_OUT_OF_BOUNDS,
e.getMessage());
} catch (CSSException e) {
throw new DOMExceptionImpl(
DOMException.SYNTAX_ERR,
DOMExceptionImpl.SYNTAX_ERROR,
e.getMessage());
} catch (IOException e) {
throw new DOMExceptionImpl(
DOMException.SYNTAX_ERR,
DOMExceptionImpl.SYNTAX_ERROR,
e.getMessage());
}
return index;
}
public void deleteRule(int index) throws DOMException {
if (this.readOnly) {
throw new DOMExceptionImpl(
DOMException.NO_MODIFICATION_ALLOWED_ERR,
DOMExceptionImpl.READ_ONLY_STYLE_SHEET);
}
try {
((CSSRuleListImpl)getCssRules()).delete(index);
} catch (ArrayIndexOutOfBoundsException e) {
throw new DOMExceptionImpl(
DOMException.INDEX_SIZE_ERR,
DOMExceptionImpl.ARRAY_OUT_OF_BOUNDS,
e.getMessage());
}
}
public boolean isReadOnly() {
return this.readOnly;
}
public void setReadOnly(boolean b) {
this.readOnly = b;
}
public void setOwnerNode(Node ownerNode) {
this.ownerNode = ownerNode;
}
public void setParentStyleSheet(StyleSheet parentStyleSheet) {
this.parentStyleSheet = parentStyleSheet;
}
public void setHref(String href) {
this.href = href;
}
public void setTitle(String title) {
this.title = title;
}
public void setMediaText(String mediaText) {
InputSource source = new InputSource(new StringReader(mediaText));
try
{
// TODO get SAC Parser version from System property?
SACMediaList sml = new SACParserCSS2().parseMedia(source);
this.media = new MediaListImpl(sml);
}
catch (IOException e)
{
// TODO handle exception
}
}
public void setOwnerRule(CSSRule ownerRule) {
this.ownerRule = ownerRule;
}
public void setCssRules(CSSRuleList rules) {
this.cssRules = rules;
}
public String toString() {
return this.getCssRules().toString();
}
/**
* Imports referenced CSSStyleSheets.
*
* @param recursive <code>true</code> if the import should be done
* recursively, <code>false</code> otherwise
*/
public void importImports(boolean recursive)
throws DOMException
{
for (int i = 0; i < this.getCssRules().getLength(); i++)
{
CSSRule cssRule = this.getCssRules().item(i);
if (cssRule.getType() == CSSRule.IMPORT_RULE)
{
CSSImportRule cssImportRule = (CSSImportRule) cssRule;
try
{
java.net.URI importURI = new java.net.URI(this.getBaseUri())
.resolve(cssImportRule.getHref());
CSSStyleSheetImpl importedCSS = (CSSStyleSheetImpl)
new CSSOMParser().parseStyleSheet(new InputSource(
importURI.toString()), null, importURI.toString());
if (recursive)
{
importedCSS.importImports(recursive);
}
MediaList mediaList = cssImportRule.getMedia();
if (mediaList.getLength() == 0)
{
mediaList.appendMedium("all");
}
CSSMediaRuleImpl cssMediaRule =
new CSSMediaRuleImpl(this, null, mediaList);
cssMediaRule.setRuleList(
(CSSRuleListImpl) importedCSS.getCssRules());
this.deleteRule(i);
((CSSRuleListImpl) this.getCssRules()).insert(cssMediaRule, i);
}
catch (java.net.URISyntaxException e)
{
// TODO handle exception
throw new DOMException(DOMException.SYNTAX_ERR,
e.getLocalizedMessage());
}
catch (IOException e)
{
// TODO handle exception
}
}
}
}
}