View Javadoc
1   /*
2    * Licensed to The Apereo Foundation under one or more contributor license
3    * agreements. See the NOTICE file distributed with this work for additional
4    * information regarding copyright ownership.
5    *
6    *
7    * The Apereo Foundation licenses this file to you under the Educational
8    * Community License, Version 2.0 (the "License"); you may not use this file
9    * except in compliance with the License. You may obtain a copy of the License
10   * at:
11   *
12   *   http://opensource.org/licenses/ecl2.txt
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
17   * License for the specific language governing permissions and limitations under
18   * the License.
19   *
20   */
21  package org.opencastproject.elasticsearch.index.objects.series;
22  
23  import static org.opencastproject.security.api.SecurityConstants.GLOBAL_ADMIN_ROLE;
24  
25  import org.opencastproject.elasticsearch.api.SearchTerms;
26  import org.opencastproject.elasticsearch.impl.AbstractSearchQuery;
27  import org.opencastproject.elasticsearch.impl.IndexSchema;
28  import org.opencastproject.security.api.Permissions;
29  import org.opencastproject.security.api.Permissions.Action;
30  import org.opencastproject.security.api.User;
31  import org.opencastproject.util.requests.SortCriterion.Order;
32  
33  import org.apache.commons.lang3.StringUtils;
34  
35  import java.util.ArrayList;
36  import java.util.Date;
37  import java.util.HashMap;
38  import java.util.HashSet;
39  import java.util.List;
40  import java.util.Map;
41  import java.util.Set;
42  
43  /**
44   * This interface defines a fluent api for a query object used to lookup series in the search index.
45   */
46  public class SeriesSearchQuery extends AbstractSearchQuery {
47  
48    protected List<String> identifiers = new ArrayList<String>();
49    private String title = null;
50    private User user = null;
51    private String description = null;
52    private final Set<String> actions = new HashSet<String>();
53    private final List<String> subjects = new ArrayList<String>();
54    private String organization = null;
55    private String language = null;
56    private String creator = null;
57    private String license = null;
58    private String accessPolicy = null;
59    private String managedAcl = null;
60    private final List<String> organizers = new ArrayList<String>();
61    private final List<String> contributors = new ArrayList<String>();
62    private final List<String> publishers = new ArrayList<String>();
63    private Date createdFrom = null;
64    private Date createdTo = null;
65    private boolean editOnly = false;
66    private String rightsHolder = null;
67    private Long theme = null;
68    private final Map<String, String> accessControlEntries = new HashMap<>();
69  
70    private static final Map<String, String> SORT_FIELDS = Map.of(
71        SeriesIndexSchema.TITLE, SeriesIndexSchema.TITLE.concat(IndexSchema.SORT_FIELD_NAME_EXTENSION),
72        SeriesIndexSchema.DESCRIPTION, SeriesIndexSchema.DESCRIPTION.concat(IndexSchema.SORT_FIELD_NAME_EXTENSION),
73        SeriesIndexSchema.SUBJECT, SeriesIndexSchema.SUBJECT.concat(IndexSchema.SORT_FIELD_NAME_EXTENSION),
74        SeriesIndexSchema.CREATOR, SeriesIndexSchema.CREATOR.concat(IndexSchema.SORT_FIELD_NAME_EXTENSION),
75        SeriesIndexSchema.ORGANIZERS, SeriesIndexSchema.ORGANIZERS.concat(IndexSchema.SORT_FIELD_NAME_EXTENSION),
76        SeriesIndexSchema.CONTRIBUTORS, SeriesIndexSchema.CONTRIBUTORS.concat(IndexSchema.SORT_FIELD_NAME_EXTENSION),
77        SeriesIndexSchema.PUBLISHERS, SeriesIndexSchema.PUBLISHERS.concat(IndexSchema.SORT_FIELD_NAME_EXTENSION),
78        SeriesIndexSchema.RIGHTS_HOLDER, SeriesIndexSchema.RIGHTS_HOLDER.concat(IndexSchema.SORT_FIELD_NAME_EXTENSION)
79    );
80  
81    @SuppressWarnings("unused")
82    private SeriesSearchQuery() {
83    }
84  
85    @Override
86    protected String sortOrderFieldName(String field) {
87      if (SORT_FIELDS.containsKey(field)) {
88        return SORT_FIELDS.get(field);
89      }
90      return field;
91    }
92  
93    /**
94     * Creates a query that will return series documents.
95     */
96    public SeriesSearchQuery(String organization, User user) {
97      super(Series.DOCUMENT_TYPE);
98      this.organization = organization;
99      this.user = user;
100     this.actions.add(Permissions.Action.READ.toString());
101     if (!user.hasRole(GLOBAL_ADMIN_ROLE)) {
102       if (!user.getOrganization().getId().equals(organization)) {
103         throw new IllegalStateException("User's organization must match search organization");
104       }
105     }
106   }
107 
108   /**
109    * Selects series with the given identifier.
110    * <p>
111    * Note that this method may be called multiple times to support selection of multiple series.
112    *
113    * @param id
114    *          the series identifier
115    * @return the enhanced search query
116    */
117   public SeriesSearchQuery withIdentifier(String id) {
118     if (StringUtils.isBlank(id)) {
119       throw new IllegalArgumentException("Identifier cannot be null");
120     }
121     this.identifiers.add(id);
122     return this;
123   }
124 
125   /**
126    * Returns the list of series identifiers or an empty array if no identifiers have been specified.
127    *
128    * @return the identifiers
129    */
130   public String[] getIdentifier() {
131     return identifiers.toArray(new String[identifiers.size()]);
132   }
133 
134   /**
135    * Selects series with the given title.
136    *
137    * @param title
138    *          the title
139    * @return the enhanced search query
140    */
141   public SeriesSearchQuery withTitle(String title) {
142     this.title = title;
143     return this;
144   }
145 
146   /**
147    * Returns the title of the series.
148    *
149    * @return the title
150    */
151   public String getTitle() {
152     return title;
153   }
154 
155   /**
156    * Filter the series without any action checked.
157    *
158    * @return the enhanced search query
159    */
160   public SeriesSearchQuery withoutActions() {
161     this.actions.clear();
162     return this;
163   }
164 
165   /**
166    * Filter the series with the given action.
167    * <p>
168    * Note that this method may be called multiple times to support filtering by multiple actions.
169    *
170    * @param action
171    *          the action
172    * @return the enhanced search query
173    */
174   public SeriesSearchQuery withAction(Action action) {
175     if (action == null) {
176       throw new IllegalArgumentException("Action cannot be null");
177     }
178     this.actions.add(action.toString());
179     return this;
180   }
181 
182   /**
183    * Returns the list of actions or an empty array if no actions have been specified.
184    *
185    * @return the actions
186    */
187   public String[] getActions() {
188     return actions.toArray(new String[actions.size()]);
189   }
190 
191 
192   /**
193    * Filter the series with the given role and action.
194    * <p>
195    * Note that this method may be called multiple times to support filtering by multiple role and action combinations.
196    *
197    * @param role
198    *          the role
199    * @param action
200    *          the action
201    * @return the enhanced search query
202    */
203   public SeriesSearchQuery withAccessControlEntry(String role, Action action) {
204     if (StringUtils.isBlank(role)) {
205       throw new IllegalArgumentException("Role cannot be null");
206     }
207     if (action == null) {
208       throw new IllegalArgumentException("Action cannot be null");
209     }
210     this.accessControlEntries.put(role, action.toString());
211     return this;
212   }
213 
214     /**
215     * Returns the list of access control entries or an empty map if no access control entries have been specified.
216     *
217     * @return the access control entries
218     */
219   public Map<String, String> getAccessControlEntries() {
220     return accessControlEntries;
221   }
222 
223 
224   /**
225    * Selects series with the given description.
226    *
227    * @param description
228    *          the description
229    * @return the enhanced search query
230    */
231   public SeriesSearchQuery withDescription(String description) {
232     this.description = description;
233     return this;
234   }
235 
236   /**
237    * Returns the description of the series.
238    *
239    * @return the description
240    */
241   public String getDescription() {
242     return description;
243   }
244 
245   /**
246    * Selects series with the given subject.
247    * <p>
248    * Note that this method may be called multiple times to support selection of multiple series.
249    *
250    * @param subject
251    *          the subject
252    * @return the enhanced search query
253    */
254   public SeriesSearchQuery withSubject(String subject) {
255     if (StringUtils.isBlank(subject)) {
256       throw new IllegalArgumentException("Subject cannot be null");
257     }
258     this.subjects.add(subject);
259     return this;
260   }
261 
262   /**
263    * Returns the list of recording subjects or an empty array if no subject have been specified.
264    *
265    * @return the subjects
266    */
267   public String[] getSubjects() {
268     return subjects.toArray(new String[subjects.size()]);
269   }
270 
271   /**
272    * Returns the organization of the series.
273    *
274    * @return the organization
275    */
276   public String getOrganization() {
277     return organization;
278   }
279 
280   /**
281    * Returns the user of this search query
282    *
283    * @return the user of this search query
284    */
285   public User getUser() {
286     return user;
287   }
288 
289   /**
290    * Selects series with the given language.
291    *
292    * @param language
293    *          the language
294    * @return the enhanced search query
295    */
296   public SeriesSearchQuery withLanguage(String language) {
297     this.language = language;
298     return this;
299   }
300 
301   /**
302    * Returns the language of the series.
303    *
304    * @return the language
305    */
306   public String getLanguage() {
307     return language;
308   }
309 
310   /**
311    * Selects series with the given creator.
312    *
313    * @param creator
314    *          the creator
315    * @return the enhanced search query
316    */
317   public SeriesSearchQuery withCreator(String creator) {
318     this.creator = creator;
319     return this;
320   }
321 
322   /**
323    * Returns the creator of the series.
324    *
325    * @return the creator
326    */
327   public String getCreator() {
328     return creator;
329   }
330 
331   /**
332    * Selects series with the given license.
333    *
334    * @param license
335    *          the license
336    * @return the enhanced search query
337    */
338   public SeriesSearchQuery withLicense(String license) {
339     this.license = license;
340     return this;
341   }
342 
343   /**
344    * Returns the license of the series.
345    *
346    * @return the license
347    */
348   public String getLicense() {
349     return license;
350   }
351 
352   /**
353    * Selects series with the given access policy.
354    *
355    * @param accessPolicy
356    *          the access policy
357    * @return the enhanced search query
358    */
359   public SeriesSearchQuery withAccessPolicy(String accessPolicy) {
360     this.accessPolicy = accessPolicy;
361     return this;
362   }
363 
364   /**
365    * Returns the access policy of the series.
366    *
367    * @return the access policy
368    */
369   public String getAccessPolicy() {
370     return accessPolicy;
371   }
372 
373   /**
374    * Selects series with the given theme.
375    *
376    * @param theme
377    *          the theme
378    * @return the enhanced search query
379    */
380   public SeriesSearchQuery withTheme(long theme) {
381     this.theme = theme;
382     return this;
383   }
384 
385   /**
386    * Returns the theme of the series.
387    *
388    * @return the theme
389    */
390   public Long getTheme() {
391     return theme;
392   }
393 
394   /**
395    * Selects series with the given managed ACL name.
396    *
397    * @param managedAcl
398    *          the name of the managed ACL
399    * @return the enhanced search query
400    */
401   public SeriesSearchQuery withManagedAcl(String managedAcl) {
402     this.managedAcl = managedAcl;
403     return this;
404   }
405 
406   /**
407    * Returns the name of the managed ACL set to the series.
408    *
409    * @return the name of the managed ACL
410    */
411   public String getManagedAcl() {
412     return managedAcl;
413   }
414 
415   /**
416    * Selects series with the given organizers.
417    * <p>
418    * Note that this method may be called multiple times to support selection of multiple series.
419    *
420    * @param organizer
421    *          the organizer
422    * @return the enhanced search query
423    */
424   public SeriesSearchQuery withOrganizer(String organizer) {
425     if (StringUtils.isBlank(organizer)) {
426       throw new IllegalArgumentException("Organizer cannot be null");
427     }
428     this.organizers.add(organizer);
429     return this;
430   }
431 
432   /**
433    * Returns the list of series organizers or an empty array if no organizers have been specified.
434    *
435    * @return the organizers
436    */
437   public String[] getOrganizers() {
438     return organizers.toArray(new String[organizers.size()]);
439   }
440 
441   /**
442    * Selects series with the given contributor.
443    * <p>
444    * Note that this method may be called multiple times to support selection of multiple contributors.
445    *
446    * @param contributor
447    *          the contributor
448    * @return the enhanced search query
449    */
450   public SeriesSearchQuery withContributor(String contributor) {
451     if (StringUtils.isBlank(contributor)) {
452       throw new IllegalArgumentException("Contributor can't be null");
453     }
454     this.contributors.add(contributor);
455     return this;
456   }
457 
458   /**
459    * Returns the list of series contributors or an empty array if no contributor have been specified.
460    *
461    * @return the contributors
462    */
463   public String[] getContributors() {
464     return contributors.toArray(new String[contributors.size()]);
465   }
466 
467   /**
468    * Select series with the given publishers
469    *
470    * @param publisher
471    *          The publisher to add to the search query.
472    * @return This query with the added publisher
473    */
474   public SeriesSearchQuery withPublisher(String publisher) {
475     if (StringUtils.isBlank(publisher)) {
476       throw new IllegalArgumentException("Publisher can't be null");
477     }
478     this.publishers.add(publisher);
479     return this;
480   }
481 
482   /**
483    * Returns an array of series publishers or an empty array if no publisher has been specified.
484    *
485    * @return The publishers
486    */
487   public String[] getPublishers() {
488     return publishers.toArray(new String[publishers.size()]);
489   }
490 
491   /**
492    * The created date to start looking for series.
493    *
494    * @param createdFrom
495    *          The created date to start looking for series
496    * @return the enhanced search query
497    */
498   public SeriesSearchQuery withCreatedFrom(Date createdFrom) {
499     this.createdFrom = createdFrom;
500     return this;
501   }
502 
503   /**
504    * @return The Date after which all series returned should have been created
505    */
506   public Date getCreatedFrom() {
507     return createdFrom;
508   }
509 
510   /**
511    * The created date to stop looking for series.
512    *
513    * @param createdTo
514    *          The created date to stop looking for series
515    * @return the enhanced search query
516    */
517   public SeriesSearchQuery withCreatedTo(Date createdTo) {
518     this.createdTo = createdTo;
519     return this;
520   }
521 
522   /**
523    * @return The Date before which all series returned should have been created
524    */
525   public Date getCreatedTo() {
526     return createdTo;
527   }
528 
529   /**
530    * @param edit
531    *          True to only get series with edit permissions
532    * @return enhanced search query
533    */
534   public SeriesSearchQuery withEdit(Boolean edit) {
535     this.editOnly = edit;
536     return this;
537   }
538 
539   /**
540    * @return True to only get series that this user can edit.
541    */
542   public boolean isEditOnly() {
543     return editOnly;
544   }
545 
546   /**
547    * @param rightsHolder
548    *          The rights holder to search for
549    * @return enhanced query
550    */
551   public SeriesSearchQuery withRightsHolder(String rightsHolder) {
552     this.rightsHolder = rightsHolder;
553     return this;
554   }
555 
556   /**
557    * @return The rights holder to search for
558    */
559   public String getRightsHolder() {
560     return rightsHolder;
561   }
562 
563   /**
564    * Defines the sort order for the series by contributors.
565    *
566    * @param order
567    *          the order
568    * @return the enhanced search query
569    */
570   public SeriesSearchQuery sortByIdentifer(Order order) {
571     withSortOrder(SeriesIndexSchema.UID, order);
572     return this;
573   }
574 
575   /**
576    * Returns the sort order for the series created date.
577    *
578    * @return the sort order
579    */
580   public Order getSeriesIdentifierSortOrder() {
581     return getSortOrder(SeriesIndexSchema.UID);
582   }
583 
584   /**
585    * Defines the sort order for the series by contributors.
586    *
587    * @param order
588    *          the order
589    * @return the enhanced search query
590    */
591   public SeriesSearchQuery sortBySubject(Order order) {
592     withSortOrder(SeriesIndexSchema.SUBJECT, order);
593     return this;
594   }
595 
596   /**
597    * Returns the sort order for the series created date.
598    *
599    * @return the sort order
600    */
601   public Order getSeriesSubjectSortOrder() {
602     return getSortOrder(SeriesIndexSchema.SUBJECT);
603   }
604 
605   /**
606    * Defines the sort order for the series by contributors.
607    *
608    * @param order
609    *          the order
610    * @return the enhanced search query
611    */
612   public SeriesSearchQuery sortByCreator(Order order) {
613     withSortOrder(SeriesIndexSchema.CREATOR, order);
614     return this;
615   }
616 
617   /**
618    * Returns the sort order for the series created date.
619    *
620    * @return the sort order
621    */
622   public Order getSeriesCreatorSortOrder() {
623     return getSortOrder(SeriesIndexSchema.CREATOR);
624   }
625 
626   /**
627    * Defines the sort order for the series by contributors.
628    *
629    * @param order
630    *          the order
631    * @return the enhanced search query
632    */
633   public SeriesSearchQuery sortByPublishers(Order order) {
634     withSortOrder(SeriesIndexSchema.PUBLISHERS, order);
635     return this;
636   }
637 
638   /**
639    * Returns the sort order for the series created date.
640    *
641    * @return the sort order
642    */
643   public Order getSeriesPublishersSortOrder() {
644     return getSortOrder(SeriesIndexSchema.PUBLISHERS);
645   }
646 
647   /**
648    * Defines the sort order for the series by contributors.
649    *
650    * @param order
651    *          the order
652    * @return the enhanced search query
653    */
654   public SeriesSearchQuery sortByDescription(Order order) {
655     withSortOrder(SeriesIndexSchema.DESCRIPTION, order);
656     return this;
657   }
658 
659   /**
660    * Returns the sort order for the series created date.
661    *
662    * @return the sort order
663    */
664   public Order getSeriesDescriptionSortOrder() {
665     return getSortOrder(SeriesIndexSchema.DESCRIPTION);
666   }
667 
668   /**
669    * Defines the sort order for the series by contributors.
670    *
671    * @param order
672    *          the order
673    * @return the enhanced search query
674    */
675   public SeriesSearchQuery sortByLanguage(Order order) {
676     withSortOrder(SeriesIndexSchema.LANGUAGE, order);
677     return this;
678   }
679 
680   /**
681    * Returns the sort order for the series created date.
682    *
683    * @return the sort order
684    */
685   public Order getSeriesLanguageSortOrder() {
686     return getSortOrder(SeriesIndexSchema.LANGUAGE);
687   }
688 
689   /**
690    * Defines the sort order for the series by contributors.
691    *
692    * @param order
693    *          the order
694    * @return the enhanced search query
695    */
696   public SeriesSearchQuery sortByRightsHolder(Order order) {
697     withSortOrder(SeriesIndexSchema.RIGHTS_HOLDER, order);
698     return this;
699   }
700 
701   /**
702    * Returns the sort order for the series created date.
703    *
704    * @return the sort order
705    */
706   public Order getSeriesRightsHolderSortOrder() {
707     return getSortOrder(SeriesIndexSchema.RIGHTS_HOLDER);
708   }
709 
710   /**
711    * Defines the sort order for the series by contributors.
712    *
713    * @param order
714    *          the order
715    * @return the enhanced search query
716    */
717   public SeriesSearchQuery sortByLicense(Order order) {
718     withSortOrder(SeriesIndexSchema.LICENSE, order);
719     return this;
720   }
721 
722   /**
723    * Returns the sort order for the series created date.
724    *
725    * @return the sort order
726    */
727   public Order getSeriesLicenseSortOrder() {
728     return getSortOrder(SeriesIndexSchema.LICENSE);
729   }
730 
731   /**
732    * Defines the sort order for the series by contributors.
733    *
734    * @param order
735    *          the order
736    * @return the enhanced search query
737    */
738   public SeriesSearchQuery sortByContributors(Order order) {
739     withSortOrder(SeriesIndexSchema.CONTRIBUTORS, order);
740     return this;
741   }
742 
743   /**
744    * Returns the sort order for the series created date.
745    *
746    * @return the sort order
747    */
748   public Order getSeriesContributorsSortOrder() {
749     return getSortOrder(SeriesIndexSchema.CONTRIBUTORS);
750   }
751 
752   /**
753    * Defines the sort order for the managed ACL.
754    *
755    * @param order
756    *          the order
757    * @return the enhanced search query
758    */
759   public SeriesSearchQuery sortByManagedAcl(Order order) {
760     withSortOrder(SeriesIndexSchema.MANAGED_ACL, order);
761     return this;
762   }
763 
764   /**
765    * Returns the sort order for the series managed ACL.
766    *
767    * @return the sort order
768    */
769   public Order getSeriesManagedAclSortOrder() {
770     return getSortOrder(SeriesIndexSchema.MANAGED_ACL);
771   }
772 
773   /**
774    * Defines the sort order for the series created date &amp; time.
775    *
776    * @param order
777    *          the order
778    * @return the enhanced search query
779    */
780   public SeriesSearchQuery sortByCreatedDateTime(Order order) {
781     withSortOrder(SeriesIndexSchema.CREATED_DATE_TIME, order);
782     return this;
783   }
784 
785   /**
786    * Returns the sort order for the series created date.
787    *
788    * @return the sort order
789    */
790   public Order getSeriesDateSortOrder() {
791     return getSortOrder(SeriesIndexSchema.CREATED_DATE_TIME);
792   }
793 
794   /**
795    * Defines the sort order for the series by organizers.
796    *
797    * @param order
798    *          the order
799    * @return the enhanced search query
800    */
801   public SeriesSearchQuery sortByOrganizers(Order order) {
802     withSortOrder(SeriesIndexSchema.ORGANIZERS, order);
803     return this;
804   }
805 
806   /**
807    * Returns the sort order for the series organizers.
808    *
809    * @return the sort order
810    */
811   public Order getSeriesOrganizersSortOrder() {
812     return getSortOrder(SeriesIndexSchema.ORGANIZERS);
813   }
814 
815   /**
816    * Defines the sort order for the series by title.
817    *
818    * @param order
819    *          the order
820    * @return the enhanced search query
821    */
822   public SeriesSearchQuery sortByTitle(Order order) {
823     withSortOrder(SeriesIndexSchema.TITLE, order);
824     return this;
825   }
826 
827   /**
828    * Returns the sort order for the series title.
829    *
830    * @return the sort order
831    */
832   public Order getSeriesTitleSortOrder() {
833     return getSortOrder(SeriesIndexSchema.TITLE);
834   }
835 
836   @Override
837   public String toString() {
838     StringBuilder sb = new StringBuilder();
839     sb.append(SeriesSearchQuery.class.getSimpleName() + " ");
840     if (identifiers.size() > 0) {
841       sb.append("ids:'" + identifiers.toString() + "' ");
842     }
843     if (StringUtils.trimToNull(title) != null) {
844       sb.append("title:'" + title + "' ");
845     }
846     if (StringUtils.trimToNull(description) != null) {
847       sb.append("description:'" + description + "' ");
848     }
849     if (subjects.size() > 0) {
850       sb.append("subjects:'" + subjects.toString() + "' ");
851     }
852     if (StringUtils.trimToNull(organization) != null) {
853       sb.append("organization:'" + organization + "' ");
854     }
855     if (StringUtils.trimToNull(language) != null) {
856       sb.append("language:'" + language + "' ");
857     }
858     if (StringUtils.trimToNull(creator) != null) {
859       sb.append("creator:'" + creator + "' ");
860     }
861     if (StringUtils.trimToNull(license) != null) {
862       sb.append("license:'" + license + "' ");
863     }
864     if (StringUtils.trimToNull(accessPolicy) != null) {
865       sb.append("ACL:'" + accessPolicy + "' ");
866     }
867 
868     if (createdFrom != null) {
869       sb.append("Created From:'" + createdFrom + "' ");
870     }
871 
872     if (createdTo != null) {
873       sb.append("Created To:'" + createdTo + "' ");
874     }
875 
876     if (organizers.size() > 0) {
877       sb.append("organizers:'" + organizers.toString() + "' ");
878     }
879 
880     if (contributors.size() > 0) {
881       sb.append("contributors:'" + contributors.toString() + "' ");
882     }
883 
884     if (publishers.size() > 0) {
885       sb.append("publishers:'" + publishers.toString() + "' ");
886     }
887 
888     if (theme != null) {
889       sb.append("Theme:'" + theme + "' ");
890     }
891 
892     sb.append("Edit:'" + editOnly + "' ");
893 
894     if (getTerms().size() > 0) {
895       sb.append("Text:");
896       for (SearchTerms<String> searchTerm : getTerms()) {
897         sb.append("'" + searchTerm.getTerms() + "' ");
898       }
899     }
900 
901     if (StringUtils.trimToNull(rightsHolder) != null) {
902       sb.append("Rights Holder:'" + rightsHolder + "' ");
903     }
904 
905     return sb.toString();
906 
907   }
908 
909 }