001: package com.xoetrope.carousel.services;
002:
003: import java.io.BufferedWriter;
004: import java.io.File;
005: import java.io.FileOutputStream;
006: import java.io.OutputStreamWriter;
007: import java.util.Enumeration;
008: import java.util.Hashtable;
009:
010: import java.awt.BorderLayout;
011: import java.awt.Component;
012: import java.awt.Container;
013: import java.awt.event.ItemEvent;
014: import java.awt.event.ItemListener;
015: import javax.swing.BorderFactory;
016: import javax.swing.JComboBox;
017: import javax.swing.JLabel;
018: import javax.swing.JMenu;
019: import javax.swing.JMenuBar;
020: import javax.swing.JMenuItem;
021: import javax.swing.JPanel;
022: import javax.swing.JScrollPane;
023: import javax.swing.JSplitPane;
024: import javax.swing.JTree;
025: import javax.swing.SwingUtilities;
026: import javax.swing.border.EmptyBorder;
027: import javax.swing.tree.DefaultMutableTreeNode;
028: import javax.swing.tree.TreePath;
029:
030: import net.xoetrope.editor.project.XEditorProject;
031: import net.xoetrope.editor.XEditorUtilities;
032: import com.xoetrope.carousel.services.dialog.NewStaticSource;
033: import com.xoetrope.carousel.services.dialog.XLibTreeCellRenderer;
034: import com.xoetrope.carousel.services.events.ModelListener;
035: import net.xoetrope.xml.XmlElement;
036: import net.xoetrope.xui.XProjectManager;
037: import net.xoetrope.xui.data.XBaseModel;
038: import net.xoetrope.xui.data.XModel;
039:
040: /**
041: * The panel which is loaded when the 'Manage data' tab is selected. It creates
042: * a splitter pane with a JTree on the left and an XLibStaticDataEditor on the
043: * right. The tree is passed to the XLibStaticDataEditor so that it can manipulate
044: * it.
045: * This class handles editing of static as well as database data. There are
046: * different functions to handle each data type.
047: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
048: * the GNU Public License (GPL), please see license.txt for more details. If
049: * you make commercial use of this software you must purchase a commercial
050: * license from Xoetrope.</p>
051: * <p> $Revision: 1.5 $</p>
052: */
053: public class DataEditor extends JPanel implements ItemListener,
054: ModelListener {
055: private Container toolbar;
056: private JSplitPane splitPane;
057: private JPanel treePanel, editPanel;
058: private JComboBox cmbDataSources;
059: private JMenu mnuNew, mnuFile;
060: private JMenuBar mnuBar;
061: private JTree dataTree;
062: private JScrollPane dataPane;
063: private DefaultMutableTreeNode topNode;
064: private XEditorProject currentProject;
065: private StaticDataEditor staticDataEditor;
066: private XModel editModel;
067: private JLabel lblFileName;
068: private JMenuItem mnuSetModelFile, mnuSave, mnuAddStatic, mnuAddDB,
069: mnuAddWS;
070: private ModelListener modelListener;
071: private Hashtable staticModels;
072:
073: /**
074: * Assign the XEditorProject parameter to a local variable. Add a toolbar to
075: * the panel. Create a splitter pane with the tree component on the left and
076: * the dataeditor on the right. Call the function to load the datasources into
077: * the combobox.
078: * @param proj the current XEditorProject project
079: */
080: public DataEditor(XEditorProject proj) {
081: currentProject = proj;
082: add(createToolbar(), BorderLayout.NORTH);
083: treePanel = new JPanel(new BorderLayout());
084: staticDataEditor = new StaticDataEditor(currentProject);
085: staticDataEditor.setModelListener(this );
086: createStaticTree(null);
087: editPanel = new JPanel(new BorderLayout());
088: editPanel.add(staticDataEditor, BorderLayout.CENTER);
089: splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
090: treePanel, editPanel);
091: splitPane.setDividerLocation(300);
092: splitPane.setDividerSize(6);
093: splitPane.setBorder(BorderFactory.createEmptyBorder());
094: add(splitPane, BorderLayout.CENTER);
095: staticModels = new Hashtable();
096: addDataSources();
097: }
098:
099: /**
100: * set the reference to the ModelListener
101: * @param listener the ModelListener which will listen for updates
102: */
103: public void setModelListener(ModelListener listener) {
104: modelListener = listener;
105: }
106:
107: /**
108: * create the static tree. Set the cell renderer to the custom renderer.
109: * Expand the root node
110: * @param editModel the XModel from which we want to build the tree
111: */
112: private void createStaticTree(XModel editModel) {
113: createTree(StaticDataEditor.AMEND_STATIC);
114: if (editModel != null)
115: buildStaticTree(editModel);
116:
117: dataTree.setCellRenderer(new XLibTreeCellRenderer(
118: StaticDataEditor.AMEND_STATIC, editModel));
119: expandRoot();
120: }
121:
122: /**
123: * create the database tree. Set the cell renderer to the custom renderer.
124: * Expand the root node
125: */
126: private void createDatabaseTree() {
127: XmlElement ele = (XmlElement) getModelManager()
128: .getDataSources().get(cmbDataSources.getSelectedItem());
129: createTree(StaticDataEditor.AMEND_DATABASE);
130: buildDatabaseTree(ele);
131: dataTree.setCellRenderer(new XLibTreeCellRenderer(
132: StaticDataEditor.AMEND_DATABASE));
133: expandRoot();
134: }
135:
136: private ModelManager getModelManager() {
137: RouteManager routeMgr = (RouteManager) currentProject
138: .getObject(ProjectRouteManager.ROUTE_MGR_LOOKUP);
139: return routeMgr.getModelMgr();
140: }
141:
142: /**
143: * expand the root node.
144: */
145: public void expandRoot() {
146: final TreePath path = new TreePath(topNode);
147: SwingUtilities.invokeLater(new Runnable() {
148: public void run() {
149: dataTree.expandPath(path);
150: dataTree.repaint();
151: }
152: });
153: }
154:
155: /**
156: * if the datapane isn't null remove it from the panel. Create the new tree,
157: * make it editable and set the border. Pass the tree to the static data
158: * editor. expand the root node.
159: * @param amendMode indicates the type of datasource we are working
160: * with (static or database)
161: */
162: private void createTree(int amendMode) {
163: if (dataPane != null)
164: treePanel.remove(dataPane);
165: topNode = new DefaultMutableTreeNode("Datasets");
166: dataTree = new JTree(topNode);
167: if (cmbDataSources.getItemCount() == 0) {
168: dataTree.setVisible(false);
169: }
170: dataTree.setEditable(true);
171: dataTree.setBorder(new EmptyBorder(0, 0, 0, 0));
172: dataPane = new JScrollPane(dataTree);
173: staticDataEditor.setTree(dataTree, amendMode);
174: treePanel.add(dataPane, BorderLayout.CENTER);
175:
176: TreePath path = new TreePath(topNode);
177: dataTree.expandPath(path);
178: }
179:
180: /**
181: * Remove all the children from the root node and call the XLibXModelManager
182: * to build it.
183: * @param editModel the XModel from which to build the tree
184: * @return the root node.
185: */
186: private DefaultMutableTreeNode buildStaticTree(XModel editModel) {
187: topNode.removeAllChildren();
188: getModelManager().createTreeNodes(editModel, topNode, null);
189: return topNode;
190: }
191:
192: /**
193: * Remove the child nodes. Get the databaseNodes hashtable from the
194: * XLibXModelManager and add them to the tree.
195: * @param source
196: * @return
197: */
198: private DefaultMutableTreeNode buildDatabaseTree(XmlElement source) {
199: topNode.removeAllChildren();
200: Hashtable databaseNodes = getModelManager().getDatabaseNodes();
201: Enumeration e = databaseNodes.keys();
202: while (e.hasMoreElements()) {
203: String name = (String) e.nextElement();
204: DefaultMutableTreeNode child = new DefaultMutableTreeNode(
205: name);
206: topNode.add(child);
207: }
208: return topNode;
209: }
210:
211: /**
212: * Set the layout to a BorderLayout. Create the datasources combobox.
213: * @return the toolbar
214: */
215: private Component createToolbar() {
216: setLayout(new BorderLayout());
217: JPanel tempPnl = new JPanel();
218: cmbDataSources = new JComboBox();
219: cmbDataSources.addItemListener(this );
220: toolbar = new JPanel(new BorderLayout());
221: lblFileName = new JLabel();
222:
223: tempPnl.add(new JLabel("Datasource :"));
224: tempPnl.add(cmbDataSources);
225: tempPnl.add(lblFileName);
226: toolbar.add(tempPnl, BorderLayout.WEST);
227: return toolbar;
228: }
229:
230: private void addDataSources() {
231: Hashtable ht = getModelManager().getDataSources();
232: Enumeration enumeration = ht.keys();
233: while (enumeration.hasMoreElements()) {
234: String key = (String) enumeration.nextElement();
235: XmlElement src = (XmlElement) ht.get(key);
236: String type = src.getAttribute("type");
237: if (type == null || type.compareTo("") == 0
238: || type.compareTo("database") == 0)
239: cmbDataSources.addItem(key);
240: }
241: }
242:
243: /**
244: * Load the datasource specified from the value in the combobox. Determine the
245: * type of datasource we're working with and load it from the relevant file.
246: * @param evt the ItemEvent
247: */
248: public void itemStateChanged(ItemEvent evt) {
249: String datasourceName = (String) cmbDataSources
250: .getSelectedItem();
251: String fileName = getModelManager().getDataSourceAttrib(
252: datasourceName, "filename");
253: lblFileName.setText(fileName);
254: String dataSourceType = getModelManager().getDataSourceAttrib(
255: datasourceName, "type");
256: if (dataSourceType != null
257: && dataSourceType.compareTo("database") == 0) {
258: getModelManager().loadDatabaseData(fileName);
259: createDatabaseTree();
260: } else {
261: editModel = (XBaseModel) staticModels.get(datasourceName);
262: if (editModel == null)
263: editModel = (XBaseModel) getModelManager()
264: .loadStaticData(fileName);
265:
266: staticModels.put(datasourceName, editModel);
267: createStaticTree(editModel);
268: staticDataEditor.setEditModel((XBaseModel) editModel,
269: fileName, currentProject.getPath() + File.separator
270: + "resources" + File.separator);
271: }
272: dataTree.setVisible(true);
273: staticDataEditor.hideDataPanels(null);
274: }
275:
276: /**
277: * Inform the XModelListener that the XModel has changed.
278: */
279: public void modelChanged() {
280: if (modelListener != null)
281: modelListener.modelChanged();
282: }
283:
284: /**
285: * Called from the XLibPlugin when the save menu is clicked in the editor. Iterate
286: * the models in the XLibXModelManager datasources hashtable. If the model is
287: * in the local staticModels hashtable then we output it. If the 'deploy'
288: * attribute of the datasource node is set to false then we need to save the
289: * model data in the root of the project.
290: */
291: public void save() {
292: Hashtable databaseNodes = getModelManager().getDataSources();
293: Enumeration enumeration = databaseNodes.keys();
294: while (enumeration.hasMoreElements()) {
295: String name = (String) enumeration.nextElement();
296: XmlElement eleDataSource = (XmlElement) databaseNodes
297: .get(name);
298: XBaseModel model = (XBaseModel) staticModels.get(name);
299: if (model != null) {
300: String path = currentProject.getPath() + File.separator
301: + "resources" + File.separator;
302: if (eleDataSource.getAttribute("deploy").compareTo(
303: "false") == 0)
304: path = currentProject.getPath() + File.separator;
305: saveFile(path, eleDataSource.getAttribute("filename"),
306: model);
307: }
308: }
309:
310: getModelManager().writeDatasets(currentProject);
311: if (cmbDataSources.getSelectedItem() != null) {
312: XModel model = (XModel) currentProject.getModel().get(
313: (String) cmbDataSources.getSelectedItem());
314: currentProject.getModel().reset(currentProject);
315: getModelManager().readXmlFile();
316: }
317: }
318:
319: /**
320: * Save a mode to the passed filePath + fileName
321: * @param filePath the path to the model file
322: * @param fileName the name of the model file
323: * @param model the model to be output
324: */
325: void saveFile(String filePath, String fileName, XBaseModel model) {
326: try {
327: FileOutputStream fos = new FileOutputStream(filePath
328: + fileName);
329: OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8");
330: BufferedWriter bw = new BufferedWriter(osw);
331: getModelManager().write(bw, model);
332: } catch (Exception ex) {
333: ex.printStackTrace();
334: }
335: }
336:
337: /**
338: * Create a new static data source from the values entered in the NewStaticSource
339: * dialog. Check the return value of the dialog before proceeding. If OK was
340: * clicked copy the template file to the resources directory add the datasource
341: * to the XLibXModelManager and add the name to the combobox and select it
342: */
343: public void addNewStaticDataSource() {
344: NewStaticSource dlg = new NewStaticSource();
345: dlg.setLocationRelativeTo(this );
346: if (dlg.showDlg()) {
347: File f = new File(dlg.getFileName());
348: if (f.exists()) {
349: editModel = (XBaseModel) getModelManager()
350: .loadStaticData(dlg.getFileName());
351: } else {
352: String filename = currentProject.getPath()
353: + File.separator + "resources" + File.separator
354: + dlg.getFileName();
355: XEditorUtilities.copyFile(currentProject,
356: "template_staticdata.xml", filename);
357: getModelManager().addStaticDataSource(
358: dlg.getSourceName(), dlg.getFileName());
359: cmbDataSources.addItem(dlg.getSourceName());
360: cmbDataSources.setSelectedItem(dlg.getSourceName());
361: }
362: }
363: }
364:
365: /**
366: * Create a new datdabase data source from the values entered in the NewStaticSource
367: * dialog. Check the return value of the dialog before proceeding. If OK was
368: * clicked add the datasource to the XLibXModelManager and add the name to the
369: * combobox and select it
370: */
371: public void addNewDatabaseDataSource() {
372: NewStaticSource dlg = new NewStaticSource();
373: dlg.setLocationRelativeTo(this );
374: if (dlg.showDlg()) {
375: File f = new File(dlg.getFileName());
376: if (f.exists()) {
377: editModel = (XBaseModel) getModelManager()
378: .loadStaticData(dlg.getFileName());
379: } else {
380: getModelManager().addDatabaseDataSource(
381: dlg.getSourceName(), dlg.getFileName());
382: cmbDataSources.addItem(dlg.getSourceName());
383: cmbDataSources.setSelectedItem(dlg.getSourceName());
384: }
385: }
386: }
387: }
|