View Javadoc

1   /***
2    * 
3    */
4   package org.telscenter.pas.otrunk;
5   
6   import java.awt.BorderLayout;
7   import java.awt.Color;
8   import java.awt.Component;
9   import java.awt.Dimension;
10  import java.awt.event.ActionEvent;
11  import java.awt.event.ActionListener;
12  import java.awt.event.ComponentEvent;
13  import java.awt.event.ComponentListener;
14  import java.beans.beancontext.BeanContextServices;
15  import java.io.BufferedReader;
16  import java.io.ByteArrayInputStream;
17  import java.io.ByteArrayOutputStream;
18  import java.io.File;
19  import java.io.FileInputStream;
20  import java.io.FileReader;
21  import java.io.InputStream;
22  import java.io.StringReader;
23  import java.net.URL;
24  import java.util.HashMap;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Timer;
29  import java.util.TimerTask;
30  import java.util.TooManyListenersException;
31  import java.util.logging.Level;
32  import java.util.logging.Logger;
33  
34  import javax.swing.BorderFactory;
35  import javax.swing.JButton;
36  import javax.swing.JLabel;
37  import javax.swing.JOptionPane;
38  import javax.swing.JPanel;
39  
40  import net.sf.sail.common.beansupport.IIconProvider;
41  import net.sf.sail.core.beans.event.SessionEvent;
42  import net.sf.sail.core.beans.event.SessionEventListener;
43  import net.sf.sail.core.beans.service.AgentService;
44  import net.sf.sail.core.beans.service.AnnotationService;
45  import net.sf.sail.core.beans.service.SessionService;
46  import net.sf.sail.core.entity.IAgent;
47  import net.sf.sail.core.entity.ISock;
48  import net.sf.sail.core.entity.MismatchedAgentSetSizeException;
49  import net.sf.sail.core.entity.Rim;
50  import net.sf.sail.core.entity.Role;
51  import net.sf.sail.core.entity.UnsupportedRimShapeException;
52  
53  import org.apache.commons.io.IOUtils;
54  import org.concord.data.state.OTDataStore;
55  import org.concord.datagraph.state.OTDataAxis;
56  import org.concord.datagraph.state.OTDataCollector;
57  import org.concord.datagraph.state.OTDataGraphable;
58  import org.concord.framework.otrunk.OTControllerService;
59  import org.concord.framework.otrunk.OTObject;
60  import org.concord.framework.otrunk.view.OTFrameManager;
61  import org.concord.framework.otrunk.view.OTViewContext;
62  import org.concord.framework.otrunk.view.OTViewFactory;
63  import org.concord.otrunk.OTMLToXHTMLConverter;
64  import org.concord.otrunk.datamodel.OTDatabase;
65  import org.concord.otrunk.view.OTViewContainerPanel;
66  import org.concord.otrunk.view.OTViewerHelper;
67  import org.concord.otrunk.xml.XMLDatabase;
68  import org.telscenter.pas.beans.IWorkReporter;
69  import org.telscenter.pas.beans.PasStep;
70  import org.telscenter.pas.otrunk.skeleton.OTGenericOTrunkStep;
71  import org.telscenter.pas.service.NavigateAction;
72  import org.xhtmlrenderer.simple.XHTMLPanel;
73  
74  import com.lowagie.text.pdf.PdfPCell;
75  
76  /***
77   * @author scott
78   *
79   */
80  public class OTrunkStep extends PasStep 
81  	implements IIconProvider, SessionEventListener, IWorkReporter
82  {
83  	/***
84  	 * Logger for this class
85  	 */
86  	private static final Logger logger = Logger.getLogger(OTrunkStep.class
87  			.getName());
88  	
89  	/***
90  	 * This is not intended to be serialized by the java object serializer
91  	 * It is intended to be serialized by XMLEncoder
92  	 */
93  	private static final long serialVersionUID = 1L;
94  
95  	private OTViewerHelper viewerHelper;
96  
97  	private URL authoredDataURL;
98  	private Rim workRim;
99  
100 	private String typeName = "Otrunk Step";
101 	
102 	private BeanIcons beanIcons;
103 	
104 	private ISock workSock;
105     
106 	private OTObject target;
107 
108 	private OTControllerService controllerService;
109 	
110 	private static HashMap<String, Class> supportedTypes = new HashMap<String, Class>();
111 
112 	private Class stepType;
113 
114 	private boolean needsSetup = false;
115 	
116 	private Timer timer;
117 	
118 	private boolean needsSockEntryInit = true;
119 	
120 	public OTrunkStep()
121 	{
122 		viewerHelper = new OTViewerHelper();
123 		supportedTypes = new HashMap<String, Class>();
124 	}
125 	
126 	public URL getAuthoredDataURL()
127 	{
128 		return authoredDataURL;
129 	}
130 
131 	public void setAuthoredDataURL(URL url)
132 	{
133 		authoredDataURL = url;
134 	}
135 
136 	public BeanIcons getBeanIcons()
137 	{
138 		return beanIcons;
139 	}
140 	
141 	public void setBeanIcons(BeanIcons icons)
142 	{
143 		this.beanIcons = icons;
144 	}
145 	
146 	public Component getComponent() {
147 		return getComponent(false);
148 	}	
149 	
150 	/* (non-Javadoc)
151 	 * @see java.beans.beancontext.BeanContextChildComponentProxy#getComponent()
152 	 */
153 	public Component getComponent(boolean authoring) {
154 		JPanel panel=new JPanel(new BorderLayout(5, 5));
155 		OTViewContainerPanel otPanel = null;
156 		if (needsSetup) {
157 			try {
158 			  setupStep();
159 			} catch (Exception e) {
160 				logger.log(Level.SEVERE, "Failed to create OTObject for step", e);
161 			}
162 		}
163 		try {
164 			OTObject root = target;
165 
166 			if(root == null){
167 				OTDatabase otDB = viewerHelper.loadOTDatabase(getAuthoredDataURL());
168 				viewerHelper.loadOTrunk(otDB, panel);
169 
170 				// load the user state
171 				// get the last sock entry from the sock, get its string value
172 				// turn the string into an input stream
173 				Object lastEntry = null;
174 				if(workSock != null && workSock.size() > 0){
175 					lastEntry = workSock.peek();
176 				}
177 				if(lastEntry != null){
178 					OTDatabase userDB = null;
179 					if(lastEntry instanceof String) {
180 						StringReader reader = new StringReader((String)lastEntry);
181 
182 						// FIXME need to pass in some context url this is needed
183 						// for any referenced resources in the otml
184 						userDB = viewerHelper.loadOTDatabase(reader, null);
185 
186 					} else if(lastEntry instanceof byte[]){
187 						ByteArrayInputStream inStream = new ByteArrayInputStream((byte[])lastEntry); 
188 
189 						userDB = viewerHelper.loadOTDatabase(inStream, null);					
190 					}
191 
192 					if(userDB != null){
193 						viewerHelper.loadUserData(userDB, null);
194 						if(userDB instanceof XMLDatabase ){
195 							((XMLDatabase)userDB).setDirty(false);
196 						}
197 					} else {
198 						viewerHelper.newAnonUserData();					
199 					}
200 				} else {
201 					viewerHelper.newAnonUserData();
202 				}
203 
204 
205 				root = viewerHelper.getRootObject();
206 				otPanel = viewerHelper.createViewContainerPanel();
207 			} else {
208 				OTViewContext viewContext = 
209 					(OTViewContext) controllerService.getService(OTViewContext.class);
210 
211 				OTFrameManager frameManager = 
212 					(OTFrameManager) viewContext.getViewService(OTFrameManager.class);
213 				otPanel = new OTViewContainerPanel(frameManager);
214 				otPanel.setTopLevelContainer(true);
215 				OTViewFactory viewFactory = viewContext.createChildViewFactory();
216 				otPanel.setOTViewFactory(viewFactory);
217 			}
218 			
219 			panel.setLayout(new BorderLayout());
220 
221 			panel.add(otPanel, BorderLayout.CENTER);
222 
223 			if(authoring == true) {
224 				otPanel.setViewMode("authoring");
225 			}
226 			
227 			otPanel.setCurrentObject(root);
228 			
229 			JButton save = new JButton("Save");
230 			save.addActionListener(new ActionListener(){
231 
232 				public void actionPerformed(ActionEvent e) {
233 					saveDataInternal();
234 					JOptionPane.showMessageDialog(null, "Your data has been saved", "Saved", JOptionPane.INFORMATION_MESSAGE);
235 				}				
236 			});
237 			
238 			timer = new Timer();
239 			long delay = 60*1000; // run every 1 minute
240 			timer.scheduleAtFixedRate(new TimerTask() {
241 				@Override
242 				public void run() {
243 					// System.err.println("Saving otrunk data...");
244 					saveDataInternal();
245 				}
246 			}, delay, delay);
247 			
248 			//Fix to prevent button from stretching across frame
249 			JPanel savePanel = new JPanel();
250 			savePanel.add(save);
251 			panel.add(savePanel, BorderLayout.SOUTH);
252 		} catch (Exception e) {
253 			// TODO Auto-generated catch block
254 			e.printStackTrace();
255 		}
256 
257 		
258 		return panel;
259 	}
260 
261 	private void saveDataInternal() {
262 		saveDataInternal(true);
263 	}
264 
265 	private void saveDataInternal(boolean replace)
266 	{
267 		if (needsSockEntryInit) {
268 			// override replace so that a sockentry gets created in the current sessionbundle
269 			replace = false;
270 		}
271 		
272 		OTDatabase userDB = viewerHelper.getUserOtDB();
273 
274 		// If the database hasn't been modified, don't
275 		// save anything
276 		if(userDB instanceof XMLDatabase &&
277 				!((XMLDatabase)userDB).isDirty()){
278 			return;
279 		}
280 		
281 		try {
282 			if(workSock != null && userDB != null){
283 				byte [] bytes = new byte [1];
284 
285 				// this is a hack to test this should be moved
286 				// to the converter
287 				//getWorkRim().setShape(bytes.getClass());
288 
289 				if(getWorkRim().getShape() == bytes.getClass()){
290 					ByteArrayOutputStream out = new ByteArrayOutputStream();
291 					viewerHelper.saveOTDatabase(userDB, out);
292 					bytes = out.toByteArray();
293 					workSock.add(bytes, replace);
294 					if(userDB instanceof XMLDatabase){
295 						((XMLDatabase)userDB).setDirty(false);
296 					}
297 				} else {
298 					String userData = viewerHelper.saveOTDatabase(userDB);
299 					workSock.add(userData, replace);
300 				}
301 				needsSockEntryInit = false;
302 			} else {
303 				System.err.println("No sock in OTrunkStep - cannot save data");
304 			}
305 			
306 		} catch (Exception e1) {
307 			// TODO Auto-generated catch block
308 			e1.printStackTrace();
309 		}										
310 
311 	}
312 	
313 	public Rim getWorkRim() {
314 		return workRim;
315 	}
316 
317 	public void setWorkRim(Rim workRim) {
318 		this.workRim = workRim;
319 	}
320 
321 
322 	protected void consumeService(BeanContextServices bcs, Class<? extends Object>  serviceClass) {
323 		if (serviceClass == AgentService.class) {
324 			try {
325 				final AgentService p = (AgentService) bcs.getService(this,
326 						this, AgentService.class, this, this);
327 				IAgent agent = p.getAgentsInRole(Role.RUN_WORKGROUP).getSingle();
328 				if(workRim != null && agent != null){
329 					workSock = p.getSock(workRim, agent);
330 				}
331 			} catch (TooManyListenersException e) {
332 				e.printStackTrace();
333 			} catch (MismatchedAgentSetSizeException e) {
334 				e.printStackTrace();
335 			} catch (UnsupportedRimShapeException e) {
336 				e.printStackTrace();
337 			}
338 		}
339 		if (serviceClass == SessionService.class) {
340 			try {
341 				SessionService sessionService = (SessionService) bcs.getService(this, this,
342 						SessionService.class, this, this);
343 				sessionService.addSessionEventListener(this);
344 			} catch (TooManyListenersException e1) {
345 				// TODO Auto-generated catch block
346 				logger.severe("BeanContextServices, Class -  : exception: " + e1); //$NON-NLS-1$
347 			}
348 		}
349 
350 	}
351 
352 	public URL getIcon(int iconKind) {
353 		BeanIcons icons = getBeanIcons();
354 		if(icons == null) {
355 			return null;
356 		}
357 		return icons.getIcon(iconKind);
358 	}
359 	
360 	public static HashMap<String, Class> getSupportedTypes() {
361 			supportedTypes.put("Quick Draw", org.concord.graph.util.state.OTDrawingTool.class);
362 			supportedTypes.put("Data Graph", org.concord.datagraph.state.OTDataCollector.class);
363 			supportedTypes.put("Concord Multi Tool", org.concord.otrunk.view.document.OTCompoundDoc.class);
364 		return supportedTypes;
365 	}
366 	
367 	public void setType(Class type) {
368 		this.stepType = type;
369 		this.needsSetup  = true;
370 		
371 		//set the type name for the authoring tool
372 		for (Map.Entry<String, Class> entry : supportedTypes.entrySet()) {
373 			if( entry.getValue().equals(type )) {
374 				this.typeName = entry.getKey();
375 			}
376 		}
377 	}
378 	
379 	public void setupStep() throws Exception {
380 		// set the current step type
381 		// get the OTObject which corresponds to this step
382 		// set its target to a new object of the type specified
383 		OTGenericOTrunkStep otStep = (OTGenericOTrunkStep) controllerService.getOTObject(this);
384 		OTObject obj = otStep.getOTObjectService().createObject(stepType);
385 		otStep.setTarget(obj);
386 		this.setTarget(obj);
387 		if (stepType == OTDataCollector.class) {
388 			OTDataAxis yAxis = (OTDataAxis) otStep.getOTObjectService().createObject(OTDataAxis.class);
389 			OTDataAxis xAxis = (OTDataAxis) otStep.getOTObjectService().createObject(OTDataAxis.class);
390 			yAxis.setMin(0);
391 			yAxis.setMax(100);
392 			yAxis.setLabel("");
393 			yAxis.setUnits("");
394 			xAxis.setMin(0);
395 			xAxis.setMax(100);
396 			xAxis.setLabel("unknown");
397 			xAxis.setUnits("");
398 			((OTDataCollector)obj).setXDataAxis(xAxis);
399 			((OTDataCollector)obj).setYDataAxis(yAxis);
400 			OTDataGraphable graphable = (OTDataGraphable) otStep.getOTObjectService().createObject(OTDataGraphable.class);
401 			graphable.setDataStore((OTDataStore) otStep.getOTObjectService().createObject(OTDataStore.class));
402 			((OTDataCollector)obj).setSource(graphable);
403 		}
404 	}
405     
406     public String getType() {
407         return typeName;
408     }
409     
410 	public void stepExit() {
411 		if (timer != null) {
412 			timer.cancel();
413 		}
414 		saveDataInternal();
415 	}
416     
417 	public void sessionInitiated(SessionEvent e) {
418 	}
419 
420 	public void sessionStarted(SessionEvent e) {		
421 	}
422 
423 	public void sessionStopped(SessionEvent e) {
424 		stepExit();		
425 	}
426 
427 	public List<JLabel> getCurrentAnswers() {
428 		// TODO Auto-generated method stub
429 		return null;
430 	}
431 
432 	public List<String> getCurrentPrompts() {
433 		// TODO Auto-generated method stub
434 		return null;
435 	}
436 
437 	public List<JPanel> getCurrentStepParts() {
438 		// TODO Auto-generated method stub
439 		return null;
440 	}
441 
442 	public Map<String, String> getEntityToPromptMap() {
443 		// TODO Auto-generated method stub
444 		return null;
445 	}
446 
447 	public Integer getPossibleScore() {
448 		// TODO Auto-generated method stub
449 		return null;
450 	}
451 
452 	public JPanel getReportForLearner() {
453 		/*
454 		  
455 		//the stuff Tony and Geoff were working on to implement show all work 
456 		viewerHelper.
457 		OTJComponentView objView = getOTJComponentView(viewerHelper.getRootObject(), "printing");
458 
459         OTXHTMLView xhtmlView = null;
460         String bodyText = "";
461         if(objView instanceof OTXHTMLView) {
462             xhtmlView = (OTXHTMLView) objView;
463         	bodyText = xhtmlView.getXHTMLText(viewerHelper.getRootObject());
464         }
465         System.out.println(bodyText);
466         
467 
468 		*/
469 		
470         OTMLToXHTMLConverter oTMLToXHTMLConverter = null;
471 		File outputFile = new File("output.txt");
472 		
473 		System.out.println("Initial outputFile length: " + outputFile.length());
474 		OTObject otObject = null;
475 		Thread oTMLToXHTMLConverterThread = null;
476 		try {
477 			/*
478 			FileWriter fos = new FileWriter(outputFile);
479 			fos.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
480 			fos.close();
481 			System.out.println("Intermediate outputFile length: " + outputFile.length());
482 			
483 			FileWriter fos2 = new FileWriter(outputFile);
484 			fos2.write("abc");
485 			fos2.close();
486 			System.out.println("Intermediate outputFile length: " + outputFile.length());
487 			*/
488 			otObject = viewerHelper.getRootObject();
489 			oTMLToXHTMLConverter = new OTMLToXHTMLConverter(viewerHelper.getViewFactory(), otObject);
490 	        oTMLToXHTMLConverter.setXHTMLParams(outputFile, 1000, 1000);
491 	        oTMLToXHTMLConverterThread = new Thread (oTMLToXHTMLConverter);
492 	        oTMLToXHTMLConverterThread.start();
493 	        //oTMLToXHTMLConverterThread.join();
494 		} catch(Exception e) {
495 			System.out.println("Exception: " + e);
496 		}
497 		
498 		JLabel workLabel = new JLabel("The junk in yr trunk otrunk");
499 		JPanel p = new JPanel();
500 		p.add(workLabel);
501 		
502 		
503 		final XHTMLPanel panel = new XHTMLPanel();
504 
505 		//panel.setAntiAliased(true);
506 		//panel.setFontScalingFactor(3f);
507 		panel.setOpaque(false);
508 		panel.setBorder(BorderFactory.createMatteBorder(5, 4, 3, 2, Color.RED));
509 		
510 		//panel.setPreferredSize(new Dimension(600, 0));
511 		panel.setPreferredSize(new Dimension());
512 		panel.addComponentListener(new ComponentListener() {
513 		
514 			public void componentHidden(ComponentEvent e) {
515 				// TODO Auto-generated method stub
516 
517 			}
518 
519 			public void componentMoved(ComponentEvent e) {
520 				// TODO Auto-generated method stub
521 
522 			}
523 
524 			public void componentResized(ComponentEvent e) {
525 				//panel.relayout();
526 
527 			}
528 
529 			public void componentShown(ComponentEvent e) {
530 				// TODO Auto-generated method stub
531 
532 			}
533 		});
534 		
535 		// System.out.println("HTML TO PRINT: " + blockInteraction.getPrompt());
536 		//panel.setDocumentFromString("<?xml version="1.0" encoding="UTF-8"?>
537 		String xhtmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"DTD/xhtml1-transitional.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\"><head><title> Transitional DTD XHTML Example </title></head><body bgcolor=\"#FFFFFF\" link=\"#000000\" text=\"red\"><p>This is a transitional XHTML example</p></body></html>";
538 			
539 		InputStream stream = null;
540 		try {
541 			//stream = IOUtils.toInputStream(blockInteraction.getPrompt());
542 			stream = IOUtils.toInputStream(xhtmlString);
543 			//panel.setDocument(stream, null);
544 			
545 			StringBuffer xhtml = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"DTD/xhtml1-transitional.dtd\"><html>");
546 			
547 			
548 	        //StringBuffer fileData = new StringBuffer(1000);
549 	        BufferedReader reader = new BufferedReader(
550 	                new FileReader("output.txt"));
551 	        char[] buf = new char[1024];
552 	        int numRead=0;
553 	        while((numRead=reader.read(buf)) != -1){
554 	            xhtml.append(buf, 0, numRead);
555 	        }
556 	        reader.close();
557 	        xhtml.append("</img></html>");
558 	        
559 	        int offset = xhtml.indexOf("<img");
560 	        //xhtml.insert(offset + 4, " width='1000' height='1000'");
561 	        
562 	        stream = IOUtils.toInputStream(xhtml.toString());
563 	        
564 			System.out.println("Ending outputFile length: " + outputFile.length());
565 			
566 			FileInputStream fis = new FileInputStream(outputFile);
567 			
568 			FileReader fr = new FileReader(outputFile);
569 
570 			//DataInputStream dis = new DataInputStream(fis);
571 			System.out.println(xhtml);
572 			panel.setDocument(stream, null);
573 			//panel.setDocument(fis, null);
574 		} catch (NullPointerException e) {
575 			e.printStackTrace();
576 		} catch (Exception e) {
577 			e.printStackTrace();
578 		} finally {
579 			IOUtils.closeQuietly(stream);
580 		}
581 //		panel.setPreferredSize(new Dimension(PROMPT_PANEL_WIDTH, PROMPT_PANEL_HEIGHT));
582 //		panel.setMaximumSize(panel.getPreferredSize());
583 		
584 		
585 		
586 		return panel;
587 	}
588 
589 	public JPanel getReportForLearner(NavigateAction navigateAction) {
590 		// TODO Auto-generated method stub
591 		return null;
592 	}
593 
594 	public PdfPCell getReportForLearnerPDF() {
595 		// TODO Auto-generated method stub
596 		return null;
597 	}
598 
599 	public JPanel getReportForLearnerWithAnnotations(
600 			NavigateAction navigateAction) {
601 		// TODO Auto-generated method stub
602 		return null;
603 	}
604 
605 	public JPanel getReportForLearnerWithAnnotations() {
606 		// TODO Auto-generated method stub
607 		return null;
608 	}
609 
610 	public void initStepParts() {
611 		// TODO Auto-generated method stub
612 		
613 	}
614 
615 	public void setPossibleScore(Integer possibleScore) {
616 		// TODO Auto-generated method stub
617 		
618 	}
619 
620 	public PdfPCell getReportForLearnerPDF(AnnotationService annotationService) {
621 		// TODO Auto-generated method stub
622 		return null;
623 	}
624 
625 	public void setTarget(OTObject target) {
626 		this.target = target;		
627 	}
628 
629 	public void setControllerService(OTControllerService controllerService) {
630 		this.controllerService = controllerService;		
631 	}
632 
633 }