* The logic for handling the navigation drawer is not immediately obvious to those who do not work with it regularly.
* Proceed with caution.
- *
+ *
*
Navigation
*
* One of the main responsibilities of this activity is managing navigation between the drawer, the fragments and the
* fragments between each other. The navigation is built in two main components: navigation forward and navigating
* backwards. Each component itself is not that difficult. Together the provide an intuitive navigation.
- *
+ *
*
Forward navigation
*
* When the user navigates to a new fragment in this activity, the back stack (of the {@link #getSupportFragmentManager()}
@@ -112,7 +112,7 @@
*
* The third and last scenario is the easiest: nothing should be done when the activity is first started or recreated.
* The fragments should not be added to the back stack.
- *
+ *
*
Backwards navigation
*
* The logic above makes the backwards navigation quite simple, and can be summarized as:
@@ -149,7 +149,7 @@
* After this method call, the fragment can behave as if the arguments were directly set on the fragment itself.
*
* This function will only be called when creating a fragment, not when popping from the back stack.
- *
+ *
*
Common views and removal
*
* The activity provides some common views:
@@ -172,7 +172,7 @@
*
* The reason fragments cannot fully rely on the default lifecycle methods, such as {@link Fragment#onStop()}, is that
* the fragment is not always removed immediately by the activity when it is hidden (this as to do with performance).
- *
+ *
*
Arguments
*
* The activity has one public argument: which child fragment to load. The preferred way of using it is
@@ -683,24 +683,14 @@ public interface OnBackPressed {
private static final class TutorialEndEvent implements Event {
@Nullable
@Override
- public String getEventName() {
+ public String eventName() {
return Reporting.getEvents().tutorialComplete();
}
}
/**
- * Groups an update for the navigation drawer.
- */
- private static class DrawerUpdate {
- @NavigationSource
- final int navigationSource;
- final Fragment fragment;
- final MenuItem menuItem;
-
- private DrawerUpdate(int navigationSource, Fragment fragment, MenuItem menuItem) {
- this.navigationSource = navigationSource;
- this.fragment = fragment;
- this.menuItem = menuItem;
+ * Groups an update for the navigation drawer.
+ */
+ private record DrawerUpdate(@NavigationSource int navigationSource, Fragment fragment, MenuItem menuItem) {
}
- }
}
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/Association.java b/app/src/main/java/be/ugent/zeus/hydra/association/Association.java
index 4e6d5dbf2..43e00aaeb 100644
--- a/app/src/main/java/be/ugent/zeus/hydra/association/Association.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/Association.java
@@ -26,8 +26,8 @@
import android.os.Parcelable;
import androidx.annotation.Nullable;
+import java.util.Collections;
import java.util.List;
-import java.util.Objects;
/**
* Represents an association registered with the DSA.
@@ -35,40 +35,38 @@
* @author feliciaan
* @author Niko Strijbol
*/
-public final class Association implements Parcelable {
-
- private String abbreviation;
- private String name;
- private List path;
- @Nullable
- private String description;
- private String email;
- @Nullable
- private String logo;
- @Nullable
- private String website;
-
- public Association() {
- // Moshi uses this!
- }
-
- /** @noinspection ProtectedMemberInFinalClass*/
- protected Association(Parcel in) {
- abbreviation = in.readString();
- name = in.readString();
- path = in.createStringArrayList();
- description = in.readString();
- email = in.readString();
- logo = in.readString();
- website = in.readString();
+public record Association(
+ String abbreviation,
+ String name,
+ List path,
+ @Nullable String description,
+ @Nullable String email,
+ @Nullable String logo,
+ @Nullable String website
+) implements Parcelable {
+
+ private Association(Parcel in) {
+ this(
+ in.readString(),
+ in.readString(),
+ in.createStringArrayList(),
+ in.readString(),
+ in.readString(),
+ in.readString(),
+ in.readString()
+ );
}
public static Association unknown(String name) {
- Association association = new Association();
- association.abbreviation = "unknown";
- association.name = name;
- association.description = "Onbekende vereniging";
- return association;
+ return new Association(
+ "unknown",
+ name,
+ Collections.emptyList(),
+ "Onbekende vereniging",
+ null,
+ null,
+ null
+ );
}
@Override
@@ -98,43 +96,4 @@ public Association[] newArray(int size) {
return new Association[size];
}
};
-
- @Nullable
- public String getDescription() {
- return description;
- }
-
- @Nullable
- public String getWebsite() {
- return website;
- }
-
- /**
- * @return A name for this association. If a full name is available, that is returned. If not, the display name is.
- */
- public String getName() {
- return name;
- }
-
- public String getAbbreviation() {
- return abbreviation;
- }
-
- @Nullable
- public String getImageLink() {
- return logo;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- Association that = (Association) o;
- return Objects.equals(abbreviation, that.abbreviation);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(abbreviation);
- }
}
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/event/EventPage.java b/app/src/main/java/be/ugent/zeus/hydra/association/AssociationList.java
similarity index 63%
rename from app/src/main/java/be/ugent/zeus/hydra/association/event/EventPage.java
rename to app/src/main/java/be/ugent/zeus/hydra/association/AssociationList.java
index 5d5619a4a..b7088fc75 100644
--- a/app/src/main/java/be/ugent/zeus/hydra/association/event/EventPage.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/AssociationList.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 The Hydra authors
+ * Copyright (c) 2023 Niko Strijbol
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,33 +20,28 @@
* SOFTWARE.
*/
-package be.ugent.zeus.hydra.association.event;
+package be.ugent.zeus.hydra.association;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
/**
- * @author Niko Strijbol
+ * Top-level response object for the DSA API.
+ *
+ * This is basically an object with an association list inside it.
+ * While the list won't be null most of the time, we do not control this API,
+ * so we assume is can be null to have a more robust app.
*/
-public final class EventPage {
-
- /** @noinspection unused*/
- private List entries;
-
- public List getEntries() {
- return entries;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- EventPage eventPage = (EventPage) o;
- return Objects.equals(entries, eventPage.entries);
- }
-
+public record AssociationList(
+ @Nullable List associations
+) {
+ @NonNull
@Override
- public int hashCode() {
- return Objects.hash(entries);
+ public List associations() {
+ return Objects.requireNonNullElse(associations, Collections.emptyList());
}
}
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/common/AssociationMap.java b/app/src/main/java/be/ugent/zeus/hydra/association/AssociationMap.java
similarity index 55%
rename from app/src/main/java/be/ugent/zeus/hydra/association/common/AssociationMap.java
rename to app/src/main/java/be/ugent/zeus/hydra/association/AssociationMap.java
index 4fbd1383c..acaa015bc 100644
--- a/app/src/main/java/be/ugent/zeus/hydra/association/common/AssociationMap.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/AssociationMap.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 The Hydra authors
+ * Copyright (c) 2023 Niko Strijbol
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,24 +20,41 @@
* SOFTWARE.
*/
-package be.ugent.zeus.hydra.association.common;
+package be.ugent.zeus.hydra.association;
import android.util.Pair;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import java.util.List;
+import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import be.ugent.zeus.hydra.association.Association;
-
/**
- * Represents a mapping of association abbreviation to their object.
+ * A class representing a map of associations.
*
- * @author Niko Strijbol
+ *
+ * The AssociationMap class provides methods to access associations based on their abbreviation,
+ * check if an association was requested to be shown, and combine the requested associations with
+ * the association list.
+ *
*/
-public interface AssociationMap {
+public class AssociationMap {
+
+ private final Map associationMap;
+ private final Set associationRequested;
+
+ public AssociationMap() {
+ this(Collections.emptyList(), Collections.emptySet());
+ }
+
+ public AssociationMap(@NonNull List list, @NonNull Set requestedAssociations) {
+ this.associationMap = new HashMap<>();
+ for (var association : list) {
+ associationMap.put(association.abbreviation(), association);
+ }
+ this.associationRequested = requestedAssociations;
+ }
/**
* Get the association linked to the specified mapping.
@@ -49,29 +66,35 @@ public interface AssociationMap {
* @return The association.
*/
@NonNull
- Association get(@Nullable String abbreviation);
+ public Association get(@Nullable String abbreviation) {
+ return associationMap.computeIfAbsent(abbreviation, Association::unknown);
+ }
/**
* @return A stream of all known associations.
*/
- Stream associations();
+ @NonNull
+ public Stream associations() {
+ return associationMap.values().stream();
+ }
/**
- * Check if the associations was requested to be shown by the request that
+ * Check if the association was requested to be shown by the request that
* produced this association map.
- *
+ *
* @param abbreviation The abbreviation.
- *
* @return True if requested to be shown, false otherwise.
*/
- boolean isRequested(@NonNull String abbreviation);
+ public boolean isRequested(@NonNull String abbreviation) {
+ return associationRequested.contains(abbreviation);
+ }
/**
* Combine the {@link #isRequested(String)} data with the association list.
*/
- default List> getSelectedAssociations() {
+ public List> requestedAssociations() {
return this.associations()
- .map(a -> Pair.create(a, this.isRequested(a.getAbbreviation())))
+ .map(a -> Pair.create(a, this.isRequested(a.abbreviation())))
.collect(Collectors.toList());
}
}
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/AssociationRequest.java b/app/src/main/java/be/ugent/zeus/hydra/association/AssociationRequest.java
new file mode 100644
index 000000000..96594a81c
--- /dev/null
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/AssociationRequest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2022 The Hydra authors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package be.ugent.zeus.hydra.association;
+
+import android.content.Context;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.time.Duration;
+import java.time.temporal.ChronoUnit;
+import java.util.List;
+import java.util.Objects;
+
+import androidx.annotation.VisibleForTesting;
+
+import be.ugent.zeus.hydra.common.network.Endpoints;
+import be.ugent.zeus.hydra.common.network.JsonOkHttpRequest;
+import be.ugent.zeus.hydra.common.request.Request;
+
+/**
+ * Builder to create various requests to get associations from the DSA.
+ *
+ * @author Niko Strijbol
+ */
+public class AssociationRequest extends JsonOkHttpRequest {
+
+ private static final String FILENAME = "verenigingen";
+
+ @VisibleForTesting
+ AssociationRequest(@NonNull Context context) {
+ super(context, AssociationList.class);
+ }
+
+ @NonNull
+ @Override
+ protected String apiUrl() {
+ return Endpoints.DSA_V4 + FILENAME;
+ }
+
+ @Override
+ public Duration cacheDuration() {
+ return ChronoUnit.WEEKS.getDuration().multipliedBy(4);
+ }
+
+ public record EventsAndAssociations(
+ AssociationMap associations,
+ List events
+ ) {
+ }
+
+ public record EventItemsAndAssociations(
+ AssociationMap associations,
+ List events
+ ) {
+ }
+
+ /**
+ * Returns a request object that retrieves a list of associations.
+ *
+ * @param context The context.
+ * @return A request object that retrieves a list of associations.
+ */
+ public static Request> associationListRequest(@NonNull Context context) {
+ return new AssociationRequest(context)
+ .map(AssociationList::associations);
+ }
+
+ /**
+ * Creates a filtered event item request.
+ *
+ * This contains all events that satisfy the filter, with an association map.
+ *
+ * @param context The context of the application.
+ * @param filter The event filter to apply.
+ * @return A request object containing a pair of an association map and a list of event items.
+ */
+ public static Request filteredEventItemRequest(@NonNull Context context, @NonNull EventFilter filter) {
+ return filteredEventRequest(context, filter)
+ .map(results -> {
+ var eventItems = EventItem.fromEvents(results.events);
+ return new EventItemsAndAssociations(results.associations, eventItems);
+ });
+ }
+
+ /**
+ * Creates a filtered events request.
+ *
+ * This contains all events that satisfy the filter, with an association map.
+ *
+ * @param context The context of the application.
+ * @param optionalFilter The event filter to apply.
+ * @return A request object containing a pair of an association map and a list of events.
+ */
+ public static Request filteredEventRequest(@NonNull Context context, @Nullable EventFilter optionalFilter) {
+ var filter = Objects.requireNonNullElse(optionalFilter, new EventFilter());
+ return associationListRequest(context)
+ .andThen(associations -> {
+ var eventRequestFilter = filter.toRequestFilter(context, associations);
+ var requestedAssociations = eventRequestFilter.getRequestedAssociations();
+ var associationMap = new AssociationMap(associations, requestedAssociations);
+ return EventRequest.eventRequest(context, eventRequestFilter)
+ .map(events -> new EventsAndAssociations(associationMap, events));
+ });
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/common/AssociationVisibilityStorage.java b/app/src/main/java/be/ugent/zeus/hydra/association/AssociationVisibilityStorage.java
similarity index 92%
rename from app/src/main/java/be/ugent/zeus/hydra/association/common/AssociationVisibilityStorage.java
rename to app/src/main/java/be/ugent/zeus/hydra/association/AssociationVisibilityStorage.java
index e33a91f29..d7afc755b 100644
--- a/app/src/main/java/be/ugent/zeus/hydra/association/common/AssociationVisibilityStorage.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/AssociationVisibilityStorage.java
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
-package be.ugent.zeus.hydra.association.common;
+package be.ugent.zeus.hydra.association;
import android.content.Context;
import android.content.SharedPreferences;
@@ -33,8 +33,6 @@
import java.util.*;
import java.util.stream.Collectors;
-import be.ugent.zeus.hydra.association.Association;
-
/**
* Class that manages storing which associations the user wants to see
* and which they don't.
@@ -73,13 +71,13 @@ public static Set calculateWhitelist(Context context, List
// Start with all associations.
Set whitelist = new HashSet<>();
for (Association association : associations) {
- whitelist.add(association.getAbbreviation());
+ whitelist.add(association.abbreviation());
}
// Get the existing blacklist, either from storage or from the selected one.
Set blacklist;
if (newWhitelist == null) {
- blacklist = getBlacklist(context);
+ blacklist = blacklist(context);
// Remove any obsolete associations.
Set obsolete = new HashSet<>();
@@ -94,7 +92,7 @@ public static Set calculateWhitelist(Context context, List
} else {
blacklist = newWhitelist.stream()
.filter(p -> !p.second)
- .map(p -> p.first.getAbbreviation())
+ .map(p -> p.first.abbreviation())
.collect(Collectors.toCollection(HashSet::new));
}
@@ -110,7 +108,7 @@ public static Set calculateWhitelist(Context context, List
* Get the saved blacklist.
*/
@NonNull
- public static Set getBlacklist(@NonNull Context context) {
+ public static Set blacklist(@NonNull Context context) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
return new HashSet<>(preferences.getStringSet(PREF_BLACKLIST, new HashSet<>()));
}
@@ -123,7 +121,7 @@ public static Set getBlacklist(@NonNull Context context) {
* @param abbreviation The abbreviation of the association you want to whitelist.
*/
public static void blacklist(@NonNull Context context, @NonNull String abbreviation) {
- Set existing = getBlacklist(context);
+ Set existing = blacklist(context);
existing.add(abbreviation);
saveBlacklist(context, existing);
}
@@ -136,7 +134,7 @@ public static void blacklist(@NonNull Context context, @NonNull String abbreviat
* @param abbreviation The abbreviation of the association you want to whitelist.
*/
public static void whitelist(@NonNull Context context, @NonNull String abbreviation) {
- Set existing = getBlacklist(context);
+ Set existing = blacklist(context);
existing.remove(abbreviation);
saveBlacklist(context, existing);
}
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/event/Event.java b/app/src/main/java/be/ugent/zeus/hydra/association/Event.java
similarity index 59%
rename from app/src/main/java/be/ugent/zeus/hydra/association/event/Event.java
rename to app/src/main/java/be/ugent/zeus/hydra/association/Event.java
index 113a228f7..d8f4709b0 100644
--- a/app/src/main/java/be/ugent/zeus/hydra/association/event/Event.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/Event.java
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
-package be.ugent.zeus.hydra.association.event;
+package be.ugent.zeus.hydra.association;
import android.os.Parcel;
import android.os.Parcelable;
@@ -28,12 +28,11 @@
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
-import java.util.Objects;
-import be.ugent.zeus.hydra.association.Association;
import be.ugent.zeus.hydra.common.converter.DateTypeConverters;
import be.ugent.zeus.hydra.common.utils.DateUtils;
import com.squareup.moshi.Json;
+import io.soabase.recordbuilder.core.RecordBuilder;
/**
* Event from an {@link Association}.
@@ -41,51 +40,47 @@
* @author Niko Strijbol
* @author feliciaan
*/
-public final class Event implements Parcelable, Comparable {
-
- private long id;
- private String title;
- @Json(name = "start_time")
- private OffsetDateTime start;
- @Json(name = "end_time")
- private OffsetDateTime end;
- private String location;
- private String address;
- private String description;
- @Json(name = "infolink")
- private String url;
- private String association;
- private boolean advertise;
-
- public Event() {
- // Moshi uses this!
- }
-
- protected Event(Parcel in) {
- id = in.readLong();
- title = in.readString();
- location = in.readString();
- address = in.readString();
- description = in.readString();
- url = in.readString();
- association = in.readString();
- advertise = in.readInt() == 1;
- start = end = DateTypeConverters.toOffsetDateTime(in.readString());
- end = DateTypeConverters.toOffsetDateTime(in.readString());
+@RecordBuilder
+public record Event(
+ long id,
+ String title,
+ @Json(name = "start_time") OffsetDateTime start,
+ @Nullable @Json(name = "end_time") OffsetDateTime end,
+ @Nullable String location,
+ @Nullable String address,
+ @Nullable String description,
+ @Nullable @Json(name = "infolink") String url,
+ String association,
+ boolean advertise
+) implements Parcelable, Comparable, EventBuilder.With {
+
+ private Event(Parcel in) {
+ this(
+ in.readLong(),
+ in.readString(),
+ DateTypeConverters.toOffsetDateTime(in.readString()),
+ DateTypeConverters.toOffsetDateTime(in.readString()),
+ in.readString(),
+ in.readString(),
+ in.readString(),
+ in.readString(),
+ in.readString(),
+ in.readInt() == 1
+ );
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
dest.writeString(title);
+ dest.writeString(DateTypeConverters.fromOffsetDateTime(start));
+ dest.writeString(DateTypeConverters.fromOffsetDateTime(end));
dest.writeString(location);
dest.writeString(address);
dest.writeString(description);
dest.writeString(url);
dest.writeString(association);
dest.writeInt(advertise ? 1 : 0);
- dest.writeString(DateTypeConverters.fromOffsetDateTime(start));
- dest.writeString(DateTypeConverters.fromOffsetDateTime(end));
}
@Override
@@ -93,7 +88,7 @@ public int describeContents() {
return 0;
}
- public static final Creator CREATOR = new Creator() {
+ public static final Creator CREATOR = new Creator<>() {
@Override
public Event createFromParcel(Parcel in) {
return new Event(in);
@@ -113,8 +108,8 @@ public Event[] newArray(int size) {
*
* @return The converted start date.
*/
- public LocalDateTime getLocalStart() {
- return DateUtils.toLocalDateTime(getStart());
+ public LocalDateTime localStart() {
+ return DateUtils.toLocalDateTime(start());
}
/**
@@ -126,56 +121,23 @@ public LocalDateTime getLocalStart() {
* @return The converted end date.
*/
@Nullable
- public LocalDateTime getLocalEnd() {
- if (getEnd() == null) {
+ public LocalDateTime localEnd() {
+ if (end == null) {
return null;
}
- return DateUtils.toLocalDateTime(getEnd());
- }
-
- public String getTitle() {
- return title;
- }
-
- public OffsetDateTime getStart() {
- return start;
- }
-
- @Nullable
- public OffsetDateTime getEnd() {
- return end;
- }
-
- public String getLocation() {
- return location;
- }
-
- public String getAddress() {
- return address;
+ return DateUtils.toLocalDateTime(end);
}
public boolean hasPreciseLocation() {
- return getAddress() != null;
+ return address != null;
}
public boolean hasLocation() {
- return getLocation() != null && !getLocation().trim().isEmpty();
- }
-
- public String getDescription() {
- return description;
- }
-
- public String getUrl() {
- return url;
+ return location != null && !location.trim().isEmpty();
}
public boolean hasUrl() {
- return getUrl() != null && !getUrl().trim().isEmpty();
- }
-
- public String getAssociation() {
- return association;
+ return url != null && !url.trim().isEmpty();
}
/**
@@ -187,8 +149,12 @@ public String getAssociation() {
*
* @return The identifier.
*/
- public String getIdentifier() {
- return title + start.toString() + end.toString() + location + url + association;
+ public String identifier() {
+ String end = "";
+ if (this.end != null) {
+ end = this.end.toString();
+ }
+ return title + start.toString() + end + location + url + association;
}
/**
@@ -198,17 +164,4 @@ public String getIdentifier() {
public int compareTo(Event o) {
return start.compareTo(o.start);
}
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- Event event = (Event) o;
- return id == event.id;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(id);
- }
}
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/event/EventDetailsActivity.java b/app/src/main/java/be/ugent/zeus/hydra/association/EventDetailsActivity.java
similarity index 79%
rename from app/src/main/java/be/ugent/zeus/hydra/association/event/EventDetailsActivity.java
rename to app/src/main/java/be/ugent/zeus/hydra/association/EventDetailsActivity.java
index 8e967b68b..d4de8be26 100644
--- a/app/src/main/java/be/ugent/zeus/hydra/association/event/EventDetailsActivity.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/EventDetailsActivity.java
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
-package be.ugent.zeus.hydra.association.event;
+package be.ugent.zeus.hydra.association;
import android.content.Context;
import android.content.Intent;
@@ -43,7 +43,6 @@
import java.time.format.DateTimeFormatter;
import be.ugent.zeus.hydra.R;
-import be.ugent.zeus.hydra.association.Association;
import be.ugent.zeus.hydra.common.reporting.BaseEvents;
import be.ugent.zeus.hydra.common.reporting.Reporting;
import be.ugent.zeus.hydra.common.ui.BaseActivity;
@@ -86,39 +85,39 @@ protected void onCreate(Bundle savedInstanceState) {
assert event != null;
assert association != null;
- if (event.getTitle() != null) {
- requireToolbar().setTitle(event.getTitle());
+ if (event.title() != null) {
+ requireToolbar().setTitle(event.title());
}
- if (event.getAssociation() != null) {
- binding.eventOrganisatorMain.setText(association.getName());
+ if (event.association() != null) {
+ binding.eventOrganisatorMain.setText(association.name());
}
- if (event.getDescription() != null && !event.getDescription().trim().isEmpty()) {
- binding.description.setText(event.getDescription());
+ if (event.description() != null && !event.description().trim().isEmpty()) {
+ binding.description.setText(event.description());
LinkifyCompat.addLinks(binding.description, Linkify.EMAIL_ADDRESSES | Linkify.WEB_URLS);
} else {
hasDescription = false;
binding.eventDescriptionBlock.setVisibility(View.GONE);
}
- if (association.getDescription() != null && !association.getDescription().trim().isEmpty()) {
- binding.eventOrganisatorSmall.setText(association.getDescription());
+ if (association.description() != null && !association.description().trim().isEmpty()) {
+ binding.eventOrganisatorSmall.setText(association.description());
// If there is no event description, allow the association description to be longer.
if (!hasDescription) {
binding.eventOrganisatorSmall.setMaxLines(Integer.MAX_VALUE);
}
}
- if (association.getWebsite() != null) {
- binding.eventOrganizer.setOnClickListener(v -> NetworkUtils.maybeLaunchBrowser(v.getContext(), association.getWebsite()));
+ if (association.website() != null) {
+ binding.eventOrganizer.setOnClickListener(v -> NetworkUtils.maybeLaunchBrowser(v.getContext(), association.website()));
}
if (event.hasPreciseLocation() || event.hasLocation()) {
if (event.hasLocation()) {
- binding.location.setText(event.getLocation());
+ binding.location.setText(event.location());
} else {
- binding.location.setText(event.getAddress());
+ binding.location.setText(event.address());
}
// Make location clickable
binding.locationRow.setOnClickListener(view -> NetworkUtils.maybeLaunchIntent(this, getLocationIntent()));
@@ -126,16 +125,17 @@ protected void onCreate(Bundle savedInstanceState) {
binding.location.setText(R.string.event_detail_no_location);
}
- binding.timeStart.setText(event.getLocalStart().format(format));
+ binding.timeStart.setText(event.localStart().format(format));
- if (event.getLocalEnd() != null) {
- binding.timeEnd.setText(event.getLocalEnd().format(format));
+ var localEnd = event.localEnd();
+ if (localEnd != null) {
+ binding.timeEnd.setText(localEnd.format(format));
} else {
binding.timeEnd.setText(R.string.event_detail_date_unknown);
}
- if (event.getAssociation() != null) {
- Picasso.get().load(association.getImageLink()).into(binding.eventOrganisatorImage, new EventCallback(binding.eventOrganisatorImage));
+ if (event.association() != null) {
+ Picasso.get().load(association.logo()).into(binding.eventOrganisatorImage, new EventCallback(binding.eventOrganisatorImage));
} else {
binding.eventOrganisatorImage.setLayoutParams(new LinearLayout.LayoutParams(0, 0));
}
@@ -152,8 +152,8 @@ public boolean onOptionsItemSelected(@NonNull MenuItem item) {
supportFinishAfterTransition();
return true;
} else if (itemId == R.id.event_link) {
- NetworkUtils.maybeLaunchBrowser(this, event.getUrl());
- return true;
+ NetworkUtils.maybeLaunchBrowser(this, event.url());
+ return true;
} else if (itemId == R.id.menu_event_add_to_calendar) {
addToCalendar();
@@ -180,14 +180,14 @@ public boolean onCreateOptionsMenu(Menu menu) {
private void addToCalendar() {
Intent intent = new Intent(Intent.ACTION_INSERT)
.setData(CalendarContract.Events.CONTENT_URI)
- .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, event.getStart().toInstant().toEpochMilli())
- .putExtra(CalendarContract.Events.TITLE, event.getTitle())
- .putExtra(CalendarContract.Events.EVENT_LOCATION, event.getLocation())
- .putExtra(CalendarContract.Events.DESCRIPTION, event.getDescription())
+ .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, event.start().toInstant().toEpochMilli())
+ .putExtra(CalendarContract.Events.TITLE, event.title())
+ .putExtra(CalendarContract.Events.EVENT_LOCATION, event.location())
+ .putExtra(CalendarContract.Events.DESCRIPTION, event.description())
.putExtra(CalendarContract.Events.AVAILABILITY, CalendarContract.Events.AVAILABILITY_TENTATIVE);
- if (event.getEnd() != null) {
- intent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, event.getEnd().toInstant().toEpochMilli());
+ if (event.end() != null) {
+ intent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, event.end().toInstant().toEpochMilli());
}
NetworkUtils.maybeLaunchIntent(this, intent);
@@ -218,9 +218,9 @@ private Intent getLocationIntent() {
//If there is a precise location, use that.
if (event.hasPreciseLocation()) {
- uriLocation = Uri.parse("geo:" + GENT + "?q=" + event.getAddress());
+ uriLocation = Uri.parse("geo:" + GENT + "?q=" + event.address());
} else {
- uriLocation = Uri.parse("geo:" + GENT + "?q=" + event.getLocation());
+ uriLocation = Uri.parse("geo:" + GENT + "?q=" + event.location());
}
Intent intent = new Intent(Intent.ACTION_VIEW, uriLocation);
@@ -244,27 +244,21 @@ public void onError(Exception e) {
}
}
- private static final class EventViewedEvent implements be.ugent.zeus.hydra.common.reporting.Event {
-
- private final Event event;
-
- private EventViewedEvent(Event event) {
- this.event = event;
- }
+ private record EventViewedEvent(Event event) implements be.ugent.zeus.hydra.common.reporting.Event {
@Override
- public Bundle getParams() {
+ public Bundle params() {
BaseEvents.Params names = Reporting.getEvents().params();
Bundle params = new Bundle();
params.putString(names.itemCategory(), Event.class.getSimpleName());
- params.putString(names.itemId(), event.getIdentifier());
- params.putString(names.itemName(), event.getTitle());
+ params.putString(names.itemId(), event.identifier());
+ params.putString(names.itemName(), event.title());
return params;
}
@Nullable
@Override
- public String getEventName() {
+ public String eventName() {
return Reporting.getEvents().viewItem();
}
}
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/common/EventFilter.java b/app/src/main/java/be/ugent/zeus/hydra/association/EventFilter.java
similarity index 85%
rename from app/src/main/java/be/ugent/zeus/hydra/association/common/EventFilter.java
rename to app/src/main/java/be/ugent/zeus/hydra/association/EventFilter.java
index 9da4b129a..74a41c4a3 100644
--- a/app/src/main/java/be/ugent/zeus/hydra/association/common/EventFilter.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/EventFilter.java
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
-package be.ugent.zeus.hydra.association.common;
+package be.ugent.zeus.hydra.association;
import android.content.Context;
import android.util.Pair;
@@ -33,8 +33,6 @@
import java.util.Set;
import java.util.function.Function;
-import be.ugent.zeus.hydra.association.Association;
-
/**
* Search filter for event requests.
*
@@ -49,15 +47,15 @@ public class EventFilter {
public EventFilter() {
}
- public OffsetDateTime getAfter() {
+ public OffsetDateTime after() {
return after;
}
- public OffsetDateTime getBefore() {
+ public OffsetDateTime before() {
return before;
}
- public String getTerm() {
+ public String term() {
return term;
}
@@ -83,22 +81,22 @@ public Live() {
this.filter = getValue();
}
- public void setAfter(OffsetDateTime after) {
+ public void after(OffsetDateTime after) {
this.filter.after = after;
setValue(filter);
}
- public void setBefore(OffsetDateTime before) {
+ public void before(OffsetDateTime before) {
this.filter.before = before;
setValue(filter);
}
- public void setSelectedAssociations(List> selectedAssociations) {
+ public void selectedAssociations(List> selectedAssociations) {
this.filter.selectedAssociations = selectedAssociations;
setValue(filter);
}
- public void setTerm(String term) {
+ public void term(String term) {
this.filter.term = term;
setValue(filter);
}
@@ -107,6 +105,6 @@ public void setTerm(String term) {
public static Comparator> selectionComparator() {
return Comparator.comparing((Function, Boolean>) p -> p.second)
.reversed()
- .thenComparing(p -> p.first.getAbbreviation());
+ .thenComparing(p -> p.first.abbreviation());
}
}
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/common/EventItem.java b/app/src/main/java/be/ugent/zeus/hydra/association/EventItem.java
similarity index 50%
rename from app/src/main/java/be/ugent/zeus/hydra/association/common/EventItem.java
rename to app/src/main/java/be/ugent/zeus/hydra/association/EventItem.java
index d77fec757..e73a5788f 100644
--- a/app/src/main/java/be/ugent/zeus/hydra/association/common/EventItem.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/EventItem.java
@@ -20,40 +20,42 @@
* SOFTWARE.
*/
-package be.ugent.zeus.hydra.association.common;
+package be.ugent.zeus.hydra.association;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.ZoneId;
-import java.util.Objects;
-
-import be.ugent.zeus.hydra.association.event.Event;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
/**
- * Data structure for a list of events. The contains an item, a header or a footer, but only one of the elements.
+ * Data structure for a list of events.
+ * The event contains an item, a header or a footer, but only one of the elements.
* If it is an item, it contains some additional metadata.
*
* @author Niko Strijbol
*/
-public final class EventItem implements Comparable {
-
- private final Event event;
- private final LocalDate header;
-
- private boolean isLastOfSection;
-
- private EventItem(Event event, LocalDate header) {
- this.event = event;
- this.header = header;
+public record EventItem(
+ @Nullable Event event,
+ @Nullable LocalDate header,
+ boolean isLastOfSection
+) implements Comparable {
+
+ public static EventItem create(Event event) {
+ return new EventItem(event, null, false);
}
- public EventItem(Event event, boolean isLastOfSection) {
- this(event, null);
- this.isLastOfSection = isLastOfSection;
+ public static EventItem create(LocalDate header) {
+ return new EventItem(null, header, false);
}
- public EventItem(LocalDate header) {
- this(null, header);
+ public static EventItem create(Event event, boolean isLastOfSection) {
+ return new EventItem(event, null, isLastOfSection);
}
public boolean isHeader() {
@@ -64,6 +66,7 @@ public boolean isItem() {
return event != null;
}
+ @Override
public boolean isLastOfSection() {
if (!isItem()) {
throw new IllegalStateException("Can only be used if the EventItem contains an item.");
@@ -71,45 +74,57 @@ public boolean isLastOfSection() {
return isLastOfSection;
}
- public Event getItem() {
+ @Override
+ public Event event() {
if (!isItem()) {
throw new IllegalStateException("Can only be used if the EventItem contains an item.");
}
return event;
}
- public LocalDate getHeader() {
+ @Override
+ public LocalDate header() {
if (!isHeader()) {
throw new IllegalStateException("Can only be used if the EventItem contains a header.");
}
return header;
}
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- EventItem eventItem = (EventItem) o;
- return isLastOfSection == eventItem.isLastOfSection &&
- Objects.equals(event, eventItem.event) &&
- Objects.equals(header, eventItem.header);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(event, header, isLastOfSection);
- }
-
- public OffsetDateTime getDate() {
+ public OffsetDateTime date() {
if (isItem()) {
- return getItem().getStart();
+ return event().start();
} else {
- return getHeader().atStartOfDay(ZoneId.systemDefault()).toOffsetDateTime();
+ return header().atStartOfDay(ZoneId.systemDefault()).toOffsetDateTime();
}
}
@Override
public int compareTo(EventItem o) {
- return getDate().compareTo(o.getDate());
+ return date().compareTo(o.date());
+ }
+
+ @NonNull
+ public static List fromEvents(@NonNull List events) {
+ if (events.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ return events.stream()
+ .collect(Collectors.groupingBy(event -> event.start().toLocalDate()))
+ .entrySet()
+ .stream()
+ .flatMap(entry -> {
+ List list = entry.getValue();
+ EventItem header = EventItem.create(entry.getKey());
+ Stream events1 = list.subList(0, list.size() - 1).stream().map(EventItem::create);
+ EventItem last = EventItem.create(list.get(list.size() - 1), true);
+
+ return Stream.concat(
+ Stream.of(header),
+ Stream.concat(events1, Stream.of(last))
+ );
+ })
+ .sorted()
+ .collect(Collectors.toList());
}
}
diff --git a/app/src/test/java/be/ugent/zeus/hydra/resto/RestoMenuTest.java b/app/src/main/java/be/ugent/zeus/hydra/association/EventList.java
similarity index 84%
rename from app/src/test/java/be/ugent/zeus/hydra/resto/RestoMenuTest.java
rename to app/src/main/java/be/ugent/zeus/hydra/association/EventList.java
index dabb160fe..c3016dc85 100644
--- a/app/src/test/java/be/ugent/zeus/hydra/resto/RestoMenuTest.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/EventList.java
@@ -20,15 +20,10 @@
* SOFTWARE.
*/
-package be.ugent.zeus.hydra.resto;
-
-import be.ugent.zeus.hydra.common.ModelTest;
+package be.ugent.zeus.hydra.association;
/**
* @author Niko Strijbol
*/
-public class RestoMenuTest extends ModelTest {
- public RestoMenuTest() {
- super(RestoMenu.class);
- }
-}
\ No newline at end of file
+public record EventList(EventPage page) {
+}
diff --git a/app/src/test/java/be/ugent/zeus/hydra/resto/RestoMealTest.java b/app/src/main/java/be/ugent/zeus/hydra/association/EventPage.java
similarity index 84%
rename from app/src/test/java/be/ugent/zeus/hydra/resto/RestoMealTest.java
rename to app/src/main/java/be/ugent/zeus/hydra/association/EventPage.java
index 83045e441..2d035fc01 100644
--- a/app/src/test/java/be/ugent/zeus/hydra/resto/RestoMealTest.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/EventPage.java
@@ -20,15 +20,12 @@
* SOFTWARE.
*/
-package be.ugent.zeus.hydra.resto;
+package be.ugent.zeus.hydra.association;
-import be.ugent.zeus.hydra.common.ModelTest;
+import java.util.List;
/**
* @author Niko Strijbol
*/
-public class RestoMealTest extends ModelTest {
- public RestoMealTest() {
- super(RestoMeal.class);
- }
-}
\ No newline at end of file
+public record EventPage(List entries) {
+}
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/common/EventRequest.java b/app/src/main/java/be/ugent/zeus/hydra/association/EventRequest.java
similarity index 84%
rename from app/src/main/java/be/ugent/zeus/hydra/association/common/EventRequest.java
rename to app/src/main/java/be/ugent/zeus/hydra/association/EventRequest.java
index 3ecc7fb09..09b0db12c 100644
--- a/app/src/main/java/be/ugent/zeus/hydra/association/common/EventRequest.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/EventRequest.java
@@ -20,7 +20,7 @@
* SOFTWARE.
*/
-package be.ugent.zeus.hydra.association.common;
+package be.ugent.zeus.hydra.association;
import android.content.Context;
import android.net.Uri;
@@ -33,8 +33,6 @@
import java.util.List;
import java.util.Set;
-import be.ugent.zeus.hydra.association.event.Event;
-import be.ugent.zeus.hydra.association.event.EventList;
import be.ugent.zeus.hydra.common.network.Endpoints;
import be.ugent.zeus.hydra.common.network.JsonOkHttpRequest;
import be.ugent.zeus.hydra.common.request.Request;
@@ -85,25 +83,19 @@ public Set getRequestedAssociations() {
private final Filter filter;
- public EventRequest(Context context, Filter filter) {
+ private EventRequest(Context context, Filter filter) {
super(context, EventList.class);
this.filter = filter;
}
- public static Request> createItemRequest(Context context, Filter filter) {
+ public static Request> eventRequest(Context context, Filter filter) {
return new EventRequest(context, filter)
- .map(e -> e.getPage().getEntries())
- .map(new EventListConverter());
- }
-
- public static Request> createRequest(Context context, Filter filter) {
- return new EventRequest(context, filter)
- .map(e -> e.getPage().getEntries());
+ .map(e -> e.page().entries());
}
@NonNull
@Override
- protected String getAPIUrl() {
+ protected String apiUrl() {
Uri.Builder uri = Uri.parse(Endpoints.DSA_V4 + FILENAME).buildUpon();
for (String association : filter.requestedAssociations) {
@@ -125,12 +117,12 @@ protected String getAPIUrl() {
}
String t = uri.appendQueryParameter("page_size", "50").build().toString();
- Log.d("TAG", "getAPIUrl: " + t);
+ Log.d("TAG", "apiUrl: " + t);
return t;
}
@Override
- public Duration getCacheDuration() {
+ public Duration cacheDuration() {
return Duration.ofHours(1);
}
}
\ No newline at end of file
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/common/AssociationRequestBuilder.java b/app/src/main/java/be/ugent/zeus/hydra/association/common/AssociationRequestBuilder.java
deleted file mode 100644
index 387b84959..000000000
--- a/app/src/main/java/be/ugent/zeus/hydra/association/common/AssociationRequestBuilder.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (c) 2022 The Hydra authors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package be.ugent.zeus.hydra.association.common;
-
-import android.content.Context;
-import android.util.Pair;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
-
-import java.time.Duration;
-import java.time.temporal.ChronoUnit;
-import java.util.*;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import be.ugent.zeus.hydra.association.Association;
-import be.ugent.zeus.hydra.association.event.Event;
-import be.ugent.zeus.hydra.common.network.Endpoints;
-import be.ugent.zeus.hydra.common.network.JsonOkHttpRequest;
-import be.ugent.zeus.hydra.common.request.Request;
-import com.squareup.moshi.Json;
-
-/**
- * Builder to create various requests to get associations from the DSA.
- *
- * @author Niko Strijbol
- */
-public class AssociationRequestBuilder {
-
- /**
- * Raw representation of how the data comes to use from the API.
- */
- @VisibleForTesting
- static class AssociationList {
- @Json(name = "associations")
- private List associations;
-
- public AssociationList() {
- }
-
- @NonNull
- public List getAssociations() {
- if (associations == null) {
- return Collections.emptyList();
- } else {
- return associations;
- }
- }
- }
-
- private static class Mapper implements AssociationMap {
-
- private final Map associationMap;
- private final Set associationRequested;
-
- private Mapper(@NonNull AssociationRequestBuilder.AssociationList list, @NonNull Set requestedAssociations) {
- this.associationMap = list.getAssociations()
- .stream()
- .collect(Collectors.toMap(Association::getAbbreviation, Function.identity()));
- this.associationRequested = requestedAssociations;
- }
-
- @NonNull
- @Override
- public Association get(@Nullable String abbreviation) {
- return associationMap.computeIfAbsent(abbreviation, Association::unknown);
- }
-
- @Override
- public Stream associations() {
- return associationMap.values().stream();
- }
-
- @Override
- public boolean isRequested(@NonNull String abbreviation) {
- return associationRequested.contains(abbreviation);
- }
- }
-
- @VisibleForTesting
- static class RawRequest extends JsonOkHttpRequest {
- private static final String FILENAME = "verenigingen";
-
- RawRequest(@NonNull Context context) {
- super(context, AssociationList.class);
- }
-
- @NonNull
- @Override
- protected String getAPIUrl() {
- return Endpoints.DSA_V4 + FILENAME;
- }
-
- @Override
- public Duration getCacheDuration() {
- return ChronoUnit.WEEKS.getDuration().multipliedBy(4);
- }
- }
-
- @NonNull
- public static Request> createListRequest(@NonNull Context context) {
- return new RawRequest(context)
- .map(AssociationList::getAssociations);
- }
-
- public static Request>> createItemFilteredEventRequest(@NonNull Context context, EventFilter filter) {
- return new RawRequest(context)
- .andThen((Function, Set>>>) data -> {
- EventRequest.Filter newFilter = filter.toRequestFilter(context, data.getAssociations());
- Set requestedAssociations = newFilter.getRequestedAssociations();
- return EventRequest.createItemRequest(context, newFilter).map(e -> Pair.create(e, requestedAssociations));
- })
- .map(pair -> {
- AssociationMap map = new Mapper(pair.first, pair.second.second);
- return Pair.create(map, pair.second.first);
- });
- }
-
- public static Request>> createFilteredEventRequest(@NonNull Context context) {
- return new RawRequest(context)
- .andThen((Function, Set>>>) data -> {
- EventFilter eventFilter = new EventFilter();
- EventRequest.Filter newFilter = eventFilter.toRequestFilter(context, data.getAssociations());
- Set requestedAssociations = newFilter.getRequestedAssociations();
- return EventRequest.createRequest(context, newFilter).map(e -> Pair.create(e, requestedAssociations));
- })
- .map(pair -> {
- AssociationMap map = new Mapper(pair.first, pair.second.second);
- return Pair.create(map, pair.second.first);
- });
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/common/EventListConverter.java b/app/src/main/java/be/ugent/zeus/hydra/association/common/EventListConverter.java
deleted file mode 100644
index 162cd8aff..000000000
--- a/app/src/main/java/be/ugent/zeus/hydra/association/common/EventListConverter.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2021 The Hydra authors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package be.ugent.zeus.hydra.association.common;
-
-import java.time.LocalDate;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import be.ugent.zeus.hydra.association.event.Event;
-
-/**
- * Convert events to EventItems. The list of events MUST be sorted by start date.
- */
-class EventListConverter implements Function, List> {
-
- @Override
- public List apply(List events) {
-
- if (events.isEmpty()) {
- return Collections.emptyList();
- }
-
- return events.stream()
- .collect(Collectors.groupingBy(event -> event.getStart().toLocalDate()))
- .entrySet()
- .stream()
- .flatMap(this::convert)
- .sorted()
- .collect(Collectors.toList());
- }
-
- private Stream convert(Map.Entry> entry) {
- List list = entry.getValue();
- EventItem header = new EventItem(entry.getKey());
- Stream events = list.subList(0, list.size() - 1).stream().map(event -> new EventItem(event, false));
- EventItem last = new EventItem(list.get(list.size() - 1), true);
-
- return Stream.concat(
- Stream.of(header),
- Stream.concat(events, Stream.of(last))
- );
- }
-}
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/event/EventSorter.java b/app/src/main/java/be/ugent/zeus/hydra/association/event/EventSorter.java
deleted file mode 100644
index df9c02361..000000000
--- a/app/src/main/java/be/ugent/zeus/hydra/association/event/EventSorter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2021 The Hydra authors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package be.ugent.zeus.hydra.association.event;
-
-import java.util.List;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-/**
- * Sorts the events according to their natural ordening.
- *
- * @author Niko Strijbol
- */
-class EventSorter implements Function, List> {
- @Override
- public List apply(List events) {
- return events.stream()
- .sorted()
- .collect(Collectors.toList());
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/list/AssociationsAdapter.java b/app/src/main/java/be/ugent/zeus/hydra/association/list/AssociationAdapter.java
similarity index 96%
rename from app/src/main/java/be/ugent/zeus/hydra/association/list/AssociationsAdapter.java
rename to app/src/main/java/be/ugent/zeus/hydra/association/list/AssociationAdapter.java
index acc3a6b41..3da10d0c4 100644
--- a/app/src/main/java/be/ugent/zeus/hydra/association/list/AssociationsAdapter.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/list/AssociationAdapter.java
@@ -33,7 +33,7 @@
/**
* @author Niko Strijbol
*/
-class AssociationsAdapter extends MultiSelectAdapter {
+class AssociationAdapter extends MultiSelectAdapter {
@NonNull
@Override
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/list/AssociationViewHolder.java b/app/src/main/java/be/ugent/zeus/hydra/association/list/AssociationViewHolder.java
index 5e81b168a..350a30454 100644
--- a/app/src/main/java/be/ugent/zeus/hydra/association/list/AssociationViewHolder.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/list/AssociationViewHolder.java
@@ -58,7 +58,7 @@ class AssociationViewHolder extends DataViewHolder {
@Override
public void populate(Association data) {
- title.setText(data.getName());
+ title.setText(data.name());
checkBox.setChecked(adapter.isChecked(getBindingAdapterPosition()));
parent.setOnClickListener(v -> {
adapter.setChecked(getBindingAdapterPosition());
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/list/DateHeaderViewHolder.java b/app/src/main/java/be/ugent/zeus/hydra/association/list/DateHeaderViewHolder.java
index 21d62fd7f..f7032ffee 100644
--- a/app/src/main/java/be/ugent/zeus/hydra/association/list/DateHeaderViewHolder.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/list/DateHeaderViewHolder.java
@@ -30,7 +30,7 @@
import java.time.LocalDate;
import be.ugent.zeus.hydra.R;
-import be.ugent.zeus.hydra.association.common.EventItem;
+import be.ugent.zeus.hydra.association.EventItem;
import be.ugent.zeus.hydra.common.ui.recyclerview.viewholders.DataViewHolder;
@@ -55,6 +55,6 @@ static String formatDate(Context context, LocalDate localDate) {
@Override
public void populate(EventItem eventItem) {
- headerText.setText(formatDate(headerText.getContext(), eventItem.getHeader()));
+ headerText.setText(formatDate(headerText.getContext(), eventItem.header()));
}
}
\ No newline at end of file
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/list/EventAdapter.java b/app/src/main/java/be/ugent/zeus/hydra/association/list/EventAdapter.java
index aebc2bafc..6c1871b1e 100644
--- a/app/src/main/java/be/ugent/zeus/hydra/association/list/EventAdapter.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/list/EventAdapter.java
@@ -28,8 +28,8 @@
import java.util.Objects;
import be.ugent.zeus.hydra.R;
-import be.ugent.zeus.hydra.association.common.AssociationMap;
-import be.ugent.zeus.hydra.association.common.EventItem;
+import be.ugent.zeus.hydra.association.AssociationMap;
+import be.ugent.zeus.hydra.association.EventItem;
import be.ugent.zeus.hydra.common.ui.recyclerview.adapters.DiffAdapter;
import be.ugent.zeus.hydra.common.ui.recyclerview.viewholders.DataViewHolder;
import be.ugent.zeus.hydra.common.utils.ViewUtils;
@@ -63,7 +63,7 @@ public DataViewHolder onCreateViewHolder(@NonNull ViewGroup parent, i
@Override
public int getItemViewType(int position) {
- if (getItem(position).isHeader()) {
+ if (item(position).isHeader()) {
return HEADER_TYPE;
} else {
return super.getItemViewType(position);
diff --git a/app/src/main/java/be/ugent/zeus/hydra/association/list/EventFragment.java b/app/src/main/java/be/ugent/zeus/hydra/association/list/EventFragment.java
index 590beeb0f..2604a004f 100644
--- a/app/src/main/java/be/ugent/zeus/hydra/association/list/EventFragment.java
+++ b/app/src/main/java/be/ugent/zeus/hydra/association/list/EventFragment.java
@@ -24,7 +24,6 @@
import android.os.Bundle;
import android.util.Log;
-import android.util.Pair;
import android.view.*;
import android.widget.Button;
import android.widget.FrameLayout;
@@ -43,14 +42,12 @@
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
-import java.util.List;
import java.util.Objects;
import be.ugent.zeus.hydra.MainActivity;
import be.ugent.zeus.hydra.R;
-import be.ugent.zeus.hydra.association.common.AssociationMap;
-import be.ugent.zeus.hydra.association.common.EventFilter;
-import be.ugent.zeus.hydra.association.common.EventItem;
+import be.ugent.zeus.hydra.association.AssociationRequest;
+import be.ugent.zeus.hydra.association.EventFilter;
import be.ugent.zeus.hydra.common.arch.observers.PartialErrorObserver;
import be.ugent.zeus.hydra.common.arch.observers.ProgressObserver;
import be.ugent.zeus.hydra.common.arch.observers.SuccessObserver;
@@ -77,7 +74,7 @@ public class EventFragment extends Fragment implements MainActivity.ScheduledRem
private final EventAdapter adapter = new EventAdapter();
private final EventFilter.Live filter = new EventFilter.Live();
- private final AssociationsAdapter associationAdapter = new AssociationsAdapter();
+ private final AssociationAdapter associationAdapter = new AssociationAdapter();
private EventViewModel viewModel;
private FrameLayout bottomSheet;
private BottomSheetBehavior behavior;
@@ -140,7 +137,7 @@ public boolean onMenuItemSelected(@NonNull @NotNull MenuItem menuItem) {
.build();
picker.addOnPositiveButtonClickListener(selection -> {
OffsetDateTime offsetDateTime = Instant.ofEpochMilli(selection).atOffset(ZoneOffset.UTC);
- filter.setAfter(offsetDateTime);
+ filter.after(offsetDateTime);
});
picker.show(getChildFragmentManager(), picker.toString());
});
@@ -152,7 +149,7 @@ public boolean onMenuItemSelected(@NonNull @NotNull MenuItem menuItem) {
.build();
picker.addOnPositiveButtonClickListener(selection -> {
OffsetDateTime offsetDateTime = Instant.ofEpochMilli(selection).atOffset(ZoneOffset.UTC);
- filter.setBefore(offsetDateTime);
+ filter.before(offsetDateTime);
});
picker.show(getChildFragmentManager(), picker.toString());
});
@@ -179,18 +176,18 @@ public boolean onMenuItemSelected(@NonNull @NotNull MenuItem menuItem) {
swipeRefreshLayout.setColorSchemeColors(secondaryColour);
viewModel = new ViewModelProvider(this).get(EventViewModel.class);
- viewModel.setParams(filter.getValue());
- viewModel.getData().observe(getViewLifecycleOwner(), PartialErrorObserver.with(this::onError));
- viewModel.getData().observe(getViewLifecycleOwner(), new ProgressObserver<>(view.findViewById(R.id.progress_bar)));
- viewModel.getData().observe(getViewLifecycleOwner(), new SuccessObserver>>() {
+ viewModel.params(filter.getValue());
+ viewModel.data().observe(getViewLifecycleOwner(), PartialErrorObserver.with(this::onError));
+ viewModel.data().observe(getViewLifecycleOwner(), new ProgressObserver<>(view.findViewById(R.id.progress_bar)));
+ viewModel.data().observe(getViewLifecycleOwner(), new SuccessObserver<>() {
@Override
- protected void onSuccess(@NonNull Pair> data) {
- adapter.setAssociationMap(data.first);
- adapter.submitData(data.second);
- associationAdapter.setItemsAndState(data.first.getSelectedAssociations());
+ protected void onSuccess(@NonNull AssociationRequest.EventItemsAndAssociations data) {
+ adapter.setAssociationMap(data.associations());
+ adapter.submitData(data.events());
+ associationAdapter.itemsAndState(data.associations().requestedAssociations());
}
});
- viewModel.getRefreshing().observe(getViewLifecycleOwner(), swipeRefreshLayout::setRefreshing);
+ viewModel.refreshing().observe(getViewLifecycleOwner(), swipeRefreshLayout::setRefreshing);
swipeRefreshLayout.setOnRefreshListener(viewModel);
view.