001 /*
002 Licensed to the Apache Software Foundation (ASF) under one
003 or more contributor license agreements. See the NOTICE file
004 distributed with this work for additional information
005 regarding copyright ownership. The ASF licenses this file
006 to you under the Apache License, Version 2.0 (the
007 "License"); you may not use this file except in compliance
008 with the License. You may obtain a copy of the License at
009
010 http://www.apache.org/licenses/LICENSE-2.0
011
012 Unless required by applicable law or agreed to in writing,
013 software distributed under the License is distributed on an
014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 KIND, either express or implied. See the License for the
016 specific language governing permissions and limitations
017 under the License.
018 */
019 package org.apache.wiki.search;
020
021 import java.io.IOException;
022 import java.util.Collection;
023 import java.util.Iterator;
024 import java.util.Properties;
025 import java.util.StringTokenizer;
026 import java.util.TreeSet;
027
028 import org.apache.log4j.Logger;
029 import org.apache.wiki.WikiEngine;
030 import org.apache.wiki.WikiPage;
031 import org.apache.wiki.api.exceptions.NoRequiredPropertyException;
032 import org.apache.wiki.api.exceptions.ProviderException;
033 import org.apache.wiki.attachment.Attachment;
034 import org.apache.wiki.providers.WikiPageProvider;
035
036 /**
037 * Interface for the search providers that handle searching the Wiki
038 *
039 * @since 2.2.21.
040 */
041 public class BasicSearchProvider implements SearchProvider
042 {
043 private static final Logger log = Logger.getLogger(BasicSearchProvider.class);
044
045 private WikiEngine m_engine;
046
047 /**
048 * {@inheritDoc}
049 */
050 public void initialize(WikiEngine engine, Properties props)
051 throws NoRequiredPropertyException, IOException
052 {
053 m_engine = engine;
054 }
055
056 /**
057 * {@inheritDoc}
058 */
059 public void pageRemoved(WikiPage page) {}
060
061 /**
062 * {@inheritDoc}
063 */
064 public void reindexPage(WikiPage page) {}
065
066 /**
067 * Parses a query into something that we can use.
068 *
069 * @param query A query string.
070 * @return A parsed array.
071 */
072 public QueryItem[] parseQuery(String query)
073 {
074 StringTokenizer st = new StringTokenizer( query, " \t," );
075
076 QueryItem[] items = new QueryItem[st.countTokens()];
077 int word = 0;
078
079 log.debug("Expecting "+items.length+" items");
080
081 //
082 // Parse incoming search string
083 //
084
085 while( st.hasMoreTokens() )
086 {
087 log.debug("Item "+word);
088 String token = st.nextToken().toLowerCase();
089
090 items[word] = new QueryItem();
091
092 switch( token.charAt(0) )
093 {
094 case '+':
095 items[word].type = QueryItem.REQUIRED;
096 token = token.substring(1);
097 log.debug("Required word: "+token);
098 break;
099
100 case '-':
101 items[word].type = QueryItem.FORBIDDEN;
102 token = token.substring(1);
103 log.debug("Forbidden word: "+token);
104 break;
105
106 default:
107 items[word].type = QueryItem.REQUESTED;
108 log.debug("Requested word: "+token);
109 break;
110 }
111
112 items[word++].word = token;
113 }
114
115 return items;
116 }
117
118 private String attachmentNames(WikiPage page, String separator)
119 {
120 if(m_engine.getAttachmentManager().hasAttachments(page))
121 {
122 Collection attachments;
123 try
124 {
125 attachments = m_engine.getAttachmentManager().listAttachments(page);
126 }
127 catch (ProviderException e)
128 {
129 log.error("Unable to get attachments for page", e);
130 return "";
131 }
132
133 StringBuffer attachmentNames = new StringBuffer();
134 for( Iterator it = attachments.iterator(); it.hasNext(); )
135 {
136 Attachment att = (Attachment) it.next();
137 attachmentNames.append(att.getName());
138 if(it.hasNext())
139 attachmentNames.append(separator);
140 }
141 return attachmentNames.toString();
142 }
143
144 return "";
145 }
146
147 private Collection findPages( QueryItem[] query )
148 {
149 TreeSet<SearchResult> res = new TreeSet<SearchResult>( new SearchResultComparator() );
150 SearchMatcher matcher = new SearchMatcher( m_engine, query );
151
152 Collection allPages = null;
153 try
154 {
155 allPages = m_engine.getPageManager().getAllPages();
156 }
157 catch( ProviderException pe )
158 {
159 log.error( "Unable to retrieve page list", pe );
160 return null;
161 }
162
163 Iterator it = allPages.iterator();
164 while( it.hasNext() )
165 {
166 try
167 {
168 WikiPage page = (WikiPage) it.next();
169 if (page != null)
170 {
171 String pageName = page.getName();
172 String pageContent = m_engine.getPageManager().getPageText(pageName, WikiPageProvider.LATEST_VERSION) +
173 attachmentNames(page, " ");
174 SearchResult comparison = matcher.matchPageContent( pageName, pageContent );
175
176 if( comparison != null )
177 {
178 res.add( comparison );
179 }
180 }
181 }
182 catch( ProviderException pe )
183 {
184 log.error( "Unable to retrieve page from cache", pe );
185 }
186 catch( IOException ioe )
187 {
188 log.error( "Failed to search page", ioe );
189 }
190 }
191
192 return res;
193 }
194
195 /**
196 * {@inheritDoc}
197 */
198 public Collection findPages(String query)
199 {
200 return findPages(parseQuery(query));
201 }
202
203 /**
204 * {@inheritDoc}
205 */
206 public String getProviderInfo()
207 {
208 return "BasicSearchProvider";
209 }
210
211 }