Package ca.carleton.gcrc.couch.app.impl

Source Code of ca.carleton.gcrc.couch.app.impl.UpdateSpecifier

package ca.carleton.gcrc.couch.app.impl;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.json.JSONObject;

import ca.carleton.gcrc.couch.app.Attachment;
import ca.carleton.gcrc.couch.app.DigestComputer;
import ca.carleton.gcrc.couch.app.Document;
import ca.carleton.gcrc.couch.app.DocumentDigest;
import ca.carleton.gcrc.couch.app.DocumentUpdateProcess;

public class UpdateSpecifier {

  /**
   * Returns the actions required during a document update to modify
   * a target document so that it become equal to a source document.
   * @param sourceDoc Source document
   * @param targetDoc Document currently on the target location
   * @return Specifier that explains what needs to happen during an update
   * @throws Exception 
   */
  static public UpdateSpecifier computeUpdateSpecifier(
      Document sourceDoc
      ,JSONObject targetDoc
      ) throws Exception {
   
    DigestComputerSha1 digestComputer = new DigestComputerSha1();
    DocumentDigest dd = digestComputer.computeDocumentDigest(sourceDoc);
   
    return computeUpdateSpecifier(
        sourceDoc
        ,dd
        ,targetDoc
        ,DocumentUpdateProcess.Schedule.UPDATE_UNLESS_MODIFIED
        );
  }
 
  /**
   * Returns the actions required during a document update to modify
   * a target document so that it become equal to a source document.
   * @param sourceDoc Source document
   * @param documentDigest Digest computed for source document
   * @param targetDoc Document currently on the target location
   * @param schedule Specifies the type of update required
   * @return Specifier that explains what needs to happen during an update
   * @throws Exception 
   */
  static public UpdateSpecifier computeUpdateSpecifier(
      Document sourceDoc
      ,DocumentDigest documentDigest
      ,JSONObject targetDoc
      ,DocumentUpdateProcess.Schedule schedule
      ) throws Exception {
   
    UpdateSpecifier result = new UpdateSpecifier();
   
    // Select digest computer
    DigestComputer dc = new DigestComputerSha1();
   
    // Verify main document
    if( schedule == DocumentUpdateProcess.Schedule.UPDATE_FORCED ){
      result.setDocumentModified(true);
    } else if( null == targetDoc ) {
      // Document creation
      result.setDocumentModified(true);
    } else {
      String sourceDigest = documentDigest.getDocDigest();
      String targetDigest = dc.computeDigestFromJsonObject(targetDoc);
      if( false == sourceDigest.equals(targetDigest) ){
        result.setDocumentModified(true);
      }
    }

    // Attachments...

    // Get attachments from source document
    Map<String,Attachment> attachmentsByName = new HashMap<String,Attachment>();
    {
      Collection<Attachment> attachments = sourceDoc.getAttachments();
      if( null != attachments ) {
        for(Attachment attachment : attachments){
          attachmentsByName.put(attachment.getName(), attachment);
        }
      }
    }
   
    // Figure out which attachments should be deleted
    if( null != targetDoc ) {
      JSONObject targetAttachments = targetDoc.optJSONObject("_attachments");
      if( null != targetAttachments ){
        Iterator<?> it = targetAttachments.keys();
        while( it.hasNext() ){
          Object keyObj = it.next();
          if( keyObj instanceof String ) {
            String attachmentName = (String)keyObj;
            if( false == attachmentsByName.containsKey(attachmentName) ){
              // Target document has an attachment not available in the
              // source one. Delete.
              result.addAttachmentToDelete(attachmentName);
            }
          }
        }
      }
    }
   
    // Figure out which attachments should be uploaded
    for(Attachment attachment : attachmentsByName.values()){
      String attachmentName = attachment.getName();

      boolean shouldUpload = false;
      if( null == targetDoc ) {
        // On creation, upload all attachments
        shouldUpload = true;

      } else if( schedule == DocumentUpdateProcess.Schedule.UPDATE_FORCED ) {
        // On forced update,
        shouldUpload = true;
     
      } else {
        String attachmentContentType = attachment.getContentType();
        shouldUpload = shouldAttachmentBeUploaded(
          targetDoc
          ,attachmentName
          ,documentDigest.getAttachmentDigest(attachmentName)
          ,attachmentContentType
          );
      }
     
      if( shouldUpload ){
        result.addAttachmentToUpload(attachmentName);
      } else {
        result.addAttachmentNotModified(attachmentName);
      }
    }
   
    return result;
  }
 
  static private boolean shouldAttachmentBeUploaded(
      JSONObject targetDoc
      ,String attachmentName
      ,String attachmentDigest
      ,String attachmentContentType
      ) {
   
    JSONObject targetAttachments = targetDoc.optJSONObject("_attachments");
    if( null == targetAttachments ) {
      // No attachment on target doc. Upload.
      return true;
    }
   
    JSONObject targetAttachment = targetAttachments.optJSONObject(attachmentName);
    if( null == targetAttachment ) {
      // Target document does not have an attachment with this name
      return true;
    }
   
    String targetAttachmentContentType = targetAttachment.optString("content_type");
    if( null == targetAttachmentContentType ){
      // Attachment should have a content-type
      return true;
    }
    if( false == targetAttachmentContentType.equals(attachmentContentType) ){
      // content-type has changed
      return true;
    }
   
    JSONObject targetManifest = targetDoc.optJSONObject(DocumentManifest.MANIFEST_KEY);
    if( null == targetManifest ) {
      // Can not verify digest on target document
      return true;
    }

    JSONObject targetAttachmentManifests = targetManifest.optJSONObject("attachments");
    if( null == targetAttachmentManifests ) {
      // Can not verify digest on target document
      return true;
    }

    JSONObject targetAttachmentManifest = targetAttachmentManifests.optJSONObject(attachmentName);
    if( null == targetAttachmentManifest ) {
      // Can not verify digest on target document
      return true;
    }
   
    String targetAttachmentDigest = targetAttachmentManifest.optString("digest");
    if( null == targetAttachmentDigest ) {
      // Can not verify digest on target document
      return true;
    } else if( false == targetAttachmentDigest.equals(attachmentDigest) ){
      // Digest differs
      return true;
    }
   
    return false;
  }
 

  private boolean documentModified = false;
  private Set<String> attachmentsToDelete = new HashSet<String>();
  private Set<String> attachmentsToUpload = new HashSet<String>();
  private Set<String> attachmentsNotModified = new HashSet<String>();
 
  public boolean isDocumentModified() {
    return documentModified;
  }
  public void setDocumentModified(boolean documentModified) {
    this.documentModified = documentModified;
  }
 
  public Set<String> getAttachmentsToDelete() {
    return attachmentsToDelete;
  }
  public void addAttachmentToDelete(String attachmentName) {
    this.attachmentsToDelete.add(attachmentName);
  }
 
  public Set<String> getAttachmentsToUpload() {
    return attachmentsToUpload;
  }
  public void addAttachmentToUpload(String attachmentName) {
    this.attachmentsToUpload.add(attachmentName);
  }
 
  public Set<String> getAttachmentsNotModified() {
    return attachmentsNotModified;
  }
  public void addAttachmentNotModified(String attachmentName) {
    this.attachmentsNotModified.add(attachmentName);
  }
 
  public boolean isUpdateRequired(){
    if( documentModified ) {
      return true;
    } else if( attachmentsToDelete.size() > 0 ){
      return true;
    } else if( attachmentsToUpload.size() > 0 ){
      return true;
    }
   
    return false;
  }
}
TOP

Related Classes of ca.carleton.gcrc.couch.app.impl.UpdateSpecifier

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.