PageRenderTime 5137ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 1ms

/src/com/edgytech/umongo/DocView.java

https://github.com/agirbal/umongo
Java | 643 lines | 469 code | 79 blank | 95 comment | 96 complexity | 9cd222182475b0e680c92fed278793d8 MD5 | raw file
  1. /**
  2. * Copyright (C) 2010 EdgyTech LLC.
  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.edgytech.umongo;
  17. import com.edgytech.swingfast.*;
  18. import com.google.gson.Gson;
  19. import com.google.gson.GsonBuilder;
  20. import com.google.gson.JsonElement;
  21. import com.google.gson.JsonParser;
  22. import com.mongodb.BasicDBObject;
  23. import com.mongodb.CommandResult;
  24. import com.mongodb.DB;
  25. import com.mongodb.DBCollection;
  26. import com.mongodb.DBCursor;
  27. import com.mongodb.DBObject;
  28. import java.awt.Component;
  29. import java.io.ByteArrayOutputStream;
  30. import java.io.IOException;
  31. import java.util.Iterator;
  32. import java.util.concurrent.ExecutionException;
  33. import java.util.logging.Level;
  34. import java.util.logging.Logger;
  35. import javax.swing.SwingUtilities;
  36. import javax.swing.tree.DefaultMutableTreeNode;
  37. import javax.swing.tree.TreePath;
  38. /**
  39. *
  40. * @author antoine
  41. */
  42. public class DocView extends Zone implements EnumListener, TabInterface, Runnable {
  43. enum Item {
  44. docTree,
  45. tabDiv,
  46. tabTitle,
  47. tabClose,
  48. refresh,
  49. append,
  50. expandText,
  51. expandTextArea,
  52. indent,
  53. spawn,
  54. export,
  55. cursor,
  56. getMore,
  57. getAll,
  58. tools,
  59. startAutoUpdate,
  60. stopAutoUpdate,
  61. expandAll,
  62. collapseAll
  63. }
  64. Iterator<DBObject> iterator;
  65. DBCursor dbcursor;
  66. TabbedDiv tabbedDiv;
  67. Thread updateThread;
  68. String updateType;
  69. int updateInterval;
  70. int updateCount;
  71. boolean running;
  72. DbJob job;
  73. public DocView(String id, String label, DbJob job, Object root) {
  74. try {
  75. xmlLoad(Resource.getXmlDir(), Resource.File.docView, null);
  76. } catch (Exception ex) {
  77. getLogger().log(Level.SEVERE, null, ex);
  78. }
  79. setEnumBinding(Item.values(), this);
  80. setId(id);
  81. setLabel(label);
  82. this.job = job;
  83. setStringFieldValue(Item.tabTitle, label);
  84. getTree().label = root.toString();
  85. if (job != null) {
  86. if (job.getButton() != null) {
  87. getComponentBoundUnit(Item.spawn).enabled = true;
  88. }
  89. ((MenuItem) getBoundUnit(Item.refresh)).enabled = true;
  90. ((MenuItem) getBoundUnit(Item.append)).enabled = true;
  91. ((MenuItem) getBoundUnit(Item.startAutoUpdate)).enabled = true;
  92. }
  93. }
  94. /**
  95. * create a doc view with static document
  96. *
  97. * @param id
  98. * @param label
  99. * @param job
  100. * @param root
  101. * @param doc
  102. */
  103. public DocView(String id, String label, DbJob job, Object root, DBObject doc) {
  104. this(id, label, job, root);
  105. if (doc != null) {
  106. addDocument(doc, job, true);
  107. }
  108. }
  109. /**
  110. * create a doc view with an iterator or a cursor
  111. *
  112. * @param id
  113. * @param label
  114. * @param job
  115. * @param root
  116. * @param iterator
  117. */
  118. public DocView(String id, String label, DbJob job, Object root, Iterator<DBObject> iterator) {
  119. this(id, label, job, root);
  120. if (iterator instanceof DBCursor) {
  121. this.dbcursor = (DBCursor) iterator;
  122. this.iterator = dbcursor;
  123. ((MenuItem) getBoundUnit(Item.refresh)).enabled = true;
  124. ((MenuItem) getBoundUnit(Item.startAutoUpdate)).enabled = true;
  125. } else {
  126. this.iterator = iterator;
  127. }
  128. getMore(null);
  129. }
  130. // /**
  131. // * create a doc view from a reusable command with existing result
  132. // * @param id
  133. // * @param label
  134. // * @param job
  135. // * @param db
  136. // * @param cmd
  137. // * @param result
  138. // */
  139. // public DocView(String id, String label, DbJob job, DB db, DBObject cmd, DBObject result) {
  140. // this(id, label, job, db.getName() + ": " + cmd, result);
  141. // this.db = db;
  142. // this.cmd = cmd;
  143. //
  144. // ((MenuItem) getBoundUnit(Item.startAutoUpdate)).enabled = true;
  145. // ((MenuItem) getBoundUnit(Item.refresh)).enabled = true;
  146. // ((MenuItem) getBoundUnit(Item.append)).enabled = true;
  147. // if (result == null) {
  148. // refresh();
  149. // }
  150. // }
  151. //
  152. // /**
  153. // * create a doc view to run a simple command against a database
  154. // * @param id
  155. // * @param label
  156. // * @param col
  157. // * @param panel
  158. // * @param cmdStr
  159. // */
  160. // public DocView(String id, String label, DB db, String cmdStr) {
  161. // this(id, label, null, db, new BasicDBObject(cmdStr, 1), null);
  162. // }
  163. //
  164. // /**
  165. // * create a doc view to run a simple command against a collection
  166. // * @param id
  167. // * @param label
  168. // * @param col
  169. // * @param cmdStr
  170. // */
  171. // public DocView(String id, String label, DBCollection col, String cmdStr) {
  172. // this(id, label, null, col.getDB(), new BasicDBObject(cmdStr, col.getName()), null);
  173. // }
  174. Tree getTree() {
  175. return (Tree) getBoundUnit(Item.docTree);
  176. }
  177. public DBCursor getDBCursor() {
  178. return dbcursor;
  179. }
  180. public void close(ButtonBase button) {
  181. if (dbcursor != null) {
  182. dbcursor.close();
  183. dbcursor = null;
  184. }
  185. tabbedDiv.removeTab(this);
  186. }
  187. void addToTabbedDiv() {
  188. tabbedDiv = UMongo.instance.getTabbedResult();
  189. tabbedDiv.addTab(this, true);
  190. getTree().expandNode(getTree().getTreeNode());
  191. }
  192. public void actionPerformed(Enum enm, XmlComponentUnit unit, Object src) {
  193. }
  194. public void export(ButtonBase button) throws IOException {
  195. // export should be run in thread, to prevent concurrent mods
  196. ExportDialog dia = UMongo.instance.getGlobalStore().getExportDialog();
  197. if (!dia.show()) {
  198. return;
  199. }
  200. final DocumentSerializer ds = dia.getDocumentSerializer();
  201. try {
  202. DefaultMutableTreeNode root = getTree().getTreeNode();
  203. for (int i = 0; i < root.getChildCount(); ++i) {
  204. DefaultMutableTreeNode child = (DefaultMutableTreeNode) root.getChildAt(i);
  205. Object obj = child.getUserObject();
  206. DBObject doc = null;
  207. if (obj instanceof DBObject) {
  208. doc = (DBObject) obj;
  209. } else if (obj instanceof TreeNodeDocumentField) {
  210. doc = (DBObject) ((TreeNodeDocumentField) obj).getValue();
  211. } else if (obj instanceof TreeNodeDocument) {
  212. doc = ((TreeNodeDocument) obj).getDBObject();
  213. }
  214. if (doc != null) {
  215. ds.writeObject(doc);
  216. }
  217. }
  218. } finally {
  219. ds.close();
  220. }
  221. }
  222. public Component getTabComponent() {
  223. return getComponentBoundUnit("tabDiv").getComponent();
  224. }
  225. public void startAutoUpdate(ButtonBase button) {
  226. AutoUpdateDialog dia = UMongo.instance.getGlobalStore().getAutoUpdateDialog();
  227. if (!dia.show()) {
  228. return;
  229. }
  230. if (updateThread != null) {
  231. stopAutoUpdate(null);
  232. }
  233. updateThread = new Thread(this);
  234. updateType = dia.getComponentStringFieldValue(AutoUpdateDialog.Item.autoType);
  235. updateInterval = dia.getComponentIntFieldValue(AutoUpdateDialog.Item.autoInterval);
  236. updateCount = dia.getComponentIntFieldValue(AutoUpdateDialog.Item.autoCount);
  237. running = true;
  238. updateThread.start();
  239. getComponentBoundUnit(Item.stopAutoUpdate).enabled = true;
  240. getComponentBoundUnit(Item.stopAutoUpdate).updateComponent();
  241. }
  242. public void stopAutoUpdate(ButtonBase button) {
  243. running = false;
  244. try {
  245. updateThread.interrupt();
  246. updateThread.join();
  247. } catch (InterruptedException ex) {
  248. }
  249. updateThread = null;
  250. getComponentBoundUnit(Item.stopAutoUpdate).enabled = false;
  251. getComponentBoundUnit(Item.stopAutoUpdate).updateComponent();
  252. }
  253. public void run() {
  254. int i = 0;
  255. while (running) {
  256. try {
  257. DbJob job = null;
  258. if ("Refresh".equals(updateType) || dbcursor != null) {
  259. job = getRefreshJob();
  260. } else if ("Append".equals(updateType)) {
  261. job = getAppendJob();
  262. }
  263. final DbJob fjob = job;
  264. SwingUtilities.invokeAndWait(new Runnable() {
  265. @Override
  266. public void run() {
  267. fjob.addJob();
  268. }
  269. });
  270. try {
  271. fjob.join();
  272. } catch (InterruptedException ex) {
  273. getLogger().log(Level.WARNING, null, ex);
  274. } catch (ExecutionException ex) {
  275. getLogger().log(Level.WARNING, null, ex);
  276. }
  277. if (updateCount > 0 && ++i >= updateCount) {
  278. break;
  279. }
  280. Thread.sleep(updateInterval * 1000);
  281. } catch (Exception ex) {
  282. getLogger().log(Level.SEVERE, null, ex);
  283. }
  284. }
  285. getLogger().log(Level.INFO, "Ran " + i + " updates");
  286. }
  287. public void refresh(ButtonBase button) {
  288. getRefreshJob().addJob();
  289. }
  290. public DbJob getRefreshJob() {
  291. if (dbcursor != null) {
  292. return getUpdateCursorJob();
  293. } else {
  294. return getRefreshJob(false);
  295. }
  296. }
  297. public void append(ButtonBase button) {
  298. getAppendJob().addJob();
  299. }
  300. public DbJob getAppendJob() {
  301. return getRefreshJob(true);
  302. }
  303. public void spawn(ButtonBase button) {
  304. if (job != null) {
  305. job.spawnDialog();
  306. }
  307. }
  308. public void expandText(ButtonBase button) throws IOException {
  309. FormDialog dia = (FormDialog) button.getDialog();
  310. DefaultMutableTreeNode root = getTree().getTreeNode();
  311. DefaultMutableTreeNode select = getTree().getSelectionNode();
  312. String txt = "";
  313. if (select == null || select == root) {
  314. txt = getTextAllNodes(false);
  315. } else {
  316. txt = getTextForNode(select.getUserObject(), false);
  317. }
  318. setStringFieldValue(Item.expandTextArea, txt);
  319. dia.label = this.label;
  320. dia.show();
  321. }
  322. String getTextAllNodes(boolean indent) throws IOException {
  323. StringBuilder b = new StringBuilder();
  324. DefaultMutableTreeNode root = getTree().getTreeNode();
  325. for (int i = 0; i < root.getChildCount(); ++i) {
  326. DefaultMutableTreeNode child = (DefaultMutableTreeNode) root.getChildAt(i);
  327. Object obj = child.getUserObject();
  328. b.append(getTextForNode(obj, indent));
  329. }
  330. return b.toString();
  331. }
  332. String getTextForNode(Object obj, boolean indent) throws IOException {
  333. DBObject doc = null;
  334. if (obj instanceof DBObject) {
  335. doc = (DBObject) obj;
  336. } else if (obj instanceof TreeNodeDocumentField) {
  337. doc = (DBObject) ((TreeNodeDocumentField) obj).getValue();
  338. } else if (obj instanceof TreeNodeDocument) {
  339. doc = ((TreeNodeDocument) obj).getDBObject();
  340. }
  341. if (doc == null) {
  342. return "";
  343. }
  344. final DocumentSerializer ds = new DocumentSerializer(DocumentSerializer.Format.JSON, null);
  345. ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
  346. ds.setOutputStream(baos);
  347. try {
  348. ds.writeObject(doc);
  349. } finally {
  350. ds.close();
  351. }
  352. String txt = new String(baos.toByteArray());
  353. if (indent) {
  354. Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
  355. JsonParser jp = new JsonParser();
  356. JsonElement je = jp.parse(txt);
  357. txt = gson.toJson(je);
  358. // add newline in case there are following docs
  359. txt += "\n";
  360. }
  361. return txt;
  362. }
  363. public void indent(ButtonBase button) throws IOException {
  364. DefaultMutableTreeNode root = getTree().getTreeNode();
  365. DefaultMutableTreeNode select = getTree().getSelectionNode();
  366. String txt = "";
  367. if (select == null || select == root) {
  368. txt = getTextAllNodes(true);
  369. } else {
  370. txt = getTextForNode(select.getUserObject(), true);
  371. }
  372. setComponentStringFieldValue(Item.expandTextArea, txt);
  373. }
  374. public DbJob getRefreshJob(final boolean append) {
  375. if (job == null) {
  376. return null;
  377. }
  378. DbJob newJob = new DbJob() {
  379. BasicDBObject result;
  380. @Override
  381. public Object doRun() throws Exception {
  382. result = (BasicDBObject) job.doRun();
  383. return null;
  384. }
  385. @Override
  386. public String getNS() {
  387. return job.getNS();
  388. }
  389. @Override
  390. public String getShortName() {
  391. return job.getShortName();
  392. }
  393. @Override
  394. public void wrapUp(Object res) {
  395. super.wrapUp(res);
  396. if (res == null && result != null) {
  397. if (!append) {
  398. getTree().removeAllChildren();
  399. }
  400. addDocument(result, this);
  401. getTree().structureComponent();
  402. // result of command should be fully expanded
  403. getTree().expandAll();
  404. // panel info may need to be refreshed
  405. if (job.getPanel() != null) {
  406. job.getPanel().refresh();
  407. }
  408. }
  409. }
  410. };
  411. return newJob;
  412. }
  413. public void getMore(final int max) {
  414. new DbJob() {
  415. @Override
  416. public Object doRun() throws IOException {
  417. int i = 0;
  418. while (iterator.hasNext() && (i++ < max || max <= 0)) {
  419. DBObject obj = iterator.next();
  420. if (obj == null) {
  421. break;
  422. }
  423. addDocument(obj, null);
  424. }
  425. return null;
  426. }
  427. @Override
  428. public String getNS() {
  429. if (dbcursor != null) {
  430. return dbcursor.getCollection().getFullName();
  431. }
  432. return getLabel();
  433. }
  434. @Override
  435. public String getShortName() {
  436. return "Find";
  437. }
  438. @Override
  439. public void wrapUp(Object res) {
  440. super.wrapUp(res);
  441. if (res == null) {
  442. // res should be null
  443. // should have a cursor id now
  444. if (dbcursor != null) {
  445. BasicDBObject desc = getDescription(DocView.this.job.getRoot(dbcursor));
  446. getTree().label = desc.toString();
  447. }
  448. getTree().structureComponent();
  449. getTree().expandNode(getTree().getTreeNode());
  450. DocView.this.updateButtons();
  451. }
  452. }
  453. }.addJob();
  454. }
  455. public void getMore(ButtonBase button) {
  456. getMore(UMongo.instance.getPreferences().getGetMoreSize());
  457. }
  458. public void getAll(ButtonBase button) {
  459. getMore(0);
  460. }
  461. public DefaultMutableTreeNode getSelectedNode() {
  462. TreePath path = getTree().getSelectionPath();
  463. if (path == null || path.getPathCount() < 2) {
  464. return null;
  465. }
  466. return (DefaultMutableTreeNode) path.getLastPathComponent();
  467. }
  468. public DBObject getSelectedDocument() {
  469. TreePath path = getTree().getSelectionPath();
  470. if (path == null || path.getPathCount() < 2) {
  471. return null;
  472. }
  473. DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getPathComponent(1);
  474. Object obj = node.getUserObject();
  475. if (obj instanceof TreeNodeDocumentField) {
  476. return (DBObject) ((TreeNodeDocumentField) obj).getValue();
  477. } else if (obj instanceof DBObject) {
  478. return (DBObject) obj;
  479. } else if (obj instanceof TreeNodeDocument) {
  480. return ((TreeNodeDocument) obj).getDBObject();
  481. }
  482. return null;
  483. }
  484. String getSelectedDocumentPath() {
  485. TreePath path = getTree().getSelectionPath();
  486. String pathStr = "";
  487. if (path.getPathCount() < 2) {
  488. return null;
  489. }
  490. for (int i = 2; i < path.getPathCount(); ++i) {
  491. DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getPathComponent(i);
  492. String key = ((TreeNodeDocumentField) node.getUserObject()).getKey();
  493. pathStr += "." + key;
  494. }
  495. return pathStr.substring(1);
  496. }
  497. public DbJob getUpdateCursorJob() {
  498. if (dbcursor == null) {
  499. return null;
  500. }
  501. // final int count = getTree().getChildren().size();
  502. DbJob newJob = new DbJob() {
  503. @Override
  504. public Object doRun() throws Exception {
  505. dbcursor = (DBCursor) job.doRun();
  506. return null;
  507. }
  508. @Override
  509. public String getNS() {
  510. return job.getNS();
  511. }
  512. @Override
  513. public String getShortName() {
  514. return job.getShortName();
  515. }
  516. @Override
  517. public void wrapUp(Object res) {
  518. super.wrapUp(res);
  519. if (res == null) {
  520. iterator = dbcursor;
  521. getTree().removeAllChildren();
  522. getMore(null);
  523. }
  524. }
  525. };
  526. return newJob;
  527. }
  528. private void updateButtons() {
  529. boolean canGetMore = false;
  530. if (dbcursor != null) {
  531. // can always get more from tailable cursor
  532. canGetMore = iterator.hasNext() || dbcursor.getCursorId() > 0;
  533. } else {
  534. canGetMore = iterator.hasNext();
  535. }
  536. getComponentBoundUnit(Item.getMore).enabled = canGetMore;
  537. getComponentBoundUnit(Item.getMore).updateComponent();
  538. getComponentBoundUnit(Item.getAll).enabled = canGetMore;
  539. getComponentBoundUnit(Item.getAll).updateComponent();
  540. }
  541. public void addDocument(DBObject doc, DbJob job) {
  542. addDocument(doc, job, false);
  543. }
  544. public void addDocument(DBObject doc, DbJob job, boolean expand) {
  545. TreeNodeLabel node = new TreeNodeDocument(doc, job);
  546. getTree().addChild(node);
  547. if (expand) {
  548. getTree().expandNode(node);
  549. }
  550. }
  551. // protected void appendDoc(DBObject doc) {
  552. // TreeNodeLabel node = new TreeNodeLabel();
  553. // node.forceTreeNode(MongoUtils.dbObjectToTreeNode(doc));
  554. // getTree().addChild(node);
  555. // }
  556. public void collapseAll(ButtonBase button) {
  557. getTree().collapseAll();
  558. // need to reexpand root
  559. getTree().expandNode(getTree().getTreeNode());
  560. }
  561. public void expandAll(ButtonBase button) {
  562. getTree().expandAll();
  563. }
  564. }