From 191167bb64a9b8ca2eaa361ddbb834ef6984e3f7 Mon Sep 17 00:00:00 2001 From: Ben Fortuna Date: Thu, 25 Jan 2024 13:37:58 +1100 Subject: [PATCH] Added workspace support --- .../org/ical4j/connector/ObjectStore.java | 17 +++++-- .../local/AbstractLocalObjectStore.java | 50 ++++++++++++++++--- .../connector/local/LocalCalendarStore.java | 4 +- .../connector/local/LocalCardStore.java | 4 +- .../connector/local/AbstractLocalTest.groovy | 3 +- .../local/LocalCalendarCollectionTest.groovy | 4 +- .../local/LocalCalendarStoreTest.groovy | 4 +- .../local/LocalCardCollectionTest.groovy | 2 +- .../connector/local/LocalCardStoreTest.groovy | 4 +- .../connector/dav/CalDavCalendarStore.java | 33 +++++++++++- .../ical4j/connector/dav/CardDavStore.java | 31 +++++++++++- 11 files changed, 129 insertions(+), 27 deletions(-) diff --git a/ical4j-connector-api/src/main/java/org/ical4j/connector/ObjectStore.java b/ical4j-connector-api/src/main/java/org/ical4j/connector/ObjectStore.java index d05eef0..d76ed10 100644 --- a/ical4j-connector-api/src/main/java/org/ical4j/connector/ObjectStore.java +++ b/ical4j-connector-api/src/main/java/org/ical4j/connector/ObjectStore.java @@ -81,7 +81,9 @@ public interface ObjectStore> extends ObjectSto * exists in the store */ C addCollection(String id) throws ObjectStoreException; - + + C addCollection(String id, String workspace) throws ObjectStoreException; + /** * @param id a collection identifier * @param displayName the collection name @@ -93,7 +95,10 @@ public interface ObjectStore> extends ObjectSto */ C addCollection(String id, String displayName, String description, String[] supportedComponents, Calendar timezone) throws ObjectStoreException; - + + C addCollection(String id, String displayName, String description, + String[] supportedComponents, Calendar timezone, String workspace) throws ObjectStoreException; + /** * Removes the collection with specified id from the store. * @param id a collection identifier @@ -105,7 +110,7 @@ C addCollection(String id, String displayName, String description, */ @Deprecated C removeCollection(String id) throws ObjectStoreException, ObjectNotFoundException; - + /** * @param id a collection identifier * @return an object collection with the specified id. If no collection with the specified id @@ -115,5 +120,11 @@ C addCollection(String id, String displayName, String description, */ C getCollection(String id) throws ObjectStoreException, ObjectNotFoundException; + C getCollection(String id, String workspace) throws ObjectStoreException, ObjectNotFoundException; + List getCollections() throws ObjectStoreException, ObjectNotFoundException; + + List getCollections(String workspace) throws ObjectStoreException, ObjectNotFoundException; + + List listWorkspaces(); } diff --git a/ical4j-connector-api/src/main/java/org/ical4j/connector/local/AbstractLocalObjectStore.java b/ical4j-connector-api/src/main/java/org/ical4j/connector/local/AbstractLocalObjectStore.java index 62020d7..bfb4185 100644 --- a/ical4j-connector-api/src/main/java/org/ical4j/connector/local/AbstractLocalObjectStore.java +++ b/ical4j-connector-api/src/main/java/org/ical4j/connector/local/AbstractLocalObjectStore.java @@ -51,7 +51,12 @@ public boolean isConnected() { @Override public C addCollection(String id) throws ObjectStoreException { - File collectionDir = new File(root, id); + return addCollection(id, "default"); + } + + @Override + public C addCollection(String id, String workspace) throws ObjectStoreException { + File collectionDir = new File(getWorkspaceDir(workspace), id); if ((collectionDir.exists() && !collectionDir.isDirectory()) || (!collectionDir.exists() && !collectionDir.mkdirs())) { throw new ObjectStoreException("Unable to initialise collection"); @@ -61,7 +66,7 @@ public C addCollection(String id) throws ObjectStoreException { collection = getCollection(id); } catch (ObjectNotFoundException e) { try { - collection = newCollection(id); + collection = newCollection(id, workspace); } catch (IOException ex) { throw new ObjectStoreException(ex); } @@ -73,11 +78,17 @@ public C addCollection(String id) throws ObjectStoreException { return collection; } - protected abstract C newCollection(String id) throws IOException; + protected abstract C newCollection(String id, String workspace) throws IOException; @Override public C addCollection(String id, String displayName, String description, String[] supportedComponents, Calendar timezone) throws ObjectStoreException { - C collection = addCollection(id); + return addCollection(id, displayName, description, supportedComponents, timezone, "default"); + } + + @Override + public C addCollection(String id, String displayName, String description, String[] supportedComponents, + Calendar timezone, String workspace) throws ObjectStoreException { + C collection = addCollection(id, workspace); try { collection.setDisplayName(displayName); collection.setDescription(description); @@ -106,12 +117,17 @@ public C removeCollection(String id) throws ObjectNotFoundException, ObjectStore @Override public C getCollection(String id) throws ObjectStoreException, ObjectNotFoundException { - File collectionDir = new File(root, id); + return getCollection(id, "default"); + } + + @Override + public C getCollection(String id, String workspace) throws ObjectStoreException, ObjectNotFoundException { + File collectionDir = new File(getWorkspaceDir(workspace), id); if (!collectionDir.exists() || !collectionDir.isDirectory()) { throw new ObjectNotFoundException("Unable to retrieve collection"); } try { - return newCollection(id); + return newCollection(id, workspace); } catch (IOException e) { throw new ObjectStoreException(e); } @@ -119,12 +135,30 @@ public C getCollection(String id) throws ObjectStoreException, ObjectNotFoundExc @Override public List getCollections() { - return Arrays.stream(root.list()).map(name -> { + return getCollections("default"); + } + + @Override + public List getCollections(String workspace) { + return Arrays.stream(Objects.requireNonNull(getWorkspaceDir(workspace).list())).map(name -> { try { - return newCollection(name); + return newCollection(name, workspace); } catch (IOException e) { throw new RuntimeException(e); } }).collect(Collectors.toList()); } + + protected File getWorkspaceDir(String workspace) { + File workspaceDir = new File(root, workspace); + if (!workspaceDir.exists() && !workspaceDir.mkdir()) { + throw new IllegalArgumentException("Invalid workspace"); + } + return workspaceDir; + } + + @Override + public List listWorkspaces() { + return Arrays.asList(Objects.requireNonNull(root.list())); + } } diff --git a/ical4j-connector-api/src/main/java/org/ical4j/connector/local/LocalCalendarStore.java b/ical4j-connector-api/src/main/java/org/ical4j/connector/local/LocalCalendarStore.java index ddbf94e..b22b43e 100644 --- a/ical4j-connector-api/src/main/java/org/ical4j/connector/local/LocalCalendarStore.java +++ b/ical4j-connector-api/src/main/java/org/ical4j/connector/local/LocalCalendarStore.java @@ -14,7 +14,7 @@ public LocalCalendarStore(File root) { } @Override - protected LocalCalendarCollection newCollection(String id) throws IOException { - return new LocalCalendarCollection(new File(getRoot(), id)); + protected LocalCalendarCollection newCollection(String id, String workspace) throws IOException { + return new LocalCalendarCollection(new File(getWorkspaceDir(workspace), id)); } } diff --git a/ical4j-connector-api/src/main/java/org/ical4j/connector/local/LocalCardStore.java b/ical4j-connector-api/src/main/java/org/ical4j/connector/local/LocalCardStore.java index 6978a94..d621545 100644 --- a/ical4j-connector-api/src/main/java/org/ical4j/connector/local/LocalCardStore.java +++ b/ical4j-connector-api/src/main/java/org/ical4j/connector/local/LocalCardStore.java @@ -14,7 +14,7 @@ public LocalCardStore(File root) { } @Override - protected LocalCardCollection newCollection(String id) throws IOException { - return new LocalCardCollection(new File(getRoot(), id)); + protected LocalCardCollection newCollection(String id, String workspace) throws IOException { + return new LocalCardCollection(new File(getWorkspaceDir(workspace), id)); } } diff --git a/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/AbstractLocalTest.groovy b/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/AbstractLocalTest.groovy index a77729c..78db21b 100644 --- a/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/AbstractLocalTest.groovy +++ b/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/AbstractLocalTest.groovy @@ -6,10 +6,11 @@ import spock.lang.Specification abstract class AbstractLocalTest extends Specification { @Shared - File storeLocation + File storeLocation, workspaceLocation def setup() { storeLocation = ['build', getClass().name] + workspaceLocation = [storeLocation, 'default'] } def cleanup() { diff --git a/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCalendarCollectionTest.groovy b/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCalendarCollectionTest.groovy index eb90ca1..50b955f 100644 --- a/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCalendarCollectionTest.groovy +++ b/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCalendarCollectionTest.groovy @@ -44,7 +44,7 @@ class LocalCalendarCollectionTest extends AbstractLocalTest { collection.add(calendar) then: 'a new calendar file is created' - new File(storeLocation, + new File(workspaceLocation, "public_holidays/${calendar.getComponent(Component.VEVENT).get().getRequiredProperty(Property.UID).getValue()}.ics").exists() and: 'the listener is notified' @@ -63,7 +63,7 @@ class LocalCalendarCollectionTest extends AbstractLocalTest { def removed = collection.removeAll(calendar.getUid().value) then: 'the exsiting calendar file is deleted' - !new File(storeLocation, + !new File(workspaceLocation, "public_holidays/${calendar.getComponent(Component.VEVENT).get().getRequiredProperty(Property.UID).getValue()}.ics").exists() and: 'removed calendar is identical to added' diff --git a/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCalendarStoreTest.groovy b/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCalendarStoreTest.groovy index bb6503e..51884c8 100644 --- a/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCalendarStoreTest.groovy +++ b/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCalendarStoreTest.groovy @@ -22,7 +22,7 @@ class LocalCalendarStoreTest extends AbstractLocalTest { LocalCalendarCollection collection = calendarStore.addCollection('public_holidays') then: 'a local collection directory is added' - new File(storeLocation, 'public_holidays').exists() + new File(workspaceLocation, 'public_holidays').exists() and: 'the listener is notified' event != null && event.collection == collection @@ -41,7 +41,7 @@ class LocalCalendarStoreTest extends AbstractLocalTest { 'Victorian public holidays', [Component.VEVENT] as String[], timezone) then: 'a local collection directory is added' - new File(storeLocation, 'public_holidays').exists() + new File(workspaceLocation, 'public_holidays').exists() and: 'the collection properties are saved' collection.displayName == 'Public Holidays' diff --git a/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCardCollectionTest.groovy b/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCardCollectionTest.groovy index 60742a1..b3d2489 100644 --- a/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCardCollectionTest.groovy +++ b/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCardCollectionTest.groovy @@ -39,7 +39,7 @@ class LocalCardCollectionTest extends AbstractLocalTest { collection.add(card) then: 'a new card file is created' - new File(storeLocation, + new File(workspaceLocation, "contacts/${card.getRequiredProperty(PropertyName.UID).getValue()}.vcf").exists() and: 'the listener is notified' diff --git a/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCardStoreTest.groovy b/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCardStoreTest.groovy index cbd0387..2090fa1 100644 --- a/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCardStoreTest.groovy +++ b/ical4j-connector-api/src/test/groovy/org/ical4j/connector/local/LocalCardStoreTest.groovy @@ -22,7 +22,7 @@ class LocalCardStoreTest extends AbstractLocalTest { LocalCardCollection collection = cardStore.addCollection('contacts') then: 'a local collection directory is added' - new File(storeLocation, 'contacts').exists() + new File(workspaceLocation, 'contacts').exists() and: 'the listener is notified' event != null && event.collection == collection @@ -41,7 +41,7 @@ class LocalCardStoreTest extends AbstractLocalTest { 'Personal Contacts', ['VCARD'] as String[], timezone) then: 'a local collection directory is added' - new File(storeLocation, 'contacts').exists() + new File(workspaceLocation, 'contacts').exists() and: 'the collection properties are saved' collection.displayName == 'Contacts' diff --git a/ical4j-connector-dav/src/main/java/org/ical4j/connector/dav/CalDavCalendarStore.java b/ical4j-connector-dav/src/main/java/org/ical4j/connector/dav/CalDavCalendarStore.java index 6cd0e49..4f99d40 100644 --- a/ical4j-connector-dav/src/main/java/org/ical4j/connector/dav/CalDavCalendarStore.java +++ b/ical4j-connector-dav/src/main/java/org/ical4j/connector/dav/CalDavCalendarStore.java @@ -96,6 +96,7 @@ public CalDavCalendarStore(String prodId, URL url, PathResolver pathResolver) { /** * {@inheritDoc} */ + @Override public CalDavCalendarCollection addCollection(String id) throws ObjectStoreException { CalDavCalendarCollection collection = new CalDavCalendarCollection(this, id); try { @@ -106,9 +107,15 @@ public CalDavCalendarCollection addCollection(String id) throws ObjectStoreExcep return collection; } + @Override + public CalDavCalendarCollection addCollection(String id, String workspace) throws ObjectStoreException { + throw new UnsupportedOperationException("Workspaces not yet implemented"); + } + /** * {@inheritDoc} */ + @Override public CalDavCalendarCollection addCollection(String id, String displayName, String description, String[] supportedComponents, Calendar timezone) throws ObjectStoreException { @@ -121,6 +128,11 @@ public CalDavCalendarCollection addCollection(String id, String displayName, Str return collection; } + @Override + public CalDavCalendarCollection addCollection(String id, String displayName, String description, String[] supportedComponents, Calendar timezone, String workspace) throws ObjectStoreException { + throw new UnsupportedOperationException("Workspaces not yet implemented"); + } + /** * {@inheritDoc} */ @@ -137,6 +149,7 @@ public CalDavCalendarCollection addCollection(String id, DavPropertySet properti /** * {@inheritDoc} */ + @Override public CalDavCalendarCollection getCollection(String id) throws ObjectStoreException, ObjectNotFoundException { try { String resourcePath = pathResolver.getCalendarPath(id, "test"); @@ -157,6 +170,11 @@ public CalDavCalendarCollection getCollection(String id) throws ObjectStoreExcep } } + @Override + public CalDavCalendarCollection getCollection(String id, String workspace) throws ObjectStoreException, ObjectNotFoundException { + throw new UnsupportedOperationException("Workspaces not yet implemented"); + } + /** * {@inheritDoc} */ @@ -202,6 +220,7 @@ protected String findCalendarHomeSet(String propfindUri) throws IOException { * @throws IOException where a communications error occurs * @throws DavException where an error occurs calling the DAV method */ + @Override public List getCollections() throws ObjectStoreException, ObjectNotFoundException { try { String calHomeSetPath = findCalendarHomeSet(); @@ -213,9 +232,14 @@ public List getCollections() throws ObjectStoreExcepti throw new ObjectStoreException(de); } } - + + @Override + public List getCollections(String workspace) throws ObjectStoreException, ObjectNotFoundException { + throw new UnsupportedOperationException("Workspaces not yet implemented"); + } + protected List getCollectionsForHomeSet(CalDavCalendarStore store, - String urlForcalendarHomeSet) throws IOException, DavException { + String urlForcalendarHomeSet) throws IOException, DavException { DavPropertyNameSet principalsProps = CalDavCalendarCollection.propertiesForFetch(); return getClient().propFindResources(urlForcalendarHomeSet, principalsProps, @@ -271,6 +295,11 @@ public CalDavCalendarCollection removeCollection(String id) throws ObjectStoreEx return collection; } + @Override + public List listWorkspaces() { + throw new UnsupportedOperationException("Workspaces not yet implemented"); + } + // public CalendarCollection replace(String id, CalendarCollection calendar) { // // TODO Auto-generated method stub // return null; diff --git a/ical4j-connector-dav/src/main/java/org/ical4j/connector/dav/CardDavStore.java b/ical4j-connector-dav/src/main/java/org/ical4j/connector/dav/CardDavStore.java index 08a12cb..2739511 100644 --- a/ical4j-connector-dav/src/main/java/org/ical4j/connector/dav/CardDavStore.java +++ b/ical4j-connector-dav/src/main/java/org/ical4j/connector/dav/CardDavStore.java @@ -92,6 +92,7 @@ public CardDavStore(String prodId, URL url, PathResolver pathResolver) { /** * {@inheritDoc} */ + @Override public CardDavCollection addCollection(String id) throws ObjectStoreException { CardDavCollection collection = new CardDavCollection(this, id); try { @@ -102,6 +103,11 @@ public CardDavCollection addCollection(String id) throws ObjectStoreException { return collection; } + @Override + public CardDavCollection addCollection(String id, String workspace) throws ObjectStoreException { + throw new UnsupportedOperationException("Workspaces not yet implemented"); + } + /** * {@inheritDoc} */ @@ -129,6 +135,11 @@ public CardDavCollection getCollection(String id) throws ObjectStoreException, O } } + @Override + public CardDavCollection getCollection(String id, String workspace) throws ObjectStoreException, ObjectNotFoundException { + throw new UnsupportedOperationException("Workspaces not yet implemented"); + } + /** * {@inheritDoc} */ @@ -180,9 +191,14 @@ public List getCollections() throws ObjectStoreException, Obj throw new ObjectStoreException(e); } } - + + @Override + public List getCollections(String workspace) throws ObjectStoreException, ObjectNotFoundException { + throw new UnsupportedOperationException("Workspaces not yet implemented"); + } + protected List getCollectionsForHomeSet(CardDavStore store, - String urlForcalendarHomeSet) throws IOException, DavException { + String urlForcalendarHomeSet) throws IOException, DavException { DavPropertyNameSet principalsProps = CardDavCollection.propertiesForFetch(); return getClient().propFindResources(urlForcalendarHomeSet, principalsProps, ResourceType.ADRESSBOOK).entrySet().stream() @@ -221,6 +237,7 @@ public List getDelegatedCollections() throws Exception { /** * {@inheritDoc} */ + @Override public CardDavCollection removeCollection(String id) throws ObjectStoreException, ObjectNotFoundException { CardDavCollection collection = getCollection(id); collection.delete(); @@ -232,6 +249,12 @@ public CardDavCollection removeCollection(String id) throws ObjectStoreException // return null; // } + + @Override + public List listWorkspaces() { + throw new UnsupportedOperationException("Workspaces not yet implemented"); + } + /** * @return the prodId */ @@ -255,4 +278,8 @@ public CardDavCollection addCollection(String id, String displayName, String des throw new UnsupportedOperationException("not implemented"); } + @Override + public CardDavCollection addCollection(String id, String displayName, String description, String[] supportedComponents, Calendar timezone, String workspace) throws ObjectStoreException { + throw new UnsupportedOperationException("Workspaces not yet implemented"); + } }