/******************************************************************************* * Copyright (c) 2004, 2008 John Krasnay and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * John Krasnay - initial API and implementation *******************************************************************************/ package net.sf.vex.css; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import org.w3c.css.sac.AttributeCondition; import org.w3c.css.sac.CharacterDataSelector; import org.w3c.css.sac.CombinatorCondition; import org.w3c.css.sac.Condition; import org.w3c.css.sac.ConditionalSelector; import org.w3c.css.sac.ContentCondition; import org.w3c.css.sac.DescendantSelector; import org.w3c.css.sac.ElementSelector; import org.w3c.css.sac.LangCondition; import org.w3c.css.sac.LexicalUnit; import org.w3c.css.sac.NegativeCondition; import org.w3c.css.sac.NegativeSelector; import org.w3c.css.sac.PositionalCondition; import org.w3c.css.sac.ProcessingInstructionSelector; import org.w3c.css.sac.Selector; import org.w3c.css.sac.SiblingSelector; import org.w3c.css.sac.SimpleSelector; /** * Factory for producing serializable Conditions, LexicalUnits, and * Selectors. The SAC parser creates instances of these that may not be * serializable (and in fact, those from Flute aren't). To serialize * StyleSheets, which contain references to these SAC objects, we must * clone the objects into our own serializable ones. */ public class SacFactory { /** * Clone the given condition, returning one that is serializable. * @param condition Condition to clone. */ public Condition cloneCondition(Condition condition) { Condition clone = null; if (condition == null) { return null; } else if (condition instanceof AttributeCondition) { clone = new AttributeConditionImpl((AttributeCondition) condition); } else if (condition instanceof CombinatorCondition) { clone = new CombinatorConditionImpl((CombinatorCondition) condition, this); } else if (condition instanceof ContentCondition) { clone = new ContentConditionImpl((ContentCondition) condition); } else if (condition instanceof LangCondition) { clone = new LangConditionImpl((LangCondition) condition); } else if (condition instanceof NegativeCondition) { clone = new NegativeConditionImpl((NegativeCondition) condition, this); } else if (condition instanceof PositionalCondition) { clone = new PositionalConditionImpl((PositionalCondition) condition); } else { throw new IllegalArgumentException("Unsupported condition type: " + condition.getClass()); } return clone; } /** * Clone the given lexical unit, returning one that is serializable. * @param lu LexicalUnit to clone. */ public LexicalUnit cloneLexicalUnit(LexicalUnit lu) { if (lu == null) { return null; } else if (this.cache.containsKey(lu)) { return (LexicalUnit) this.cache.get(lu); } else { return new LexicalUnitImpl(lu, this); } } /** * Clone the given selector, returning one that is serializable. */ public Selector cloneSelector(Selector selector) { Selector clone = null; if (selector == null) { return null; } else if (selector instanceof CharacterDataSelector) { clone = new CharacterDataSelectorImpl((CharacterDataSelector) selector); } else if (selector instanceof ConditionalSelector) { clone = new ConditionalSelectorImpl((ConditionalSelector) selector, this); } else if (selector instanceof DescendantSelector) { clone = new DescendantSelectorImpl((DescendantSelector) selector, this); } else if (selector instanceof ElementSelector) { clone = new ElementSelectorImpl((ElementSelector) selector); } else if (selector instanceof NegativeSelector) { clone = new NegativeSelectorImpl((NegativeSelector) selector, this); } else if (selector instanceof ProcessingInstructionSelector) { clone = new ProcessingInstructionSelectorImpl((ProcessingInstructionSelector) selector); } else if (selector instanceof SiblingSelector) { clone = new SiblingSelectorImpl((SiblingSelector) selector, this); } else { throw new IllegalArgumentException("Unsupported selector type: " + selector.getClass()); } return clone; } //===================================================== PRIVATE private Map cache = new HashMap(); private static class ConditionImpl implements Condition, Serializable { public ConditionImpl(Condition condition) { this.type = condition.getConditionType(); } public short getConditionType() { return this.type; } private short type; } private static class AttributeConditionImpl extends ConditionImpl implements AttributeCondition { public AttributeConditionImpl(AttributeCondition condition) { super(condition); this.namespaceURI = condition.getNamespaceURI(); this.localName = condition.getLocalName(); this.specified = condition.getSpecified(); this.value = condition.getValue(); } public String getNamespaceURI() { return this.namespaceURI; } public String getLocalName() { return this.localName; } public boolean getSpecified() { return this.specified; } public String getValue() { return this.value; } private String namespaceURI; private String localName; private boolean specified; private String value; } private static class CombinatorConditionImpl extends ConditionImpl implements CombinatorCondition { public CombinatorConditionImpl(CombinatorCondition condition, SacFactory factory) { super(condition); this.firstCondition = factory.cloneCondition(condition.getFirstCondition()); this.secondCondition = factory.cloneCondition(condition.getSecondCondition()); } public Condition getFirstCondition() { return this.firstCondition; } public Condition getSecondCondition() { return this.secondCondition; } private Condition firstCondition; private Condition secondCondition; } private static class ContentConditionImpl extends ConditionImpl implements ContentCondition { public ContentConditionImpl(ContentCondition condition) { super(condition); this.data = condition.getData(); } public String getData() { return this.data; } private String data; } private static class LangConditionImpl extends ConditionImpl implements LangCondition { public LangConditionImpl(LangCondition condition) { super(condition); this.lang = condition.getLang(); } public String getLang() { return this.lang; } private String lang; } private static class NegativeConditionImpl extends ConditionImpl implements NegativeCondition { public NegativeConditionImpl(NegativeCondition condition, SacFactory factory) { super(condition); this.condition = factory.cloneCondition(condition.getCondition()); } public Condition getCondition() { return this.condition; } private Condition condition; } private static class PositionalConditionImpl extends ConditionImpl implements PositionalCondition { public PositionalConditionImpl(PositionalCondition condition) { super(condition); this.position = condition.getPosition(); this.typeNode = condition.getTypeNode(); this.type = condition.getType(); } public int getPosition() { return this.position; } public boolean getTypeNode() { return this.typeNode; } public boolean getType() { return this.type; } private int position; private boolean typeNode; private boolean type; } private static class LexicalUnitImpl implements LexicalUnit, Serializable { public LexicalUnitImpl(LexicalUnit lu, SacFactory factory) { factory.cache.put(lu, this); this.type = lu.getLexicalUnitType(); this.s = lu.getStringValue(); this.i = lu.getIntegerValue(); this.f = lu.getFloatValue(); this.functionName = lu.getFunctionName(); this.next = factory.cloneLexicalUnit(lu.getNextLexicalUnit()); this.prev = factory.cloneLexicalUnit(lu.getPreviousLexicalUnit()); this.parameters = factory.cloneLexicalUnit(lu.getParameters()); if (this.type == SAC_PERCENTAGE || this.type == SAC_EM || this.type == SAC_EX || this.type == SAC_PIXEL || this.type == SAC_CENTIMETER || this.type == SAC_MILLIMETER || this.type == SAC_INCH || this.type == SAC_POINT || this.type == SAC_PICA || this.type == SAC_DEGREE || this.type == SAC_RADIAN || this.type == SAC_GRADIAN || this.type == SAC_MILLISECOND || this.type == SAC_SECOND || this.type == SAC_HERTZ || this.type == SAC_KILOHERTZ || this.type == SAC_DIMENSION) { this.dimensionText = lu.getDimensionUnitText(); } this.stringRepresentation = lu.toString(); } public short getLexicalUnitType() { return this.type; } public LexicalUnit getNextLexicalUnit() { return this.next; } public LexicalUnit getPreviousLexicalUnit() { return this.prev; } public int getIntegerValue() { return this.i; } public float getFloatValue() { return this.f; } public String getDimensionUnitText() { return this.dimensionText; } public String getFunctionName() { return this.functionName; } public LexicalUnit getParameters() { return this.parameters; } public String getStringValue() { return this.s; } public String getStringRepresentation() { return this.stringRepresentation; } public LexicalUnit getSubValues() { return this.parameters; } //================================================= PRIVATE private LexicalUnitImpl() { } private short type; private LexicalUnit next; private LexicalUnit prev; private LexicalUnit parameters; private String s; private int i; private float f; private String functionName; private String dimensionText; private String stringRepresentation; } private static class SelectorImpl implements Selector, Serializable { public SelectorImpl(Selector selector) { this.type = selector.getSelectorType(); } public short getSelectorType() { return this.type; } private short type; } private static class CharacterDataSelectorImpl extends SelectorImpl implements CharacterDataSelector { public CharacterDataSelectorImpl(CharacterDataSelector selector) { super(selector); this.data = selector.getData(); } public String getData() { return this.data; } private String data; } private static class ConditionalSelectorImpl extends SelectorImpl implements ConditionalSelector { public ConditionalSelectorImpl(ConditionalSelector selector, SacFactory factory) { super(selector); this.condition = factory.cloneCondition(selector.getCondition()); this.simpleSelector = (SimpleSelector) factory.cloneSelector(selector.getSimpleSelector()); } public SimpleSelector getSimpleSelector() { return this.simpleSelector; } public Condition getCondition() { return this.condition; } private Condition condition; private SimpleSelector simpleSelector; } private static class DescendantSelectorImpl extends SelectorImpl implements DescendantSelector { public DescendantSelectorImpl(DescendantSelector selector, SacFactory factory) { super(selector); this.ancestor = factory.cloneSelector(selector.getAncestorSelector()); this.simpleSelector = (SimpleSelector) factory.cloneSelector(selector.getSimpleSelector()); } public Selector getAncestorSelector() { return this.ancestor; } public SimpleSelector getSimpleSelector() { return this.simpleSelector; } private Selector ancestor; private SimpleSelector simpleSelector; } private static class ElementSelectorImpl extends SelectorImpl implements ElementSelector { public ElementSelectorImpl(ElementSelector selector) { super(selector); this.namespaceURI = selector.getNamespaceURI(); this.localName = selector.getLocalName(); } public String getNamespaceURI() { return this.namespaceURI; } public String getLocalName() { return this.localName; } private String namespaceURI; private String localName; } private static class NegativeSelectorImpl extends SelectorImpl implements NegativeSelector { public NegativeSelectorImpl(NegativeSelector selector, SacFactory factory) { super(selector); this.simpleSelector = (SimpleSelector) factory.cloneSelector(selector.getSimpleSelector()); } public SimpleSelector getSimpleSelector() { return this.simpleSelector; } private SimpleSelector simpleSelector; } private static class ProcessingInstructionSelectorImpl extends SelectorImpl implements ProcessingInstructionSelector { public ProcessingInstructionSelectorImpl(ProcessingInstructionSelector selector) { super(selector); this.target = selector.getTarget(); this.data = selector.getData(); } public String getTarget() { return this.target; } public String getData() { return this.data; } private String target; private String data; } private static class SiblingSelectorImpl extends SelectorImpl implements SiblingSelector { private SiblingSelectorImpl(SiblingSelector selector, SacFactory factory) { super(selector); this.nodeType = selector.getNodeType(); this.selector = factory.cloneSelector(selector.getSelector()); this.siblingSelector = (SimpleSelector) factory.cloneSelector(selector.getSiblingSelector()); } public short getNodeType() { return this.nodeType; } public Selector getSelector() { return this.selector; } public SimpleSelector getSiblingSelector() { return this.siblingSelector; } private short nodeType; private Selector selector; private SimpleSelector siblingSelector; } }