View Javadoc
1   /**
2    * This file Copyright (c) 2013-2018 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.jackrabbit;
35  
36  import static info.magnolia.test.hamcrest.NodeMatchers.hasProperty;
37  import static info.magnolia.test.hamcrest.NodeMatchers.nodeName;
38  import static info.magnolia.test.hamcrest.UtilMatchers.regexMatch;
39  import static org.hamcrest.Matchers.*;
40  import static org.junit.Assert.*;
41  
42  import info.magnolia.cms.util.QueryUtil;
43  import info.magnolia.context.MgnlContext;
44  import info.magnolia.importexport.DataTransporter;
45  import info.magnolia.jcr.util.NodeUtil;
46  import info.magnolia.test.RepositoryTestCase;
47  
48  import java.io.File;
49  import java.io.FileInputStream;
50  import java.io.InputStream;
51  import java.util.Collection;
52  
53  import javax.jcr.ImportUUIDBehavior;
54  import javax.jcr.Node;
55  import javax.jcr.NodeIterator;
56  import javax.jcr.RepositoryException;
57  import javax.jcr.Session;
58  import javax.jcr.query.Query;
59  import javax.jcr.query.QueryManager;
60  import javax.jcr.query.QueryResult;
61  import javax.jcr.query.Row;
62  
63  import org.hamcrest.FeatureMatcher;
64  import org.hamcrest.Matcher;
65  import org.junit.Before;
66  import org.junit.Test;
67  
68  import com.google.common.collect.ImmutableList;
69  import com.google.common.collect.Iterables;
70  
71  
72  public class JackrabbitIndexingConfigurationTest extends RepositoryTestCase {
73  
74      private static final String UUID_PATTERN = ".*[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}.*";
75  
76      @Override
77      @Before
78      public void setUp() throws Exception {
79          super.setUp();
80  
81          File inputFile = new File(getClass().getResource("/website.demo-project.about.xml").getFile());
82  
83          InputStream inputStream = new FileInputStream(inputFile);
84  
85          DataTransporter.importXmlStream(inputStream, "website", "/", "test-stream", false, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, true, false);
86      }
87  
88      @Test
89      public void excludedPropertiesAreNotFoundInFullTextSearch() throws RepositoryException {
90          // GIVEN
91          String statement = "select * from [mgnl:page]";
92          Collection<Node> collection = executeQuery(statement);
93          assertThat(collection, hasSize(6));
94  
95          // WHEN
96          statement = "select * from [nt:base] as t where contains(t.[jcr:primaryType], 'mgnl:page')";
97          collection = executeQuery(statement);
98  
99          // THEN
100         assertThat(collection, hasSize(0));
101     }
102 
103     @Test
104     public void excludedPropertiesAreFoundInWhereEquals() throws RepositoryException {
105         // WHEN
106         String statement = "select * from [nt:base] as t where t.[jcr:primaryType] = 'mgnl:page'";
107         Collection<Node> collection = executeQuery(statement);
108 
109         // THEN
110         assertThat(collection, hasSize(6));
111     }
112 
113     @Test
114     public void excludedPropertiesAreFoundInWhereLike() throws RepositoryException {
115         // WHEN
116         String statement = "select * from [nt:base] as t where t.[jcr:primaryType] like 'mgnl:pag%'";
117         Collection<Node> collection = executeQuery(statement);
118 
119         // THEN
120         assertThat(collection, hasSize(6));
121     }
122 
123     @Test
124     public void titlePropertyIsBoosted() throws RepositoryException {
125         // WHEN
126         String statement = "select * from [mgnl:page] as t where contains(t.*, 'article') order by score() desc";
127         Collection<Node> collection = executeQuery(statement);
128 
129         // THEN
130         final Node first = Iterables.get(collection, 0);
131         final Node last = Iterables.getLast(collection);
132 
133         assertThat(first, allOf(
134                 nodeName("subsection-articles"),
135                 hasProperty("title", containsString("Articles"))
136         ));
137 
138         assertThat(last, allOf(
139                 nodeName("article"),
140                         hasProperty("title", not(containsString("article"))))
141         );
142     }
143 
144     @SuppressWarnings("unchecked")
145     @Test
146     public void indexConfigurationAggregatesAreasAndComponentsIntoMgnlPageFullIndex() throws RepositoryException {
147         // first case: searched text is at /page/area/component level
148         String statement = "select * from [mgnl:page] as t where contains(t.*, 'angleso')";
149         Collection<Node> nodes = executeQuery(statement);
150 
151         assertThat(nodes, containsInAnyOrder(
152                 hasProperty("title", "Standard Article"),
153                 hasProperty("title", "History"),
154                 hasProperty("title", "Article with TOC")
155         ));
156 
157         // now use the old way of getting nt:base nodes and then let info.magnolia.cms.util.QueryUtil.search(String, String, String, String) do the post-processing
158         // in Java in order to get the ancestors of type mgnl:page and filter out any duplicates. We should get the same result as above.
159         statement = "select * from [nt:base] as t where contains(t.*, 'angleso')";
160         nodes = executeQuery(statement, "mgnl:page");
161 
162         assertThat(nodes, contains(
163                 hasProperty("title", "Standard Article"),
164                 hasProperty("title", "History"),
165                 hasProperty("title", "Article with TOC")
166                 ));
167 
168         // second case: searched text is at /page/area/component/area/component level
169         statement = "select * from [mgnl:page] as t where contains(t.*, 'see also')";
170         nodes = executeQuery(statement);
171 
172         assertThat(nodes, contains(
173                 hasProperty("title", "Standard Article")));
174 
175         statement = "select * from [nt:base] as t where contains(t.*, 'see also')";
176         nodes = executeQuery(statement, "mgnl:page");
177 
178         assertThat(nodes, contains(
179                 hasProperty("title", "Standard Article")));
180     }
181 
182     @Test
183     public void excerptFunction() throws RepositoryException {
184         String statement = "SELECT rep:excerpt() from mgnl:page WHERE contains(., 'article')";
185         Session session = MgnlContext.getJCRSession("website");
186         QueryManager manager = session.getWorkspace().getQueryManager();
187         // excerpt functionality isn't supported in JCR_SQL2 https://issues.apache.org/jira/browse/JCR-3609
188         Query query = manager.createQuery(statement, Query.SQL);
189         // We need to work with QueryResult#rows anyway, so QueryUtil won't help
190         QueryResult result = query.execute();
191 
192         @SuppressWarnings("unchecked")
193         final ImmutableList<Row> rows = ImmutableList.<Row> copyOf(result.getRows());
194 
195         assertThat(rows, everyItem(column("rep:excerpt()", allOf(
196                 either(containsString("This is the abstract for the <strong>article</strong> page")).or(containsString("Teaser to an <strong>Article</strong>")),
197                 not(containsString("&lt;")),
198                 not(containsString("&gt;")),
199                 not(containsString("&quot;")),
200                 not(regexMatch(UUID_PATTERN))
201                 ))));
202 
203     }
204 
205     @Test
206     public void mgnlTagsMultivaluedPropertyIsNotExcludedFromFullTextSearch() throws RepositoryException {
207         // WHEN
208         String statement = "select * from [nt:base] as t where contains(t.*, 'foo')";
209         Collection<Node> collection = executeQuery(statement);
210 
211         // THEN
212         assertEquals(1, collection.size());
213 
214         // WHEN
215         statement = "select * from [nt:base] as t where contains(t.[mgnl:tags], 'bar')";
216         collection = executeQuery(statement);
217 
218         // THEN
219         assertEquals(1, collection.size());
220     }
221 
222     private static FeatureMatcher<Row, String> column(final String columnName, final Matcher<String> valueMatcher) {
223         return new FeatureMatcher<Row, String>(valueMatcher, columnName + " string value", columnName) {
224             @Override
225             protected String featureValueOf(Row row) {
226                 try {
227                     return row.getValue(columnName).getString();
228                 } catch (RepositoryException e) {
229                     throw new RuntimeException(e);
230                 }
231             }
232         };
233     }
234 
235     protected Collection<Node> executeQuery(String statement) throws RepositoryException {
236         NodeIterator result = QueryUtil.search("website", statement, Query.JCR_SQL2);
237         return NodeUtil.getCollectionFromNodeIterator(result);
238     }
239 
240     protected Collection<Node> executeQuery(String statement, String returnItemType) throws RepositoryException {
241         NodeIterator result = QueryUtil.search("website", statement, Query.JCR_SQL2, returnItemType);
242         return NodeUtil.getCollectionFromNodeIterator(result);
243     }
244 }