1 package jp.sourceforge.stigmata.result;
3 import java.io.BufferedReader;
5 import java.io.FileNotFoundException;
6 import java.io.FileReader;
7 import java.io.FileWriter;
8 import java.io.IOException;
9 import java.io.PrintWriter;
10 import java.net.MalformedURLException;
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.Iterator;
15 import java.util.List;
18 import javax.xml.namespace.QName;
19 import javax.xml.stream.XMLEventReader;
20 import javax.xml.stream.XMLInputFactory;
21 import javax.xml.stream.XMLStreamException;
22 import javax.xml.stream.events.EndElement;
23 import javax.xml.stream.events.StartElement;
24 import javax.xml.stream.events.XMLEvent;
26 import jp.sourceforge.stigmata.Birthmark;
27 import jp.sourceforge.stigmata.BirthmarkContext;
28 import jp.sourceforge.stigmata.BirthmarkElement;
29 import jp.sourceforge.stigmata.BirthmarkEnvironment;
30 import jp.sourceforge.stigmata.BirthmarkSet;
31 import jp.sourceforge.stigmata.BirthmarkStoreException;
32 import jp.sourceforge.stigmata.BirthmarkStoreTarget;
33 import jp.sourceforge.stigmata.ComparisonMethod;
34 import jp.sourceforge.stigmata.ExtractionTarget;
35 import jp.sourceforge.stigmata.ExtractionUnit;
36 import jp.sourceforge.stigmata.Stigmata;
37 import jp.sourceforge.stigmata.printer.xml.ExtractionResultSetXmlPrinter;
38 import jp.sourceforge.stigmata.spi.BirthmarkSpi;
39 import jp.sourceforge.stigmata.ui.swing.ExtensionFilter;
40 import jp.sourceforge.stigmata.utils.MultipleIterator;
43 * This class manages extracted birthmarks as xml file.
44 * This instance do not use {@link ExtractionTarget <code>ExtractionTarget</code>}.
46 * @author Haruaki Tamada
48 public class XmlFileExtractionResultSet extends AbstractExtractionResultSet{
49 private boolean addmode = true;
50 private File storeDirectory;
51 private Map<ExtractionTarget, XmlFile> files = new HashMap<ExtractionTarget, XmlFile>();
53 XmlFileExtractionResultSet(BirthmarkContext context){
57 XmlFileExtractionResultSet(BirthmarkContext context, File storeDirectory){
59 this.storeDirectory = storeDirectory;
62 public XmlFileExtractionResultSet(BirthmarkContext context, boolean tableType){
63 super(context, tableType);
66 public XmlFileExtractionResultSet(File directory){
67 super(Stigmata.getInstance().createContext());
70 storeDirectory = directory;
72 BirthmarkContext context = getContext();
73 context.setStoreTarget(BirthmarkStoreTarget.XMLFILE);
74 if(files.containsKey(ExtractionTarget.TARGET_X)
75 && files.containsKey(ExtractionTarget.TARGET_Y)){
76 context.setComparisonMethod(ComparisonMethod.ROUND_ROBIN_XY);
79 context.setComparisonMethod(ComparisonMethod.ROUND_ROBIN_SAME_PAIR);
82 for(File file: storeDirectory.listFiles(new ExtensionFilter("xml"))){
83 String fileName = file.getName();
84 String name = fileName.substring(0, fileName.lastIndexOf('.'));
85 ExtractionTarget et = ExtractionTarget.valueOf(name);
87 files.put(et, new XmlFile(file, context, false));
93 public void addBirthmarkSet(ExtractionTarget target, BirthmarkSet set) throws BirthmarkStoreException{
95 if(target == ExtractionTarget.TARGET_BOTH){
96 throw new IllegalArgumentException("unknown target: " + target);
98 XmlFile xml = files.get(target);
100 xml = new XmlFile(new File(getStoreDirectory(), target.name() + ".xml"), getContext());
101 files.put(target, xml);
103 xml.addBirthmarkSet(set);
106 throw new BirthmarkStoreException("destination is already closed.");
111 public Iterator<BirthmarkSet> birthmarkSets(ExtractionTarget target){
114 XmlFile xml = files.get(target);
115 Iterator<BirthmarkSet> iterator;
117 iterator = xml.birthmarkSets();
119 else if(target == ExtractionTarget.TARGET_BOTH){
120 MultipleIterator<BirthmarkSet> mi = new MultipleIterator<BirthmarkSet>();
121 boolean addflag = false;
122 if(files.containsKey(ExtractionTarget.TARGET_X)){
124 mi.add(files.get(ExtractionTarget.TARGET_X).birthmarkSets());
126 if(files.containsKey(ExtractionTarget.TARGET_Y)){
128 mi.add(files.get(ExtractionTarget.TARGET_Y).birthmarkSets());
130 if(!addflag && files.containsKey(ExtractionTarget.TARGET_XY)){
131 mi.add(files.get(ExtractionTarget.TARGET_XY).birthmarkSets());
143 public int getBirthmarkSetSize(ExtractionTarget target){
145 XmlFile xml = files.get(target);
147 size = xml.getBirthmarkSetSize();
149 else if(target == ExtractionTarget.TARGET_BOTH){
150 if(files.containsKey(ExtractionTarget.TARGET_X)){
151 size += files.get(ExtractionTarget.TARGET_X).getBirthmarkSetSize();
153 if(files.containsKey(ExtractionTarget.TARGET_Y)){
154 size += files.get(ExtractionTarget.TARGET_Y).getBirthmarkSetSize();
156 if(size == 0 && files.containsKey(ExtractionTarget.TARGET_XY)){
157 size += files.get(ExtractionTarget.TARGET_XY).getBirthmarkSetSize();
164 public BirthmarkStoreTarget getStoreTarget(){
165 return BirthmarkStoreTarget.XMLFILE;
169 public void removeAllBirthmarkSets(ExtractionTarget target){
170 XmlFile xml = files.get(target);
172 xml.removeAllBirthmarkSets();
174 else if(target == ExtractionTarget.TARGET_BOTH){
175 for(XmlFile file: files.values()){
176 file.removeAllBirthmarkSets();
182 public void removeBirthmarkSet(ExtractionTarget target, BirthmarkSet set){
183 XmlFile xml = files.get(target);
185 xml.removeBirthmarkSet(set);
187 else if(target == ExtractionTarget.TARGET_BOTH){
188 throw new IllegalArgumentException("unknown target: " + target);
192 private File getStoreDirectory(){
193 if(storeDirectory == null){
194 storeDirectory = new File(BirthmarkEnvironment.getStigmataHome(), "extracted_birthmarks/" + generateId());
196 if(!storeDirectory.exists()){
197 storeDirectory.mkdirs();
199 return storeDirectory;
202 private void closeAllStream(){
205 for(XmlFile file: files.values()){
212 * Iterator class for reading birthmark xml file by StAX.
214 * @author Haruaki Tamada
216 private static class BirthmarkSetStAXIterator implements Iterator<BirthmarkSet>{
217 private XMLEventReader reader = null;
218 private BirthmarkSet nextObject;
219 private List<URL> validItems;
220 private BirthmarkEnvironment env;
221 private BirthmarkContext context;
223 public BirthmarkSetStAXIterator(File file, List<URL> validItems, BirthmarkContext context){
225 XMLInputFactory factory = XMLInputFactory.newInstance();
226 BufferedReader in = new BufferedReader(new FileReader(file));
227 reader = factory.createXMLEventReader(in);
228 } catch(FileNotFoundException e){
229 } catch(XMLStreamException e){
231 this.validItems = validItems;
232 this.context = context;
233 this.env = context.getEnvironment();
235 nextObject = findNext();
236 } catch(XMLStreamException e){
242 public boolean hasNext(){
243 boolean flag = nextObject != null;
247 } catch(XMLStreamException e){
255 public BirthmarkSet next(){
256 BirthmarkSet next = nextObject;
258 nextObject = findNext();
259 } catch(XMLStreamException e){
266 public void remove(){
269 private BirthmarkSet findNext() throws XMLStreamException{
270 BirthmarkSet nextObject = null;
272 nextObject = findNextImpl();
273 } while(nextObject != null && validItems != null && !validItems.contains(nextObject.getLocation()));
277 private BirthmarkSet findNextImpl() throws XMLStreamException{
278 String className = null;
279 BirthmarkSet bs = null;
280 Birthmark birthmark = null;
281 BirthmarkSpi service = null;
283 while(reader.hasNext()){
284 // XMLEvent event = reader.peek();
285 XMLEvent event = reader.nextEvent();
286 if(event.isStartElement()){
287 StartElement se = event.asStartElement();
288 String part = se.getName().getLocalPart();
289 if(part.equals("unit")){
290 ExtractionUnit unit = ExtractionUnit.valueOf(reader.getElementText());
292 context.setExtractionUnit(unit);
295 else if(part.equals("birthmark-type")){
296 String type = reader.getElementText();
297 if(env.getService(type) != null){
298 context.addBirthmarkType(type);
301 else if(part.equals("name")){
302 className = reader.getElementText();
304 else if(part.equals("location")){
305 String location = reader.getElementText();
306 if(className == null || location == null){
307 throw new XMLStreamException("incompatible with definition");
310 URL url = new URL(location);
311 bs = new BirthmarkSet(className, url);
312 } catch(MalformedURLException e){
316 else if(part.equals("element")){
318 BirthmarkElement be = service.buildBirthmarkElement(reader.getElementText());
319 birthmark.addElement(be);
322 else if(part.equals("birthmark")){
323 String type = se.getAttributeByName(new QName("type")).getValue();
324 service = env.getService(type);
326 birthmark = service.buildBirthmark();
327 bs.addBirthmark(birthmark);
334 else if(event.isEndElement()){
335 EndElement ee = event.asEndElement();
336 if(ee.getName().getLocalPart().equals("extracted-birthmark")){
341 // reader.nextEvent();
348 * This class represents a xml file about XmlFileExtractionResultSet.
350 * @author Haruaki Tamada
352 private static class XmlFile{
353 private ExtractionResultSetXmlPrinter formatter;
354 private BirthmarkContext context;
355 private List<URL> addList = new ArrayList<URL>();
358 private PrintWriter out;
360 public XmlFile(File file, BirthmarkContext context){
362 this.context = context;
365 public XmlFile(File file, BirthmarkContext context, boolean addflag){
367 this.context = context;
373 public void addBirthmarkSet(BirthmarkSet bs) throws BirthmarkStoreException{
374 if(formatter == null){
376 out = new PrintWriter(new FileWriter(file));
377 formatter = new ExtractionResultSetXmlPrinter();
378 formatter.printHeader(out);
379 out.printf(" <unit>%s</unit>%n", context.getExtractionUnit());
380 out.printf(" <birthmark-types>%n");
381 for(String type: context.getBirthmarkTypes()){
382 out.printf(" <birthmark-type>%s</birthmark-type>%n", type);
384 out.printf(" </birthmark-types>%n");
386 }catch(IOException e){
389 if(out == null || formatter == null){
390 throw new BirthmarkStoreException("destination is closed on some reason");
393 addList.add(bs.getLocation());
394 formatter.printBirthmarkSet(out, bs);
397 public Iterator<BirthmarkSet> birthmarkSets(){
398 return new BirthmarkSetStAXIterator(file, addList, context);
401 public void closeStream(){
402 if(formatter != null){
403 formatter.printFooter(out);
410 public int getBirthmarkSetSize(){
413 for(Iterator<BirthmarkSet> i = birthmarkSets(); i.hasNext(); ){
422 public void removeAllBirthmarkSets(){
428 public void removeBirthmarkSet(BirthmarkSet set){
429 boolean removeFlag = addList.remove(set.getLocation());