Skip to content

Commit

Permalink
Refactored path resolution for caldav implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
benfortuna committed Dec 1, 2023
1 parent 7407ad1 commit 85e0986
Showing 1 changed file with 78 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,58 +57,81 @@ public interface PathResolver {
* @param resourcePath a path component representing a resource
* @return a string representing the repository path to the resource
*/
String getRepositoryPath(String resourcePath, String wspPath);
String getCalendarPath(String resourcePath, String wspPath);

String getCardPath(String resourcePath, String wspPath);

String getResourceName(String repositoryPath, String wspPath);

/**
* Default path resolver configurations for some popular CalDAV/CardDAV implementations.
*
* Each configuration provides a pattern for the follow path types:
* - principals, or who has access to the calendar/card resources
* - calendar collections, containers for icalendar objects
* - card collections, containers for vcard objects
*
* A configuration also provides a general path pattern that is used to extract the component paths
* from a full repository path, such that:
* - pathPattern(principalPath(resource))[resource] == resource
* - pathPattern(calendarPath(resource))[resource] == resource
* - pathPattern(cardPath(resource))[resource] == resource
*/
enum Defaults implements PathResolver {

CHANDLER( "/%s/", "/users/%s",
"/users/(\\w+)/?"),
CHANDLER( "/%s/", "/users/%s", "",
"/users/(?<resource>\\w+)/?"),

RADICALE( "/%s", "/", "/([\\w]+)/?"),
RADICALE( "/%s",
"/%2$s/%1$s",
"/%2$s/%1$s",
"\\/(?<wsp>[\\w]+)\\/(?<resource>[\\w]+)"),

BAIKAL( "/", "/calendars/%s",
"/calendars/([\\w]+)/?"),
BAIKAL( "/principals/%s",
"/calendars/%2$s/%1$s",
"/addressbooks/%2$s/%1$s",
"\\/(?<type>(principals|calendars|addressbooks))\\/((?<wsp>[\\w]+)\\/)?(?<resource>[\\w]+)"),

CGP("/", "/", "/(\\w+)/?"),
CGP("/", "/", "","/(?<resource>\\w+)/?"),

KMS("/", "/", "/(\\w+)/?"),
KMS("/", "/", "","/(?<resource>\\w+)/?"),

ZIMBRA("/principals/users/%s/", "/dav/%s/",
"/(\\w+)/?"),
ZIMBRA("/principals/users/%s/", "/dav/%s/", "",
"/(?<resource>\\w+)/?"),

ICAL_SERVER( "/principals/users/%s/", "/dav/%s/",
"/(\\w+)/?"),
ICAL_SERVER( "/principals/users/%s/", "/dav/%s/", "",
"/(?<resource>\\w+)/?"),

CALENDAR_SERVER( "/%s/", "/%s", "/(\\w+)/?"),
CALENDAR_SERVER( "/%s/", "/dav/%s", "","/(?<resource>\\w+)/?"),

GCAL( "/%s/user", "/%s/events",
"/\\w+/events/?"),
GCAL( "/%s/user", "/%s/events", "",
"/(?<resource>\\w+)/events/?"),

SOGO("/%s/", "/%s/", "/(\\w+)/?"),
SOGO("/%s/", "/%s/", "","/(?<resource>\\w+)/?"),

DAVICAL("/%s/", "/%s/", "/(\\w+)/?"),
DAVICAL("/%s/", "/%s/", "","/(?<resource>\\w+)/?"),

BEDEWORK("/principals/users/%s/", "/users/%s",
"/users/(\\w+)/?"),
BEDEWORK("/principals/users/%s/", "/ucaldav/users/%s", "",
"/users/(?<resource>\\w+)/?"),

ORACLE_CS("/principals/%s/", "/home/%s/",
"/home/(\\w+)/?"),
ORACLE_CS("/principals/%s/", "/home/%s/", "",
"/home/(?<resource>\\w+)/?"),

GENERIC("/%s", "/%s", "/(\\w+)");
GENERIC("/%s", "/%s", "","/(?<resource>\\w+)");

private final String principalPathBase;
private final String principalPath;

private final String calendarPathBase;
private final String calendarPath;

private final Pattern calendarPathPattern;
private final String cardPath;

Defaults(String principalPathBase, String calendarPathBase,
String calendarPathPattern) {
this.principalPathBase = principalPathBase;
this.calendarPathBase = calendarPathBase;
this.calendarPathPattern = Pattern.compile("^" + calendarPathPattern + "$");
private final Pattern pathPattern;

Defaults(String principalPath, String calendarPath, String cardPath, String pathPattern) {
this.principalPath = principalPath;
this.calendarPath = calendarPath;
this.cardPath = cardPath;
this.pathPattern = Pattern.compile(pathPattern);
}

/**
Expand All @@ -118,12 +141,23 @@ enum Defaults implements PathResolver {
* @return the user path for a server implementation
*/
@Override
public String getRepositoryPath(String resourceName, String wspPath) {
public String getCalendarPath(String resourceName, String wspPath) {
if (wspPath != null && !wspPath.isEmpty()) {
return String.format("/%s", String.format(calendarPath, resourceName, wspPath))
.replaceAll("/+", "/");
} else {
return String.format("/%s", String.format(calendarPath, resourceName, ""))
.replaceAll("/+", "/");
}
}

@Override
public String getCardPath(String resourcePath, String wspPath) {
if (wspPath != null && !wspPath.isEmpty()) {
return String.format("/%s%s", wspPath, String.format(calendarPathBase, resourceName))
return String.format("/%s", String.format(cardPath, resourcePath, wspPath))
.replaceAll("/+", "/");
} else {
return String.format("/%s", String.format(calendarPathBase, resourceName))
return String.format("/%s", String.format(cardPath, resourcePath, ""))
.replaceAll("/+", "/");
}
}
Expand All @@ -135,13 +169,16 @@ public String getRepositoryPath(String resourceName, String wspPath) {
*/
@Override
public String getResourceName(String repositoryPath, String wspPath) {
Matcher matcher = calendarPathPattern.matcher(repositoryPath);
if (matcher.matches() && matcher.groupCount() > 0) {
if (wspPath != null && !wspPath.isEmpty()) {
return String.format("%s/%s", wspPath, matcher.group(1));
} else {
return matcher.group(1);
}
Matcher matcher = pathPattern.matcher(repositoryPath);
// if (matcher.matches() && matcher.groupCount() > 0) {
// if (wspPath != null && !wspPath.isEmpty()) {
// return String.format("%s/%s", wspPath, matcher.group(1));
// } else {
// return matcher.group(1);
// }
// }
if (matcher.matches()) {
return matcher.group("resource");
}
return null;
}
Expand All @@ -154,7 +191,7 @@ public String getResourceName(String repositoryPath, String wspPath) {
*/
@Override
public String getPrincipalPath(String calendarId) {
return String.format(principalPathBase, calendarId);
return String.format(principalPath, calendarId);
}
}
}

0 comments on commit 85e0986

Please sign in to comment.