/p_vis/treemap/src/main/java/edu/zjut/treemap/core/TreemapState.java

https://github.com/yulewei/p_vis · Java · 1118 lines · 895 code · 104 blank · 119 comment · 316 complexity · ef670ac4e38133771d77ba5a38c21286 MD5 · raw file

  1. package edu.zjut.treemap.core;
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. import java.util.HashMap;
  5. import java.util.List;
  6. import java.util.Map;
  7. import edu.zjut.common.data.attr.DataField;
  8. import edu.zjut.common.data.attr.FieldType;
  9. import edu.zjut.treemap.hive.Expression;
  10. import edu.zjut.treemap.hive.ExpressionNotSupportedException;
  11. import edu.zjut.treemap.hive.Hive;
  12. import edu.zjut.treemap.hive.Path;
  13. import edu.zjut.treemap.hive.Preset;
  14. import edu.zjut.treemap.hive.Type;
  15. import edu.zjut.treemap.hive.Variable;
  16. import edu.zjut.treemap.summary.SummariseField;
  17. import edu.zjut.treemap.summary.SummariseNull;
  18. /**
  19. * Stores the state of a treemap
  20. *
  21. * Implements HiVE, enabling it to read and write state - those states that it
  22. * supports
  23. *
  24. * @author Aidan Slingsby, giCentre
  25. *
  26. */
  27. public class TreemapState implements Hive {
  28. protected DataField[] hierFields = new DataField[0];
  29. protected SummariseField[][] sizeFields;
  30. protected SummariseField[][] orderFields;
  31. protected SummariseField[][] colourFields;
  32. protected Layout[] layouts;
  33. protected Object[] filterValues;
  34. protected List<DataField> allowedHierFields;
  35. protected List<SummariseField> allowedSizeFields;
  36. protected List<SummariseField> allowedOrderFields;
  37. protected List<SummariseField> allowedColourFields;
  38. protected List<Layout> allowedLayouts;
  39. protected Map<String, DataField> hierFieldsLookup;
  40. protected Map<String, SummariseField> sizeFieldsLookup;
  41. protected Map<String, SummariseField> orderFieldsLookup;
  42. protected Map<String, SummariseField> colourFieldsLookup;
  43. // These are used by other classes to assess whether the treemap has changed
  44. // state
  45. protected boolean hierChanged = false;
  46. protected boolean orderChanged = false;
  47. protected boolean sizeChanged = false;
  48. protected boolean colorChanged = false;
  49. protected boolean layoutChanged = false;
  50. protected boolean appearanceChanged = false;
  51. // Marker variable that means use default
  52. protected SummariseNull summariseNull = null;
  53. // Hashmap of the appearance states for each appearance type (see below)
  54. protected HashMap<AppearanceType, Integer>[] appearanceValues;
  55. public TreemapState(List<DataField> hierFields,
  56. List<SummariseField> sumFields) {
  57. this(hierFields, new ArrayList<SummariseField>(sumFields),
  58. new ArrayList<SummariseField>(sumFields),
  59. new ArrayList<SummariseField>(sumFields), null);
  60. }
  61. public TreemapState(List<DataField> allowedHierFields,
  62. List<SummariseField> allowedOrderFields,
  63. List<SummariseField> allowedSizeFields,
  64. List<SummariseField> allowedColourFields,
  65. List<Layout> allowedLayouts) {
  66. this.orderFields = new SummariseField[2][0];
  67. this.sizeFields = new SummariseField[1][0];
  68. this.colourFields = new SummariseField[1][0];
  69. this.layouts = new Layout[0];
  70. this.filterValues = new Object[0];
  71. this.appearanceValues = new HashMap[0];
  72. if (allowedLayouts == null) {
  73. allowedLayouts = new ArrayList<Layout>();
  74. allowedLayouts.add(Layout.ST);
  75. allowedLayouts.add(Layout.HZ);
  76. allowedLayouts.add(Layout.VT);
  77. allowedLayouts.add(Layout.SP);
  78. allowedLayouts.add(Layout.SA);
  79. }
  80. this.summariseNull = new SummariseNull("Null");
  81. this.allowedHierFields = allowedHierFields;
  82. this.allowedOrderFields = allowedOrderFields;
  83. this.allowedOrderFields.remove(null);
  84. this.allowedOrderFields.add(0, summariseNull);
  85. this.allowedSizeFields = allowedSizeFields;
  86. this.allowedSizeFields.remove(null);
  87. this.allowedSizeFields.add(0, summariseNull);
  88. this.allowedColourFields = allowedColourFields;
  89. this.allowedColourFields.remove(null);
  90. this.allowedColourFields.add(0, summariseNull);
  91. this.allowedLayouts = allowedLayouts;
  92. hierFieldsLookup = new HashMap<String, DataField>();
  93. for (DataField dataField : allowedHierFields) {
  94. hierFieldsLookup.put(dataField.getName(), dataField);
  95. }
  96. orderFieldsLookup = new HashMap<String, SummariseField>();
  97. for (SummariseField summariseField : allowedOrderFields) {
  98. orderFieldsLookup.put(summariseField.getName(), summariseField);
  99. }
  100. sizeFieldsLookup = new HashMap<String, SummariseField>();
  101. for (SummariseField summariseField : allowedSizeFields) {
  102. sizeFieldsLookup.put(summariseField.getName(), summariseField);
  103. }
  104. colourFieldsLookup = new HashMap<String, SummariseField>();
  105. for (SummariseField summariseField : allowedColourFields) {
  106. colourFieldsLookup.put(summariseField.getName(), summariseField);
  107. }
  108. }
  109. public List<DataField> getAllowedHierFields() {
  110. return allowedHierFields;
  111. }
  112. public List<SummariseField> getAllowedSizeFields() {
  113. return allowedSizeFields;
  114. }
  115. public List<SummariseField> getAllowedOrderFields() {
  116. return allowedOrderFields;
  117. }
  118. public List<SummariseField> getAllowedColourFields() {
  119. return allowedColourFields;
  120. }
  121. public List<Layout> getAllowedLayouts() {
  122. return allowedLayouts;
  123. }
  124. public int getNumLevels() {
  125. return hierFields.length;
  126. }
  127. public SummariseField[][] getSizeFields() {
  128. return sizeFields;
  129. }
  130. public void setSizeFields(SummariseField[][] sizeFields) {
  131. this.sizeFields = sizeFields;
  132. }
  133. public HashMap<AppearanceType, Integer> getAppearance(int level) {
  134. return appearanceValues[level];
  135. }
  136. public DataField[] getHierFields() {
  137. return hierFields;
  138. }
  139. public Object[] getFilterValues() {
  140. return filterValues;
  141. }
  142. public SummariseField[][] getOrderFields() {
  143. return orderFields;
  144. }
  145. public SummariseField[][] getColourFields() {
  146. return colourFields;
  147. }
  148. public Layout[] getLayouts() {
  149. return layouts;
  150. }
  151. public boolean isEmpty() {
  152. return hierFields.length == 0;
  153. }
  154. /**
  155. * Swap two levels in the hierarchy
  156. *
  157. * Swaps two levels along with the all the corresponding states
  158. *
  159. * In line with HiVE, levels should be numbered from 1
  160. *
  161. * @param level1
  162. * Level to swap with the other level
  163. * @param level2
  164. * Level to swap with the other level
  165. */
  166. public void swap(int level1, int level2) {
  167. level1--;
  168. level2--;
  169. int length = hierFields.length;
  170. if (level1 == level2 || level1 >= length || level2 >= length) {
  171. System.err.println("Cannot cut swap levels " + level1 + " and "
  172. + level2);
  173. return;
  174. }
  175. // copy the state
  176. DataField[] newHierFields = new DataField[length];
  177. SummariseField[][] newSizeFields = new SummariseField[sizeFields.length][length];
  178. SummariseField[][] newOrderFields = new SummariseField[orderFields.length][length];
  179. SummariseField[][] newColourFields = new SummariseField[colourFields.length][length];
  180. Layout[] newLayouts = new Layout[length];
  181. HashMap<AppearanceType, Integer>[] newAppearanceValues = new HashMap[length];
  182. Object[] newFilterValues = new Object[length];
  183. for (int i = 0; i < length; i++) {
  184. newHierFields[i] = hierFields[i];
  185. for (int j = 0; j < newSizeFields.length; j++) {
  186. newSizeFields[j][i] = sizeFields[j][i];
  187. }
  188. for (int j = 0; j < newOrderFields.length; j++) {
  189. newOrderFields[j][i] = orderFields[j][i];
  190. }
  191. for (int j = 0; j < newColourFields.length; j++) {
  192. newColourFields[j][i] = colourFields[j][i];
  193. }
  194. newLayouts[i] = layouts[i];
  195. newAppearanceValues[i] = appearanceValues[i];
  196. newFilterValues[i] = filterValues[i];
  197. }
  198. // ½»»»level1
  199. newHierFields[level1] = hierFields[level2];
  200. for (int j = 0; j < newSizeFields.length; j++) {
  201. newSizeFields[j][level1] = sizeFields[j][level2];
  202. }
  203. for (int j = 0; j < newOrderFields.length; j++) {
  204. newOrderFields[j][level1] = orderFields[j][level2];
  205. }
  206. for (int j = 0; j < newColourFields.length; j++) {
  207. newColourFields[j][level1] = colourFields[j][level2];
  208. }
  209. newLayouts[level1] = layouts[level2];
  210. newAppearanceValues[level1] = appearanceValues[level2];
  211. newFilterValues[level1] = filterValues[level2];
  212. // ½»»»level2
  213. newHierFields[level2] = hierFields[level1];
  214. for (int j = 0; j < newSizeFields.length; j++) {
  215. newSizeFields[j][level2] = sizeFields[j][level1];
  216. }
  217. for (int j = 0; j < newOrderFields.length; j++) {
  218. newOrderFields[j][level2] = orderFields[j][level1];
  219. }
  220. for (int j = 0; j < newColourFields.length; j++) {
  221. newColourFields[j][level2] = colourFields[j][level1];
  222. }
  223. newLayouts[level2] = layouts[level1];
  224. newAppearanceValues[level2] = appearanceValues[level1];
  225. newFilterValues[level2] = filterValues[level1];
  226. hierFields = newHierFields;
  227. sizeFields = newSizeFields;
  228. orderFields = newOrderFields;
  229. colourFields = newColourFields;
  230. layouts = newLayouts;
  231. appearanceValues = newAppearanceValues;
  232. filterValues = newFilterValues;
  233. }
  234. /**
  235. * Cut a level from the hierarchy
  236. *
  237. * @param level
  238. * Level to cut
  239. */
  240. public void cut(int level) {
  241. int length = hierFields.length;
  242. if (level >= length) {
  243. System.err.println("Cannot cut level " + level);
  244. return;
  245. }
  246. DataField[] newHierarchyFields = new DataField[length - 1];
  247. SummariseField[][] newSizeFields = new SummariseField[sizeFields.length][length - 1];
  248. SummariseField[][] newOrderFields = new SummariseField[orderFields.length][length - 1];
  249. SummariseField[][] newColourFields = new SummariseField[colourFields.length][length - 1];
  250. HashMap<AppearanceType, Integer>[] newAppearanceValues = new HashMap[length - 1];
  251. Layout[] newLayouts = new Layout[length - 1];
  252. Object[] newFilterValues = new Object[length - 1];
  253. if (length > 1) {
  254. for (int i = 0; i < length; i++) {
  255. if (i < level) {
  256. newHierarchyFields[i] = hierFields[i];
  257. for (int j = 0; j < newSizeFields.length; j++) {
  258. newSizeFields[j][i] = sizeFields[j][i];
  259. }
  260. for (int j = 0; j < newOrderFields.length; j++) {
  261. newOrderFields[j][i] = orderFields[j][i];
  262. }
  263. for (int j = 0; j < newColourFields.length; j++) {
  264. newColourFields[j][i] = colourFields[j][i];
  265. }
  266. newLayouts[i] = layouts[i];
  267. newAppearanceValues[i] = appearanceValues[i];
  268. newFilterValues[i] = filterValues[i];
  269. } else if (i > level) {
  270. newHierarchyFields[i - 1] = hierFields[i];
  271. for (int j = 0; j < newSizeFields.length; j++) {
  272. newSizeFields[j][i - 1] = sizeFields[j][i];
  273. }
  274. for (int j = 0; j < newOrderFields.length; j++) {
  275. newOrderFields[j][i - 1] = orderFields[j][i];
  276. }
  277. for (int j = 0; j < newColourFields.length; j++) {
  278. newColourFields[j][i - 1] = colourFields[j][i];
  279. }
  280. newLayouts[i - 1] = layouts[i];
  281. newAppearanceValues[i - 1] = appearanceValues[i];
  282. newFilterValues[i - 1] = filterValues[i];
  283. }
  284. }
  285. }
  286. hierFields = newHierarchyFields;
  287. sizeFields = newSizeFields;
  288. orderFields = newOrderFields;
  289. colourFields = newColourFields;
  290. layouts = newLayouts;
  291. filterValues = newFilterValues;
  292. appearanceValues = newAppearanceValues;
  293. }
  294. /**
  295. * Insert a level
  296. *
  297. * @param level
  298. * The level at which to insert
  299. * @param hierarchyField
  300. * The variable to insert
  301. * @param orderField
  302. * The order
  303. * @param sizeField
  304. * The size
  305. * @param colourField
  306. * The colour
  307. * @param layout
  308. * The layout
  309. */
  310. public void insert(int level, DataField hierarchyField,
  311. SummariseField[] orderField, SummariseField[] sizeField,
  312. SummariseField[] colourField, Layout layout) {
  313. int length = hierFields.length;
  314. if (level > length) {
  315. System.err.println("Cannot cut level " + level);
  316. return;
  317. }
  318. DataField[] newHierarchyFields = new DataField[length + 1];
  319. SummariseField[][] newSizeFields = new SummariseField[sizeFields.length][length + 1];
  320. SummariseField[][] newOrderFields = new SummariseField[orderFields.length][length + 1];
  321. SummariseField[][] newColourFields = new SummariseField[colourFields.length][length + 1];
  322. Layout[] newLayouts = new Layout[length + 1];
  323. Object[] newFilterValues = new Object[length + 1];
  324. HashMap<AppearanceType, Integer>[] newAppearanceValues = new HashMap[length + 1];
  325. if (length == 0) {
  326. newHierarchyFields[0] = hierarchyField;
  327. for (int j = 0; j < newSizeFields.length; j++) {
  328. newSizeFields[j][0] = sizeField[j];
  329. }
  330. for (int j = 0; j < newOrderFields.length; j++) {
  331. newOrderFields[j][0] = orderField[j];
  332. }
  333. for (int j = 0; j < newColourFields.length; j++) {
  334. newColourFields[j][0] = colourField[j];
  335. }
  336. newLayouts[0] = layout;
  337. newAppearanceValues[0] = new HashMap<AppearanceType, Integer>();
  338. for (AppearanceType appearanceType : AppearanceType.values()) {
  339. newAppearanceValues[0].put(appearanceType,
  340. appearanceType.defaultValue());
  341. }
  342. newFilterValues[0] = null;
  343. }
  344. for (int i = 0; i < newHierarchyFields.length; i++) {
  345. if (i < level) {
  346. newHierarchyFields[i] = hierFields[i];
  347. for (int j = 0; j < newSizeFields.length; j++) {
  348. newSizeFields[j][i] = sizeFields[j][i];
  349. }
  350. for (int j = 0; j < newOrderFields.length; j++) {
  351. newOrderFields[j][i] = orderFields[j][i];
  352. }
  353. for (int j = 0; j < newColourFields.length; j++) {
  354. newColourFields[j][i] = colourFields[j][i];
  355. }
  356. newLayouts[i] = layouts[i];
  357. newAppearanceValues[i] = appearanceValues[i];
  358. newFilterValues[i] = filterValues[i];
  359. } else if (i == level) {
  360. newHierarchyFields[i] = hierarchyField;
  361. for (int j = 0; j < newSizeFields.length; j++) {
  362. newSizeFields[j][i] = sizeField[j];
  363. }
  364. for (int j = 0; j < newOrderFields.length; j++) {
  365. newOrderFields[j][i] = orderField[j];
  366. }
  367. for (int j = 0; j < newColourFields.length; j++) {
  368. newColourFields[j][i] = colourField[j];
  369. }
  370. newLayouts[i] = layout;
  371. newFilterValues[i] = null;
  372. newAppearanceValues[i] = new HashMap<AppearanceType, Integer>();
  373. for (AppearanceType appearanceType : AppearanceType.values()) {
  374. newAppearanceValues[i].put(appearanceType,
  375. appearanceType.defaultValue());
  376. }
  377. } else {
  378. newHierarchyFields[i] = hierFields[i - 1];
  379. for (int j = 0; j < newSizeFields.length; j++) {
  380. newSizeFields[j][i] = sizeFields[j][i - 1];
  381. }
  382. for (int j = 0; j < newOrderFields.length; j++) {
  383. newOrderFields[j][i] = orderFields[j][i - 1];
  384. }
  385. for (int j = 0; j < newColourFields.length; j++) {
  386. newColourFields[j][i] = colourFields[j][i - 1];
  387. }
  388. newLayouts[i] = layouts[i - 1];
  389. newAppearanceValues[i] = appearanceValues[i - 1];
  390. newFilterValues[i] = filterValues[i - 1];
  391. }
  392. }
  393. hierFields = newHierarchyFields;
  394. sizeFields = newSizeFields;
  395. orderFields = newOrderFields;
  396. colourFields = newColourFields;
  397. layouts = newLayouts;
  398. appearanceValues = newAppearanceValues;
  399. filterValues = newFilterValues;
  400. }
  401. /**
  402. * Reset change flag. Call whether you've read these
  403. */
  404. public void resetChangeFlags() {
  405. hierChanged = false;
  406. orderChanged = false;
  407. sizeChanged = false;
  408. colorChanged = false;
  409. layoutChanged = false;
  410. appearanceChanged = false;
  411. }
  412. public boolean isChanged() {
  413. return hierChanged || orderChanged || sizeChanged || colorChanged
  414. || layoutChanged || appearanceChanged;
  415. }
  416. public boolean isHierChanged() {
  417. return hierChanged;
  418. }
  419. public void setHierChanged(boolean hierChanged) {
  420. this.hierChanged = hierChanged;
  421. }
  422. public boolean orderChanged() {
  423. return orderChanged;
  424. }
  425. public boolean isSizeChanged() {
  426. return sizeChanged;
  427. }
  428. public void setSizeChanged(boolean sizeChanged) {
  429. this.sizeChanged = sizeChanged;
  430. }
  431. public boolean isColorChanged() {
  432. return colorChanged;
  433. }
  434. public void setColorChanged(boolean colorChanged) {
  435. this.colorChanged = colorChanged;
  436. }
  437. public boolean layoutChanged() {
  438. return layoutChanged;
  439. }
  440. public boolean isLayoutChanged() {
  441. return layoutChanged;
  442. }
  443. public void setLayoutChanged(boolean layoutChanged) {
  444. this.layoutChanged = layoutChanged;
  445. }
  446. public boolean isAppearanceChanged() {
  447. return appearanceChanged;
  448. }
  449. public void setAppearanceChanged(boolean appearanceChanged) {
  450. this.appearanceChanged = appearanceChanged;
  451. }
  452. public boolean applyExpressions(Collection<Expression> expressions) {
  453. HashMap<AppearanceType, Integer>[] oldAppearance = appearanceValues;
  454. this.clear();
  455. boolean flag = true;
  456. // do hier first
  457. for (Expression expression : expressions) {
  458. if (expression.getType().equals(Type.S_HIER)
  459. || expression.getType().equals(Type.O_HIER)) {
  460. try {
  461. flag = applyOperator(expression);
  462. } catch (ExpressionNotSupportedException e) {
  463. System.err.println(e);
  464. }
  465. }
  466. }
  467. // then do layouts
  468. for (Expression expression : expressions) {
  469. if (expression.getType().equals(Type.S_LAYOUT)
  470. || expression.getType().equals(Type.O_LAYOUT)) {
  471. try {
  472. flag = applyOperator(expression);
  473. } catch (ExpressionNotSupportedException e) {
  474. System.err.println(e);
  475. }
  476. }
  477. }
  478. // then do everything else except focus
  479. for (Expression expression : expressions) {
  480. if (!expression.getType().equals(Type.S_HIER)
  481. && !expression.getType().equals(Type.O_HIER)
  482. && !expression.getType().equals(Type.S_FOCUS)
  483. && !expression.getType().equals(Type.O_FOCUS)
  484. && !expression.getType().equals(Type.S_LAYOUT)
  485. && !expression.getType().equals(Type.O_LAYOUT)) {
  486. try {
  487. flag = applyOperator(expression);
  488. } catch (ExpressionNotSupportedException e) {
  489. System.err.println(e);
  490. }
  491. }
  492. }
  493. // finally, do focus
  494. for (Expression expression : expressions) {
  495. if (expression.getType().equals(Type.S_FOCUS)
  496. || expression.getType().equals(Type.O_FOCUS)) {
  497. try {
  498. flag = applyOperator(expression);
  499. } catch (ExpressionNotSupportedException e) {
  500. System.err.println(e);
  501. }
  502. }
  503. }
  504. // then restore appearance
  505. // store appearance - to restore later
  506. int len = oldAppearance.length < appearanceValues.length ? oldAppearance.length
  507. : appearanceValues.length;
  508. if (oldAppearance.length > 0) {
  509. for (int i = 0; i < len; i++) {
  510. for (AppearanceType appearanceType : oldAppearance[i].keySet()) {
  511. appearanceValues[i].put(appearanceType,
  512. oldAppearance[i].get(appearanceType));
  513. }
  514. }
  515. }
  516. return flag;
  517. }
  518. /**
  519. * Apply operator
  520. *
  521. * @param expression
  522. * HiVE expression to apply
  523. */
  524. public boolean applyOperator(Expression expression)
  525. throws ExpressionNotSupportedException {
  526. // HIER
  527. if (expression.getType() == Type.S_HIER
  528. || expression.getType() == Type.O_HIER) {
  529. int startLevel = expression.getLevel() - 1;
  530. if (startLevel > this.hierFields.length) {
  531. System.err.println("Current hierarchy is not deep enough for "
  532. + expression);
  533. return false;
  534. }
  535. // each each variable in o/sHier
  536. for (int i = 0; i < expression.getVarGroups().size(); i++) {
  537. if (expression.getVarGroups().get(i).length != 1) {
  538. System.err
  539. .println("Hierarchy variables must only be in groups of one");
  540. return false;
  541. }
  542. Variable var = expression.getVarGroups().get(i)[0];
  543. if (!var.isDataVariable()) {
  544. System.err
  545. .println("The hierarchy can only have variables in.");
  546. return false;
  547. }
  548. DataField dataField = hierFieldsLookup.get(var.getName());
  549. if (dataField == null) {
  550. System.err.println(var.getName() + " not found for "
  551. + expression);
  552. return false;
  553. }
  554. DataField hierarchyField = dataField;
  555. int level = startLevel + i;
  556. if (level >= this.getNumLevels()) {
  557. // then INSERT
  558. SummariseField[] orderField = new SummariseField[orderFields.length];
  559. SummariseField[] sizeField = new SummariseField[sizeFields.length];
  560. SummariseField[] colourField = new SummariseField[colourFields.length];
  561. Layout layout = null;
  562. if (level == 0) {
  563. for (int j = 0; j < orderFields.length; j++) {
  564. orderField[j] = summariseNull;
  565. }
  566. for (int j = 0; j < sizeFields.length; j++) {
  567. sizeField[j] = summariseNull;
  568. }
  569. for (int j = 0; j < colourFields.length; j++) {
  570. colourField[j] = summariseNull;
  571. }
  572. layout = allowedLayouts.get(0);
  573. } else {
  574. // otherwise fill with the previous leaf values
  575. for (int j = 0; j < orderFields.length; j++) {
  576. orderField[j] = orderFields[j][level - 1];
  577. }
  578. for (int j = 0; j < sizeFields.length; j++) {
  579. sizeField[j] = sizeFields[j][level - 1];
  580. }
  581. for (int j = 0; j < colourFields.length; j++) {
  582. colourField[j] = colourFields[j][level - 1];
  583. }
  584. layout = layouts[level - 1];
  585. }
  586. insert(level, hierarchyField, orderField, sizeField,
  587. colourField, layout);
  588. } else {
  589. this.hierFields[level] = hierarchyField;
  590. }
  591. }
  592. hierChanged = true;
  593. return true;
  594. }
  595. // ORDER, SIZE and COLOR
  596. else if (expression.getType() == Type.S_ORDER
  597. || expression.getType() == Type.O_ORDER
  598. || expression.getType() == Type.S_SIZE
  599. || expression.getType() == Type.O_SIZE
  600. || expression.getType() == Type.S_COLOR
  601. || expression.getType() == Type.O_COLOR) {
  602. int startLevel = expression.getLevel() - 1;
  603. SummariseField[][] oldFields = null;
  604. Map<String, SummariseField> fieldsLookups = null;
  605. if (expression.getType() == Type.S_ORDER
  606. || expression.getType() == Type.O_ORDER) {
  607. oldFields = this.orderFields;
  608. fieldsLookups = orderFieldsLookup;
  609. } else if (expression.getType() == Type.S_SIZE
  610. || expression.getType() == Type.O_SIZE) {
  611. oldFields = this.sizeFields;
  612. fieldsLookups = sizeFieldsLookup;
  613. } else if (expression.getType() == Type.S_COLOR
  614. || expression.getType() == Type.O_COLOR) {
  615. oldFields = this.colourFields;
  616. fieldsLookups = colourFieldsLookup;
  617. }
  618. if (startLevel + expression.getVarGroups().size() > oldFields[0].length) {
  619. System.err.println("Hierarchy not deep enough");
  620. return false;
  621. }
  622. SummariseField[][] newFields = new SummariseField[oldFields.length][oldFields[0].length];
  623. for (int i = 0; i < oldFields[0].length; i++) {
  624. // if the i is at a level that's not to be changed by the
  625. // operator
  626. // then just copy the state
  627. if (i < startLevel
  628. || i >= startLevel + expression.getVarGroups().size()) {
  629. for (int j = 0; j < oldFields.length; j++) {
  630. newFields[j][i] = oldFields[j][i];
  631. }
  632. } else {
  633. // otherwise, set according to the operator
  634. Variable[] varGroup = expression.getVarGroups().get(
  635. i - startLevel);
  636. // if we are changing the order values... (we need to change
  637. // the layouts too)
  638. if (expression.getType() == Type.S_ORDER
  639. || expression.getType() == Type.O_ORDER) {
  640. if (varGroup.length == 1) {
  641. SummariseField summariseField = fieldsLookups
  642. .get(varGroup[0].getName());
  643. if (summariseField == null
  644. && varGroup[0].isDataVariable()) {
  645. System.err.println(varGroup[0].getName()
  646. + " not found for " + expression);
  647. return false;
  648. }
  649. if (summariseField == null) {
  650. summariseField = summariseNull;
  651. }
  652. newFields[0][i] = summariseField;
  653. newFields[1][i] = summariseNull;
  654. this.layouts[i] = Layout.ST;
  655. } else if (varGroup.length == 2
  656. && varGroup[0].getName().equals(
  657. Preset.NULL.toString())
  658. && !varGroup[1].getName().equals(
  659. Preset.NULL.toString())) {
  660. SummariseField summariseField = fieldsLookups
  661. .get(varGroup[1].getName());
  662. if (summariseField == null
  663. && varGroup[1].isDataVariable()) {
  664. System.err.println(varGroup[1].getName()
  665. + " not found for " + expression);
  666. return false;
  667. }
  668. if (summariseField == null) {
  669. summariseField = summariseNull;
  670. }
  671. newFields[0][i] = summariseField;
  672. newFields[1][i] = summariseNull;
  673. this.layouts[i] = Layout.VT;
  674. } else if (varGroup.length == 2
  675. && !varGroup[0].getName().equals(
  676. Preset.NULL.toString())
  677. && varGroup[1].getName().equals(
  678. Preset.NULL.toString())) {
  679. SummariseField summariseField = fieldsLookups
  680. .get(varGroup[0].getName());
  681. if (summariseField == null
  682. && varGroup[0].isDataVariable()) {
  683. System.err.println(varGroup[0].getName()
  684. + " not found for " + expression);
  685. return false;
  686. }
  687. if (summariseField == null) {
  688. summariseField = summariseNull;
  689. }
  690. newFields[0][i] = summariseField;
  691. newFields[1][i] = summariseNull;
  692. this.layouts[i] = Layout.HZ;
  693. } else {
  694. SummariseField summariseField = fieldsLookups
  695. .get(varGroup[0].getName());
  696. if (summariseField == null
  697. && varGroup[0].isDataVariable()) {
  698. System.err.println(varGroup[0].getName()
  699. + " not found for " + expression);
  700. return false;
  701. }
  702. if (summariseField == null) {
  703. summariseField = summariseNull;
  704. }
  705. newFields[0][i] = summariseField;
  706. summariseField = fieldsLookups.get(varGroup[1]
  707. .getName());
  708. if (summariseField == null
  709. && varGroup[1].isDataVariable()) {
  710. System.err.println(varGroup[0].getName()
  711. + " not found for " + expression);
  712. return false;
  713. }
  714. if (summariseField == null) {
  715. summariseField = summariseNull;
  716. }
  717. newFields[1][i] = summariseField;
  718. // if layout is already set to ABS_POSITION, retain
  719. // this... otherwise use TWO_DIMENSIONAL
  720. if (!this.layouts[i].equals(Layout.SA)) {
  721. this.layouts[i] = Layout.SP;
  722. }
  723. }
  724. } else {
  725. // if we are changing the size/colour values...
  726. for (int j = 0; j < newFields.length; j++) {
  727. if (j < varGroup.length) {
  728. if (varGroup[j].isDataVariable()) {
  729. // use the data variable
  730. SummariseField summariseField = fieldsLookups
  731. .get(varGroup[j].getName());
  732. newFields[j][i] = summariseField;
  733. }
  734. else if (expression.getType() == Type.S_SIZE
  735. || expression.getType() == Type.O_SIZE) {
  736. // else use summariseNull if size
  737. newFields[j][i] = summariseNull;
  738. } else if (varGroup[j].getName().equals(
  739. Preset.HIER.toString())) {
  740. // else use summarisenull (must be colour)
  741. newFields[j][i] = summariseNull;
  742. } else {
  743. // must be no colour
  744. newFields[j][i] = null;
  745. }
  746. }
  747. }
  748. }
  749. }
  750. }
  751. if (expression.getType() == Type.S_ORDER
  752. || expression.getType() == Type.O_ORDER) {
  753. orderFields = newFields;
  754. orderChanged = true;
  755. } else if (expression.getType() == Type.S_SIZE
  756. || expression.getType() == Type.O_SIZE) {
  757. sizeFields = newFields;
  758. sizeChanged = true;
  759. } else if (expression.getType() == Type.S_COLOR
  760. || expression.getType() == Type.O_COLOR) {
  761. colourFields = newFields;
  762. colorChanged = true;
  763. }
  764. return true;
  765. }
  766. // LAYOUTs
  767. else if (expression.getType() == Type.S_LAYOUT
  768. || expression.getType() == Type.O_LAYOUT) {
  769. int startLevel = expression.getLevel() - 1;
  770. Layout[] oldLayouts = layouts;
  771. if (startLevel + expression.getVarGroups().size() > oldLayouts.length) {
  772. System.err.println("Hierarchy not deep enough");
  773. return false;
  774. }
  775. Layout[] newLayouts = new Layout[oldLayouts.length];
  776. for (int i = 0; i < oldLayouts.length; i++) {
  777. // if the i is at a level that's not to be changed by the
  778. // operator
  779. // then just copy the state
  780. if (i < startLevel
  781. || i >= startLevel + expression.getVarGroups().size()) {
  782. newLayouts[i] = oldLayouts[i];
  783. } else {
  784. // otherwise, set according to the operator
  785. Variable[] varGroup = expression.getVarGroups().get(
  786. i - startLevel);
  787. // if we are changing the size/colour values...
  788. if (varGroup[0].getName().equals(
  789. Preset.CARTESIAN.toString())) {
  790. newLayouts[i] = Layout.SA;
  791. } else if (varGroup[0].getName().equals(
  792. Preset.SPACE_FILLING.toString())) {
  793. // unfortunately, this cannot distinguish between
  794. // ONE_DIM_TOP_BOTTOM, ONE_DIM_ORDERED_SQUARIFIED or
  795. // ONE_DIM_STRIP, so defaults to former
  796. // depends on order
  797. SummariseField[] orderFields = new SummariseField[this
  798. .getOrderFields().length];
  799. for (int j = 0; j < orderFields.length; j++) {
  800. orderFields[j] = this.getOrderFields()[j][i];
  801. }
  802. if (orderFields[0] == null && orderFields[1] != null) {
  803. newLayouts[i] = Layout.VT;
  804. } else if (orderFields[0] != null
  805. && orderFields[1] == null) {
  806. newLayouts[i] = Layout.HZ;
  807. } else {
  808. newLayouts[i] = Layout.SP;
  809. }
  810. } else {
  811. System.err.println("Not a valid layout");
  812. return false;
  813. }
  814. }
  815. }
  816. this.layouts = newLayouts;
  817. this.layoutChanged = true;
  818. return true;
  819. }
  820. // FOCUS
  821. if (expression.getType() == Type.S_FOCUS
  822. || expression.getType() == Type.O_FOCUS) {
  823. List<String> pathElements = expression.getPath().getValues();
  824. for (int i = 0; i < hierFields.length; i++) {
  825. if (i >= pathElements.size() || pathElements.get(i).equals("*")) {
  826. filterValues[i] = null;
  827. } else {
  828. if (hierFields[i].getFieldType().equals(FieldType.DOUBLE)) {
  829. filterValues[i] = Double.parseDouble(pathElements
  830. .get(i));
  831. } else if (hierFields[i].getFieldType().equals(
  832. FieldType.INT)) {
  833. filterValues[i] = Integer.parseInt(pathElements.get(i));
  834. } else {
  835. filterValues[i] = pathElements.get(i);
  836. }
  837. }
  838. }
  839. hierChanged = true;
  840. return true;
  841. }
  842. else {
  843. throw new ExpressionNotSupportedException();
  844. }
  845. }
  846. /**
  847. * Returns the state
  848. *
  849. * @return List of states
  850. */
  851. public List<Expression> getState() {
  852. ArrayList<Expression> expressions = new ArrayList<Expression>();
  853. // Hierarchy
  854. Expression expression = new Expression(Type.S_HIER);
  855. for (int i = 0; i < hierFields.length; i++) {
  856. expression.addVar("$" + hierFields[i].getName());
  857. }
  858. expressions.add(expression);
  859. // Order
  860. expression = new Expression(Type.S_ORDER);
  861. for (int i = 0; i < orderFields[0].length; i++) {
  862. String[] varStrings = null;
  863. if (layouts[i] == Layout.ST || layouts[i] == Layout.OS) {
  864. // One dimensional ordering
  865. if (orderFields[0][i] == null
  866. || orderFields[0][i] instanceof SummariseNull) {
  867. varStrings = new String[] { Preset.HIER.toString() };
  868. } else {
  869. varStrings = new String[] { "$"
  870. + orderFields[0][i].getName() };
  871. }
  872. } else if (layouts[i] == Layout.HZ || layouts[i] == Layout.VT) {
  873. // One dimensional ordering vertically or horizontally
  874. String varName;
  875. if (orderFields[0][i] == null
  876. || orderFields[0][i] instanceof SummariseNull) {
  877. varName = Preset.HIER.toString();
  878. } else {
  879. varName = "$" + orderFields[0][i].getName();
  880. }
  881. if (layouts[i] == Layout.HZ) {
  882. varStrings = new String[] { varName, Preset.NULL.toString() };
  883. } else {
  884. varStrings = new String[] { Preset.NULL.toString(), varName };
  885. }
  886. } else {
  887. // Two-dimensional ordering
  888. varStrings = new String[2];
  889. if (orderFields[0][i] == null
  890. || orderFields[0][i] instanceof SummariseNull) {
  891. varStrings[0] = Preset.HIER.toString();
  892. } else {
  893. varStrings[0] = "$" + orderFields[0][i].getName();
  894. }
  895. if (orderFields.length > 1) {
  896. if (orderFields[1][i] == null
  897. || orderFields[1][i] instanceof SummariseNull) {
  898. varStrings[1] = Preset.HIER.toString();
  899. } else {
  900. varStrings[1] = "$" + orderFields[1][i].getName();
  901. }
  902. } else {
  903. varStrings[1] = Preset.NULL.toString();
  904. }
  905. }
  906. expression.addVarGroup(varStrings);
  907. }
  908. expressions.add(expression);
  909. // Size
  910. expression = new Expression(Type.S_SIZE);
  911. if (sizeFields.length == 1) {
  912. for (int i = 0; i < sizeFields[0].length; i++) {
  913. if (sizeFields[0][i] == null
  914. || sizeFields[0][i] instanceof SummariseNull) {
  915. expression.addVar(Preset.FIXED.toString());
  916. } else {
  917. expression.addVar("$" + sizeFields[0][i].getName());
  918. }
  919. }
  920. } else {
  921. for (int i = 0; i < sizeFields[0].length; i++) {
  922. String[] varGroupString = new String[sizeFields.length];
  923. for (int j = 0; j < sizeFields.length; j++) {
  924. if (sizeFields[j][i] == null
  925. || sizeFields[j][i] instanceof SummariseNull) {
  926. varGroupString[j] = Preset.FIXED.toString();
  927. } else {
  928. varGroupString[j] = "$" + sizeFields[j][i].getName();
  929. }
  930. }
  931. expression.addVarGroup(varGroupString);
  932. }
  933. }
  934. expressions.add(expression);
  935. // Colour
  936. expression = new Expression(Type.S_COLOR);
  937. // assume that colourFields is a rectangular 2D array
  938. if (colourFields.length == 1) {
  939. for (int i = 0; i < colourFields[0].length; i++) {
  940. if (colourFields[0][i] == null) {
  941. expression.addVar(Preset.NULL.toString());
  942. } else if (colourFields[0][i] instanceof SummariseNull) {
  943. expression.addVar(Preset.HIER.toString());// if HIERARCHY,
  944. // use the
  945. // conditioning
  946. // variable
  947. } else {
  948. expression.addVar("$" + colourFields[0][i].getName());
  949. }
  950. }
  951. } else {
  952. for (int i = 0; i < colourFields[0].length; i++) {
  953. String[] varGroupString = new String[colourFields.length];
  954. for (int j = 0; j < colourFields.length; j++) {
  955. if (colourFields[j][i] == null) {
  956. varGroupString[j] = Preset.NULL.toString();
  957. } else if (colourFields[j][i] instanceof SummariseNull) {
  958. varGroupString[j] = Preset.HIER.toString();
  959. } else {
  960. varGroupString[j] = "$" + colourFields[j][i].getName();
  961. }
  962. }
  963. expression.addVarGroup(varGroupString);
  964. }
  965. }
  966. expressions.add(expression);
  967. // Layouts
  968. expression = new Expression(Type.S_LAYOUT);
  969. for (int i = 0; i < layouts.length; i++) {
  970. if (layouts[i].equals(Layout.SA)) {
  971. expression.addVar(Preset.CARTESIAN.toString());// currently, all
  972. // the layouts
  973. // are space
  974. // filling
  975. } else {
  976. expression.addVar(Preset.SPACE_FILLING.toString());
  977. }
  978. }
  979. expressions.add(expression);
  980. // focus/filter
  981. expression = new Expression(Type.S_FOCUS);
  982. Path path = new Path();
  983. boolean noFilters = true;
  984. for (int i = 0; i < hierFields.length; i++) {
  985. if (this.filterValues[i] != null) {
  986. noFilters = false;
  987. }
  988. }
  989. // Only return oFocus if there are any filters (i.e. path is not "/")
  990. if (!noFilters) {
  991. for (int i = 0; i < hierFields.length; i++) {
  992. if (this.filterValues[i] == null) {
  993. path.addWildcard();
  994. } else {
  995. path.addNode(filterValues[i].toString());
  996. }
  997. }
  998. expression.setPath(path);
  999. expression.addVar(Preset.SELECT.toString());
  1000. expressions.add(expression);
  1001. }
  1002. return expressions;
  1003. }
  1004. /**
  1005. * Clears the state
  1006. */
  1007. public void clear() {
  1008. hierFields = new DataField[0];
  1009. sizeFields = new SummariseField[sizeFields.length][0];
  1010. orderFields = new SummariseField[orderFields.length][0];
  1011. colourFields = new SummariseField[colourFields.length][0];
  1012. layouts = new Layout[0];
  1013. }
  1014. }