1 package jp.sourceforge.stigmata.result;
7 import java.io.BufferedReader;
9 import java.io.FileNotFoundException;
10 import java.io.FileReader;
11 import java.io.FileWriter;
12 import java.io.IOException;
13 import java.io.PrintWriter;
14 import java.net.MalformedURLException;
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.Iterator;
19 import java.util.List;
22 import javax.xml.namespace.QName;
23 import javax.xml.stream.XMLEventReader;
24 import javax.xml.stream.XMLInputFactory;
25 import javax.xml.stream.XMLStreamException;
26 import javax.xml.stream.events.EndElement;
27 import javax.xml.stream.events.StartElement;
28 import javax.xml.stream.events.XMLEvent;
30 import jp.sourceforge.stigmata.Birthmark;
31 import jp.sourceforge.stigmata.BirthmarkContext;
32 import jp.sourceforge.stigmata.BirthmarkElement;
33 import jp.sourceforge.stigmata.BirthmarkEnvironment;
34 import jp.sourceforge.stigmata.BirthmarkSet;
35 import jp.sourceforge.stigmata.BirthmarkStoreException;
36 import jp.sourceforge.stigmata.BirthmarkStoreTarget;
37 import jp.sourceforge.stigmata.ComparisonMethod;
38 import jp.sourceforge.stigmata.ExtractionTarget;
39 import jp.sourceforge.stigmata.ExtractionUnit;
40 import jp.sourceforge.stigmata.Stigmata;
41 import jp.sourceforge.stigmata.printer.xml.ExtractionResultSetXmlPrinter;
42 import jp.sourceforge.stigmata.spi.BirthmarkSpi;
43 import jp.sourceforge.stigmata.ui.swing.ExtensionFilter;
44 import jp.sourceforge.stigmata.utils.MultipleIterator;
47 * This class manages extracted birthmarks as xml file.
48 * This instance do not use {@link ExtractionTarget <code>ExtractionTarget</code>}.
50 * @author Haruaki Tamada
52 public class XmlFileExtractionResultSet extends AbstractExtractionResultSet{
53 private boolean addmode = true;
54 private File storeDirectory;
55 private Map<ExtractionTarget, XmlFile> files = new HashMap<ExtractionTarget, XmlFile>();
57 XmlFileExtractionResultSet(BirthmarkContext context){
61 XmlFileExtractionResultSet(BirthmarkContext context, File storeDirectory){
63 this.storeDirectory = storeDirectory;
66 public XmlFileExtractionResultSet(BirthmarkContext context, boolean tableType){
67 super(context, tableType);
70 public XmlFileExtractionResultSet(File directory){
71 super(Stigmata.getInstance().createContext());
74 storeDirectory = directory;
76 BirthmarkContext context = getContext();
77 context.setStoreTarget(BirthmarkStoreTarget.XMLFILE);
78 if(files.containsKey(ExtractionTarget.TARGET_X)
79 && files.containsKey(ExtractionTarget.TARGET_Y)){
80 context.setComparisonMethod(ComparisonMethod.ROUND_ROBIN_XY);
83 context.setComparisonMethod(ComparisonMethod.ROUND_ROBIN_SAME_PAIR);
86 for(File file: storeDirectory.listFiles(new ExtensionFilter("xml"))){
87 String fileName = file.getName();
88 String name = fileName.substring(0, fileName.lastIndexOf('.'));
89 ExtractionTarget et = ExtractionTarget.valueOf(name);
91 files.put(et, new XmlFile(file, context, false));
97 public void addBirthmarkSet(ExtractionTarget target, BirthmarkSet set) throws BirthmarkStoreException{
99 if(target == ExtractionTarget.TARGET_BOTH){
100 throw new IllegalArgumentException("unknown target: " + target);
102 XmlFile xml = files.get(target);
104 xml = new XmlFile(new File(getStoreDirectory(), target.name() + ".xml"), getContext());
105 files.put(target, xml);
107 xml.addBirthmarkSet(set);
110 throw new BirthmarkStoreException("destination is already closed.");
115 public Iterator<BirthmarkSet> birthmarkSets(ExtractionTarget target){
118 XmlFile xml = files.get(target);
119 Iterator<BirthmarkSet> iterator;
121 iterator = xml.birthmarkSets();
123 else if(target == ExtractionTarget.TARGET_BOTH){
124 MultipleIterator<BirthmarkSet> mi = new MultipleIterator<BirthmarkSet>();
125 boolean addflag = false;
126 if(files.containsKey(ExtractionTarget.TARGET_X)){
128 mi.add(files.get(ExtractionTarget.TARGET_X).birthmarkSets());
130 if(files.containsKey(ExtractionTarget.TARGET_Y)){
132 mi.add(files.get(ExtractionTarget.TARGET_Y).birthmarkSets());
134 if(!addflag && files.containsKey(ExtractionTarget.TARGET_XY)){
135 mi.add(files.get(ExtractionTarget.TARGET_XY).birthmarkSets());
147 public int getBirthmarkSetSize(ExtractionTarget target){
149 XmlFile xml = files.get(target);
151 size = xml.getBirthmarkSetSize();
153 else if(target == ExtractionTarget.TARGET_BOTH){
154 if(files.containsKey(ExtractionTarget.TARGET_X)){
155 size += files.get(ExtractionTarget.TARGET_X).getBirthmarkSetSize();
157 if(files.containsKey(ExtractionTarget.TARGET_Y)){
158 size += files.get(ExtractionTarget.TARGET_Y).getBirthmarkSetSize();
160 if(size == 0 && files.containsKey(ExtractionTarget.TARGET_XY)){
161 size += files.get(ExtractionTarget.TARGET_XY).getBirthmarkSetSize();
168 public BirthmarkStoreTarget getStoreTarget(){
169 return BirthmarkStoreTarget.XMLFILE;
173 public void removeAllBirthmarkSets(ExtractionTarget target){
174 XmlFile xml = files.get(target);
176 xml.removeAllBirthmarkSets();
178 else if(target == ExtractionTarget.TARGET_BOTH){
179 for(XmlFile file: files.values()){
180 file.removeAllBirthmarkSets();
186 public void removeBirthmarkSet(ExtractionTarget target, BirthmarkSet set){
187 XmlFile xml = files.get(target);
189 xml.removeBirthmarkSet(set);
191 else if(target == ExtractionTarget.TARGET_BOTH){
192 throw new IllegalArgumentException("unknown target: " + target);
196 private File getStoreDirectory(){
197 if(storeDirectory == null){
198 storeDirectory = new File(BirthmarkEnvironment.getStigmataHome(), "extracted_birthmarks/" + generateId());
200 if(!storeDirectory.exists()){
201 storeDirectory.mkdirs();
203 return storeDirectory;
206 private void closeAllStream(){
209 for(XmlFile file: files.values()){
216 * Iterator class for reading birthmark xml file by StAX.
218 * @author Haruaki Tamada
220 private static class BirthmarkSetStAXIterator implements Iterator<BirthmarkSet>{
221 private XMLEventReader reader = null;
222 private BirthmarkSet nextObject;
223 private List<URL> validItems;
224 private BirthmarkEnvironment env;
225 private BirthmarkContext context;
227 public BirthmarkSetStAXIterator(File file, List<URL> validItems, BirthmarkContext context){
229 XMLInputFactory factory = XMLInputFactory.newInstance();
230 BufferedReader in = new BufferedReader(new FileReader(file));
231 reader = factory.createXMLEventReader(in);
232 } catch(FileNotFoundException e){
233 } catch(XMLStreamException e){
235 this.validItems = validItems;
236 this.context = context;
237 this.env = context.getEnvironment();
239 nextObject = findNext();
240 } catch(XMLStreamException e){
246 public boolean hasNext(){
247 boolean flag = nextObject != null;
251 } catch(XMLStreamException e){
259 public BirthmarkSet next(){
260 BirthmarkSet next = nextObject;
262 nextObject = findNext();
263 } catch(XMLStreamException e){
270 public void remove(){
273 private BirthmarkSet findNext() throws XMLStreamException{
274 BirthmarkSet nextObject = null;
276 nextObject = findNextImpl();
277 } while(nextObject != null && validItems != null && !validItems.contains(nextObject.getLocation()));
281 private BirthmarkSet findNextImpl() throws XMLStreamException{
282 String className = null;
283 BirthmarkSet bs = null;
284 Birthmark birthmark = null;
285 BirthmarkSpi service = null;
287 while(reader.hasNext()){
288 // XMLEvent event = reader.peek();
289 XMLEvent event = reader.nextEvent();
290 if(event.isStartElement()){
291 StartElement se = event.asStartElement();
292 String part = se.getName().getLocalPart();
293 if(part.equals("unit")){
294 ExtractionUnit unit = ExtractionUnit.valueOf(reader.getElementText());
296 context.setExtractionUnit(unit);
299 else if(part.equals("birthmark-type")){
300 String type = reader.getElementText();
301 if(env.getService(type) != null){
302 context.addBirthmarkType(type);
305 else if(part.equals("name")){
306 className = reader.getElementText();
308 else if(part.equals("location")){
309 String location = reader.getElementText();
310 if(className == null || location == null){
311 throw new XMLStreamException("incompatible with definition");
314 URL url = new URL(location);
315 bs = new BirthmarkSet(className, url);
316 } catch(MalformedURLException e){
320 else if(part.equals("element")){
322 BirthmarkElement be = service.buildBirthmarkElement(reader.getElementText());
323 birthmark.addElement(be);
326 else if(part.equals("birthmark")){
327 String type = se.getAttributeByName(new QName("type")).getValue();
328 service = env.getService(type);
330 birthmark = service.buildBirthmark();
331 bs.addBirthmark(birthmark);
338 else if(event.isEndElement()){
339 EndElement ee = event.asEndElement();
340 if(ee.getName().getLocalPart().equals("extracted-birthmark")){
345 // reader.nextEvent();
352 * This class represents a xml file about XmlFileExtractionResultSet.
354 * @author Haruaki Tamada
356 private static class XmlFile{
357 private ExtractionResultSetXmlPrinter formatter;
358 private BirthmarkContext context;
359 private List<URL> addList = new ArrayList<URL>();
362 private PrintWriter out;
364 public XmlFile(File file, BirthmarkContext context){
366 this.context = context;
369 public XmlFile(File file, BirthmarkContext context, boolean addflag){
371 this.context = context;
377 public void addBirthmarkSet(BirthmarkSet bs) throws BirthmarkStoreException{
378 if(formatter == null){
380 out = new PrintWriter(new FileWriter(file));
381 formatter = new ExtractionResultSetXmlPrinter();
382 formatter.printHeader(out);
383 out.printf(" <unit>%s</unit>%n", context.getExtractionUnit());
384 out.printf(" <birthmark-types>%n");
385 for(String type: context.getBirthmarkTypes()){
386 out.printf(" <birthmark-type>%s</birthmark-type>%n", type);
388 out.printf(" </birthmark-types>%n");
390 }catch(IOException e){
393 if(out == null || formatter == null){
394 throw new BirthmarkStoreException("destination is closed on some reason");
397 addList.add(bs.getLocation());
398 formatter.printBirthmarkSet(out, bs);
401 public Iterator<BirthmarkSet> birthmarkSets(){
402 return new BirthmarkSetStAXIterator(file, addList, context);
405 public void closeStream(){
406 if(formatter != null){
407 formatter.printFooter(out);
414 public int getBirthmarkSetSize(){
417 for(Iterator<BirthmarkSet> i = birthmarkSets(); i.hasNext(); ){
426 public void removeAllBirthmarkSets(){
432 public void removeBirthmarkSet(BirthmarkSet set){
433 boolean removeFlag = addList.remove(set.getLocation());