Package com.moesol.geoserver.sync.format

Source Code of com.moesol.geoserver.sync.format.FeatureCollectionSha1Sync

/**
*
*  #%L
*  geoserver-sync-core
*  $Id:$
*  $HeadURL:$
*  %%
*  Copyright (C) 2013 Moebius Solutions Inc.
*  %%
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as
*  published by the Free Software Foundation, either version 2 of the
*  License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public
*  License along with this program.  If not, see
<http://www.gnu.org/licenses/gpl-2.0.html>.
*  #L%
*
*/

package com.moesol.geoserver.sync.format;




import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.geoserver.platform.ServiceException;
import org.geoserver.wfs.request.FeatureCollectionResponse;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.util.logging.Logging;
import org.opengis.feature.Feature;

import com.google.gson.Gson;
import com.moesol.geoserver.sync.core.FeatureSha1;
import com.moesol.geoserver.sync.core.IdAndValueSha1s;
import com.moesol.geoserver.sync.core.ServerReconciler;
import com.moesol.geoserver.sync.core.Sha1Value;
import com.moesol.geoserver.sync.core.VersionFeatures;
import com.moesol.geoserver.sync.filter.Sha1SyncFilterFunction;
import com.moesol.geoserver.sync.format.FeatureCollectionSha1Sync;
import com.moesol.geoserver.sync.grouper.Sha1JsonLevelGrouper;
import com.moesol.geoserver.sync.json.Sha1SyncJson;
import com.moesol.geoserver.sync.json.Sha1SyncPositionHash;

/**
* SHA-1 set check. The order of the features should not matter, just the set existence.
* Therefore, we record the SHA-1 for each feature then sort the SHA-1's and finally
* run SHA-1 over the SHA-1's.
*
* Apartment model threading.
*
* @author Moebius Solutions, Inc.
*/
public class FeatureCollectionSha1Sync {
  private static final Logger LOGGER = Logging.getLogger(FeatureCollectionSha1Sync.class.getName());
  private static final Sha1SyncJson EMPTY_SET =
    new Sha1SyncJson().level(-1).hashes(new ArrayList<Sha1SyncPositionHash>());
  public static PrintStream TRACE_RESPONSE = null;
 
  private final Charset UTF8 = Charset.forName("UTF-8");
  private final PrintWriter m_out;
  private final FeatureSha1 m_featureSha1Sync = new FeatureSha1();
  private final int INITIAL_LIST_SIZE = 4096;
  private List<IdAndValueSha1s> m_featureSha1s = new ArrayList<IdAndValueSha1s>(INITIAL_LIST_SIZE);
  private VersionFeatures versionFeatures = VersionFeatures.VERSION1;

  /** collection we are working on */
  private FeatureCollectionResponse m_featureCollectionResponse;
  private Sha1SyncJson m_remoteSha1SyncJson = EMPTY_SET;

  public FeatureCollectionSha1Sync(OutputStream output) throws ServiceException {
    m_out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(output, UTF8)));
  }

  public void write(FeatureCollectionResponse featureCollection) {
    captureFilterParameters();
    setCollection(featureCollection);
      Sha1SyncJson response = compute();
    LOGGER.log(Level.FINE, "output({0}})", response);
      if (TRACE_RESPONSE != null) {
        response.dumpSha1SyncJson("RESPONSE", TRACE_RESPONSE);
      }
    writeAsJsone(response);
      Sha1SyncFilterFunction.clearThreadLocals()
  }

  private void captureFilterParameters() {
    String atts = Sha1SyncFilterFunction.getFormatOptions();
    Sha1SyncJson sha1SyncJson = Sha1SyncFilterFunction.getSha1SyncJson();
   
    LOGGER.log(Level.FINER, "filter options {0}, filter JSON {1}",
        new Object[] { atts, sha1SyncJson });
    if (atts != null) {
      parseAttributesToInclude(atts);
    }
    if (sha1SyncJson != null) {
      setRemoteSha1SyncJson(sha1SyncJson);
    } else if (m_remoteSha1SyncJson != null) {
      // already set (unit test)
    } else {
      setRemoteSha1SyncJson(EMPTY_SET);
    }
  }

  public void setCollection(FeatureCollectionResponse featureCollectionResponse){
    m_featureCollectionResponse = featureCollectionResponse;
  }
 
  public void setRemoteSha1SyncJson(Sha1SyncJson remote) {
    this.m_remoteSha1SyncJson = remote;
    versionFeatures = VersionFeatures.fromSha1SyncJson(remote);
    }

  public Sha1SyncJson compute() {
    if (m_remoteSha1SyncJson.level() < 0) {
      return computeZero();
    }
    return computeServerResponse();
  }
 
  public Sha1SyncJson computeZero() {
    LOGGER.log(Level.FINE, "attributes={0}, sync={1}",
        new Object[] { m_featureSha1Sync.getAttributesToInclude(), m_remoteSha1SyncJson});
    @SuppressWarnings("rawtypes")
    List<FeatureCollection> resultsList = m_featureCollectionResponse.getFeature();
      processAllCollections(resultsList);
     
      Sha1JsonLevelGrouper grouper = new Sha1JsonLevelGrouper(versionFeatures, m_featureSha1s);
      grouper.groupForLevel(0);
      return grouper.getJson();
  }

  public Sha1SyncJson computeServerResponse() {
    @SuppressWarnings("rawtypes")
    List<FeatureCollection> resultsList = m_featureCollectionResponse.getFeature();
      processAllCollections(resultsList);
     
     
      Sha1JsonLevelGrouper grouper = new Sha1JsonLevelGrouper(versionFeatures, m_featureSha1s);
      grouper.groupForLevel(m_remoteSha1SyncJson.level());
      Sha1SyncJson localSha1SyncJson = grouper.getJson();
     
      grouper.groupForLevel(m_remoteSha1SyncJson.level() + 1);
      Sha1SyncJson outputSha1SyncJson = grouper.getJson();
     
      ServerReconciler recon = new ServerReconciler(localSha1SyncJson, m_remoteSha1SyncJson);
      recon.filterDownNextLevel(outputSha1SyncJson);
     
    LOGGER.log(Level.FINER, "attributes({0}), local({1}), remote({2})",
        new Object[] { m_featureSha1Sync.getAttributesToInclude(), localSha1SyncJson, m_remoteSha1SyncJson});
      return outputSha1SyncJson;
  }
 
  private void processAllCollections(@SuppressWarnings("rawtypes") List<FeatureCollection> resultsList) {
    List<IdAndValueSha1s> sha1s = Sha1SyncFilterFunction.getFeatureSha1s();
    if (sha1s != null) {
      m_featureSha1s = sha1s;
      return; // Filter beat us to it, no work for us :-)
    }
 
    for (int i = 0; i < resultsList.size(); i++) {
      FeatureCollection<?,?> collection = resultsList.get(i);
      processOne(collection);
    }
  }

  private void processOne(FeatureCollection<?,?> collection) {
        FeatureIterator<?> iterator = collection.features();
        try {
            while (iterator.hasNext()) {
              Feature feature = iterator.next();
              sha1One(feature);

            }
        } finally {
          iterator.close();
        }
  }

  public void sha1One(Feature feature) {
    Sha1Value idSha1 = m_featureSha1Sync.computeIdSha1(feature);
    Sha1Value valueSha1 = m_featureSha1Sync.computeValueSha1(feature);
    m_featureSha1s.add(new IdAndValueSha1s(idSha1, valueSha1));
  }
 
  private void writeAsJsone(Sha1SyncJson json) {
    Gson gson = new Gson();
    gson.toJson(json, m_out);
      m_out.flush();
  }
 
  public void parseAttributesToInclude(String atts) {
    m_featureSha1Sync.parseAttributesToInclude(atts);
  }
 
  static String [] parseAttributes(String atts) {
    if (atts == null) {
      return new String[0];
    }
    String[] r = atts.split("[,\\s]+");
    if (r[0].isEmpty()) {
      return new String[0];
    }
    return r;
  }

  public void parseSha1SyncJson(String sha1SyncJson) {
    if (sha1SyncJson == null) {
      setRemoteSha1SyncJson(EMPTY_SET);
      return;
    }
    setRemoteSha1SyncJson(new Gson().fromJson(sha1SyncJson, Sha1SyncJson.class));
  }

}
TOP

Related Classes of com.moesol.geoserver.sync.format.FeatureCollectionSha1Sync

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.