summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Morgan <jesse@jesterpm.net>2018-07-14 12:28:00 -0700
committerJesse Morgan <jesse@jesterpm.net>2018-07-14 12:28:00 -0700
commit3b9058128ed3d5d96928725413ea4977f690d0f2 (patch)
tree4e90349000bd0b7d4cfcfa04c48ba6b649f3d155
parent633d0cebff548b6a54ac33e464447d93e800bf12 (diff)
Add data models for GroupSearch APIgroups-api
-rw-r--r--src/main/java/com/p4square/ccbapi/model/CCBIDReference.java48
-rw-r--r--src/main/java/com/p4square/ccbapi/model/GroupSearchResult.java218
-rw-r--r--src/main/java/com/p4square/ccbapi/model/SearchGroupsCriteriaFields.java17
-rw-r--r--src/main/java/com/p4square/ccbapi/model/SearchGroupsRequest.java169
-rw-r--r--src/main/java/com/p4square/ccbapi/model/SearchGroupsResponse.java27
-rw-r--r--src/main/java/com/p4square/ccbapi/model/SortOrder.java6
-rw-r--r--src/test/java/com/p4square/ccbapi/model/SearchGroupsResponseTest.java50
-rw-r--r--src/test/resources/com/p4square/ccbapi/model/ccb_group_search_response.xml41
8 files changed, 576 insertions, 0 deletions
diff --git a/src/main/java/com/p4square/ccbapi/model/CCBIDReference.java b/src/main/java/com/p4square/ccbapi/model/CCBIDReference.java
new file mode 100644
index 0000000..bc76368
--- /dev/null
+++ b/src/main/java/com/p4square/ccbapi/model/CCBIDReference.java
@@ -0,0 +1,48 @@
+package com.p4square.ccbapi.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlValue;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+/**
+ * Specialization of {@link Reference}.
+ *
+ * This class exists because CCB has two different names for the "id"
+ * attribute of a reference.
+ */
+@XmlAccessorType(XmlAccessType.NONE)
+/* package-private */ class CCBIDReference {
+ @XmlAttribute(name="ccb_id")
+ private int id;
+
+ @XmlValue
+ private String name;
+
+ public CCBIDReference() {}
+
+ public CCBIDReference(Reference r) {
+ this.id = r.getId();
+ this.name = r.getName();
+ }
+
+ public Reference toReference() {
+ final Reference r = new Reference();
+ r.setId(id);
+ r.setName(name);
+ return r;
+ }
+
+ public static final class Adapter extends XmlAdapter<CCBIDReference, Reference> {
+ @Override
+ public Reference unmarshal(CCBIDReference ccbidReference) throws Exception {
+ return ccbidReference.toReference();
+ }
+
+ @Override
+ public CCBIDReference marshal(Reference reference) throws Exception {
+ return new CCBIDReference(reference);
+ }
+ }
+}
diff --git a/src/main/java/com/p4square/ccbapi/model/GroupSearchResult.java b/src/main/java/com/p4square/ccbapi/model/GroupSearchResult.java
new file mode 100644
index 0000000..0c8acd5
--- /dev/null
+++ b/src/main/java/com/p4square/ccbapi/model/GroupSearchResult.java
@@ -0,0 +1,218 @@
+package com.p4square.ccbapi.model;
+
+import javax.xml.bind.annotation.*;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+@XmlRootElement(name="item")
+@XmlAccessorType(XmlAccessType.NONE)
+public class GroupSearchResult {
+
+ @XmlElement(name="id")
+ private int id;
+
+ @XmlElement(name="name")
+ private String name;
+
+ @XmlElement(name="group_type_name")
+ private String groupTypeName;
+
+ @XmlElement(name="grouping_name")
+ private String departmentName;
+
+ @XmlElement(name="area_name")
+ @XmlJavaTypeAdapter(CCBIDReference.Adapter.class)
+ private Reference area;
+
+ @XmlElement(name="meet_day_name")
+ private String meetingDayName;
+
+ @XmlElement(name="meet_time_name")
+ private String meetingTimeName;
+
+ @XmlElement(name="description")
+ private String description;
+
+ /**
+ * This attribute is undefined in the CCB docs. I suspect that it is
+ * the negative {@link GroupProfile#isActive()} attribute, but since
+ * "Group must be active" to be included in the search results, I
+ * have no way to confirm.
+ *
+ * I'm leaving this field inaccessible until it can be confirmed.
+ */
+ @XmlElement(name="status_id")
+ private int statusId;
+
+ @XmlElement(name="messaging_type")
+ @XmlJavaTypeAdapter(InteractionTypeAdapter.class)
+ private InteractionType interactionType;
+
+ @XmlElement(name="membership_type")
+ @XmlJavaTypeAdapter(MembershipTypeAdapter.class)
+ private MembershipType membershipType;
+
+ @XmlElement(name="owner_name")
+ @XmlJavaTypeAdapter(CCBIDReference.Adapter.class)
+ private Reference mainLeader;
+
+ @XmlElement(name="owner_email_primary")
+ private String mainLeaderEmail;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getGroupTypeName() {
+ return groupTypeName;
+ }
+
+ public void setGroupTypeName(String groupTypeName) {
+ this.groupTypeName = groupTypeName;
+ }
+
+ public String getDepartmentName() {
+ return departmentName;
+ }
+
+ public void setDepartmentName(String departmentName) {
+ this.departmentName = departmentName;
+ }
+
+ public Reference getArea() {
+ return area;
+ }
+
+ public void setArea(Reference area) {
+ this.area = area;
+ }
+
+ public String getMeetingDayName() {
+ return meetingDayName;
+ }
+
+ public void setMeetingDayName(String meetingDayName) {
+ this.meetingDayName = meetingDayName;
+ }
+
+ public String getMeetingTimeName() {
+ return meetingTimeName;
+ }
+
+ public void setMeetingTimeName(String meetingTimeName) {
+ this.meetingTimeName = meetingTimeName;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public InteractionType getInteractionType() {
+ return interactionType;
+ }
+
+ public void setInteractionType(InteractionType interactionType) {
+ this.interactionType = interactionType;
+ }
+
+ public MembershipType getMembershipType() {
+ return membershipType;
+ }
+
+ public void setMembershipType(MembershipType membershipType) {
+ this.membershipType = membershipType;
+ }
+
+ public Reference getMainLeader() {
+ return mainLeader;
+ }
+
+ public void setMainLeader(Reference mainLeader) {
+ this.mainLeader = mainLeader;
+ }
+
+ public String getMainLeaderEmail() {
+ return mainLeaderEmail;
+ }
+
+ public void setMainLeaderEmail(String mainLeaderEmail) {
+ this.mainLeaderEmail = mainLeaderEmail;
+ }
+
+ /**
+ * GroupProfile and GroupSearchResult use different serializations of the InteractionType enumeration.
+ */
+ private static final class InteractionTypeAdapter extends XmlAdapter<String, InteractionType> {
+ @Override
+ public InteractionType unmarshal(String s) throws Exception {
+ switch (s) {
+ case "Interact":
+ return InteractionType.MEMBERS_INTERACT;
+ case "Announce":
+ return InteractionType.ANNOUNCEMENT_ONLY;
+ default:
+ throw new IllegalArgumentException("Unknown InteractionType string '" + s + "'");
+ }
+ }
+
+ @Override
+ public String marshal(InteractionType membershipType) throws Exception {
+ switch (membershipType) {
+ case MEMBERS_INTERACT:
+ return "Interact";
+ case ANNOUNCEMENT_ONLY:
+ return "Announce";
+ case ADMINISTRATIVE:
+ throw new UnsupportedOperationException("InteractionType.ADMINISTRATIVE not allowed in search.");
+ default:
+ throw new UnsupportedOperationException("No support for " + membershipType);
+ }
+ }
+ }
+
+ /**
+ * GroupProfile and GroupSearchResult use different serializations of the MembershipType enumeration.
+ */
+ private static final class MembershipTypeAdapter extends XmlAdapter<String, MembershipType> {
+ @Override
+ public MembershipType unmarshal(String s) throws Exception {
+ switch (s) {
+ case "Request":
+ return MembershipType.MODERATED;
+ case "Open":
+ return MembershipType.OPEN;
+ default:
+ throw new IllegalArgumentException("Unknown MembershipType string '" + s + "'");
+ }
+ }
+
+ @Override
+ public String marshal(MembershipType membershipType) throws Exception {
+ switch (membershipType) {
+ case MODERATED:
+ return "Request";
+ case OPEN:
+ return "Open";
+ default:
+ throw new UnsupportedOperationException("No support for " + membershipType);
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/com/p4square/ccbapi/model/SearchGroupsCriteriaFields.java b/src/main/java/com/p4square/ccbapi/model/SearchGroupsCriteriaFields.java
new file mode 100644
index 0000000..4b3a7b3
--- /dev/null
+++ b/src/main/java/com/p4square/ccbapi/model/SearchGroupsCriteriaFields.java
@@ -0,0 +1,17 @@
+package com.p4square.ccbapi.model;
+
+/**
+ * Criteria fields in a {@link SearchGroupsRequest}.
+ */
+public enum SearchGroupsCriteriaFields {
+ AREA,
+ CAMPUS,
+ HAS_CHILDCARE,
+ MEETING_DAY,
+ MEETING_TIME,
+ DEPARTMENT,
+ GROUP_TYPE,
+ UDF_PULLDOWN_1,
+ UDF_PULLDOWN_2,
+ UDF_PULLDOWN_3;
+}
diff --git a/src/main/java/com/p4square/ccbapi/model/SearchGroupsRequest.java b/src/main/java/com/p4square/ccbapi/model/SearchGroupsRequest.java
new file mode 100644
index 0000000..141fdd5
--- /dev/null
+++ b/src/main/java/com/p4square/ccbapi/model/SearchGroupsRequest.java
@@ -0,0 +1,169 @@
+package com.p4square.ccbapi.model;
+
+/**
+ * SearchGroupsRequest is the set of options for the group_search API.
+ */
+public class SearchGroupsRequest {
+ // Criteria
+ private int areaId;
+ private int campusId;
+ private boolean hasChildcare;
+ private int meetingDayId;
+ private int meetingTimeId;
+ private int departmentId;
+ private int groupTypeId;
+ private int udfPulldown1ValueId;
+ private int udfPulldown2ValueId;
+ private int udfPulldown3ValueId;
+
+ // Controls
+ private int limitRecordsStart;
+ private int limitRecordsPerPage;
+ private OrderByCriterion[] orderBy = new OrderByCriterion[0];
+
+ public int getAreaId() {
+ return areaId;
+ }
+
+ public SearchGroupsRequest withAreaId(int areaId) {
+ this.areaId = areaId;
+ return this;
+ }
+
+ public int getCampusId() {
+ return campusId;
+ }
+
+ public SearchGroupsRequest withCampusId(int campusId) {
+ this.campusId = campusId;
+ return this;
+ }
+
+ public boolean hasChildcare() {
+ return hasChildcare;
+ }
+
+ public SearchGroupsRequest withChildcare(boolean hasChildcare) {
+ this.hasChildcare = hasChildcare;
+ return this;
+ }
+
+ public int getMeetingDayId() {
+ return meetingDayId;
+ }
+
+ public SearchGroupsRequest withMeetingDayId(int meetingDayId) {
+ this.meetingDayId = meetingDayId;
+ return this;
+ }
+
+ public int getMeetingTimeId() {
+ return meetingTimeId;
+ }
+
+ public SearchGroupsRequest withMeetingTimeId(int meetingTimeId) {
+ this.meetingTimeId = meetingTimeId;
+ return this;
+ }
+
+ public int getDepartmentId() {
+ return departmentId;
+ }
+
+ public SearchGroupsRequest withDepartmentId(int departmentId) {
+ this.departmentId = departmentId;
+ return this;
+ }
+
+ public int getGroupTypeId() {
+ return groupTypeId;
+ }
+
+ public SearchGroupsRequest withGroupTypeId(int groupTypeId) {
+ this.groupTypeId = groupTypeId;
+ return this;
+ }
+
+ public int getUdfPulldown1ValueId() {
+ return udfPulldown1ValueId;
+ }
+
+ public SearchGroupsRequest withUdfPulldown1ValueId(int udfPulldown1ValueId) {
+ this.udfPulldown1ValueId = udfPulldown1ValueId;
+ return this;
+ }
+
+ public int getUdfPulldown2ValueId() {
+ return udfPulldown2ValueId;
+ }
+
+ public SearchGroupsRequest withUdfPulldown2ValueId(int udfPulldown2ValueId) {
+ this.udfPulldown2ValueId = udfPulldown2ValueId;
+ return this;
+ }
+
+ public int getUdfPulldown3ValueId() {
+ return udfPulldown3ValueId;
+ }
+
+ public SearchGroupsRequest withUdfPulldown3ValueId(int udfPulldown3ValueId) {
+ this.udfPulldown3ValueId = udfPulldown3ValueId;
+ return this;
+ }
+
+ public int getLimitRecordsStart() {
+ return limitRecordsStart;
+ }
+
+ public SearchGroupsRequest withLimitRecordsStart(int limitRecordsStart) {
+ this.limitRecordsStart = limitRecordsStart;
+ return this;
+ }
+
+ public int getLimitRecordsPerPage() {
+ return limitRecordsPerPage;
+ }
+
+ public SearchGroupsRequest withLimitRecordsPerPage(int limitRecordsPerPage) {
+ this.limitRecordsPerPage = limitRecordsPerPage;
+ return this;
+ }
+
+ public OrderByCriterion[] getOrderBy() {
+ return orderBy;
+ }
+
+ public SearchGroupsRequest withOrderBy(OrderByCriterion[] orderBy) {
+ if (orderBy == null) {
+ this.orderBy = new OrderByCriterion[0];
+ } else if (orderBy.length > 3) {
+ throw new IllegalArgumentException("At most 3 orderBy criteria are allowed.");
+ } else {
+ this.orderBy = orderBy;
+ }
+ return this;
+ }
+
+ public final class OrderByCriterion {
+ private SearchGroupsCriteriaFields field;
+ private SortOrder order = SortOrder.ASCENDING;
+
+ public SearchGroupsCriteriaFields getField() {
+ return field;
+ }
+
+ public OrderByCriterion withField(SearchGroupsCriteriaFields field) {
+ this.field = field;
+ return this;
+ }
+
+ public SortOrder getOrder() {
+ return order;
+ }
+
+ public OrderByCriterion withOrder(SortOrder order) {
+ this.order = order;
+ return this;
+ }
+ }
+}
diff --git a/src/main/java/com/p4square/ccbapi/model/SearchGroupsResponse.java b/src/main/java/com/p4square/ccbapi/model/SearchGroupsResponse.java
new file mode 100644
index 0000000..c89525a
--- /dev/null
+++ b/src/main/java/com/p4square/ccbapi/model/SearchGroupsResponse.java
@@ -0,0 +1,27 @@
+package com.p4square.ccbapi.model;
+
+import javax.xml.bind.annotation.*;
+import java.util.List;
+
+/**
+ * SearchGroupsResponse models the response from the group_search API.
+ */
+@XmlRootElement(name="response")
+@XmlAccessorType(XmlAccessType.NONE)
+public class SearchGroupsResponse extends CCBAPIResponse {
+
+ @XmlElementWrapper(name = "items")
+ @XmlElement(name="item")
+ private List<GroupSearchResult> results;
+
+ /**
+ * @return The list of individuals retrieved from CCB.
+ */
+ public List<GroupSearchResult> getResults() {
+ return results;
+ }
+
+ public void setResults(List<GroupSearchResult> results) {
+ this.results = results;
+ }
+}
diff --git a/src/main/java/com/p4square/ccbapi/model/SortOrder.java b/src/main/java/com/p4square/ccbapi/model/SortOrder.java
new file mode 100644
index 0000000..3287f95
--- /dev/null
+++ b/src/main/java/com/p4square/ccbapi/model/SortOrder.java
@@ -0,0 +1,6 @@
+package com.p4square.ccbapi.model;
+
+public enum SortOrder {
+ ASCENDING,
+ DESCENDING;
+}
diff --git a/src/test/java/com/p4square/ccbapi/model/SearchGroupsResponseTest.java b/src/test/java/com/p4square/ccbapi/model/SearchGroupsResponseTest.java
new file mode 100644
index 0000000..57aadfb
--- /dev/null
+++ b/src/test/java/com/p4square/ccbapi/model/SearchGroupsResponseTest.java
@@ -0,0 +1,50 @@
+package com.p4square.ccbapi.model;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class SearchGroupsResponseTest extends XmlBinderTestBase {
+
+ /**
+ * Assert that all of the fields bind appropriately for a single profile response.
+ */
+ @Test
+ public void testGetGroupProfilesResponse() throws Exception {
+ final SearchGroupsResponse response = parseFile("ccb_group_search_response.xml",
+ SearchGroupsResponse.class);
+
+ assertNull("Response should not have errors", response.getErrors());
+ assertNotNull(response.getResults());
+ assertEquals(1, response.getResults().size());
+
+ final GroupSearchResult group = response.getResults().get(0);
+
+ // IDs
+ assertEquals(750, group.getId());
+
+ assertEquals("Adamant by Lisa Bevere Book Study", group.getName());
+ assertTrue(group.getDescription().startsWith("What is the truth?"));
+
+ // Main Leader
+ assertReferenceEquals(26102, "Jane Doe", group.getMainLeader());
+ assertEquals("jane.doe@example.com", group.getMainLeaderEmail());
+
+ // Attributes
+ assertEquals(InteractionType.MEMBERS_INTERACT, group.getInteractionType());
+ assertEquals(MembershipType.MODERATED, group.getMembershipType());
+
+ // Reference Attributes
+ assertEquals("Tuesday", group.getMeetingDayName());
+ assertEquals("7:00 pm", group.getMeetingTimeName());
+ assertEquals("Community", group.getGroupTypeName());
+ assertEquals("Adults", group.getDepartmentName());
+ assertReferenceEquals(18, "Puyallup", group.getArea());
+ }
+
+ private void assertReferenceEquals(int id, String name, Reference ref) {
+ assertEquals(id, ref.getId());
+ assertEquals(name, ref.getName());
+ }
+
+} \ No newline at end of file
diff --git a/src/test/resources/com/p4square/ccbapi/model/ccb_group_search_response.xml b/src/test/resources/com/p4square/ccbapi/model/ccb_group_search_response.xml
new file mode 100644
index 0000000..1e29c82
--- /dev/null
+++ b/src/test/resources/com/p4square/ccbapi/model/ccb_group_search_response.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ccb_api>
+ <request>
+ <parameters>
+ <argument value="group_search" name="srv"/>
+ </parameters>
+ </request>
+ <response>
+ <service>group_search</service>
+ <service_action>execute</service_action>
+ <availability>public</availability>
+ <items count="1">
+ <item>
+ <item_id type="groups">750</item_id>
+ <id>750</id>
+ <name>Adamant by Lisa Bevere Book Study</name>
+ <group_type_name>Community</group_type_name>
+ <grouping_name>Adults</grouping_name>
+ <area_name ccb_id="18">Puyallup</area_name>
+ <meet_day_name>Tuesday</meet_day_name>
+ <meet_time_name>7:00 pm</meet_time_name>
+ <description>What is the truth?&#13;
+ &#13;
+ This has become the defining question of our time. But while everyone has an opinion, truth, it seems, is getting harder and harder to find. Perhaps that's because we are searching for something when we should be looking for someone. &#13;
+ &#13;
+ Truth has a name.&#13;
+ &#13;
+ More ancient than time and more present than this moment, the truth is not a river that changes with the cultural currents, but a rock--immovable, invincible, unshakeable--and the cornerstone of all we are and ever dream to be.&#13;
+ &#13;
+ 100 79588 0 79588 0 0 39774 0 --:--:-- 0:00:02 -Theologically deep yet intimately accessible. Adamant will be an anchor for your soul in a raging sea of opinions, giving you a clear sense of direction in a wandering world.&#13;
+ Every Other Tuesday Beginning in September 2018</description>
+ <status_id>1</status_id>
+ <messaging_type>Interact</messaging_type>
+ <membership_type>Request</membership_type>
+ <owner_name ccb_id="26102">Jane Doe</owner_name>
+ <owner_email_primary>jane.doe@example.com</owner_email_primary>
+ </item>
+
+ </items>
+ </response>
+</ccb_api> \ No newline at end of file