Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/com/fieldexpert/fbapi4j/Case.java
Original file line number Diff line number Diff line change
Expand Up @@ -178,5 +178,33 @@ public void setAssignedTo(Integer personId) {
fields.put(Fbapi4j.IX_PERSON_ASSIGNED_TO, personId);
fields.remove(Fbapi4j.S_PERSON_ASSIGNED_TO);
}

/***
* A general-purpose getter for any field. Particularly useful for obtaining
* fields set up as custom in the {@link CaseHandler}. This is typically used
* for those fields belonging to third-party plugins.
*
* @throws IllegalArgumentException If the column specified does not exist
*/
public Object getField(String fieldName) throws IllegalArgumentException {
Object value = null;

if (fields.containsKey(fieldName)) {
value = fields.get(fieldName);
} else {
throw new IllegalArgumentException(String.format("Unknown field specified '%s'", fieldName));
}

return value;
}

/***
* A general-purpose setter for any field. Particularly useful for obtaining
* fields set up as custom in the {@link CaseHandler}. This is typically used
* for those fields belonging to third-party plugins.
*/
public void setField(String fieldName, Object fieldValue) {
fields.put(fieldName, fieldValue);
}

}
66 changes: 61 additions & 5 deletions src/com/fieldexpert/fbapi4j/CaseHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@

import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.w3c.dom.Document;
Expand All @@ -26,10 +29,46 @@

class CaseHandler extends AbstractHandler<Case> {

private static final String cols = collectionToCommaDelimitedString(asList(Fbapi4j.S_PROJECT, Fbapi4j.S_AREA, Fbapi4j.S_SCOUT_DESCRIPTION, Fbapi4j.S_TITLE, Fbapi4j.S_EVENT, Fbapi4j.EVENTS));

CaseHandler(Dispatch dispatch, Util util, String token) {
/** The complete set of supported columns, i.e. the contents of {@link #DEFAULT_COLUMNS} merged with the custom columns from {@link #PROP_COLUMNS} */
private Set<String> supportedColumns;
/** A string representation of {@link #supportedColumns}, which can be used for encoded queries against FogBugz */
private String supportedColumnsCSV;

/** A set containing {@link #DEFAULT_COLUMNS} */
private Set<String> defaultColumns;

/** The default columns to request for each case - regardless of custom configuration */
static final String[] DEFAULT_COLUMNS = {Fbapi4j.S_PROJECT, Fbapi4j.S_AREA, Fbapi4j.S_SCOUT_DESCRIPTION, Fbapi4j.S_TITLE, Fbapi4j.S_EVENT, Fbapi4j.EVENTS};

/** The property used to list a CSV of additional columns to support */
static final String PROP_COLUMNS = "case.columns";
/** The delimiter of the CSV property as per {@link #PROP_COLUMNS} */
static final String FIELD_CSV_DELIM = ",";

CaseHandler(Dispatch dispatch, Util util, String token, Properties properties) {
super(dispatch, util, token);
configureColumns(properties);
}

/***
* Configure additional columns to be made available.
* @param properties Application configuration
*/
private void configureColumns(Properties properties) {
supportedColumns = new HashSet<String>();
defaultColumns = new HashSet<String>();
// Add those supported by default - i.e. core fogbugz fields
defaultColumns.addAll(asList(DEFAULT_COLUMNS));
supportedColumns.addAll(defaultColumns);

if (properties.containsKey(PROP_COLUMNS)) {
String[] configuredColumns = properties.getProperty(PROP_COLUMNS).split(FIELD_CSV_DELIM);
for (String currentColumn : configuredColumns) {
supportedColumns.add(currentColumn);
}
}

supportedColumnsCSV = collectionToCommaDelimitedString(supportedColumns);
}

private void allowed(Case c, AllowedOperation operation) {
Expand All @@ -42,6 +81,15 @@ private void allowed(Case c, AllowedOperation operation) {
Case build(Map<String, String> data, Document doc) {
Case c = new Case(Integer.parseInt(data.get(Fbapi4j.IX_BUG)), data.get(Fbapi4j.S_PROJECT), data.get(Fbapi4j.S_AREA), //
data.get(Fbapi4j.S_TITLE), data.get(Fbapi4j.S_SCOUT_DESCRIPTION));

// Add allthe supported columns to the case
for (String currentColumn : supportedColumns) {
// We assume the default columns are handled elsewhere
if (! defaultColumns.contains(supportedColumns)) {
c.setField(currentColumn, data.get(currentColumn));
}
}

List<Event> events = events(doc, c);
c.addEvents(events);
update(c, data);
Expand Down Expand Up @@ -96,7 +144,7 @@ public List<Case> findAll() {
}

public Case findById(Integer id) {
return find(new Request(Fbapi4j.SEARCH, util.map(Fbapi4j.TOKEN, token, Fbapi4j.QUERY, id, Fbapi4j.COLS, cols)));
return find(new Request(Fbapi4j.SEARCH, util.map(Fbapi4j.TOKEN, token, Fbapi4j.QUERY, id, Fbapi4j.COLS, supportedColumnsCSV)));
}

public Case findByName(String name) {
Expand All @@ -105,7 +153,7 @@ public Case findByName(String name) {

public List<Case> query(String... criterion) {
String q = collectionToCommaDelimitedString(asList(criterion));
Response resp = dispatch.invoke(new Request(Fbapi4j.SEARCH, util.map(Fbapi4j.TOKEN, token, Fbapi4j.COLS, cols, Fbapi4j.QUERY, q)));
Response resp = dispatch.invoke(new Request(Fbapi4j.SEARCH, util.map(Fbapi4j.TOKEN, token, Fbapi4j.COLS, supportedColumnsCSV, Fbapi4j.QUERY, q)));
return list(resp);
}

Expand Down Expand Up @@ -162,4 +210,12 @@ private void update(Case c, Map<String, String> data) {
}
c.setAllowedOperations(operations);
}

/***
* A ready-only copy of the set of columns supported.
* @return Read-only collection of columns
*/
protected Collection<String> getSupportedColumns() {
return Collections.unmodifiableCollection(supportedColumns);
}
}
2 changes: 1 addition & 1 deletion src/com/fieldexpert/fbapi4j/ConnectedSession.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class ConnectedSession implements Session {

private void initHandlers() {
handlers.put(Area.class, areaHandler = new AreaHandler(dispatch, util, token));
handlers.put(Case.class, caseHandler = new CaseHandler(dispatch, util, token));
handlers.put(Case.class, caseHandler = new CaseHandler(dispatch, util, token, dispatch.getProperties()));
handlers.put(Person.class, new PersonHandler(dispatch, util, token));
handlers.put(Priority.class, new PriorityHandler(dispatch, util, token));
handlers.put(Project.class, new ProjectHandler(dispatch, util, token));
Expand Down
29 changes: 29 additions & 0 deletions test/com/fieldexpert/fbapi4j/CaseTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.fieldexpert.fbapi4j;

import static junit.framework.Assert.assertEquals;
import junit.framework.AssertionFailedError;

import org.junit.Test;

Expand All @@ -14,5 +15,33 @@ public void basic() {
assertEquals("Misc", bug.getArea());
assertEquals("Test Case Title", bug.getTitle());
}

@Test
public void customColumnSetter() {
Case bug = new Case("fbapi4j", "Misc", "Test Case Title", "Blue Smoke");
bug.setField("some-field", "some-value");

assertEquals("Custom field getter didn't return value given to setter", "some-value", bug.getField("some-field"));
}

@Test
public void customColumnUnsetGetter() {
Case bug = new Case("fbapi4j", "Misc", "Test Case Title", "Blue Smoke");

boolean caughtException = false;
try {
// When we call a getter, without having set the field.....
bug.getField("some-field");
} catch (IllegalArgumentException ex) {
// ... we expect to get an IAE!
caughtException = true;
}

if (! caughtException) {
throw new AssertionFailedError(String.format(
"Calling custom column getter on Case should throw %s if column not previously set",
IllegalArgumentException.class.getSimpleName()));
}
}

}
36 changes: 36 additions & 0 deletions test/com/fieldexpert/fbapi4j/CustomColumnTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.fieldexpert.fbapi4j;

import static org.junit.Assert.assertTrue;

import java.util.Properties;

import org.junit.Test;

public class CustomColumnTest {

/***
* If custom columns are specified, ensure the case handler correctly adds them to its list of
* supported columns.
*/
@Test
public void testCustColumnSetup () {
Properties propsWithCustomColumns = new Properties();
propsWithCustomColumns.setProperty(CaseHandler.PROP_COLUMNS, "some-column-a" + CaseHandler.FIELD_CSV_DELIM + "some-column-b");
CaseHandler caseHandler = new CaseHandler(null, null, null, propsWithCustomColumns);

assertTrue("The case handler should support 'some-column-a'", caseHandler.getSupportedColumns().contains("some-column-a"));
assertTrue("The case handler should support 'some-column-b'", caseHandler.getSupportedColumns().contains("some-column-b"));
}

/***
* Test the custom columns logic doesn't affect the default columns handling
*/
@Test
public void testDefaultColumns() {
CaseHandler caseHandler = new CaseHandler(null, null, null, new Properties());
for (String currentDefaultColumn : CaseHandler.DEFAULT_COLUMNS) {
assertTrue(String.format("The case handler should support the default column '%s'", currentDefaultColumn),
caseHandler.getSupportedColumns().contains(currentDefaultColumn));
}
}
}