Source code: recoinx/clef/CLEFClient.java
1
2 package recoinx.clef;
3
4 import javax.swing.*;
5
6 import org.apache.log4j.Logger;
7 import org.dom4j.Document;
8 import org.dom4j.DocumentException;
9 import org.dom4j.Element;
10 import org.dom4j.io.OutputFormat;
11 import org.dom4j.io.SAXReader;
12 import org.dom4j.io.XMLWriter;
13
14 import java.util.Iterator;
15 import java.util.Vector;
16 import java.util.Enumeration;
17 import java.awt.Dimension;
18 import java.awt.GridBagConstraints;
19 import java.awt.GridBagLayout;
20 import java.awt.Insets;
21 import java.awt.event.ActionEvent;
22 import java.awt.event.ActionListener;
23 import java.awt.event.WindowListener;
24 import java.awt.BorderLayout;
25 import java.io.BufferedReader;
26 import java.io.BufferedWriter;
27 import java.io.File;
28 import java.io.FileWriter;
29 import java.io.IOException;
30 import java.io.Reader;
31 import java.io.StringReader;
32 import java.io.Writer;
33 import java.rmi.RemoteException;
34 import java.rmi.RMISecurityManager;
35 import java.rmi.Naming;
36 import java.rmi.server.UnicastRemoteObject;
37
38 import recoin.container.Result;
39 import recoin.container.ResultList;
40
41 /**
42 * The CLEFClient represents an application that offers graphical means to
43 * enter all parameters needed to execute the retrieval process, send them and
44 * process the results upon completion.
45 * @author Jan H. Scheufen
46 * @version 0.2.9
47 */
48 public class CLEFClient implements ActionListener, WindowListener
49 {
50 /**
51 * The logger for this class.
52 */
53 static Logger logger;
54 /**
55 * A SAXReader to read XML files.
56 */
57 private SAXReader xmlReader;
58 /**
59 * A SAXWriter to write XML files.
60 */
61 private XMLWriter xmlWriter;
62 /**
63 * A TRECFormatWriter to create the official TREC format for results.
64 */
65 private TRECFormatWriter formatWriter;
66 /**
67 * The file with the topics.
68 */
69 private File topicFile = null;
70 /**
71 * The URL of the CLEF RMI service.
72 */
73 private String serverURL = "rmi://localhost/RMICLEFService";
74 /**
75 * The RemoteCLEFConnector.
76 */
77 private RemoteCLEFConnector remoteConnector;
78 /**
79 * A JFrame for this CLEFClient.
80 */
81 private JFrame appletFrame;
82 /**
83 * The JTextFields.
84 */
85 private JTextField tfCutOff, tfTopicNumber, tfTopicPath, tfSavePath;
86 /**
87 * The JLabels.
88 */
89 private JLabel lTopic, lSave, lMessage;
90 /**
91 * The JButtons.
92 */
93 private JButton bBrowseTopic, bBrowseSave, bSubmit;
94 /**
95 * A RMI service that receives the answer from the RemoteCLEFConnector.
96 */
97 private CLEFClient.RMIClient client;
98 /**
99 * A CLEFFileChooser to select the topic file from the file system.
100 */
101 private CLEFFileChooser topicChooser;
102 /**
103 * A CLEFFileChooser to select the directory to save results to from the file system.
104 */
105 private CLEFFileChooser saveChooser;
106
107 /**
108 * Creates a new CLEFClient.
109 */
110 public CLEFClient()
111 {
112 super();
113
114 logger = Logger.getLogger( CLEFClient.class.getName() );
115
116 xmlReader = new SAXReader();
117
118 try
119 {
120 client = new RMIClient();
121 }
122 catch( RemoteException e )
123 {
124 logger.error("Couldn't initiate RemoteClient.", e);
125 }
126
127 remoteConnector = lookupConnector( serverURL );
128
129 initiateComponents();
130
131 // create the CLEFFileChoosers
132 topicChooser = new CLEFFileChooser( System.getProperty("user.dir") , "Select the XML topic file." );
133 saveChooser = new CLEFFileChooser( System.getProperty("user.dir") , "Select a directory to save to." );
134 saveChooser.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY );
135
136 appletFrame.setLocation(100,100);
137 appletFrame.pack();
138 appletFrame.setVisible(true);
139 logger.debug("CLEFClient created.");
140 }
141
142 /**
143 * Looks up the RemoteCLEFConnector service in the rmiregistry using the specified URL.
144 * @param connectorURL the URL of the RMI service
145 * @return a RemotePublicConnector
146 */
147 public RemoteCLEFConnector lookupConnector(String connectorURL)
148 {
149 RemoteCLEFConnector rcc = null;
150 try
151 {
152 // Overwriting security methods.
153 System.setSecurityManager (new RMISecurityManager() {
154 public void checkConnect (String host, int port) {}
155 public void checkConnect (String host, int port, Object context) {}
156 public void checkAccept (String host, int port) {}
157 public void checkRead (String file) {}
158 public void checkWrite (String file) {}
159 // allow access to system properties
160 public void checkPropertyAccess(String key) {}
161 });
162
163 rcc = (RemoteCLEFConnector) Naming.lookup( connectorURL );
164 }
165 catch( Exception e )
166 {
167 logger.error("Error lookupConnector()", e);
168 }
169
170 return rcc;
171 }
172
173 /**
174 * Handles ActionEvents from the buttons of this CLEFClient and triggers the
175 * submit mechanism or opens the CLEFFileChooser, for example.
176 * @param e the ActionEvent
177 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
178 */
179 public void actionPerformed(ActionEvent event)
180 {
181 try
182 {
183 JButton button = (JButton)event.getSource();
184 //######### BROWSE TOPIC ###########
185 if( button.equals( bBrowseTopic ) )
186 {
187 int value = topicChooser.showOpenDialog( appletFrame );
188 if( value == JFileChooser.APPROVE_OPTION )
189 {
190 String filePath = topicChooser.getSelectedFile().getAbsolutePath();
191 tfTopicPath.setText( filePath );
192 }
193 }
194 //######### BROWSE SAVEPATH ###########
195 else if( button.equals( bBrowseSave ) )
196 {
197 int value = saveChooser.showOpenDialog( appletFrame );
198 if( value == JFileChooser.APPROVE_OPTION )
199 {
200 String filePath = saveChooser.getSelectedFile().getAbsolutePath();
201 tfSavePath.setText( filePath );
202 }
203 }
204 //######### SUBMIT ###########
205 else if( button.equals( bSubmit ) )
206 {
207 Document topicDoc = null;
208 if( tfTopicPath.getText().equals("") )
209 {
210 //logger.error("Topic file not specified in CLEFClient!");
211 printMessage("ERROR: You must specify a topic file!");
212 return;
213 }
214 else if( tfSavePath.getText().equals("") )
215 {
216 //logger.error("Topic file not specified in CLEFClient!");
217 printMessage("ERROR: You must specify a directory to save to!");
218 return;
219 }
220 else
221 {
222 // TODO no verfification if specified files/dirs exist!
223 topicDoc = createDocument( new File( tfTopicPath.getText() ) );
224 client.setSavePath( tfSavePath.getText() );
225 }
226
227 CLEFQuery query = null;
228
229 int cutOff = 0;
230 try
231 {
232 cutOff = Integer.parseInt(tfCutOff.getText());
233 }
234 catch( NumberFormatException e )
235 {
236 printMessage("ERROR: The value in the Cut Off field is not numerical!");
237 return;
238 }
239
240 // if topicNumber is specified process particular topic
241 String topicNumber = tfTopicNumber.getText();
242 if( !topicNumber.equals("") )
243 {
244 Iterator topicIter = getTopicIterator( topicDoc );
245 while( topicIter.hasNext() )
246 {
247 Element topic = (Element)topicIter.next();
248 // find topic with specified topicNumber
249 if( topic.element("num").getTextTrim().equals( topicNumber ) )
250 {
251 // create a new query for this topic
252 query = new CLEFQuery( topicNumber );
253 if( cutOff > 0 )
254 query.setCutOff( cutOff );
255 query.addTopic( topic.elementTextTrim("EN-desc"), CLEFConstants.ENGLISH );
256 break;
257 }
258 }
259 // Send to RMI service
260 remoteConnector.acceptQuery( client, query );
261 }
262 // otherwise process all topics
263 else
264 {
265 // Get an iterator over the topics
266 Iterator topicIter = getTopicIterator( topicDoc );
267 while( topicIter.hasNext() )
268 {
269 Element topic = (Element)topicIter.next();
270 // create a new query for this topic
271 query = new CLEFQuery( topicNumber );
272 if( cutOff > 0 )
273 query.setCutOff( cutOff );
274 query.addTopic( topic.elementTextTrim("EN-desc"), CLEFConstants.ENGLISH );
275 // Send to RMI service
276 remoteConnector.acceptQuery( client, query );
277 logger.debug("Query abgeschickt.");
278 }
279 }
280 }
281 }
282 catch( RemoteException e )
283 {
284 logger.error("RemoteException beim Senden des CLEFQuery.", e);
285 }
286 catch (DocumentException e)
287 {
288 logger.error("Unable to create topic document.", e);
289 }
290 }
291
292 /**
293 * Outputs the specified message to the user.
294 * @param msg the message
295 */
296 private void printMessage(String msg)
297 {
298 this.lMessage.setText( msg );
299 }
300
301 /**
302 * Main-method of this CLEFClient that starts the client.
303 * @param args
304 */
305 public static void main(String[] args)
306 {
307 new CLEFClient();
308 }
309
310 /**
311 * Exits this CLEFClient.
312 * @param windowEvent
313 * @see java.awt.event.WindowListener#windowClosing(java.awt.event.WindowEvent)
314 */
315 public void windowClosing(java.awt.event.WindowEvent windowEvent)
316 {
317 System.exit(0);
318 }
319
320 /**
321 * Empty implementation of WindowListener method.
322 * @param e the WindowEvent
323 * @see java.awt.event.WindowListener#windowActivated(java.awt.event.WindowEvent)
324 */
325 public void windowActivated(java.awt.event.WindowEvent windowEvent)
326 {
327
328 }
329
330 /**
331 * Empty implementation of WindowListener method.
332 * @param e the WindowEvent
333 * @see java.awt.event.WindowListener#windowDeiconified(java.awt.event.WindowEvent)
334 */
335 public void windowDeiconified(java.awt.event.WindowEvent windowEvent)
336 {
337
338 }
339
340 /**
341 * Empty implementation of WindowListener method.
342 * @param e the WindowEvent
343 * @see java.awt.event.WindowListener#windowDeactivated(java.awt.event.WindowEvent)
344 */
345 public void windowDeactivated(java.awt.event.WindowEvent windowEvent)
346 {
347
348 }
349
350 /**
351 * Empty implementation of WindowListener method.
352 * @param e the WindowEvent
353 * @see java.awt.event.WindowListener#windowIconified(java.awt.event.WindowEvent)
354 */
355 public void windowIconified(java.awt.event.WindowEvent windowEvent)
356 {
357
358 }
359
360 /**
361 * Empty implementation of WindowListener method.
362 * @param e the WindowEvent
363 * @see java.awt.event.WindowListener#windowClosed(java.awt.event.WindowEvent)
364 */
365 public void windowClosed(java.awt.event.WindowEvent windowEvent)
366 {
367
368 }
369
370 /**
371 * Empty implementation of WindowListener method.
372 * @param e the WindowEvent
373 * @see java.awt.event.WindowListener#windowOpened(java.awt.event.WindowEvent)
374 */
375 public void windowOpened(java.awt.event.WindowEvent windowEvent)
376 {
377
378 }
379
380 /**
381 * Initiates the GUI components of this CLEFClient.
382 */
383 private void initiateComponents()
384 {
385 // GUI zusammenbauen
386 appletFrame = new JFrame("CLEF Client");
387 //appletFrame.setSize(500,350);
388 appletFrame.addWindowListener(this);
389 // the content pane already has an implicit BorderLayout by default
390
391 GridBagConstraints constraints = new GridBagConstraints();
392
393 // create main panel with GridBagLayout
394 JPanel mainPanel = new JPanel();
395 mainPanel.setLayout( new GridBagLayout() );
396
397 // Topic Label
398 lTopic = new JLabel("Topic File:");
399 constraints.gridx = 0;
400 constraints.gridy = 0;
401 constraints.insets = new Insets(5, 10, 2, 5);
402 constraints.anchor = GridBagConstraints.WEST;
403 constraints.gridwidth = 2;
404 mainPanel.add(lTopic, constraints);
405
406 // TopicPath Textfield
407 tfTopicPath = new JTextField(30);
408 constraints.gridx = 0;
409 constraints.gridy = 1;
410 constraints.insets = new Insets(2, 10, 5, 5);
411 constraints.anchor = GridBagConstraints.WEST;
412 mainPanel.add(tfTopicPath, constraints);
413
414 // Topic Browse Button
415 bBrowseTopic = new JButton("Browse");
416 bBrowseTopic.addActionListener( this );
417 constraints.gridx = 2;
418 constraints.gridy = 1;
419 constraints.insets = new Insets(2, 5, 5, 10);
420 constraints.anchor = GridBagConstraints.EAST;
421 constraints.gridwidth = 1;
422 mainPanel.add(bBrowseTopic, constraints);
423
424 // SaveAs Label
425 lSave = new JLabel("Save Results to");
426 constraints.gridx = 0;
427 constraints.gridy = 2;
428 constraints.insets = new Insets(5, 10, 2, 5);
429 constraints.anchor = GridBagConstraints.WEST;
430 constraints.gridwidth = 2;
431 mainPanel.add(lSave, constraints);
432
433 // SavePath Textfield
434 tfSavePath = new JTextField(30);
435 constraints.gridx = 0;
436 constraints.gridy = 3;
437 constraints.insets = new Insets(2, 10, 5, 5);
438 constraints.anchor = GridBagConstraints.WEST;
439 mainPanel.add(tfSavePath, constraints);
440
441 // SavePath Browse Button
442 bBrowseSave = new JButton("Browse");
443 bBrowseSave.addActionListener( this );
444 constraints.gridx = 2;
445 constraints.gridy = 3;
446 constraints.insets = new Insets(2, 5, 5, 10);
447 constraints.anchor = GridBagConstraints.EAST;
448 constraints.gridwidth = 1;
449 mainPanel.add(bBrowseSave, constraints);
450
451 // Topic Number Label
452 JLabel lTopicNo = new JLabel("Topic Number:");
453 constraints.gridx = 0;
454 constraints.gridy = 4;
455 constraints.insets = new Insets(5, 10, 5, 5);
456 constraints.anchor = GridBagConstraints.WEST;
457 mainPanel.add(lTopicNo, constraints);
458
459 // Topic Number Textfield
460 tfTopicNumber = new JTextField( 5 );
461 tfTopicNumber.setEditable(true);
462 constraints.gridx = 1;
463 constraints.gridy = 4;
464 //constraints.gridwidth = GridBagConstraints.REMAINDER;
465 constraints.insets = new Insets(5, 5, 5, 5);
466 mainPanel.add(tfTopicNumber, constraints);
467
468 // Cut Off Label
469 JLabel lCutOff = new JLabel("Cut Off:");
470 constraints.gridx = 0;
471 constraints.gridy = 5;
472 constraints.insets = new Insets(5, 10, 5, 5);
473 mainPanel.add(lCutOff, constraints);
474
475 // Cut Off Textfield
476 tfCutOff = new JTextField( 5 );
477 tfCutOff.setEditable(true);
478 constraints.gridx = 1;
479 constraints.gridy = 5;
480 constraints.insets = new Insets(5, 5, 5, 5);
481 mainPanel.add(tfCutOff, constraints);
482
483 // Submit Button
484 bSubmit = new JButton("Submit");
485 bSubmit.addActionListener( this );
486 constraints.gridx = 0;
487 constraints.gridy = 6;
488 constraints.gridwidth = 3;
489 constraints.insets = new Insets(15, 5, 15, 5);
490 constraints.anchor = GridBagConstraints.CENTER;
491 constraints.gridwidth = 3;
492 mainPanel.add(bSubmit, constraints);
493
494 // Message Label
495 lMessage = new JLabel();
496
497 appletFrame.getContentPane().add( mainPanel, BorderLayout.CENTER );
498 appletFrame.getContentPane().add( lMessage, BorderLayout.SOUTH );
499
500 }
501
502 /**
503 * Returns a org.dom4j.Document that represents the specified file.
504 * @param file the File to parse.
505 * @return the Document representation.
506 * @throws org.dom4j.DocumentException
507 */
508 private Document createDocument(File file) throws DocumentException
509 {
510 Document document = null;
511 try
512 {
513 document = xmlReader.read(file);
514 }
515 catch( java.net.MalformedURLException e )
516 {
517 logger.error("MalformedURLException in createDocument(File).");
518 }
519 return document;
520 }
521
522 /**
523 * Returns a org.dom4j.Document that is created using the specified Reader.
524 * @param reader a Reader to read the input from
525 * @return the document representation.
526 * @throws org.dom4j.DocumentException
527 */
528 private Document createDocument( Reader reader ) throws DocumentException
529 {
530 Document document = null;
531 document = xmlReader.read( reader );
532 return document;
533 }
534
535 /**
536 * Returns an Iterator ocer the topic elements in the specified Document.
537 * @param doc the Document
538 * @return the topic Iterator
539 */
540 private Iterator getTopicIterator( Document doc )
541 {
542 Element root = doc.getRootElement();
543 return root.elementIterator("top");
544 }
545
546 /**
547 * Writes the specified Document using the specified XMLWriter
548 * @param writer a XMLWriter
549 * @param doc the Document
550 */
551 private void writeDoc( XMLWriter writer, Document doc )
552 {
553 try
554 {
555 writer.write( doc );
556 writer.flush();
557 }
558 catch (IOException e)
559 {
560 logger.debug("IOException in writeDoc. ", e);
561 }
562 }
563
564 /**
565 * Inner class that implements an RMI service to receive the results from the
566 * RemoteCLEFConnector.
567 */
568 protected class RMIClient extends UnicastRemoteObject implements RemoteCLEFClient
569 {
570 /**
571 * The path where to save any results.
572 */
573 private String savePath = "";
574
575 /**
576 * Creates a new RMIClient.
577 * @throws RemoteException
578 */
579 public RMIClient() throws RemoteException
580 {
581 }
582
583 /**
584 * The remote method that is called by the RemoteCLEFConnector to return any results.
585 * @param v a Vector of ResultList objects
586 */
587 public void receiveResults(Vector results)
588 {
589 try
590 {
591 logger.debug("Receiving "+results.size()+" results.");
592 BufferedWriter writer = null;
593 Document doc = null;
594 // iterate through ResultLists
595 for( Enumeration listEnum = results.elements(); listEnum.hasMoreElements(); )
596 {
597 ResultList list = (ResultList)listEnum.nextElement();
598 String filePath = "";
599 String formatPath = "";
600 String content = "";
601 String ps = File.separator;
602 if( list instanceof CLEFResultList )
603 {
604 CLEFResultList clefList = (CLEFResultList)list;
605 filePath = savePath+ps+clefList.getTopicNumber()+"_"+clefList.getTopic().getLanguage()+"_"+list.getChainID()+".xml";
606 formatPath = savePath+ps+clefList.getTopicNumber()+"_"+clefList.getTopic().getLanguage()+"_"+list.getChainID()+"_trec.txt";
607 content = clefList.toXML();
608 }
609 else if( list instanceof CLEFMergedResultList )
610 {
611 CLEFMergedResultList mergedList = (CLEFMergedResultList)list;
612 int i=1;
613 String marker = mergedList.getLanguage() != -1 ? CLEFConstants.getLanguageName(mergedList.getLanguage())+"_merged" : "merged_"+(i++);
614 filePath = savePath+ps+mergedList.getTopicNumber()+"_"+marker+"_"+list.getChainID()+".xml";
615 formatPath = savePath+ps+mergedList.getTopicNumber()+"_"+marker+"_"+list.getChainID()+"_trec.txt";
616 content = mergedList.toXML();
617 }
618
619 try
620 {
621 logger.debug("Writing file '"+filePath+"'.");
622 // create BufferedWriter and XMLWriter
623 writer = new BufferedWriter( new FileWriter( filePath ) );
624 OutputFormat format = OutputFormat.createPrettyPrint();
625 // Suppress XML declaration since no root element is added!
626 //format.setSuppressDeclaration(true);
627 xmlWriter = new XMLWriter( writer, format );
628 formatWriter = new TRECFormatWriter( new FileWriter(formatPath) );
629
630 doc = createDocument( new BufferedReader( new StringReader( content ) ) );
631 // write the XML file
632 writeDoc( xmlWriter, doc );
633 // write the official format file
634 formatWriter.writeFormattedDoc( "runid", doc );
635 formatWriter.close();
636 }
637 catch (IOException e)
638 {
639 logger.error("Couldn't write to file: "+filePath, e);
640 }
641 }
642 }
643 catch( DocumentException de )
644 {
645 logger.error("Unable to create XML Document.", de);
646 }
647 catch (Exception e)
648 {
649 logger.error("Exception while receiving results.", e);
650 }
651
652 logger.debug("Results stored. Query finished.");
653
654 /*
655 if( results.size() == 0 )
656 JOptionPane.showMessageDialog(null, "Es wurden keine ResultLists zur�ckgegeben!", "Suche erfolglos", JOptionPane.INFORMATION_MESSAGE);
657 else
658 JOptionPane.showMessageDialog(null, "Es wurden "+results.size()+" ResultLists zur�ckgegeben!", "Suche erfolgreich", JOptionPane.INFORMATION_MESSAGE);
659 */
660
661 /* Remove comments if you want to display the ResultLists in individual frames.
662
663 Vector frames = new Vector();
664
665 int coordinate = 30;
666 for( Enumeration enum = results.elements(); enum.hasMoreElements(); )
667 {
668 ResultList rl = (ResultList)enum.nextElement();
669 ResultFrame rf = new ResultFrame(rl);
670 frames.add(rf);
671 rf.setLocation(coordinate, coordinate);
672 rf.pack();
673 rf.show();
674 coordinate += 15;
675 }
676 */
677 }
678
679 /**
680 * Returns the path where results are saved.
681 * @return the path
682 */
683 public String getSavePath()
684 {
685 return savePath;
686 }
687
688 /**
689 * Sets the path where results are saved to the specified path.
690 * @param path the path
691 */
692 public void setSavePath(String path)
693 {
694 savePath = path;
695 }
696
697 }
698
699 /**
700 * Inner class that represents a single JFrame to display the results.
701 */
702 private class ResultFrame extends JFrame
703 {
704 /**
705 * The ResultList that is displayed.
706 */
707 private ResultList resultList;
708 /**
709 * A JTextArea to render the ResultList.
710 */
711 private JTextArea textArea;
712
713 /**
714 * Creates a new ResultFrame with the specified ResultList.
715 * @param list the ResultList
716 */
717 public ResultFrame(ResultList list)
718 {
719 resultList = list;
720 init();
721 renderResultList();
722 }
723
724 /**
725 * Initiates the GUI components of this ResultFrame.
726 */
727 private void init()
728 {
729 setTitle( resultList.getName() );
730 textArea = new JTextArea(60,80);
731 textArea.setEditable(false);
732 JScrollPane scrollPane = new JScrollPane(textArea);
733 scrollPane.setPreferredSize(new Dimension(700, 500));
734 getContentPane().setLayout( new BorderLayout() );
735 getContentPane().add(scrollPane, BorderLayout.CENTER);
736 }
737
738 /**
739 * Renders the results in a formatted form.
740 */
741 private void renderResultList()
742 {
743 String nl = System.getProperty("line.separator");
744 Result result = null;
745 Enumeration resultEnum = resultList.getResults().elements();
746 while( resultEnum.hasMoreElements() )
747 {
748 result = (Result) resultEnum.nextElement();
749 textArea.append( result.toXML() + nl );
750 }
751 }
752 }
753
754 /**
755 * The CLEFFileChooser class represents a JFileChooser to select a file or a folder
756 * from the file system.
757 */
758 private class CLEFFileChooser extends JFileChooser
759 {
760 /**
761 * Creates a new CLEFFileChooser with the specified path that is used to set
762 * a path to start from.
763 * @param path a path to start from
764 * @param title the dialog's title
765 */
766 CLEFFileChooser( String path, String title )
767 {
768 super( path );
769 setDialogTitle( title );
770 }
771 }
772
773 /**
774 * The TRECFormatWriter class extends the BufferedWriter to print to a File.
775 * It provides methods that format retrieval results to the official TREC
776 * format and print them.
777 * @author Jan H. Scheufen
778 * @version 0.2.9
779 */
780 private class TRECFormatWriter extends BufferedWriter
781 {
782 /**
783 * Creates a new TRECFormatWriter with the specified Writer.
784 * @param out a Writer
785 */
786 public TRECFormatWriter(Writer out)
787 {
788 super(out);
789 }
790
791 /**
792 * Writes the specified Document if the root element discovered equals
793 * CLEFRESULTLIST or CLEFMERGEDRESULTLIST.<br>
794 * The inidividual results are transformed into the official TREC result
795 * format using the specified String as run ID.
796 * @param runID the run ID to print
797 * @param doc the Document with the results
798 * @throws IOException
799 */
800 public void writeFormattedDoc( String runID, Document doc ) throws IOException
801 {
802 Element root = doc.getRootElement();
803 Iterator iter = null;
804 if( root.getName().equals("CLEFRESULTLIST") )
805 {
806 logger.debug("Getting Iterator over CLEFRESULT elements.");
807 iter = root.elementIterator("CLEFRESULT");
808 }
809 else if( root.getName().equals("CLEFMERGEDRESULTLIST") )
810 {
811 logger.debug("Getting Iterator over MERGEDRESULT elements.");
812 iter = root.elementIterator("MERGEDRESULT");
813 }
814
815 if( iter != null )
816 {
817 String topic = root.element("TOPIC").getTextTrim();
818 // remove letters from start if present
819 if( !topic.equals("") )
820 {
821 boolean ok = false;
822 do
823 {
824 // try to parse first char
825 try
826 {
827 Integer.valueOf( String.valueOf(topic.charAt(0)) );
828 ok = true;
829 }
830 catch (NumberFormatException e)
831 {
832 // shorten topic
833 topic = topic.substring(1);
834 }
835 }
836 while( !ok && topic.length() > 0 );
837 }
838
839 Element result;
840 int i = 0;
841 String nl = System.getProperty("line.separator");
842 String prefix = topic+" Q0 ";
843 String resultString = "";
844 logger.debug("Writing TREC format file for topic '"+topic+"'.");
845 try
846 {
847 while( iter.hasNext() )
848 {
849 result = (Element)iter.next();
850 resultString = prefix;
851 resultString += result.element("DOCNO").getTextTrim()+" "+(++i)+" ";
852 resultString += result.element("SCORE").getTextTrim()+" "+runID+nl;
853 write( resultString );
854 flush();
855 }
856 }
857 catch (IOException e)
858 {
859 logger.error("Unable to write resultString '"+resultString+"'.", e);
860 //throw e;
861 }
862 }
863 else
864 {
865 logger.error("Couldn't create Iterator over results in Document "+doc);
866 }
867 }
868
869 }
870
871 }