/*
 * Copyright 2015 Jo Rabin
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.linguafranca.xml;

import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.XMLEvent;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * A filter to accept a stream, interpret as XML, allow transformation
 * as XML then forward as a stream.
 *
 * <p>Although this means that the interpretation of the XML will happen
 * twice, here and in the target application, some such applications
 * do not accept XML streams. e.g. the Simple XML framework.
 *
 * @author jo
 */
@SuppressWarnings({"WeakerAccess", "unused"})
public class XmlOutputStreamFilter extends PipedOutputStream {

    Future<Boolean> future;

    public XmlOutputStreamFilter(final OutputStream outputStream, final XmlEventTransformer eventTransformer) throws IOException {

        Callable<Boolean> output = new Callable<Boolean>() {
            public Boolean call() {
                    try {
                        XMLEventReader eventReader = new com.fasterxml.aalto.stax.InputFactoryImpl()
                                .createXMLEventReader(new PipedInputStream(XmlOutputStreamFilter.this));
                        XMLEventWriter eventWriter = new com.fasterxml.aalto.stax.OutputFactoryImpl()
                                .createXMLEventWriter(outputStream);

                        XMLEvent event = null;
                        while (eventReader.hasNext()) {
                            event = eventReader.nextEvent();
                            event = eventTransformer.transform(event);
                            eventWriter.add(event);
                            eventWriter.flush();
                        }

                        eventReader.close();
                        eventWriter.flush();
                        eventWriter.close();
                        outputStream.flush();
                        outputStream.close();
                    } catch (XMLStreamException | IOException e) {
                        throw new IllegalStateException(e);
                    }
                    return true;
             }
        };
        future = Executors.newSingleThreadExecutor().submit(output);
    }

    public void cancel(boolean interrupt){
        future.cancel(interrupt);
    }

    public boolean isDone(){
        return future.isDone();
    }

    public boolean await() throws IOException {
        try {
            return future.get();
        } catch (InterruptedException | ExecutionException e) {
            throw new IOException(e);
        }
    }

    @Override
    public void flush() throws IOException {
        super.flush();
    }

    @Override
    public void close() throws IOException {
        super.close();
    }
}


@@ -1520,16 +1520,26 @@
  %7B%0A%0A    
+protected 
 Future%3CB
@@ -1553,16 +1553,65 @@
  future;
+%0A    protected PipedInputStream pipedInputStream;
 %0A%0A    pu
@@ -1732,24 +1732,97 @@
 xception %7B%0A%0A
+        super();%0A        pipedInputStream = new PipedInputStream(this);%0A%0A
         Call
@@ -1918,38 +1918,30 @@
             
-    
 try %7B%0A
-    
             
@@ -2045,36 +2045,32 @@
                 
-    
 .createXMLEventR
@@ -2075,21 +2075,17 @@
 tReader(
-new P
+p
 ipedInpu
@@ -2095,43 +2095,11 @@
 ream
-(XmlOutputStreamFilter.this));%0A    
+);%0A
     
@@ -2212,36 +2212,32 @@
                 
-    
 .createXMLEventW
@@ -2270,36 +2270,32 @@
                 
-    
 XMLEvent event =
@@ -2321,20 +2321,16 @@
         
-  
-  
 while (e
@@ -2349,28 +2349,24 @@
 asNext()) %7B%0A
-    
             
@@ -2426,36 +2426,32 @@
                 
-  
-  
 event = eventTra
@@ -2493,36 +2493,32 @@
                 
-    
 eventWriter.add(
@@ -2541,36 +2541,32 @@
                 
- 
-   
 eventWriter.flus
@@ -2590,20 +2590,16 @@
         
-    
 %7D%0A%0A     
@@ -2609,28 +2609,24 @@
             
- 
-   
 eventReader.
@@ -2626,36 +2626,32 @@
 Reader.close();%0A
-    
                 
@@ -2687,36 +2687,32 @@
                 
-    
 eventWriter.clos
@@ -2708,36 +2708,32 @@
 Writer.close();%0A
-    
                 
@@ -2770,36 +2770,32 @@
                 
-    
 outputStream.clo
@@ -2812,28 +2812,24 @@
             
-   
- 
 %7D catch (XML
@@ -2875,36 +2875,32 @@
                 
-    
 throw new Illega
@@ -2931,34 +2931,26 @@
             
-  
-  %7D%0A    
+%7D%0A
             
@@ -2966,17 +2966,16 @@
 n true;%0A
- 
         

Change instantiation order of piped streams