001package com.ganteater.ae.desktop;
002
003import java.awt.BorderLayout;
004import java.awt.Color;
005import java.awt.FileDialog;
006import java.awt.Font;
007import java.awt.event.ActionEvent;
008import java.awt.event.ActionListener;
009import java.awt.event.WindowAdapter;
010import java.awt.event.WindowEvent;
011import java.io.File;
012import java.util.Map;
013import java.util.Vector;
014
015import javax.swing.BorderFactory;
016import javax.swing.JButton;
017import javax.swing.JDialog;
018import javax.swing.JEditorPane;
019import javax.swing.JLabel;
020import javax.swing.JOptionPane;
021import javax.swing.JPanel;
022import javax.swing.JScrollPane;
023import javax.swing.JTextField;
024import javax.swing.JToolBar;
025import javax.swing.JTree;
026
027import org.apache.commons.lang.ArrayUtils;
028import org.apache.commons.lang.StringEscapeUtils;
029import org.apache.commons.lang.StringUtils;
030import org.apache.commons.lang.exception.ExceptionUtils;
031
032import com.ganteater.ae.AEWorkspace;
033import com.ganteater.ae.CommandException;
034import com.ganteater.ae.ILogger;
035import com.ganteater.ae.RecipeRunner;
036import com.ganteater.ae.TaskThread;
037import com.ganteater.ae.desktop.ui.AEFrame;
038import com.ganteater.ae.desktop.ui.AttachButton;
039import com.ganteater.ae.desktop.ui.Button;
040import com.ganteater.ae.desktop.ui.HyperlinkAdapter;
041import com.ganteater.ae.desktop.ui.JParsedown;
042import com.ganteater.ae.desktop.ui.OptionPane;
043import com.ganteater.ae.desktop.util.UIUtils;
044import com.ganteater.ae.processor.BaseProcessor;
045import com.ganteater.ae.processor.Processor;
046import com.ganteater.ae.util.xml.easyparser.Node;
047
048public class WorkPlace extends RecipeRunner {
049
050        private static final Font ABOUT_FONT = new Font("SansSerif", Font.PLAIN, 12);
051        private static final String MAIL_ATTR_NAME = "email";
052
053        protected JToolBar aboutButtonPanel = new JToolBar();
054
055        protected String recipeFilePath;
056
057        protected FileDialog theAttacFileDialog;
058        protected JLabel fTitleTest = new JLabel();
059        protected JTextField theConfigName = new JTextField();
060        private AEFrame aeFrame = null;
061        private JDialog aboutDialog;
062
063        public WorkPlace(AEFrame aeFrame, Node aConfigNode, Map<String, Object> aSystemVariables) {
064                super(aeFrame.getWorkspace(), aConfigNode, aSystemVariables);
065                aConfigNode.getVector(true);
066                this.aeFrame = aeFrame;
067                theConfigName.setEditable(false);
068
069                theConfigName.setFont(new Font("Dialog", Font.PLAIN, 9));
070                theConfigName.setBackground(Color.lightGray);
071
072                theAttacFileDialog = new FileDialog(JOptionPane.getRootFrame(), "Storing attach in file", FileDialog.SAVE);
073                theAttacFileDialog.setDirectory(System.getProperty("user.home"));
074
075                fTitleTest.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4));
076
077                JPanel thePanelLogo = new JPanel(new BorderLayout());
078
079                thePanelLogo.add(theConfigName, BorderLayout.SOUTH);
080
081                JPanel theComp = new JPanel(new BorderLayout());
082                JPanel theCompTitle = new JPanel(new BorderLayout());
083                theComp.add(theCompTitle, BorderLayout.NORTH);
084        }
085
086        protected void setActiveTest(String theActiveTest) throws CommandException {
087                if (theActiveTest != null) {
088                        recipeFilePath = getManager().getTestPath(theActiveTest);
089                }
090
091                runTest(recipeFilePath, createLog(theActiveTest, true));
092        }
093
094        @Override
095        public void startTask(String aNameTask) {
096                setTestName(aNameTask);
097        }
098
099        @Override
100        public void setTestName(String aNameTask) {
101                fTitleTest.setText(aNameTask);
102        }
103
104        @Override
105        public void endTask(boolean aErrorState) {
106                super.endTask(aErrorState);
107
108                if (!aErrorState) {
109                        fTitleTest.setText(" Recipe done.");
110                } else {
111                        fTitleTest.setText(" Recipe failed.");
112                }
113
114                manager.progressValue(0, 0, !aErrorState);
115        }
116
117        public void runTest(String aTestFile, ILogger aLog) {
118                if (aTestFile == null) {
119                        return;
120                }
121                recipeFilePath = aTestFile;
122
123                TaskThread theThread = new TaskThread(this, aTestFile);
124                theThread.start();
125        }
126
127        public String getTestFile() {
128                return recipeFilePath;
129        }
130
131        public void setTestsFile(String aTestsFile) {
132                recipeFilePath = aTestsFile;
133        }
134
135        @Override
136        public String inputFile(File defaultFile, Processor taskProcessor) {
137                String theResult = null;
138
139                String preferedFile = AEWorkspace.getInstance().getDefaultUserConfiguration(".inputFile",
140                                defaultFile == null ? null : defaultFile.getAbsolutePath());
141
142                if (preferedFile != null) {
143                        defaultFile = new File(preferedFile);
144                }
145
146                theResult = preferedFile;
147
148                if (preferedFile == null || !getManager().isConsoleDefaultInput("inputFile", null)) {
149                        FileDialog fileDialog = new FileDialog(JOptionPane.getRootFrame(), "Loading file in property ",
150                                        FileDialog.LOAD);
151
152                        if (defaultFile != null) {
153                                if (defaultFile.isDirectory()) {
154                                        fileDialog.setDirectory(defaultFile.getParent());
155                                } else {
156                                        fileDialog.setFile(defaultFile.getName());
157                                }
158                        }
159
160                        fileDialog.setVisible(true);
161
162                        theResult = fileDialog.getDirectory() + fileDialog.getFile();
163                        AEWorkspace.getInstance().setDefaultUserConfiguration(".inputFile", theResult);
164                }
165
166                return theResult;
167        }
168
169        @Override
170        public void aboutTest(String theTaskName, Node aCurrentAction) {
171                if (theTaskName == null)
172                        return;
173                setAbout(theTaskName, aCurrentAction);
174        }
175
176        protected void setAbout(String theTaskName, Node aCurrentAction) {
177                JPanel aboutPanel = new JPanel();
178                aboutPanel.setLayout(new BorderLayout());
179                aboutPanel.setBorder(BorderFactory.createBevelBorder(10));
180
181                aboutDialog = new JDialog(JOptionPane.getRootFrame(), "About", false);
182                aboutDialog.addWindowListener(new WindowAdapter() {
183                        @Override
184                        public void windowClosing(WindowEvent e) {
185                                UIUtils.saveDialogPreferedView(aboutDialog, "Task:" + theTaskName);
186                        }
187
188                        @Override
189                        public void windowDeactivated(WindowEvent e) {
190                                UIUtils.saveDialogPreferedView(aboutDialog, "Task:" + theTaskName);
191                        }
192                });
193                aboutDialog.getContentPane().add(aboutPanel);
194                UIUtils.applyPreferedView(aboutDialog, "Task:" + theTaskName, 400, 600);
195
196                StringBuilder theBuffer = new StringBuilder();
197
198                Node[] theAuthorNodes = aCurrentAction.getNodes("author");
199
200                theBuffer.append("<html><body>");
201                Node[] descriptions = aCurrentAction.getNodes("description");
202                for (Node description : descriptions) {
203                        String text = description.getInnerXMLText();
204                        text = StringEscapeUtils.unescapeXml(text);
205
206                        JParsedown pd = new JParsedown();
207                        String markdown = pd.text(text);
208                        theBuffer.append(markdown);
209                }
210                if (!ArrayUtils.isEmpty(descriptions) && ArrayUtils.isNotEmpty(theAuthorNodes)) {
211                        theBuffer.append("<hr/>");
212                }
213
214                if (theAuthorNodes != null) {
215                        for (int i = 0; i < theAuthorNodes.length; i++) {
216                                if (theAuthorNodes[i].getAttribute("name") != null)
217                                        theBuffer.append(
218                                                        "Authore: <font color=\"red\">" + theAuthorNodes[i].getAttribute("name") + "</font><br>");
219                                if (theAuthorNodes[i].getAttribute(MAIL_ATTR_NAME) != null)
220                                        theBuffer.append("E-mail: <a href='mailto:" + theAuthorNodes[i].getAttribute(MAIL_ATTR_NAME) + "'>"
221                                                        + theAuthorNodes[i].getAttribute(MAIL_ATTR_NAME) + "</a><br>");
222                                if (theAuthorNodes[i].getAttribute("messager") != null)
223                                        theBuffer.append("Messager: " + theAuthorNodes[i].getAttribute("messager") + "<br>");
224                                if (theAuthorNodes[i].getAttribute("phone") != null)
225                                        theBuffer.append("Phone: " + theAuthorNodes[i].getAttribute("phone") + "<br>");
226                                if (theAuthorNodes.length > 1)
227                                        theBuffer.append("<hr>");
228                        }
229                }
230
231                theBuffer.append("</body></html>");
232
233                JEditorPane aboutPane = new JEditorPane();
234                aboutPane.setContentType("text/html");
235                aboutPane.setText(theBuffer.toString());
236                aboutPane.addHyperlinkListener(new HyperlinkAdapter(manager));
237
238                aboutPane.setEditable(false);
239                aboutPane.setFont(ABOUT_FONT);
240
241                aboutPanel.add(new JScrollPane(aboutPane), BorderLayout.CENTER);
242                aboutButtonPanel.removeAll();
243
244                if (ArrayUtils.isNotEmpty(descriptions) || ArrayUtils.isNotEmpty(theAuthorNodes)) {
245                        JButton aboutButton = new Button("about.png");
246                        aboutButton.addActionListener(x -> showAboutPanel());
247                        aboutButtonPanel.add(aboutButton);
248                }
249
250                Node[] theDocNodes = aCurrentAction.getNodes("attach/file");
251
252                if (theDocNodes != null && theDocNodes.length > 0) {
253                        for (int i = 0; i < theDocNodes.length; i++) {
254                                JLabel theButton = new AttachButton(this, theDocNodes[i], theTaskName);
255                                aboutButtonPanel.add(theButton);
256                        }
257
258                }
259
260        }
261
262        private void showAboutPanel() {
263                aboutDialog.setVisible(true);
264        }
265
266        @Override
267        public void criticalError(CommandException aThrowable, Processor processor) {
268                if (!aThrowable.isReviewed()) {
269                        String message = ExceptionUtils.getMessage(aThrowable);
270                        if (StringUtils.isBlank(message)) {
271                                message = "Message is absent. Please see stack trace.";
272                        }
273                        OptionPane.showMessageDialog(aeFrame, message, "Critical exception", JOptionPane.ERROR_MESSAGE);
274                }
275                super.criticalError(aThrowable, processor);
276        }
277
278        @Override
279        public void checkFailure(CommandException e, Processor processor) {
280                String message = e.getMessage();
281                if (StringUtils.startsWith(message, "com.ganteater.ae.desktop.util.AssertionFailedError")) {
282                        message = StringUtils.substringAfter(message, "com.ganteater.ae.desktop.util.");
283                }
284                if (message.length() > 1000) {
285                        message = "Check Failure. See log messages.";
286                }
287
288                String formatMessage = formatMessage(message);
289
290                JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), formatMessage, "Exception",
291                                JOptionPane.ERROR_MESSAGE);
292
293                super.checkFailure(e, processor);
294        }
295
296        private String formatMessage(String message) {
297                if (message == null) {
298                        return "Something went wrong. The error message is empty.";
299                }
300
301                StringBuilder result = new StringBuilder();
302                int length = 0;
303                for (int i = 0; i < message.length(); i++) {
304                        char c = message.charAt(i);
305                        result.append(c);
306                        length++;
307                        if (c == '\n') {
308                                length = 0;
309                        }
310                        if (c == ' ' && length > 80) {
311                                result.append('\n');
312                                length = 0;
313                        }
314                }
315
316                return result.toString();
317        }
318
319        class PanelTree extends JPanel implements ActionListener {
320                private static final long serialVersionUID = 1L;
321
322                JTree jTree = null;
323
324                boolean fExpandRow = true;
325
326                JButton theButton = new JButton("Collapse");
327
328                public PanelTree(Vector<Vector<String>> theVector) {
329                        super(new BorderLayout());
330                        jTree = new JTree(theVector);
331
332                        jTree.setEditable(true);
333
334                        for (int i = 0; i < jTree.getRowCount(); i++) {
335                                jTree.expandRow(i);
336                        }
337
338                        JScrollPane scroll = new JScrollPane(jTree);
339                        add(scroll, BorderLayout.CENTER);
340                }
341
342                public void actionPerformed(ActionEvent e) {
343                        fExpandRow = !fExpandRow;
344                        if (fExpandRow) {
345                                theButton.setText("Collapse");
346                                for (int i = 0; i < jTree.getRowCount(); i++) {
347                                        jTree.expandRow(i);
348                                }
349                        } else {
350                                theButton.setText("Expand");
351                                for (int i = jTree.getRowCount(); i >= 0; i--) {
352                                        jTree.collapseRow(i);
353                                }
354                        }
355                }
356        }
357
358        @Override
359        public Processor getTaskProcessor() {
360                Processor processor = super.getTaskProcessor();
361                if (processor == null) {
362                        String testFile = getTestFile();
363                        if (testFile == null) {
364                                testFile = getManager().getStartDir().getAbsolutePath();
365                        }
366                        processor = new BaseProcessor(getManager(), getLogger(), new File(testFile).getParentFile());
367                        processor.setTestListener(this);
368                }
369                return processor;
370        }
371
372        public AEFrame getAeFrame() {
373                return aeFrame;
374        }
375
376}