4 Replies Latest reply on Sep 26, 2014 11:06 AM by Antoine Mischler

    Recommended way to handle a trash system in a Modeshape repository

    Antoine Mischler Newbie

      We need to implement a trash system that handle deletion/restoring and permanent deletion of repository elements.

       

      I'm thinking of three possible ways to implement this feature:

       

      1. Marking deleted nodes with a [deleted] mixin
      2. Moving deleted nodes under a /root/trash node in the current workspace
      3. Moving deleted nodes under another workspace

       

      For 2. and 3., we can in both cases either keep the original path or move all nodes at the same level and keep a reference to their original path as a property.

       

      Each of these approach has benefits and drawbacks especially regarding to queries. With 1., and 2. all queries must take care to filter marked nodes or nodes under the trash nodes. This is not the case with 3. Due to this I have got a preference for the 3. approach. However, the David's Model (http://wiki.apache.org/jackrabbit/DavidsModel#Rule_.233%3a_Workspaces_are_for_clone.28.29.2C_merge.28.29_and_update.28.2…) does not seem to recommend the workspace approach for this use case. Is there any drawback that I am missing with the workspace approach? Is there another recommended way to handle such a trash system within a modeshape repository?

        • 1. Re: Recommended way to handle a trash system in a Modeshape repository
          Randall Hauch Master

          Option 3 is probably not as easy as you think. In order to keep the path the same, you probably have to create a bunch of intermediary ancestor nodes, and then manage them should the trashed items need to be restored (and copied back to the other workspace). The big disadvantage, though, is that you can't really move nodes between workspaces - you can copy and remove, but not move per se.

           

          In this case, I would probably lean towards following David's Model and not using a separate workspace. Personally, I like option #1 -- it's very simple and low overhead. Yes, you have to make sure that you always filter out deleted nodes, and the only area of complication will be node names. Opiton #2 is pretty attractive, too, especially if you don't need to maintain the path of the original node; for example, you might created a "deletedItem" node that contains the original plus the path back to the original location, as well as any other information you want to retain (when, who, etc.). Moving is also much better than copying.

           

          A 4th option you didn't consider is to have a ".trash" item (potentially) under each parent.

          1 of 1 people found this helpful
          • 2. Re: Recommended way to handle a trash system in a Modeshape repository
            Antoine Mischler Newbie

            Thanks for your helpful answer. I did not realize the complications with the workspace approach, so we'll opt for the option #1.

             

            I have got an additional question regarding the query to filter out the deleted nodes with this option. I'm trying to do something like :

             

            SELECT * FROM [test:myType] WHERE [jcr.mixinTypes] != [mix:deleted]

             

            However, this query seems to exclude all nodes, even those who don't have the [mix:deleted] mixin. How can I exclude the nodes with the [mix:deleted] mixin from the query result?

            • 3. Re: Re: Recommended way to handle a trash system in a Modeshape repository
              Randall Hauch Master

              You might try using a set operation

               

              SELECT * FROM [test:myType] WHERE ...

              EXCEPT

              SELECT * FROM [mix:deleted] WHERE ...

               

              You probably want to use criteria on the second part that narrows it down to roughly the same area of the repository, so the number of nodes found there is relatively small. For example, if you're trying to find all (deleted and non-deleted) nodes under "/a/b/c/d", you then this query can do this:

               

              SELECT * FROM [test:myType] AS node

                       JOIN [someType] AS ancestor ON ISDESCENDANT(node,ancestor)

                       WHERE PATH(ancestor) = '/a/b/c/d'

                               

              Then, you can find all non-deleted nodes under "/a/b/c/d" by combining that query but excluding all deleted nodes:

               

              SELECT * FROM [test:myType] AS node

                       JOIN [someType] AS ancestor ON ISDESCENDANT(node,ancestor)

                       WHERE PATH(ancestor) = '/a/b/c/d'

              EXCEPT

              SELECT * FROM [mix:deleted] AS node

                       JOIN [someType] AS ancestor ON ISDESCENDANT(node,ancestor)

                       WHERE PATH(ancestor) = '/a/b/c/d'

               

              Of course, you can add more criteria, too. (You'd probably want to add it in the first query of the EXCEPT.

               

              Alternatively, you can use a subquery to find the deleted nodes, and a NOT criteria. But I think using EXCEPT is easier to understand.