Exemplo n.º 1
0
  /**
   * Merge a local file with a Google Drive File.
   *
   * <p>The last modification is used to check which file to sync from. Then, the md5 checksum of
   * the file is used to check whether or not the file's content should be sync'ed.
   *
   * @param localFileUri Local file URI to save local changes against.
   * @param localFile Local file cursor to retrieve data from.
   * @param driveFile Google Drive file.
   */
  private void mergeFiles(Uri localFileUri, Cursor localFile, File driveFile) {
    long localFileModificationDate = localFile.getLong(COLUMN_INDEX_MODIFICATION_DATE);

    Log.d(
        TAG,
        "Modification dates: "
            + localFileModificationDate
            + " - "
            + driveFile.getModifiedDate().getValue());
    if (localFileModificationDate > driveFile.getModifiedDate().getValue()) {
      try {
        if (localFile.getShort(COLUMN_INDEX_DELETED) != 0) {
          Log.d(TAG, "  > Deleting Drive file.");
          mService.files().delete(driveFile.getId()).execute();
          mProvider.delete(localFileUri, null, null);
        } else {
          String localNote = localFile.getString(COLUMN_INDEX_NOTE);
          File updatedFile = null;

          // Update drive file.
          Log.d(TAG, "  > Updating Drive file.");
          driveFile.setTitle(localFile.getString(COLUMN_INDEX_TITLE));

          if (md5(localNote) != driveFile.getMd5Checksum()) {
            // Update both content and metadata.
            ByteArrayContent content = ByteArrayContent.fromString(TEXT_PLAIN, localNote);
            updatedFile = mService.files().update(driveFile.getId(), driveFile, content).execute();
          } else {
            // Only update the metadata.
            updatedFile = mService.files().update(driveFile.getId(), driveFile).execute();
          }

          ContentValues values = new ContentValues();
          values.put(
              NotePad.Notes.COLUMN_NAME_MODIFICATION_DATE,
              updatedFile.getModifiedDate().getValue());
          mProvider.update(localFileUri, values, null, null);
        }
      } catch (IOException e) {
        e.printStackTrace();
      } catch (RemoteException e) {
        e.printStackTrace();
      }
    } else if (localFileModificationDate < driveFile.getModifiedDate().getValue()) {
      // Update local file.
      Log.d(TAG, "  > Updating local file.");
      ContentValues values = new ContentValues();
      values.put(NotePad.Notes.COLUMN_NAME_TITLE, driveFile.getTitle());
      values.put(
          NotePad.Notes.COLUMN_NAME_MODIFICATION_DATE, driveFile.getModifiedDate().getValue());
      // Only download the content if it has changed.
      if (md5(localFile.getString(COLUMN_INDEX_NOTE)) != driveFile.getMd5Checksum()) {
        values.put(NotePad.Notes.COLUMN_NAME_NOTE, getFileContent(driveFile));
      }
      try {
        mProvider.update(localFileUri, values, null, null);
      } catch (RemoteException e) {
        e.printStackTrace();
      }
    }
  }
  private void addToSnapshot(Snapshot root, ChangeRecord remoteChange) {
    switch (remoteChange.getOperation()) {
      case REMOTE_INSERT:
        String localName = stub.storage().remoteToLocal().get(remoteChange.getRemoteFileId());
        if (StringUtils.isEmpty(localName)) {
          // Insert failed
          return;
        }
        File localFile = DriveUtils.absolutePath(localName);
        String parent = DriveUtils.relativePath(localFile.getParentFile());
        if (root.getName().equals(parent)) {
          for (Snapshot sn : root.getChildren()) {
            if (sn.getName().equals(localName)) return;
          }
          Snapshot sn = stub.snapshot().make(localFile);
          root.addChild(sn);
        } else {
          for (Snapshot sn : root.getChildren()) {
            if (parent.startsWith(sn.getName())) {
              addToSnapshot(sn, remoteChange);
              return;
            }
          }
          // TODO the operations are not in sequence.
          // Didn't find?
          logger.warn(
              MessageFormat.format("Remote insert cannot find local parent {0}", remoteChange));
          // throw new IllegalArgumentException();
        }
        break;
      case REMOTE_CHANGE:
        {
          String fileName = remoteChange.getLocalFile();
          if (fileName.equals(root.getName())) {
            com.google.api.services.drive.model.File remoteFile = remoteChange.getContext(0);
            root.setMd5Checksum(remoteFile.getMd5Checksum());
          } else {
            for (Snapshot sn : root.getChildren()) {
              if (fileName.startsWith(sn.getName())) {
                addToSnapshot(sn, remoteChange);
                return;
              }
            }
            // Didn't find?
            logger.error(
                MessageFormat.format(
                    "Local root doesn't contain this file {0}. Should be an error.", remoteChange));
            // throw new IllegalArgumentException();
          }
          break;
        }
      case REMOTE_RENAME:
        {
          String fileName = remoteChange.getLocalFile();

          if (root.getName().startsWith(fileName)) {
            String newName = remoteChange.getContext(1);
            root.setName(root.getName().replaceFirst(fileName, newName));
            for (Snapshot sn : root.getChildren()) {
              addToSnapshot(sn, remoteChange);
            }
          } else {
            for (Snapshot sn : root.getChildren()) {
              if (fileName.startsWith(sn.getName())) {
                addToSnapshot(sn, remoteChange);
                return;
              }
            }
            // Didn't find?
            logger.error(
                MessageFormat.format(
                    "Remote rename cannot find local corresponding {0}, should be an error",
                    remoteChange));
            // throw new IllegalArgumentException();
          }
          break;
        }
      case REMOTE_DELETE:
        String fileName = remoteChange.getLocalFile();
        if (StringUtils.isEmpty(fileName)) {
          return;
        }
        for (int i = 0; i < root.getChildren().size(); i++) {
          Snapshot sn = root.getChildren().get(i);
          if (fileName.equals(sn.getName())) {
            root.getChildren().remove(sn);
            return;
          }
          if (fileName.startsWith(sn.getName())) {
            addToSnapshot(sn, remoteChange);
            return;
          }
        }
        // Didn't find?
        logger.warn(
            MessageFormat.format(
                "Remote change cannot find local corresponding {0}, possibly caused by deleting of parent folder",
                remoteChange));
        // This means the remote change is out of date
        break;
      default:
        throw new IllegalArgumentException();
    }
  }