You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SelectorUtil.java 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /*
  2. * Copyright 2000-2013 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.sass.internal.selector;
  17. import java.util.logging.Level;
  18. import java.util.logging.Logger;
  19. import org.w3c.css.sac.CombinatorCondition;
  20. import org.w3c.css.sac.Condition;
  21. import org.w3c.css.sac.ConditionFactory;
  22. import org.w3c.css.sac.ConditionalSelector;
  23. import org.w3c.css.sac.DescendantSelector;
  24. import org.w3c.css.sac.ElementSelector;
  25. import org.w3c.css.sac.Selector;
  26. import org.w3c.css.sac.SelectorFactory;
  27. import org.w3c.css.sac.SelectorList;
  28. import org.w3c.css.sac.SiblingSelector;
  29. import org.w3c.css.sac.SimpleSelector;
  30. import org.w3c.flute.parser.selectors.AndConditionImpl;
  31. import org.w3c.flute.parser.selectors.AttributeConditionImpl;
  32. import org.w3c.flute.parser.selectors.ChildSelectorImpl;
  33. import org.w3c.flute.parser.selectors.ClassConditionImpl;
  34. import org.w3c.flute.parser.selectors.ConditionFactoryImpl;
  35. import org.w3c.flute.parser.selectors.DirectAdjacentSelectorImpl;
  36. import org.w3c.flute.parser.selectors.ElementSelectorImpl;
  37. import org.w3c.flute.parser.selectors.IdConditionImpl;
  38. import org.w3c.flute.parser.selectors.PseudoClassConditionImpl;
  39. import org.w3c.flute.parser.selectors.PseudoElementSelectorImpl;
  40. import org.w3c.flute.parser.selectors.SelectorFactoryImpl;
  41. import com.vaadin.sass.internal.parser.SelectorListImpl;
  42. public class SelectorUtil {
  43. public static String toString(CompositeSelector compositeSelector) {
  44. StringBuilder builder = new StringBuilder();
  45. if (compositeSelector != null) {
  46. if (compositeSelector.getFirst() != null) {
  47. builder.append(toString(compositeSelector.getFirst())).append(
  48. " ");
  49. }
  50. if (compositeSelector.getSecond() != null) {
  51. builder.append(toString(compositeSelector.getSecond()));
  52. }
  53. }
  54. return builder.toString();
  55. }
  56. public static String toString(SelectorList selectorList) {
  57. StringBuilder stringBuilder = new StringBuilder();
  58. for (int i = 0; i < selectorList.getLength(); i++) {
  59. String selectorString = toString(selectorList.item(i));
  60. stringBuilder.append(selectorString);
  61. if (selectorList.getLength() > i + 1) {
  62. stringBuilder.append(", ");
  63. }
  64. }
  65. return stringBuilder.toString();
  66. }
  67. public static String toString(Selector selector) {
  68. if (selector == null) {
  69. return "";
  70. }
  71. if (selector.getSelectorType() == Selector.SAC_CONDITIONAL_SELECTOR) {
  72. StringBuilder stringBuilder = new StringBuilder();
  73. ConditionalSelector conditionalSelector = (ConditionalSelector) selector;
  74. String simpleSelectorString = toString(conditionalSelector
  75. .getSimpleSelector());
  76. if (simpleSelectorString != null) {
  77. stringBuilder.append(simpleSelectorString);
  78. }
  79. String conditionString = getConditionString(conditionalSelector
  80. .getCondition());
  81. stringBuilder.append(conditionString);
  82. return stringBuilder.toString();
  83. } else if (selector.getSelectorType() == Selector.SAC_DESCENDANT_SELECTOR) {
  84. return getDecendantSelectorString((DescendantSelector) selector,
  85. " ");
  86. } else if (selector.getSelectorType() == Selector.SAC_CHILD_SELECTOR) {
  87. DescendantSelector childSelector = (DescendantSelector) selector;
  88. String seperator = " > ";
  89. if (childSelector.getSimpleSelector() instanceof PseudoElementSelectorImpl) {
  90. seperator = "::";
  91. }
  92. return getDecendantSelectorString((DescendantSelector) selector,
  93. seperator);
  94. } else if (selector.getSelectorType() == Selector.SAC_ELEMENT_NODE_SELECTOR) {
  95. ElementSelectorImpl elementSelector = (ElementSelectorImpl) selector;
  96. return elementSelector.getLocalName() == null ? ""
  97. : elementSelector.getLocalName();
  98. } else if (selector.getSelectorType() == Selector.SAC_DIRECT_ADJACENT_SELECTOR) {
  99. DirectAdjacentSelectorImpl directAdjacentSelector = (DirectAdjacentSelectorImpl) selector;
  100. StringBuilder stringBuilder = new StringBuilder();
  101. stringBuilder
  102. .append(toString(directAdjacentSelector.getSelector()));
  103. stringBuilder.append(" + ");
  104. stringBuilder.append(toString(directAdjacentSelector
  105. .getSiblingSelector()));
  106. return stringBuilder.toString();
  107. } else if (selector.getSelectorType() == Selector.SAC_PSEUDO_ELEMENT_SELECTOR) {
  108. PseudoElementSelectorImpl pseudoElementSelectorImpl = (PseudoElementSelectorImpl) selector;
  109. return pseudoElementSelectorImpl.getLocalName();
  110. } else if (selector.getSelectorType() == CompositeSelector.SCSS_COMPOSITE_SELECTOR) {
  111. return toString((CompositeSelector) selector);
  112. } else {
  113. log("SU !Unknown selector type, type: "
  114. + selector.getSelectorType() + ", " + selector.toString());
  115. }
  116. return "";
  117. }
  118. private static String getDecendantSelectorString(
  119. DescendantSelector selector, String separator) {
  120. StringBuilder stringBuilder = new StringBuilder();
  121. String ancestor = toString(selector.getAncestorSelector());
  122. String simpleSelector = toString(selector.getSimpleSelector());
  123. stringBuilder.append(ancestor);
  124. stringBuilder.append(separator);
  125. stringBuilder.append(simpleSelector);
  126. return stringBuilder.toString();
  127. }
  128. private static String getConditionString(Condition condition) {
  129. short conditionType = condition.getConditionType();
  130. if (conditionType == Condition.SAC_CLASS_CONDITION) {
  131. ClassConditionImpl classCondition = (ClassConditionImpl) condition;
  132. return "." + classCondition.getValue();
  133. } else if (conditionType == Condition.SAC_ID_CONDITION) {
  134. IdConditionImpl idCondition = (IdConditionImpl) condition;
  135. return "#" + idCondition.getValue();
  136. } else if (conditionType == Condition.SAC_AND_CONDITION) {
  137. AndConditionImpl andCondition = (AndConditionImpl) condition;
  138. return getConditionString(andCondition.getFirstCondition())
  139. + getConditionString(andCondition.getSecondCondition());
  140. } else if (conditionType == Condition.SAC_ATTRIBUTE_CONDITION) {
  141. AttributeConditionImpl attributeCondition = (AttributeConditionImpl) condition;
  142. StringBuilder string = new StringBuilder();
  143. string.append('[');
  144. string.append(attributeCondition.getLocalName());
  145. String value = attributeCondition.getValue();
  146. if ("true".equals(value) || "false".equals(value)) {
  147. string.append("=").append(value).append(']');
  148. } else {
  149. string.append("=\"");
  150. string.append(attributeCondition.getValue());
  151. string.append("\"]");
  152. }
  153. return string.toString();
  154. } else if (conditionType == Condition.SAC_PSEUDO_CLASS_CONDITION) {
  155. PseudoClassConditionImpl pseudoClassCondition = (PseudoClassConditionImpl) condition;
  156. return ":" + pseudoClassCondition.getValue();
  157. } else {
  158. log("CU !condition type not identified, type: " + conditionType
  159. + ", " + condition.toString());
  160. return "";
  161. }
  162. }
  163. public static boolean hasParentSelector(SelectorList selectorList) {
  164. String selectorString = toString(selectorList);
  165. return selectorString.contains("&");
  166. }
  167. public static SelectorList createNewSelectorListFromAnOldOneWithSomPartReplaced(
  168. SelectorList oldList, String toBeReplacedSelectorName,
  169. SelectorList candidateSelectorList) throws Exception {
  170. if (candidateSelectorList.getLength() != 1) {
  171. throw new Exception("Candidate selector should not be a list");
  172. }
  173. if (!(candidateSelectorList.item(0) instanceof SimpleSelector)) {
  174. throw new Exception(
  175. "Candidate selector should only be a SimpleSelector");
  176. }
  177. SelectorListImpl newSelectorList = new SelectorListImpl();
  178. SimpleSelector candidateSelector = (SimpleSelector) candidateSelectorList
  179. .item(0);
  180. for (int i = 0; i < oldList.getLength(); i++) {
  181. Selector selector = oldList.item(i);
  182. newSelectorList.addSelector(createSelectorWithSomePartReplaced(
  183. selector, toBeReplacedSelectorName, candidateSelector));
  184. }
  185. return newSelectorList;
  186. }
  187. private static Selector createSelectorWithSomePartReplaced(
  188. Selector selector, String toBeReplacedSelectorName,
  189. SimpleSelector candidateSelector) {
  190. if (!toString(selector).contains(toBeReplacedSelectorName)) {
  191. return selector;
  192. }
  193. SelectorFactory factory = new SelectorFactoryImpl();
  194. if (selector instanceof SimpleSelector) {
  195. return createSimpleSelectorWithSomePartReplaced(
  196. (SimpleSelector) selector, toBeReplacedSelectorName,
  197. candidateSelector);
  198. } else if (selector instanceof DescendantSelector) {
  199. DescendantSelector descendantSelector = (DescendantSelector) selector;
  200. Selector ancestor = descendantSelector.getAncestorSelector();
  201. SimpleSelector simpleSelector = descendantSelector
  202. .getSimpleSelector();
  203. return factory.createDescendantSelector(
  204. createSelectorWithSomePartReplaced(ancestor,
  205. toBeReplacedSelectorName, candidateSelector),
  206. createSimpleSelectorWithSomePartReplaced(simpleSelector,
  207. toBeReplacedSelectorName, candidateSelector));
  208. } else if (selector instanceof DirectAdjacentSelectorImpl) {
  209. SiblingSelector siblingSelector = (SiblingSelector) selector;
  210. Selector ancestor = siblingSelector.getSelector();
  211. SimpleSelector simpleSelector = siblingSelector
  212. .getSiblingSelector();
  213. return factory.createDirectAdjacentSelector(
  214. Selector.SAC_DIRECT_ADJACENT_SELECTOR, ancestor,
  215. simpleSelector);
  216. } else if (selector instanceof CompositeSelector) {
  217. CompositeSelector compositeSelector = (CompositeSelector) selector;
  218. Selector first = compositeSelector.getFirst();
  219. Selector second = compositeSelector.getSecond();
  220. return new CompositeSelector(createSelectorWithSomePartReplaced(
  221. first, toBeReplacedSelectorName, candidateSelector),
  222. createSelectorWithSomePartReplaced(second,
  223. toBeReplacedSelectorName, candidateSelector));
  224. }
  225. return null;
  226. }
  227. private static SimpleSelector createSimpleSelectorWithSomePartReplaced(
  228. SimpleSelector simpleSelector, String toBeReplacedSelectorName,
  229. SimpleSelector candidateSelector) {
  230. if (simpleSelector == null
  231. || !toString(simpleSelector).contains(toBeReplacedSelectorName)) {
  232. return simpleSelector;
  233. }
  234. if (simpleSelector instanceof ElementSelector
  235. && candidateSelector instanceof ElementSelector) {
  236. return candidateSelector;
  237. }
  238. if (simpleSelector instanceof ConditionalSelector) {
  239. return createConditionSelectorWithSomePartReplaced(
  240. (ConditionalSelector) simpleSelector,
  241. toBeReplacedSelectorName, candidateSelector);
  242. }
  243. return simpleSelector;
  244. }
  245. private static ConditionalSelector createConditionSelectorWithSomePartReplaced(
  246. ConditionalSelector oldConditionSelector,
  247. String toBeReplacedSelectorName, SimpleSelector candidateSelector) {
  248. if (oldConditionSelector == null
  249. || !toString(oldConditionSelector).contains(
  250. toBeReplacedSelectorName)) {
  251. return oldConditionSelector;
  252. }
  253. SelectorFactory selectorFactory = new SelectorFactoryImpl();
  254. if (candidateSelector instanceof ElementSelector) {
  255. return selectorFactory.createConditionalSelector(candidateSelector,
  256. oldConditionSelector.getCondition());
  257. }
  258. if (candidateSelector instanceof ConditionalSelector) {
  259. // TODO some cases not covered.
  260. ConditionalSelector candidateConditionSelector = (ConditionalSelector) candidateSelector;
  261. Condition newCondition = createConditionWithSomePartReplaced(
  262. oldConditionSelector.getCondition(),
  263. toBeReplacedSelectorName,
  264. candidateConditionSelector.getCondition());
  265. return selectorFactory.createConditionalSelector(
  266. oldConditionSelector.getSimpleSelector(), newCondition);
  267. }
  268. return oldConditionSelector;
  269. }
  270. private static Condition createConditionWithSomePartReplaced(
  271. Condition oldCondition, String toBeReplaced, Condition candidate) {
  272. if (oldCondition == null
  273. || !getConditionString(oldCondition).contains(toBeReplaced)) {
  274. return oldCondition;
  275. }
  276. if (oldCondition.getConditionType() == Condition.SAC_AND_CONDITION) {
  277. ConditionFactory conditionFactory = new ConditionFactoryImpl();
  278. CombinatorCondition oldCombinatorCondition = (CombinatorCondition) oldCondition;
  279. Condition newFirstCondition = createConditionWithSomePartReplaced(
  280. oldCombinatorCondition.getFirstCondition(), toBeReplaced,
  281. candidate);
  282. Condition newSecondCondition = createConditionWithSomePartReplaced(
  283. oldCombinatorCondition.getSecondCondition(), toBeReplaced,
  284. candidate);
  285. return conditionFactory.createAndCondition(newFirstCondition,
  286. newSecondCondition);
  287. } else {
  288. return candidate;
  289. }
  290. }
  291. public static boolean equals(Selector one, Selector another) {
  292. return one == null ? another == null : toString(one).equals(
  293. toString(another));
  294. }
  295. public static Selector createSelectorAndreplaceSelectorVariableWithValue(
  296. Selector selector, String variable, String value) throws Exception {
  297. SelectorFactoryImpl factory = new SelectorFactoryImpl();
  298. ElementSelector es = factory.createElementSelector(
  299. null,
  300. ((ElementSelector) selector).getLocalName().replaceAll(
  301. variable, value));
  302. if (selector instanceof ConditionalSelector) {
  303. return factory.createConditionalSelector(es,
  304. ((ConditionalSelector) selector).getCondition());
  305. } else if (selector instanceof DescendantSelector) {
  306. return factory.createDescendantSelector(es,
  307. ((DescendantSelector) selector).getSimpleSelector());
  308. } else if (selector instanceof ChildSelectorImpl) {
  309. return factory.createChildSelector(es,
  310. ((DescendantSelector) selector).getSimpleSelector());
  311. } else {
  312. throw new Exception("Invalid selector type");
  313. }
  314. }
  315. private static void log(String msg) {
  316. Logger.getLogger(SelectorUtil.class.getName()).log(Level.INFO, msg);
  317. }
  318. }