/*
* 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.
*
* Contributions from 2013-2017 where performed either by US government
* employees, or under US Veterans Health Administration contracts.
*
* US Veterans Health Administration contributions by government employees
* are work of the U.S. Government and are not subject to copyright
* protection in the United States. Portions contributed by government
* employees are USGovWork (17USC ยง105). Not subject to copyright.
*
* Contribution by contractors to the US Veterans Health Administration
* during this period are contractually contributed under the
* Apache License, Version 2.0.
*
* See: https://www.usa.gov/government-works
*
* Contributions prior to 2013:
*
* Copyright (C) International Health Terminology Standards Development Organisation.
* Licensed under the Apache License, Version 2.0.
*
*/
package sh.isaac.pombuilder.converter;
//~--- JDK imports ------------------------------------------------------------
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
//~--- non-JDK imports --------------------------------------------------------
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import sh.isaac.api.util.ArtifactUtilities;
import sh.isaac.api.util.DownloadUnzipTask;
import sh.isaac.api.util.WorkExecutors;
import sh.isaac.pombuilder.FileUtil;
import sh.isaac.pombuilder.artifacts.Converter;
//~--- classes ----------------------------------------------------------------
/**
*
* {@link ConverterOptionParam}
*
* The set of options that apply to a particular converter. Converters build this object, and serialize it to json, and publish it to maven.
* Consumers (the GUI) read the json file, and pass it here, or ask us to read the json file and parse it.
*
* @author <a href="mailto:daniel.armbrust.list@gmail.com">Dan Armbrust</a>
*/
public class ConverterOptionParam {
/** The Constant MAVEN_FILE_TYPE. */
public static final String MAVEN_FILE_TYPE = "options.json";
/** The Constant LOG. */
private static final Logger LOG = LogManager.getLogger();
//~--- fields --------------------------------------------------------------
/** The display name. */
private String displayName;
/** The internal name. */
private String internalName;
/** The description. */
private String description;
/** The allow no selection. */
private boolean allowNoSelection;
/** The allow multi select. */
private boolean allowMultiSelect;
/** The suggested pick list values. */
private ConverterOptionParamSuggestedValue[] suggestedPickListValues;
//~--- constructors --------------------------------------------------------
/**
* Instantiates a new converter option param.
*/
@SuppressWarnings("unused")
private ConverterOptionParam() {
// for jackson
}
/**
* Instantiates a new converter option param.
*
* @param displayName The name of this option
* @param internalName The name to use when writing the option to a pom file
* @param description A description suitable for display to end users of the system (in the GUI)
* @param allowNoSelection true if it is valid for the user to select 0 entries from the pick list, false if they must select 1 or more.
* @param allowMultiSelect true if it is valie for the user to select more than 1 entry from the pick list, false if they may select at most 1.
* @param suggestedPickListValues the values to provide the user to select from. This may not be an all-inclusive list of values - the
* user should still have the option to provide their own value.
*/
@SafeVarargs
public ConverterOptionParam(String displayName,
String internalName,
String description,
boolean allowNoSelection,
boolean allowMultiSelect,
ConverterOptionParamSuggestedValue... suggestedPickListValues) {
this.displayName = displayName;
this.internalName = internalName;
this.description = description;
this.allowNoSelection = allowNoSelection;
this.allowMultiSelect = allowMultiSelect;
this.suggestedPickListValues = suggestedPickListValues;
}
//~--- methods -------------------------------------------------------------
/**
* Equals.
*
* @param obj the obj
* @return true, if successful
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final ConverterOptionParam other = (ConverterOptionParam) obj;
if (this.allowNoSelection != other.allowNoSelection) {
return false;
}
if (this.allowMultiSelect != other.allowMultiSelect) {
return false;
}
if (this.description == null) {
if (other.description != null) {
return false;
}
} else if (!this.description.equals(other.description)) {
return false;
}
if (this.displayName == null) {
if (other.displayName != null) {
return false;
}
} else if (!this.displayName.equals(other.displayName)) {
return false;
}
if (this.internalName == null) {
if (other.internalName != null) {
return false;
}
} else if (!this.internalName.equals(other.internalName)) {
return false;
}
if (!Arrays.equals(this.suggestedPickListValues, other.suggestedPickListValues)) {
return false;
}
return true;
}
/**
* Read the options specification from a json file found on the provided maven artifact server, with the provided artifact type.
* May return an empty array, will not return null.
*
* @param artifact the artifact
* @param baseMavenUrl the base maven url
* @param mavenUsername the maven username
* @param mavenPassword the maven password
* @return the converter option param[]
* @throws Exception the exception
*/
public static ConverterOptionParam[] fromArtifact(Converter artifact,
String baseMavenUrl,
String mavenUsername,
String mavenPassword)
throws Exception {
File tempFolder = null;
try {
LOG.debug("Trying to read 'options.json' for {} from '{}'", artifact, baseMavenUrl);
tempFolder = File.createTempFile("jsonDownload", "");
tempFolder.delete();
tempFolder.mkdir();
// First, try to get the pom file to validate the params they sent us. If this fails, they sent bad info, and we fail.
final URL pomURL = ArtifactUtilities.makeFullURL(baseMavenUrl,
mavenUsername,
mavenPassword,
artifact.getGroupId(),
artifact.getArtifactId(),
artifact.getVersion(),
artifact.getClassifier(),
"pom");
DownloadUnzipTask dut = new DownloadUnzipTask(mavenUsername, mavenPassword, pomURL, false, true, tempFolder);
WorkExecutors.get()
.getExecutor()
.execute(dut);
final File pomFile = dut.get();
if (!pomFile.exists()) {
LOG.debug("Throwing back an exception, as no pom was readable for the specified artifact");
throw new Exception("Failed to find the pom file for the specified project");
} else {
pomFile.delete();
}
// Now that we know that the credentials / artifact / version are good - see if there is a config file (there may not be)
try {
final URL config = ArtifactUtilities.makeFullURL(baseMavenUrl,
mavenUsername,
mavenPassword,
artifact.getGroupId(),
artifact.getArtifactId(),
artifact.getVersion(),
artifact.getClassifier(),
MAVEN_FILE_TYPE);
dut = new DownloadUnzipTask(mavenUsername, mavenPassword, config, false, true, tempFolder);
WorkExecutors.get()
.getExecutor()
.execute(dut);
final File jsonFile = dut.get();
final ConverterOptionParam[] temp = fromFile(jsonFile);
if (LOG.isDebugEnabled()) {
LOG.debug("Found options: {}", Arrays.toString(temp));
} else {
LOG.info("Read {} options", temp.length);
}
jsonFile.delete();
return temp;
} catch (final Exception e) {
// If we successfully downloaded the pom file, but failed here, just assume this file doesn't exist / isn't applicable to this converter.
LOG.info("No config file found for converter " + artifact.getArtifactId());
return new ConverterOptionParam[] {};
}
} finally {
try {
FileUtil.recursiveDelete(tempFolder);
} catch (final Exception e) {
LOG.error("Problem cleaning up temp folder " + tempFolder, e);
}
}
}
/**
* Read the options specification from a json file.
*
* @param jsonConverterOptionFile the json converter option file
* @return the converter option param[]
* @throws IOException Signals that an I/O exception has occurred.
*/
public static ConverterOptionParam[] fromFile(File jsonConverterOptionFile)
throws IOException {
final ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(jsonConverterOptionFile, ConverterOptionParam[].class);
}
/**
* Hash code.
*
* @return the int
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (this.allowNoSelection ? 1231
: 1237);
result = prime * result + (this.allowMultiSelect ? 1231
: 1237);
result = prime * result + ((this.description == null) ? 0
: this.description.hashCode());
result = prime * result + ((this.displayName == null) ? 0
: this.displayName.hashCode());
result = prime * result + ((this.internalName == null) ? 0
: this.internalName.hashCode());
result = prime * result + Arrays.hashCode(this.suggestedPickListValues);
return result;
}
/**
* Serialize to json.
*
* @param options the options
* @param outputFile the output file
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void serialize(ConverterOptionParam[] options, File outputFile)
throws IOException {
final ObjectMapper mapper = new ObjectMapper();
try {
mapper.writeValue(outputFile, options);
} catch (final JsonProcessingException e) {
throw new RuntimeException("Unexpected error", e);
}
}
/**
* To string.
*
* @return the string
*/
@Override
public String toString() {
return "ConverterOptionParam [displayName=" + this.displayName + ", internalName=" + this.internalName +
", description=" + this.description + ", allowNoSelection=" + this.allowNoSelection +
", allowMultiSelect=" + this.allowMultiSelect + ", suggestedPickListValues=" +
Arrays.toString(this.suggestedPickListValues) + "]";
}
//~--- get methods ---------------------------------------------------------
/**
* true if it is valie for the user to select more than 1 entry from the pick list, false if they may select at most 1.
*
* @return true, if allow multi select
*/
public boolean isAllowMultiSelect() {
return this.allowMultiSelect;
}
/**
* true if it is valid for the user to select 0 entries from the pick list, false if they must select 1 or more.
*
* @return true, if allow no selection
*/
public boolean isAllowNoSelection() {
return this.allowNoSelection;
}
/**
* The description of this option suitable to display to the end user, in a GUI.
*
* @return the description
*/
public String getDescription() {
return this.description;
}
/**
* The displayName of this option - suitable for GUI use to the end user.
*
* @return the display name
*/
public String getDisplayName() {
return this.displayName;
}
/**
* The internalName of this option - use when creating the pom file.
*
* @return the internal name
*/
public String getInternalName() {
return this.internalName;
}
/**
* Gets the suggested pick list values.
*
* @return the suggested pick list values
*/
public ConverterOptionParamSuggestedValue[] getSuggestedPickListValues() {
return this.suggestedPickListValues;
}
}