com.tfgridiron.crowdsource.cmdline.ArchiveCreator.java Source code

Java tutorial

Introduction

Here is the source code for com.tfgridiron.crowdsource.cmdline.ArchiveCreator.java

Source

/*
 * Copyright (c) Justin Moore.
 * 
 * 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 com.tfgridiron.crowdsource.cmdline;

import com.google.api.client.http.ByteArrayContent;
import com.google.api.client.util.DateTime;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.ParentReference;
import com.google.api.services.drive.model.Permission;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.WorksheetEntry;

import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author justin@tfgridiron.com (Justin Moore)
 * 
 */
public class ArchiveCreator {
    private final ApiUtils apiUtils;

    public ArchiveCreator(ApiUtils apiUtils) {
        this.apiUtils = apiUtils;
    }

    public ArchiveMetadata createArchive(String season, Map<String, String> weekFolders,
            SpreadsheetIndexer spreadsheetIndexer, String destinationFolderId) throws Exception {
        // 0: Refresh everything
        spreadsheetIndexer.refreshMetadataFromSources(season, weekFolders);
        // 1: Check to make sure the worksheet exists
        Map<String, SpreadsheetMetadata> spreadsheetMetadata = spreadsheetIndexer
                .getSpreadsheetMetadataBySeason(season);
        if (spreadsheetMetadata == null) {
            return null;
        }
        // 2: Create an in-memory byte buffer with a zip wrapper around it
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zipfile = new ZipOutputStream(outputStream);
        // TODO(P2): Per-game files or one big file?
        zipfile.putNextEntry(new ZipEntry(Constants.ARCHIVE_PLAY_BY_PLAY_OUTFILE));
        // 3: One-by-one add the files
        Set<SpreadsheetMetadata> allMetadata = new TreeSet<SpreadsheetMetadata>(spreadsheetMetadata.values());
        Set<SpreadsheetMetadata> includedMetadata = new TreeSet<SpreadsheetMetadata>();
        for (SpreadsheetMetadata metadata : allMetadata) {
            if (!metadata.getIsDone()) {
                continue;
            }
            if (!addOneSpreadsheet(metadata, zipfile)) {
                System.err.println("Error adding spreadsheet " + metadata.getTitle() + " to archive");
                return null;
            }
            includedMetadata.add(metadata);
        }
        zipfile.close();
        // 4: Checksum the completed archive (take the sorted set of checksums and checksum those)
        String checksum = checksumFileCollection(spreadsheetIndexer, includedMetadata);
        DateTime maxLastUpdated = getMaxLastUpdated(spreadsheetIndexer, includedMetadata);
        // 5: Upload the file
        File uploadedFile = uploadFile(season + ".zip", outputStream.toByteArray(), destinationFolderId);
        System.out.println("New ZIP file at " + uploadedFile.getWebContentLink());
        // 6: Create an ArchiveMetadata object and return it
        return new ArchiveMetadata(season, uploadedFile.getWebContentLink(), includedMetadata.size(),
                maxLastUpdated, uploadedFile.getId(), checksum);
    }

    public DateTime getMaxLastUpdated(SpreadsheetIndexer spreadsheetIndexer,
            Set<SpreadsheetMetadata> includedMetadata) {
        DateTime maxLastUpdated = null;
        for (SpreadsheetMetadata m : includedMetadata) {
            if (maxLastUpdated == null) {
                maxLastUpdated = m.getLastUpdated();
            } else if (m.getLastUpdated().getValue() > maxLastUpdated.getValue()) {
                maxLastUpdated = m.getLastUpdated();
            }
        }
        return maxLastUpdated;
    }

    public String checksumFileCollection(SpreadsheetIndexer spreadsheetIndexer,
            Set<SpreadsheetMetadata> includedMetadata) {
        Set<String> allChecksums = new TreeSet<String>();
        for (SpreadsheetMetadata m : includedMetadata) {
            allChecksums.add(m.getChecksum());
        }
        Hasher hasher = Hashing.sha512().newHasher();
        for (String checksum : allChecksums) {
            hasher.putString(checksum);
        }
        return hasher.hash().toString();
    }

    private boolean addOneSpreadsheet(SpreadsheetMetadata metadata, ZipOutputStream zipfile) throws Exception {
        String entryUrl = "https://spreadsheets.google.com/feeds/spreadsheets/" + metadata.getEntryKey();
        SpreadsheetEntry spreadsheetEntry = apiUtils.getSpreadsheetService().getEntry(new URL(entryUrl),
                SpreadsheetEntry.class);
        for (WorksheetEntry worksheet : spreadsheetEntry.getWorksheets()) {
            if (Constants.PLAY_BY_PLAY_WORKSHEET_NAME.equals(worksheet.getTitle().getPlainText())) {
                String csvContents = SpreadsheetWriter.worksheetToCsv(apiUtils.getSpreadsheetService(), worksheet);
                zipfile.write(csvContents.getBytes());
                return true;
            }
        }
        return false;
    }

    private File uploadFile(String fileName, byte[] fileContents, String destinationFolderId) throws Exception {
        File fileMetadata = new File();
        fileMetadata.setTitle(fileName);
        if (destinationFolderId != null && !destinationFolderId.isEmpty()) {
            ParentReference parent = new ParentReference();
            parent.setId(destinationFolderId);
            fileMetadata.setParents(Collections.singletonList(parent));
        }
        ByteArrayContent content = new ByteArrayContent("application/zip", fileContents);
        File f = apiUtils.getDrive().files().insert(fileMetadata, content).execute();
        Permission p = new Permission();
        p.setRole("reader").setType("anyone").setValue("me");
        apiUtils.getDrive().permissions().insert(f.getId(), p).setSendNotificationEmails(false).execute();
        return apiUtils.getDrive().files().get(f.getId()).execute();
    }
}