package com.socrata.datasync.validation;
import com.socrata.datasync.PublishMethod;
import com.socrata.datasync.SocrataConnectionInfo;
import com.socrata.datasync.Utils;
import com.socrata.datasync.config.CommandLineOptions;
import com.socrata.datasync.job.GISJob;
import com.socrata.datasync.job.JobStatus;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.io.FilenameUtils;
import java.io.File;
import java.util.*;
public class GISJobValidity {
public static final String GEOJSON_EXT = "geojson";
public static final String ZIP_EXT = "zip";
public static final String KML_EXT = "kml";
public static final String KMZ_EXT = "kmz";
public static final List<String> allowedGeoFileToPublishExtensions = Arrays.asList(GEOJSON_EXT, ZIP_EXT, KML_EXT, KMZ_EXT);
/**
* Checks that the command line arguments are sensible
* NB: it is expected that this is run before 'configure'.
* @param cmd the commandLine object constructed from the user's options
* @return true if the commandLine is approved, false otherwise
*/
public static boolean validateArgs(CommandLine cmd) {
return validateDatasetIdArg(cmd) &&
validateFileToPublishArg(cmd) &&
validatePublishMethodArg(cmd) &&
validateProxyArgs(cmd);
}
/**
* @return an error JobStatus if any input is invalid, otherwise JobStatus.VALID
*/
public static JobStatus validateJobParams(SocrataConnectionInfo connectionInfo, GISJob job) {
if (connectionInfo.getUrl().equals("") || connectionInfo.getUrl().equals("https://")) {
return JobStatus.INVALID_DOMAIN;
}
if (!Utils.uidIsValid(job.getDatasetID())) {
return JobStatus.INVALID_DATASET_ID;
}
String fileToPublish = job.getFileToPublish();
if (fileToPublish.equals("")) {
return JobStatus.MISSING_FILE_TO_PUBLISH;
}
File publishFile = new File(fileToPublish);
if (!publishFile.exists() || publishFile.isDirectory()) {
JobStatus errorStatus = JobStatus.FILE_TO_PUBLISH_DOESNT_EXIST;
errorStatus.setMessage(fileToPublish + ": File to publish does not exist");
return errorStatus;
}
String fileExtension = FilenameUtils.getExtension(fileToPublish);
if (!allowedGeoFileToPublishExtensions.contains(fileExtension)) {
return JobStatus.FILE_TO_PUBLISH_INVALID_GIS_FORMAT;
}
return JobStatus.VALID;
}
/**
* This method attempts to map layers in the existing dataset to layers found in a shapefile,
* so that we replace existing layers where possible instead of creating new ones and changing
* the 4x4 / API endpoint of the dataset.
*/
public static JobStatus validateLayerMapping(GISJob job) {
try {
job.initializeLayerMapping();
return JobStatus.VALID;
} catch (IllegalArgumentException e) {
// This means getDatasetInfo was unable to parse the response into a GeoDataset object.
return JobStatus.NOT_A_GEO_DATASET;
} catch (Exception e) {
// If something unexpected went wrong,
// Throw it so it can be debugged
// (The rest of Datasync seems to like to swallow exceptions)
throw new RuntimeException(e);
}
}
private static boolean validateFileToPublishArg(CommandLine cmd) {
if (cmd.getOptionValue(CommandLineOptions.FILE_TO_PUBLISH_FLAG) != null) {
return true;
} else {
System.err.println("Missing required argument: -f,--" + CommandLineOptions.FILE_TO_PUBLISH_FLAG + " is required");
return false;
}
}
private static boolean validateDatasetIdArg(CommandLine cmd) {
if (cmd.getOptionValue(CommandLineOptions.DATASET_ID_FLAG) != null) {
return true;
} else {
System.err.println("Missing required argument: -i,--" + CommandLineOptions.DATASET_ID_FLAG + " is required");
return false;
}
}
private static boolean validatePublishMethodArg(CommandLine cmd) {
String method = cmd.getOptionValue("m");
String publishingWithDi2 = cmd.getOptionValue(CommandLineOptions.PUBLISH_VIA_DI2_FLAG);
String publishingWithFtp = cmd.getOptionValue(CommandLineOptions.PUBLISH_VIA_FTP_FLAG);
String controlFilePath = cmd.getOptionValue(CommandLineOptions.PATH_TO_CONTROL_FILE_FLAG);
if (method == null && controlFilePath == null
&& isNullOrFalse(publishingWithFtp) && isNullOrFalse(publishingWithDi2)) {
System.err.println("Missing required argument: -m,--" +
CommandLineOptions.PUBLISH_METHOD_FLAG + " is required");
return false;
} else if (method == null && controlFilePath == null
&& (!isNullOrFalse(publishingWithFtp) || !isNullOrFalse(publishingWithDi2))) {
// if publishing via ftp or di2/http, we want to err about the control file, not the method arg
return true;
} else if (method == null && controlFilePath != null) {
// have a control file, don't need the method arg (and would ignore it anyway)
return true;
} else { // method != null
boolean publishMethodValid = false;
for (PublishMethod m : PublishMethod.values()) {
if (m.name().equalsIgnoreCase(method))
publishMethodValid = true;
}
if (!publishMethodValid) {
System.err.println("Invalid argument: -m,--" + CommandLineOptions.PUBLISH_METHOD_FLAG + " must be " +
Arrays.toString(PublishMethod.values()));
return false;
}
return true;
}
}
private static boolean validateProxyArgs(CommandLine cmd) {
String username = cmd.getOptionValue(CommandLineOptions.PROXY_USERNAME_FLAG);
String password = cmd.getOptionValue(CommandLineOptions.PROXY_PASSWORD_FLAG);
if(username == null && password != null) {
System.err.println("Missing required argument: -pun,--" + CommandLineOptions.PROXY_USERNAME_FLAG + " is required if" +
" supplying proxy credentials with -ppw, --" + CommandLineOptions.PROXY_PASSWORD_FLAG);
return false;
} else if(username != null && password == null) {
System.err.println("Missing required argument: -ppw,--" + CommandLineOptions.PROXY_PASSWORD_FLAG + " is required if" +
" supplying proxy credentials with -pun, --" + CommandLineOptions.PROXY_USERNAME_FLAG);
return false;
}
return true;
}
private static boolean isNullOrFalse(String s) {
return s == null || s.equalsIgnoreCase("false");
}
}