Skip to content

Commit

Permalink
Merge pull request #3 from jdimatteo/master
Browse files Browse the repository at this point in the history
Multi Level Drop Downs
  • Loading branch information
vimil committed Sep 27, 2013
2 parents d5df95a + d56396c commit c678747
Show file tree
Hide file tree
Showing 12 changed files with 476 additions and 20 deletions.
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@
</developer>
</developers>

<dependencies>
<dependency>
<groupId>net.sf.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>2.0</version>
</dependency>
</dependencies>

<!-- get every artifact through maven.glassfish.org, which proxies all the artifacts that we need -->
<repositories>
<repository>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import hudson.util.FormValidation;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
Expand All @@ -19,6 +20,9 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedHashMap;

import javax.servlet.ServletException;

Expand All @@ -32,6 +36,8 @@
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;

import au.com.bytecode.opencsv.CSVReader;

public class ExtendedChoiceParameterDefinition extends ParameterDefinition {
private static final long serialVersionUID = -2946187268529865645L;

Expand All @@ -44,6 +50,10 @@ public class ExtendedChoiceParameterDefinition extends ParameterDefinition {
public static final String PARAMETER_TYPE_RADIO = "PT_RADIO";

public static final String PARAMETER_TYPE_TEXT_BOX = "PT_TEXTBOX";

public static final String PARAMETER_TYPE_MULTI_LEVEL_SINGLE_SELECT = "PT_MULTI_LEVEL_SINGLE_SELECT";

public static final String PARAMETER_TYPE_MULTI_LEVEL_MULTI_SELECT = "PT_MULTI_LEVEL_MULTI_SELECT";

@Extension
public static class DescriptorImpl extends ParameterDescriptor {
Expand All @@ -52,7 +62,7 @@ public String getDisplayName() {
return Messages.ExtendedChoiceParameterDefinition_DisplayName();
}

public FormValidation doCheckPropertyFile(@QueryParameter final String propertyFile, @QueryParameter final String propertyKey) throws IOException, ServletException {
public FormValidation doCheckPropertyFile(@QueryParameter final String propertyFile, @QueryParameter final String propertyKey, @QueryParameter final String type) throws IOException, ServletException {
if(StringUtils.isBlank(propertyFile)) {
return FormValidation.ok();
}
Expand All @@ -76,7 +86,12 @@ public FormValidation doCheckPropertyFile(@QueryParameter final String propertyF
return FormValidation.warning(Messages.ExtendedChoiceParameterDefinition_PropertyFileDoesntExist(), propertyFile);
}

if(StringUtils.isNotBlank(propertyKey)) {
if( type.equals(PARAMETER_TYPE_MULTI_LEVEL_SINGLE_SELECT)
|| type.equals(PARAMETER_TYPE_MULTI_LEVEL_MULTI_SELECT))
{
return FormValidation.ok();
}
else if(StringUtils.isNotBlank(propertyKey)) {
if(project.getProperty(propertyKey) != null) {
return FormValidation.ok();
}
Expand All @@ -89,18 +104,20 @@ public FormValidation doCheckPropertyFile(@QueryParameter final String propertyF
}
}

public FormValidation doCheckPropertyKey(@QueryParameter final String propertyFile, @QueryParameter final String propertyKey) throws IOException, ServletException {
return doCheckPropertyFile(propertyFile, propertyKey);
public FormValidation doCheckPropertyKey(@QueryParameter final String propertyFile, @QueryParameter final String propertyKey,
@QueryParameter final String type) throws IOException, ServletException {
return doCheckPropertyFile(propertyFile, propertyKey, type);
}

public FormValidation doCheckDefaultPropertyFile(@QueryParameter final String defaultPropertyFile,
@QueryParameter final String defaultPropertyKey) throws IOException, ServletException {
return doCheckPropertyFile(defaultPropertyFile, defaultPropertyKey);
@QueryParameter final String defaultPropertyKey, @QueryParameter final String type) throws IOException, ServletException {
return doCheckPropertyFile(defaultPropertyFile, defaultPropertyKey, type);
}

public FormValidation doCheckDefaultPropertyKey(@QueryParameter final String defaultPropertyFile,
@QueryParameter final String defaultPropertyKey) throws IOException, ServletException {
return doCheckPropertyFile(defaultPropertyFile, defaultPropertyKey);
@QueryParameter final String defaultPropertyKey, @QueryParameter final String type) throws IOException, ServletException
{
return doCheckPropertyFile(defaultPropertyFile, defaultPropertyKey, type);
}
}

Expand All @@ -111,7 +128,7 @@ public FormValidation doCheckDefaultPropertyKey(@QueryParameter final String def
private String type;

private String value;

private String propertyFile;

private String propertyKey;
Expand Down Expand Up @@ -194,17 +211,39 @@ public ParameterValue createValue(StaplerRequest request) {
}
return null;
}

@Override
public ParameterValue createValue(StaplerRequest request, JSONObject jO) {
public ParameterValue createValue(StaplerRequest request, JSONObject jO) {
Object value = jO.get("value");
String strValue = "";
if(value instanceof String) {
strValue = (String)value;
}
else if(value instanceof JSONArray) {
JSONArray jsonValues = (JSONArray)value;
strValue = StringUtils.join(jsonValues.iterator(), getMultiSelectDelimiter());
if ( type.equals(PARAMETER_TYPE_MULTI_LEVEL_SINGLE_SELECT)
|| type.equals(PARAMETER_TYPE_MULTI_LEVEL_MULTI_SELECT))
{
final int valuesBetweenLevels = this.value.split(",").length;

Iterator it = jsonValues.iterator();
for (int i = 1; it.hasNext(); i++)
{
String nextValue = it.next().toString();
if (i % valuesBetweenLevels == 0)
{
if (strValue.length() > 0)
{
strValue += getMultiSelectDelimiter();
}
strValue += nextValue;
}
}
}
else
{
strValue = StringUtils.join(jsonValues.iterator(), getMultiSelectDelimiter());
}
}

if(quoteValue) {
Expand All @@ -224,7 +263,8 @@ public ParameterValue getDefaultParameterValue() {
}
return super.getDefaultParameterValue();
}


// note that computeValue is not called by multiLevel.jelly
private String computeValue(String value, String propertyFilePath, String propertyKey) {
if(!StringUtils.isBlank(propertyFile) && !StringUtils.isBlank(propertyKey)) {
try {
Expand Down Expand Up @@ -295,7 +335,156 @@ public void setDefaultPropertyKey(String defaultPropertyKey) {
public String getEffectiveValue() {
return computeValue(value, propertyFile, propertyKey);
}

private ArrayList<Integer> columnIndicesForDropDowns(String[] headerColumns)
{
ArrayList<Integer> columnIndicesForDropDowns = new ArrayList<Integer>();

String[] dropDownNames = value.split(",");

for (String dropDownName : dropDownNames)
{
for (int i = 0; i < headerColumns.length; ++i)
{
if (headerColumns[i].equals(dropDownName))
{
columnIndicesForDropDowns.add(new Integer(i));
}
}
}

return columnIndicesForDropDowns;
}

LinkedHashMap<String, LinkedHashSet<String>> calculateChoicesByDropdownId() throws Exception
{
List<String[]> fileLines =
new CSVReader(new FileReader(propertyFile), '\t').readAll();

if (fileLines.size() < 2)
{
throw new Exception("Multi level tab delimited file must have at least 2 "
+ "lines (one for the header, and one or more for the data)");
}

ArrayList<Integer> columnIndicesForDropDowns =
columnIndicesForDropDowns(fileLines.get(0));

List<String[]> dataLines = fileLines.subList(1, fileLines.size());

LinkedHashMap<String, LinkedHashSet<String>> choicesByDropdownId =
new LinkedHashMap<String, LinkedHashSet<String>>();

String prefix = getName() + " dropdown MultiLevelMultiSelect 0";
choicesByDropdownId.put(prefix, new LinkedHashSet<String>());

for (int i=0; i < columnIndicesForDropDowns.size(); ++i)
{
String prettyCurrentColumnName = value.split(",")[i];
prettyCurrentColumnName = prettyCurrentColumnName.toLowerCase();
prettyCurrentColumnName = prettyCurrentColumnName.replace("_", " ");

for (String[] dataLine : dataLines)
{
String priorLevelDropdownId = prefix;
String currentLevelDropdownId = prefix;

int column = 0;
for (int j=0; j <= i; ++j)
{
column = columnIndicesForDropDowns.get(j);

if (j < i)
{
priorLevelDropdownId += " " + dataLine[column];
}
currentLevelDropdownId += " " + dataLine[column];
}
if (i != columnIndicesForDropDowns.size() - 1)
{
choicesByDropdownId.put(currentLevelDropdownId, new LinkedHashSet<String>());
}
LinkedHashSet<String> choicesForPriorDropdown
= choicesByDropdownId.get(priorLevelDropdownId);
choicesForPriorDropdown.add("Select a " + prettyCurrentColumnName
+ "...");
choicesForPriorDropdown.add(dataLine[column]);
}
}

return choicesByDropdownId;
}

public String getMultiLevelDropdownIds() throws Exception
{
String dropdownIds = new String();

LinkedHashMap<String, LinkedHashSet<String>> choicesByDropdownId =
calculateChoicesByDropdownId();

for (String id : choicesByDropdownId.keySet())
{
if (dropdownIds.length() > 0)
{
dropdownIds += ",";
}
dropdownIds += id;
}

return dropdownIds;

/* dropdownIds is of a form like this:
return name + " dropdown MultiLevelMultiSelect 0,"
// next select the source of the genome -- each genome gets a seperate dropdown id:"
+ name + " dropdown MultiLevelMultiSelect 0 HG18,dropdown MultiLevelMultiSelect 0 ZZ23,"
// next select the cell type of the source -- each source gets a seperate dropdown id
+ name + " dropdown MultiLevelMultiSelect 0 HG18 Diffuse large B-cell lymphoma, dropdown MultiLevelMultiSelect 0 HG18 Multiple Myeloma,"
+ name + " dropdown MultiLevelMultiSelect 0 ZZ23 Neuroblastoma,"
// next select the name from the cell type -- each cell type gets a seperate dropdown id
+ name + " dropdown MultiLevelMultiSelect 0 HG18 Diffuse large B-cell lymphoma LY1,"
+ name + " dropdown MultiLevelMultiSelect 0 HG18 Multiple Myeloma MM1S,"
+ name + " dropdown MultiLevelMultiSelect 0 ZZ23 Neuroblastoma BE2C,"
+ name + " dropdown MultiLevelMultiSelect 0 ZZ23 Neuroblastoma SKNAS";*/
}

public Map<String, String> getChoicesByDropdownId() throws Exception
{
LinkedHashMap<String, LinkedHashSet<String>> choicesByDropdownId =
calculateChoicesByDropdownId();

Map<String, String> collapsedMap = new LinkedHashMap<String, String>();

for (String dropdownId : choicesByDropdownId.keySet())
{
String choices = new String();
for (String choice : choicesByDropdownId.get(dropdownId))
{
if (choices.length() > 0)
{
choices += ",";
}
choices += choice;
}

collapsedMap.put(dropdownId, choices);
}

/* collapsedMap is of a form like this:
collapsedMap.put(name + " dropdown MultiLevelMultiSelect 0", "Select a genome...,HG18,ZZ23");
collapsedMap.put(name + " dropdown MultiLevelMultiSelect 0 HG18", "Select a source...,Diffuse large B-cell lymphoma,Multiple Myeloma");
collapsedMap.put(name + " dropdown MultiLevelMultiSelect 0 ZZ23", "Select a source...,Neuroblastoma");
collapsedMap.put(name + " dropdown MultiLevelMultiSelect 0 HG18 Diffuse large B-cell lymphoma","Select a cell type...,LY1");
collapsedMap.put(name + " dropdown MultiLevelMultiSelect 0 HG18 Multiple Myeloma","Select a cell type...,MM1S");
collapsedMap.put(name + " dropdown MultiLevelMultiSelect 0 ZZ23 Neuroblastoma","Select a cell type...,BE2C,SKNAS");
collapsedMap.put(name + " dropdown MultiLevelMultiSelect 0 HG18 Diffuse large B-cell lymphoma LY1","Select a name...,LY1_BCL6_DMSO,LY1_BCL6_JQ1");
collapsedMap.put(name + " dropdown MultiLevelMultiSelect 0 HG18 Multiple Myeloma MM1S", "Select a name...,MM1S_BRD4_150nM_JQ1,MM1S_BRD4_500nM_JQ1");
collapsedMap.put(name + " dropdown MultiLevelMultiSelect 0 ZZ23 Neuroblastoma BE2C", "Select a name...,BE2C_BRD4");
collapsedMap.put(name + " dropdown MultiLevelMultiSelect 0 ZZ23 Neuroblastoma SKNAS", "Select a name...,SKNAS_H3K4ME3");
*/

return collapsedMap;
}

public String getValue() {
return value;
}
Expand Down Expand Up @@ -347,5 +536,4 @@ public void setDefaultPropertyFile(String defaultPropertyFile) {
public Map<String, Boolean> getDefaultValueMap() {
return computeDefaultValueMap();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,24 @@
</j:when>
<j:otherwise>
<option value="PT_TEXTBOX">Text Box</option>
</j:otherwise>
</j:choose>
</j:otherwise>
</j:choose>
<j:choose>
<j:when test="${instance.type eq 'PT_MULTI_LEVEL_SINGLE_SELECT'}">
<option value="PT_MULTI_LEVEL_SINGLE_SELECT" selected="selected">Multi-Level Single Select</option>
</j:when>
<j:otherwise>
<option value="PT_MULTI_LEVEL_SINGLE_SELECT">Multi-Level Single Select</option>
</j:otherwise>
</j:choose>
<j:choose>
<j:when test="${instance.type eq 'PT_MULTI_LEVEL_MULTI_SELECT'}">
<option value="PT_MULTI_LEVEL_MULTI_SELECT" selected="selected">Multi-Level Multi Select</option>
</j:when>
<j:otherwise>
<option value="PT_MULTI_LEVEL_MULTI_SELECT">Multi-Level Multi Select</option>
</j:otherwise>
</j:choose>
</select>
</f:entry>
<f:entry title="Value" field="value">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
Absolute path (specified without using environment variables).
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<div>
Initial selection of the single-select or mult-select box.
<br><br>In case of the multi-select box, default value can be a comma separated string.
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div>
The <a href="http://download.oracle.com/javase/6/docs/api/java/util/Properties.html">properties file</a>
is a collection of key,value pairs of the form key=value1,value2,...
<br><br>
Property files may reference other properties. For example:
<blockquote>
prop1=a,b,c,d,e<br>
prop2=${prop1},f,g,h
</blockquote>
The properties file can be placed anywhere on the file-system that Jenkins can access.
<br><br>
This property file has different meaning for multi-level select -- see the parameter type help for more info.
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<div>
The property of the property file to use.
<br><br>
For example, if the property file was the following:
<blockquote>
prop1=a,b,c,d,e<br>
prop2=1,2,3,4
</blockquote>
Then you could specify the property as either prop1 or prop2.
</div>
Loading

0 comments on commit c678747

Please sign in to comment.