SearchResultSelectionGeneratable

Leveraging the SearchResultSelectionGeneratable annotation, you can create a complex Content type with a search result action. For example, you can have a MultiMediaGallery type that consists of Image and Video slides. A query for Image or Video types displays an associated action in the Search Panel. Invoking the action creates a MultiMediaGallery object with any Image or Video objects selected in the search results.

The following steps show how to construct a search result action that creates a MultiMediaGallery content type.

Step 1: Create the Content Type

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
@SearchResultSelectionGeneratable.ItemTypes({Image.class, Video.class})
public class MultiMediaGallery extends Content {

   private List<Slide> slides;
   public List<Slide> getSlides() { return slides; }
   public void setSlides(List<Slide> slides) { this.slides = slides; }

   @Embedded
   private static abstract class Slide extends Record { }

   private static class ImageSlide extends Slide {
      private Image image;

      public Image getImage() {
         return image;
      }

      public void setImage(Image image) {
         this.image = image;
      }
   }

   private static class VideoSlide extends Slide {
      private Video video;

      public Video getVideo() {
         return video;
      }

      public void setVideo(Video video) {
         this.video = video;
      }
   }

   public void fromSelection(SearchResultSelection selection) {

      for (Object object : selection.createItemsQuery().selectAll()) {
         if (object instanceof Image) {
             // If the selected object is an Image, create a new ImageSlide to wrap it.
             ImageSlide imageSlide = new ImageSlide();
             imageSlide.setImage((Image) object);
             getSlides().add(imageSlide);

         } else if (object instanceof Video) {
             // If the selected object is a Video, create a new VideoSlide to wrap it.
             VideoSlide videoSlide = new VideoSlide();
             videoSlide.setVideo((Video) object);
             getSlides().add(videoSlide);
         }
         // Ignore any other objects that are not Images or Videos
      }
   }
}

In the previous snippet—

  • Line 1 is the class annotation that enables MultiMediaGallery objects to be created from Image and Video objects returned in search results.
  • Lines 4 to 6 define a list for a Slide type and associated getter and setter methods.
  • Lines 8 to 9 embed an abstract Slide class.
  • Lines 11 to 21 implement an ImageSlide inner class for slides consisting of Image objects.
  • Lines 23 to 33 implement a VideoSlide inner class for slides consisting of Video objects.
  • Lines 35 to 52 implement the fromSelection method from the SearchResultSelectionGeneratable interface. The method creates Image or Video slides from the SearchResultSelection object. After usage of the SearchResultSelection to create a new Content instance, the SearchResultSelection is destroyed.

Step 2: Implement SearchResultAction

The SearchResultAction implementation displays the applicable action button in the Search Panel.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class MultiMediaGalleryAction implements SearchResultAction {

   @Override
   public int getPosition() {
      return 0;
   }

   @Override
   public boolean shouldDisplay(ToolPageContext page, Search search, SearchResultSelection selection) {
      return true;
   }

   // @Override
   public void writeHtml(
      ToolPageContext page,
      Search search,
      SearchResultSelection selection)
      throws IOException {

      if (selection == null) {
         return;
      }

      page.writeStart("div", "class", "searchResult-action-simple");

      page.writeStart("a",
             "class", "button",
             "target", "toolUserMultiMedia",
             "href", new UrlBuilder(page.getRequest())
                     .absolutePath(page.toolPath(CmsTool.class, "toolUserMultiMedia"))
                     .parameter("selectionId", selection.getId()));
      page.writeHtml(page.localize(MultiMediaGalleryAction.class, "action.MultiMediaGalleryAction"));
      page.writeEnd();
      page.writeEnd();
   }
}

In the previous snippet—

  • Lines 20–22 check for search results that are selected in the UI. If there are no selections, then the implementation does not display the action button.
  • Lines 29–31 construct the URL to the page servlet, specified in the servlet routing path as toolUserMultiMedia. Only one parameter is passed to the servlet, selectionId, returned by the SearchResultSelection#getId() method.
  • Line 32 specifies the label on the action button. The label is retrieved from a localization resource file.

When results are selected in the Search Panel, the “Create MultiMediaGallery” button appears.

../../../_images/actions2.png

Step 3: Implement Page Servlet

The page servlet invoked from the search result action creates the MultiMediaGallery objects from the search result selections.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
@RoutingFilter.Path(application = "cms", value = "toolUserMultiMedia")
public class ToolUserMultiMedia extends PageServlet {

   @Override
   protected String getPermissionId() {
      return null;
   }

   @Override
   protected void doService(ToolPageContext page) throws IOException, ServletException {

      UUID selectionId = page.param(UUID.class, "selectionId");
      SearchResultSelection selection = Query.from(SearchResultSelection.class).where("_id = ?", selectionId).first();

      MultiMediaGallery gallery = new MultiMediaGallery();
      gallery.fromSelection(selection);
      gallery.save();
   }
}
  • Line 1 specifies the annotation @RoutingFilter.Path of the servlet as “toolUserMultiMedia”.
  • Line 12 gets the value of the selectionId parameter passed from MultiMediaGalleryAction.
  • Line 13 performs a query to get the SearchResultSelection object identified by selectionId.
  • Lines 15–17 create a MultiMediaGallery object. Note that the SearchResultSelection object can represent selections of various content types. However, MultiMediaGallery is limited to Image and Video item types, so the implemented fromSelection method creates gallery slides from only those types.