/src/org/mt4j/components/css/style/CSSSelector.java

http://mt4j.googlecode.com/ · Java · 755 lines · 466 code · 103 blank · 186 comment · 183 complexity · fbc4d6cc0592f15c2db44f088c6bdf65 MD5 · raw file

  1. package org.mt4j.components.css.style;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import org.mt4j.components.MTCanvas;
  5. import org.mt4j.components.MTComponent;
  6. import org.mt4j.components.css.util.CSSKeywords.CSSSelectorType;
  7. /**
  8. * The Class CSSSelector.
  9. */
  10. public class CSSSelector {
  11. /** The primary part of the selector */
  12. String primary = null;
  13. /** The type of the primary part of the selector */
  14. CSSSelectorType primaryType = null;
  15. /** The secondary part of the selector. */
  16. String secondary = null;
  17. /** The type of the secondary part of the selector. */
  18. CSSSelectorType secondaryType = null;
  19. /**
  20. * Instantiates a new CSS selector.
  21. *
  22. * @param primary the primary part of the selector
  23. * @param primaryType the type of the primary part of the selector
  24. */
  25. public CSSSelector(String primary, CSSSelectorType primaryType) {
  26. super();
  27. this.primary = check(primary);
  28. this.primaryType = primaryType;
  29. }
  30. /** Does the selector have a child. */
  31. boolean selectChild = false;
  32. /** The child. */
  33. CSSSelector child = null;
  34. /**
  35. * Gets the primary part of the selector
  36. *
  37. * @return the primary part of the selector
  38. */
  39. public String getPrimary() {
  40. return primary;
  41. }
  42. /**
  43. * Sets the primary part of the selector.
  44. *
  45. * @param primary the new primary part of the selector
  46. */
  47. public void setPrimary(String primary) {
  48. this.primary = check(primary);
  49. }
  50. /**
  51. * Gets the type of the primary part of the selector.
  52. *
  53. * @return the type of the primary part of the selector.
  54. */
  55. public CSSSelectorType getPrimaryType() {
  56. return primaryType;
  57. }
  58. /**
  59. * Sets the type of the primary part of the selector.
  60. *
  61. * @param primaryType the new type of the primary part of the selector.
  62. */
  63. public void setPrimaryType(CSSSelectorType primaryType) {
  64. this.primaryType = primaryType;
  65. }
  66. /**
  67. * Gets the secondary part of the selector.
  68. *
  69. * @return the secondary part of the selector
  70. */
  71. public String getSecondary() {
  72. return secondary;
  73. }
  74. /**
  75. * Sets the secondary part of the selector
  76. *
  77. * @param secondary the new secondary part of the selector
  78. */
  79. public void setSecondary(String secondary) {
  80. this.secondary = check(secondary);
  81. }
  82. /**
  83. * Sets the secondary.
  84. *
  85. * @param secondary the secondary part of the selector
  86. * @param type the type of the secondary part of the selector
  87. */
  88. public void setSecondary(String secondary, CSSSelectorType type) {
  89. this.secondary = check(secondary);
  90. this.secondaryType = type;
  91. }
  92. /**
  93. * Gets the type of the secondary part of the selector
  94. *
  95. * @return the type of the secondary part of the selector
  96. */
  97. public CSSSelectorType getSecondaryType() {
  98. return secondaryType;
  99. }
  100. /**
  101. * Sets the type of the secondary part of the selector
  102. *
  103. * @param secondaryType the new secondary type of the secondary part of the selector
  104. */
  105. public void setSecondaryType(CSSSelectorType secondaryType) {
  106. this.secondaryType = secondaryType;
  107. }
  108. /**
  109. * Checks if the selector has a child.
  110. *
  111. * @return true, if is select child
  112. */
  113. public boolean isSelectChild() {
  114. return selectChild;
  115. }
  116. /**
  117. * Sets, whether the selector has a child
  118. *
  119. * @param selectChild the new select child
  120. */
  121. public void setSelectChild(boolean selectChild) {
  122. this.selectChild = selectChild;
  123. }
  124. /**
  125. * Gets the child.
  126. *
  127. * @return the child
  128. */
  129. public CSSSelector getChild() {
  130. if (selectChild) return child;
  131. else return null;
  132. }
  133. /**
  134. * Sets the child.
  135. *
  136. * @param child the new child
  137. */
  138. public void setChild(CSSSelector child) {
  139. if (child != null) {
  140. this.selectChild = true;
  141. this.child = child;
  142. } else {
  143. this.selectChild = false;
  144. this.child = null;
  145. }
  146. }
  147. /* (non-Javadoc)
  148. * @see java.lang.Object#hashCode()
  149. */
  150. @Override
  151. public int hashCode() {
  152. final int prime = 31;
  153. int result = 1;
  154. result = prime * result + ((child == null) ? 0 : child.hashCode());
  155. result = prime * result + ((primary == null) ? 0 : primary.hashCode());
  156. result = prime * result
  157. + ((primaryType == null) ? 0 : primaryType.hashCode());
  158. result = prime * result
  159. + ((secondary == null) ? 0 : secondary.hashCode());
  160. result = prime * result
  161. + ((secondaryType == null) ? 0 : secondaryType.hashCode());
  162. return result;
  163. }
  164. /* (non-Javadoc)
  165. * @see java.lang.Object#equals(java.lang.Object)
  166. */
  167. @Override
  168. public boolean equals(Object obj) {
  169. if (this == obj)
  170. return true;
  171. if (obj == null)
  172. return false;
  173. if (getClass() != obj.getClass())
  174. return false;
  175. CSSSelector other = (CSSSelector) obj;
  176. if (child == null) {
  177. if (other.child != null)
  178. return false;
  179. } else if (!child.equals(other.child))
  180. return false;
  181. if (primary == null) {
  182. if (other.primary != null)
  183. return false;
  184. } else if (!primary.equalsIgnoreCase(other.primary))
  185. return false;
  186. if (primaryType == null) {
  187. if (other.primaryType != null)
  188. return false;
  189. } else if (!primaryType.equals(other.primaryType))
  190. return false;
  191. if (secondary == null) {
  192. if (other.secondary != null)
  193. return false;
  194. } else if (!secondary.equalsIgnoreCase(other.secondary))
  195. return false;
  196. if (secondaryType == null) {
  197. if (other.secondaryType != null)
  198. return false;
  199. } else if (!secondaryType.equals(other.secondaryType))
  200. return false;
  201. return true;
  202. }
  203. /* (non-Javadoc)
  204. * @see java.lang.Object#toString()
  205. */
  206. @Override
  207. public String toString() {
  208. String childString = "";
  209. if (child != null) childString = " Child: " + child.toString();
  210. if (primary != null) {
  211. if (secondary != null) {
  212. return "Primary Selector: " + primary +
  213. " (" + primaryType + "), Secondary Selector: " + secondary + " (" + secondaryType + ")" + childString;
  214. } else {
  215. return "Primary Selector: " + primary +
  216. " (" + primaryType + ")" + childString;
  217. }
  218. }
  219. return "No Selector";
  220. }
  221. /**
  222. * Replace all unwanted characters (" ", ".", "#")
  223. *
  224. * @param input the input
  225. * @return the string
  226. */
  227. private String check(String input) {
  228. return input.replace(" ", "").replace(".", "").replace("#", "");
  229. }
  230. /**
  231. * Checks, whether the selector applies to a component
  232. *
  233. * @param c the MTComponent
  234. * @return the priority of the selector (0 if does not apply)
  235. * Selector: Pos1 Pos2 > Pos3 Pos 4
  236. * 100-199 200-299 300-399 400-499
  237. */
  238. public int appliesTo(MTComponent c) {
  239. // Selector: Pos1 Pos2 > Pos3 Pos 4
  240. // 100-199 200-299 300-399 400-499
  241. List<String> superclasses = getSuperclasses(c.getClass());
  242. try {
  243. if (secondary == null && child == null) {
  244. switch (primaryType) {
  245. case TYPE:
  246. String type = superclasses.get(0);
  247. if (primary.equalsIgnoreCase(type.replace(" ", ""))) {
  248. return 175;
  249. }
  250. break;
  251. case CLASS:
  252. int i = 0;
  253. for (String s: superclasses) {
  254. i++;
  255. if (primary.equalsIgnoreCase(s.replace(" ", ""))) {
  256. return 150 - i;
  257. }
  258. }
  259. break;
  260. case ID:
  261. if (c.getCSSID() != "" && primary.equalsIgnoreCase(c.getCSSID().replace(" ", ""))) {
  262. return 199;
  263. }
  264. break;
  265. case UNIVERSAL:
  266. return 100;
  267. default:
  268. break;
  269. }
  270. return 0;
  271. } else if (child == null) {
  272. switch (secondaryType) {
  273. case TYPE:
  274. String type = superclasses.get(0);
  275. if (secondary.equalsIgnoreCase(type.replace(" ", ""))) {
  276. if (containsParent(c,1) != 0) return 200 + containsParent(c,1) - 25;
  277. }
  278. break;
  279. case CLASS:
  280. for (String s: superclasses) {
  281. if (secondary.equalsIgnoreCase(s.replace(" ", ""))) {
  282. if (containsParent(c,1) != 0)
  283. return 200 + containsParent(c,1) - 50;
  284. }
  285. }
  286. break;
  287. case ID:
  288. if (c.getCSSID() != "" && secondary.equalsIgnoreCase(c.getCSSID().replace(" ", ""))) {
  289. if (containsParent(c,1) != 0)
  290. return 200 + containsParent(c,1);
  291. }
  292. break;
  293. case UNIVERSAL:
  294. if (containsParent(c,1) != 0)
  295. return 200 + (100 - containsParent(c,1));
  296. default:
  297. break;
  298. }
  299. return 0;
  300. } else {
  301. //return child.appliesTo(c);
  302. if (secondary == null && child.secondary == null) {
  303. switch (child.primaryType) {
  304. case TYPE:
  305. String type = superclasses.get(0);
  306. if (child.primary.equalsIgnoreCase(type.replace(" ", ""))) {
  307. if (containsParent(c,5) != 0)
  308. return 300 + containsParent(c,5) - 25;
  309. }
  310. break;
  311. case CLASS:
  312. for (String s: superclasses) {
  313. if (child.primary.equalsIgnoreCase(s.replace(" ", ""))) {
  314. if (containsParent(c,5) != 0)
  315. return 300 + containsParent(c,5) - 50;
  316. }
  317. }
  318. break;
  319. case ID:
  320. if (c.getCSSID() != "" && child.primary.equalsIgnoreCase(c.getCSSID().replace(" ", ""))) {
  321. if (containsParent(c,5) != 0)
  322. return 300 + containsParent(c,5);
  323. }
  324. break;
  325. case UNIVERSAL:
  326. if (containsParent(c,5) != 0)
  327. return 300 + (100 - containsParent(c,5));
  328. default:
  329. break;
  330. }
  331. return 0;
  332. } else if (secondary == null) {
  333. switch (child.secondaryType) {
  334. case TYPE:
  335. String type = superclasses.get(0);
  336. if (child.secondary.equalsIgnoreCase(type.replace(" ", ""))) {
  337. if (containsParent(c,4) != 0)
  338. return 300 + containsParent(c,4) -25;
  339. }
  340. break;
  341. case CLASS:
  342. for (String s: superclasses) {
  343. if (child.secondary.equalsIgnoreCase(s.replace(" ", ""))) {
  344. if (containsParent(c,4) != 0)
  345. return 300 + containsParent(c,4) - 50;
  346. }
  347. }
  348. break;
  349. case ID:
  350. if (c.getCSSID() != "" && child.secondary.equalsIgnoreCase(c.getCSSID().replace(" ", ""))) {
  351. if (containsParent(c,4) != 0)
  352. return 300 + containsParent(c,4);
  353. }
  354. break;
  355. case UNIVERSAL:
  356. if (containsParent(c,4) != 0)
  357. return 300 + (100 - containsParent(c,4));
  358. default:
  359. break;
  360. }
  361. return 0;
  362. } else if (child.secondary == null) {
  363. switch (child.primaryType) {
  364. case TYPE:
  365. String type = superclasses.get(0);
  366. if (child.primary.equalsIgnoreCase(type.replace(" ", ""))) {
  367. if (containsParent(c,2) != 0)
  368. return 300 + containsParent(c,2) - 25;
  369. }
  370. break;
  371. case CLASS:
  372. for (String s: superclasses) {
  373. if (child.primary.equalsIgnoreCase(s.replace(" ", ""))) {
  374. if (containsParent(c,2) != 0)
  375. return 300 + containsParent(c,2) - 50;
  376. }
  377. }
  378. break;
  379. case ID:
  380. if (c.getCSSID() != "" && child.primary.equalsIgnoreCase(c.getCSSID().replace(" ", ""))) {
  381. if (containsParent(c,2) != 0)
  382. return 300 + containsParent(c,2);
  383. }
  384. break;
  385. case UNIVERSAL:
  386. if (containsParent(c,2) != 0)
  387. return 300 + (100 - containsParent(c,2));
  388. default:
  389. break;
  390. }
  391. return 0;
  392. } else {
  393. switch (child.secondaryType) {
  394. case TYPE:
  395. String type = superclasses.get(0);
  396. if (child.secondary.equalsIgnoreCase(type.replace(" ", ""))) {
  397. return 400 + containsParent(c,3) - 25;
  398. }
  399. break;
  400. case CLASS:
  401. for (String s: superclasses) {
  402. if (child.secondary.equalsIgnoreCase(s.replace(" ", ""))) {
  403. return 400 + containsParent(c,3) - 50;
  404. }
  405. }
  406. break;
  407. case ID:
  408. if (c.getCSSID() != "" && child.secondary.equalsIgnoreCase(c.getCSSID().replace(" ", ""))) {
  409. return 400 + containsParent(c,3);
  410. }
  411. break;
  412. case UNIVERSAL:
  413. return 400 + (100 - containsParent(c,3));
  414. default:
  415. break;
  416. }
  417. return 0;
  418. }
  419. }
  420. } catch (Exception e) {
  421. e.printStackTrace();
  422. }
  423. return 0;
  424. }
  425. /**
  426. * Checks, whether the Selector applies to a parent of the component
  427. *
  428. * @param c the MTComponent
  429. * @param level the level, for which to search
  430. * @return the hierarchy level, on which it was found (0, if not found)
  431. */
  432. private int containsParent(MTComponent c, int level) {
  433. //Level:
  434. //1: Parent Match
  435. //2: Grandparent Parent > Match
  436. //3: Grandgrandparent Grandparent > Parent Match
  437. //4: Grandparent > Parent Match
  438. //5: Parent > Match
  439. try {
  440. if (c.getParent() != null) {
  441. switch (level) {
  442. case 1:
  443. return searchLevelsOne(c);
  444. case 2:
  445. return searchLevelsTwo(c);
  446. case 3:
  447. return searchLevelsThree(c);
  448. case 4:
  449. return searchLevelsFour(c);
  450. case 5:
  451. return searchLevelsFive(c);
  452. }
  453. }
  454. } catch (Exception e) {
  455. System.out.println("Selector not found - not enough levels?");
  456. }
  457. return 0;
  458. }
  459. /**
  460. * Searches, whether a parent matches the primary part of the selector
  461. *
  462. * @param c the MTComponent
  463. * @return the level, where the selector applies (0 if not found)
  464. */
  465. private int searchLevelsOne(MTComponent c) {
  466. //Search all above levels for instance of Selector
  467. int numberOfLevels = numberOfLevels(c);
  468. try {
  469. if (numberOfLevels > 1) {
  470. for (int i = 2; i <= numberOfLevels; i++) {
  471. if (isMatch(primaryType, primary, getComponentAtLevel(c,i))) {
  472. return 99 - i;
  473. }
  474. }
  475. }
  476. } catch (Exception e) {
  477. }
  478. return 0;
  479. }
  480. /**
  481. * Searches, whether a grandparent matches the primary part of the selector and the parent matches the secondary part
  482. *
  483. * @param c the MTComponent
  484. * @return the level, where the selector applies (0 if not found)
  485. */
  486. private int searchLevelsTwo(MTComponent c) {
  487. //Search all upper levels for Grandparent, Level 1 = Match, Level 2 = Parent (Parent must be directly over child)
  488. int numberOfLevels = numberOfLevels(c);
  489. try {
  490. if (numberOfLevels > 2) {
  491. isMatch(secondaryType, secondary, getComponentAtLevel(c,2));
  492. for (int i = 3; i <= numberOfLevels; i++) {
  493. if (isMatch(primaryType, primary, getComponentAtLevel(c,i))) {
  494. return 100-i;
  495. }
  496. }
  497. }
  498. } catch (Exception e) {
  499. }
  500. return 0;
  501. }
  502. /**
  503. * Searches, whether a grand-grandparent matches the primary part of the selector and the grandparent matches the secondary part, while the parent matches the primary part of the child
  504. *
  505. * @param c the c
  506. * @return the level, where the selector applies (0 if not found)
  507. */
  508. private int searchLevelsThree(MTComponent c) {
  509. int numberOfLevels = numberOfLevels(c);
  510. // boolean found = false;
  511. try {
  512. if (numberOfLevels > 3) {
  513. for (int i=3; i<=numberOfLevels-1; i++) {
  514. for (int j=i+1; j <= numberOfLevels; j++) {
  515. if (isMatch(primaryType, primary, getComponentAtLevel(c,j)) &&
  516. isMatch(secondaryType, secondary, getComponentAtLevel(c, i)) &&
  517. isMatch(child.getPrimaryType(), child.getPrimary(), getComponentAtLevel(c,i-1))) {
  518. return 104 - i - j;
  519. }
  520. }
  521. }
  522. }
  523. } catch (Exception e) {
  524. }
  525. return 0;
  526. }
  527. /**
  528. * Search whether a grandparent matches the primary part of the selector and a parent matches the primary part of the child
  529. *
  530. * @param c the c
  531. * @return the level, where the selector applies (0 if not found)
  532. */
  533. private int searchLevelsFour (MTComponent c) {
  534. //return isMatch(primaryType, primary, c.getParent().getParent()) &&
  535. //isMatch(child.getPrimaryType(), child.getPrimary(), c.getParent());
  536. int numberOfLevels = numberOfLevels(c);
  537. // boolean found = false;
  538. if (numberOfLevels > 2) {
  539. for (int i=3; i <= numberOfLevels; i++) {
  540. if (isMatch(primaryType, primary, getComponentAtLevel(c,i)) &&
  541. isMatch(child.getPrimaryType(), child.getPrimary(), getComponentAtLevel(c,i-1))) {
  542. return 100 - i;
  543. }
  544. }
  545. }
  546. return 0;
  547. }
  548. /**
  549. * Searches, whether a parent matches the primary part of the selector
  550. *
  551. * @param c the MTComponent
  552. * @return the level, where the selector applies (0 if not found)
  553. */
  554. private int searchLevelsFive(MTComponent c) {
  555. //Search all above levels for instance of Selector
  556. int numberOfLevels = numberOfLevels(c);
  557. // boolean found = false;
  558. // int foundAtLevel = 0;
  559. try {
  560. if (numberOfLevels > 1) {
  561. if (isMatch(primaryType, primary, getComponentAtLevel(c,2))) {
  562. return 99 - 2;
  563. }
  564. }
  565. } catch (Exception e) {
  566. }
  567. return 0;
  568. }
  569. /**
  570. * Gets the component at a certain level in the hierarchy
  571. *
  572. * @param c the MTComponent
  573. * @param level the level, at which to look
  574. * @return the component at that level
  575. */
  576. private MTComponent getComponentAtLevel(MTComponent c,int level) {
  577. try {
  578. if (level <= 1) {
  579. return c;
  580. } else {
  581. return getComponentAtLevel(c.getParent(), level-1);
  582. }
  583. } catch (Exception e) {
  584. return null;
  585. }
  586. }
  587. /**
  588. * Determines the Number of levels in the hierarchy
  589. *
  590. * @param c the MTComponent
  591. * @return the number of levels
  592. */
  593. private int numberOfLevels(MTComponent c) {
  594. try {
  595. if (c instanceof MTCanvas || c == null) {
  596. return 0;
  597. } else {
  598. return numberOfLevels(c.getParent()) + 1;
  599. }
  600. } catch (Exception e) {
  601. return 0;
  602. }
  603. }
  604. /**
  605. * Checks if the object name or ID matches the selector
  606. *
  607. * @param type the selector type
  608. * @param selector the selector
  609. * @param c the MTComponent
  610. * @return true, if is a match
  611. */
  612. private boolean isMatch(CSSSelectorType type, String selector, MTComponent c) {
  613. try {
  614. if (c != null && c instanceof MTComponent) {
  615. List<String> superclasses = getSuperclasses(c.getClass());
  616. switch (type) {
  617. case TYPE:
  618. if (superclasses.get(0).replace(" ", "").equalsIgnoreCase(selector)) return true;
  619. break;
  620. case CLASS:
  621. for (String s: superclasses) {
  622. if (selector.equalsIgnoreCase(s.replace(" ", ""))) return true;
  623. }
  624. break;
  625. case ID:
  626. if (c.getCSSID() != "" && c.getCSSID().replace(" ", "").equalsIgnoreCase(selector)) return true;
  627. break;
  628. default:
  629. System.out.println("WTF? Unknown Type " + type + " with Selector " + selector);
  630. }
  631. }
  632. } catch (Exception e) {
  633. System.out.println("Someting went wrong with finding " + selector + " in " + c.getClass().getSimpleName());
  634. }
  635. return false;
  636. }
  637. /**
  638. * Gets the superclasses of a class
  639. *
  640. * @param c the Class
  641. * @return the superclasses
  642. */
  643. private List<String> getSuperclasses(Class<?> c) {
  644. List<String> superclasses = new ArrayList<String>();
  645. superclasses.add(c.getSimpleName().toUpperCase().replace(" ", ""));
  646. while (c.getSuperclass() != null) {
  647. c = c.getSuperclass();
  648. superclasses.add(c.getSimpleName().toUpperCase().replace(" ", ""));
  649. }
  650. return superclasses;
  651. }
  652. }