Package org.geoserver.geosync

Source Code of org.geoserver.geosync.RecordingTransactionListener$BBoxFilter

package org.geoserver.geosync;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
import java.util.Set;
import java.util.Map;
import java.util.HashMap;
import java.util.Date;
import java.io.File;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.FileWriter;
import java.io.StringReader;
import java.awt.geom.Rectangle2D;

import javax.servlet.http.HttpServletRequest;

import org.geoserver.wfs.TransactionEventType;
import org.geoserver.wfs.TransactionListener;
import org.geoserver.wfs.WFSException;
import org.geoserver.wfs.TransactionEvent;
import org.geoserver.wfs.xml.v1_1_0.WFS;
import org.geoserver.wfs.xml.v1_1_0.WFSConfiguration;
import org.vfny.geoserver.global.GeoserverDataDirectory;
import org.vfny.geoserver.global.ConfigurationException;

import org.geotools.xml.Encoder;
import org.geotools.xml.Parser;
import org.geotools.xs.bindings.XSDateTimeBinding;
import org.geotools.feature.FeatureCollection;
import org.geotools.geometry.jts.ReferencedEnvelope;

import org.apache.xml.serialize.OutputFormat;

import net.opengis.wfs.WfsFactory;
import net.opengis.wfs.TransactionType;
import net.opengis.wfs.InsertElementType;
import net.opengis.wfs.DeleteElementType;
import net.opengis.wfs.UpdateElementType;

import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.feed.synd.SyndFeedImpl;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndEntryImpl;
import com.sun.syndication.feed.synd.SyndContent;
import com.sun.syndication.feed.synd.SyndContentImpl;
import com.sun.syndication.feed.synd.SyndLink;
import com.sun.syndication.feed.synd.SyndLinkImpl;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;
import com.sun.syndication.io.SyndFeedOutput;
import com.sun.syndication.propono.atom.common.AtomService;
import com.sun.syndication.propono.atom.common.Workspace;
import com.sun.syndication.propono.atom.common.Collection;
import com.sun.syndication.feed.module.georss.GMLModuleImpl;
import com.sun.syndication.feed.module.georss.GeoRSSModule;
import com.sun.syndication.feed.module.georss.GeoRSSUtils;
import com.sun.syndication.feed.module.georss.SimpleModuleImpl;
import com.sun.syndication.feed.module.georss.geometries.Position;
import com.sun.syndication.feed.module.georss.geometries.Envelope;

public class RecordingTransactionListener implements TransactionListener{
    private static Set recordWorthyEvents;
    private List myHistory;
    private WFSConfiguration xmlConfiguration;

    static {
        recordWorthyEvents = new TreeSet();
        recordWorthyEvents.add(TransactionEventType.PRE_INSERT);
        recordWorthyEvents.add(TransactionEventType.PRE_UPDATE);
        recordWorthyEvents.add(TransactionEventType.PRE_DELETE);
    }

    public RecordingTransactionListener(){
        myHistory = new ArrayList();
    }

    public void dataStoreChange(TransactionEvent event) throws WFSException{
        if ( recordWorthyEvents.contains( event.getType() ) && !event.getAffectedFeatures().isEmpty() ) {
            try {
                String layer = event.getLayerName().getLocalPart();
                SyndFeed feed = readFeed(layer);
                List l = feed.getEntries();
                SyndEntry entry = eventToEntry(event);
                l.add(entry);
                feed.setEntries(l);
                saveFeed(layer,feed);
            } catch (Exception e){
                e.printStackTrace();
                // LOG ERROR HERE!!
            }
        }
    }
   
    public WFSConfiguration getWFSConfig(){
        return xmlConfiguration;
    }

    public void setWFSConfig(WFSConfiguration wfsc){
        xmlConfiguration = wfsc;
    }

    public File getFile( String layer ) throws ConfigurationException{
        File f = GeoserverDataDirectory.findCreateConfigDir("geosync");
        return new File(f, layer + "-history.xml");
    }

    public SyndFeed readFeed(String layer) throws Exception{
        //create an empty feed
        SyndFeed feed;
       
        File file = getFile(layer);
        if ( file.exists() ) {
            //read the feed from disk filtering as need be
            synchronized ( this ) {
                SyndFeedInput input = new SyndFeedInput();
                feed = input.build(new XmlReader(getFile(layer)));   
            }
        }
        else {
            //create a new empty feed
            feed = new SyndFeedImpl();
            feed.setFeedType("atom_1.0");
            feed.setTitle(layer + " changes");
        }
       
        return feed;
    }

    public SyndFeed filterFeed(String layer, Map params, String baseUrl,HttpServletRequest reqthrows Exception{
       
        SyndFeed feed = readFeed(layer);
        HistoryFilter filter = getFilter(params);
        List entries = feed.getEntries();
        for (int i = 0; i < entries.size(); i++){
            SyndEntry entry = (SyndEntry)entries.get(i);
            if (!filter.pass(entry)){
                entries.remove(i);
                i--;
            }
        }
       
        //set the link element
        SyndLink link = new SyndLinkImpl();
        link.setHref(req.getRequestURL().toString());
        feed.setLink(link);
       
        return feed;
    }

    public void saveFeed(String layer, SyndFeed feed) throws Exception{
        File f = getFile(layer);
        synchronized ( this ) {
            PrintWriter writer = new PrintWriter(new FileWriter(f));
            SyndFeedOutput out = new SyndFeedOutput();
            out.output(feed, writer);   
        }
    }

    public SyndEntry eventToEntry(TransactionEvent evt) throws Exception{
        SyndEntry entry = new SyndEntryImpl();
        entry.setTitle("Changes to " + evt.getLayerName().getLocalPart());
        // entry.setLink("http://geoserver.org/a");
        entry.setPublishedDate(new Date());

        //encode the content as the wfs transcation
        SyndContent description = new SyndContentImpl();
        description.setType("text/xml");
        description.setValue(encodeTransaction( evt ));

        // attach the content to the entry
        List contents = new ArrayList();
        contents.add(description);
        entry.setContents(contents);

        // Add the georss info
        ReferencedEnvelope refenv = evt.getAffectedFeatures().getBounds();

        GeoRSSModule geoInfo = new GMLModuleImpl();
        double minLat = refenv.getMinimum(0),
               minLong = refenv.getMinimum(1),
               maxLat = refenv.getMaximum(0),
               maxLong = refenv.getMaximum(1);
        Envelope bounds = new Envelope(minLat, minLong, maxLat, maxLong);
        geoInfo.setGeometry(bounds);
        List modules = entry.getModules();
        modules.add(geoInfo);
        entry.setModules(modules);

        return entry;
    }
   
    String encodeTransaction( TransactionEvent e ) throws IOException {
        TransactionType tx = WfsFactory.eINSTANCE.createTransactionType();
        Object source = e.getSource();

        if ( source instanceof InsertElementType ) {
            tx.getInsert().add( source );
        }
        else if ( source instanceof UpdateElementType ) {
            tx.getUpdate().add( source );
        }
        else if ( source instanceof DeleteElementType ) {
            tx.getDelete().add( source );
        }

        Encoder encoder = new Encoder( xmlConfiguration );
        OutputFormat of = new OutputFormat();
        of.setOmitXMLDeclaration( true );
        encoder.setOutputFormat( of );

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        encoder.encode( tx, WFS.TRANSACTION, out );
        return new String( out.toByteArray() );
    }


    public List getHistoryList(String layername){
        List matches = new ArrayList();
        Iterator it = myHistory.iterator();

        while (it.hasNext()){
            TransactionEvent e = (TransactionEvent) it.next();
            if ( e.getLayerName().equals( layername ) ) {
                matches.add( e );
            }
        }
       
        return matches;
    }

    public List getFullHistoryList(){
        return myHistory;
    }

    private HistoryFilter getFilter(Map filterParams){
        Iterator it = filterParams.entrySet().iterator();
        List filters = new ArrayList();
       
        Date start, end = null;
        while (it.hasNext()){
            Map.Entry entry = (Map.Entry)it.next();
            String key = (String) entry.getKey();
            String value = (String) entry.getValue();
           
            if ( "bbox".equalsIgnoreCase( key ) ) {
                BBoxFilter f = new BBoxFilter();
                f.initialize( value );
               
                filters.add( f );
            }
            else if ( "startIndex".equalsIgnoreCase( key ) ) {
                int index = Integer.parseInt( (String) entry.getValue() );
                filters.add( new IndexFilter( index ) );
            }
            else if ( "dtstart".equalsIgnoreCase( key ) ) {
                DateFilter filter = new DateFilter( DateFilter.BEFORE );
                filter.initialize( value );
               
                filters.add( filter );
            }
            else if ( "dtend".equalsIgnoreCase( key) ) {
                DateFilter filter = new DateFilter( DateFilter.AFTER );
                filter.initialize( value );
               
                filters.add( filter );
            }
           
        }
        return new CompositeFilter(filters);
    }

    public interface HistoryFilter {
        public void initialize(String param);
        public boolean pass(SyndEntry entry);
    }

    public class CompositeFilter implements HistoryFilter {
        private List myFilters;

        public CompositeFilter(List filters){
            myFilters = filters;
        }

        public void initialize(String param){
            // no need
        }

        public boolean pass(SyndEntry entry){
            Iterator it = myFilters.iterator();
           
            while (it.hasNext()){
                HistoryFilter f = (HistoryFilter)it.next();
                if (f != null && !f.pass(entry)){
                    return false;
                }
            }

            return true;
        }
    }

    public class IndexFilter implements HistoryFilter {
        int index;
        int counter = 0;
       
        public IndexFilter( int index ) {
            this.index = index;
        }
      
        public void initialize(String param) {
           
        }

        public boolean pass(SyndEntry entry) {
            return ++counter >= index;
        }
    }
   
    public class DateFilter implements HistoryFilter{
       
        public static final int BEFORE = 0;
        public static final int AFTER = 1;
       
        Date myDate;
        int rel;
       
        public DateFilter( int rel ) {
            this.rel = rel;
        }
       
        public void initialize(String param){
            try {
                myDate = ((Calendar) new XSDateTimeBinding().parse(null, param )).getTime();
            } catch (Exception e) {
                throw new RuntimeException( e );
            }
        }

        public boolean pass(SyndEntry entry){
            switch ( rel ) {
            case BEFORE:
                return myDate.before( entry.getUpdatedDate() );
            case AFTER:
                return myDate.after( entry.getUpdatedDate() );
            }
           
            throw new RuntimeException();
        }
    }

    public class BBoxFilter implements HistoryFilter{
        //Rectangle2D myBBox;
        com.vividsolutions.jts.geom.Envelope myBBox;

        public void initialize(String param){
            String[] parts = param.split(",");
            double minLat = Double.valueOf(parts[0]);
            double minLon = Double.valueOf(parts[1]);
            double maxLat = Double.valueOf(parts[2]);
            double maxLon = Double.valueOf(parts[3]);
            myBBox = new com.vividsolutions.jts.geom.Envelope(minLon, maxLon, minLat,maxLat);
        }

        public boolean pass(SyndEntry entry){
            GeoRSSModule geo = GeoRSSUtils.getGeoRSS(entry);
            if (geo != null && myBBox != null && geo.getGeometry() instanceof Envelope){
                Envelope env = (Envelope) geo.getGeometry();
                com.vividsolutions.jts.geom.Envelope box =
                    new com.vividsolutions.jts.geom.Envelope( env.getMinLongitude(), env.getMaxLongitude(),
                        env.getMinLatitude(), env.getMaxLatitude() );
                return myBBox.intersects( box );
            }
            return true;
        }
    }

    public class LayerNameFilter implements HistoryFilter{
        String myLayer;

        public void initialize(String param){
            myLayer = param;
        }

        public boolean pass(SyndEntry entry){
            try{
                String xmlBlob = ((SyndContent)entry.getContents().get(0)).getValue();
                Parser parser = new Parser(xmlConfiguration);
                TransactionType tx = (TransactionType) parser.parse(new StringReader(xmlBlob));

                Set qnames = new TreeSet();

                Iterator it = tx.getInsert().iterator();
                while (it.hasNext()){
                    InsertElementType iet = (InsertElementType)it.next();
                    Iterator iter = iet.getFeature().iterator();
                    while (iter.hasNext()){
                        qnames.add(((SimpleFeature)iter.next()).getFeatureType().getTypeName());
                    }
                }

                it = tx.getDelete().iterator();
                while (it.hasNext()){
                    DeleteElementType det = (DeleteElementType)it.next();
                    qnames.add(det.getTypeName().getLocalPart());
                }

                it = tx.getUpdate().iterator();
                while (it.hasNext()){
                    UpdateElementType uet = (UpdateElementType)it.next();
                    qnames.add(uet.getTypeName().getLocalPart());
                }

                return qnames.contains(myLayer);// evt.getLayerName().toString());
            } catch (Exception e){
                e.printStackTrace();
                // pass since we didn't understand, I guess
                // TODO: revisit and decide whether unparsable stuff should stay in the feed
                return true;
            }
        }
    }

}
TOP

Related Classes of org.geoserver.geosync.RecordingTransactionListener$BBoxFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.