View Javadoc

1   package de.iqser.portlets;
2   
3   import java.io.IOException;
4   import java.util.ArrayList;
5   import java.util.List;
6   import java.util.Set;
7   import java.util.SortedSet;
8   import java.util.TreeSet;
9   
10  import javax.portlet.ActionRequest;
11  import javax.portlet.ActionResponse;
12  import javax.portlet.PortletContext;
13  import javax.portlet.PortletException;
14  import javax.portlet.PortletPreferences;
15  import javax.portlet.PortletRequestDispatcher;
16  import javax.portlet.RenderRequest;
17  import javax.portlet.RenderResponse;
18  import javax.portlet.WindowState;
19  import javax.servlet.http.HttpServletRequest;
20  import javax.servlet.http.HttpSession;
21  
22  import com.liferay.portal.kernel.log.Log;
23  import com.liferay.portal.kernel.log.LogFactoryUtil;
24  import com.liferay.portal.kernel.util.ParamUtil;
25  import com.liferay.portal.util.PortalUtil;
26  
27  import de.iqser.beans.BreadcrumbBean;
28  import de.iqser.beans.ContentBean;
29  import de.iqser.portlets.IqserBasePortlet;
30  import de.iqser.service.PortletIQserService;
31  
32  public class DisplayPortlet extends IqserBasePortlet {
33  	
34  	public final static String ALL_TYPES= "All types";
35  	public final static String PARAM_ALL_TYPES= "PARAM_ALL_TYPES";
36  	public final static String PARAM_CONTENT_LIST= "PARAM_CONTENT_LIST";
37  	public final static String PARAM_CONTENT_TYPES= "PARAM_CONTENT_TYPES";
38  	public final static String PARAM_CONTENT_TOTAL= "PARAM_CONTENT_TOTAL";
39  	public final static String PARAM_RELATED_LEVEL= "PARAM_RELATED_LEVEL";
40  	
41  	public final static String PREF_MIN_SCORE= "min Score";
42  	public final static String PREF_MAX_RESULTS= "max Results";
43  	public final static String PREF_SCROLLBAR_HEIGHT= "listHeight";
44  	public final static String PREF_SCROLLBAR_WIDTH= "listWidth";
45  	
46  	private static Log _ilog = LogFactoryUtil.getLog(DisplayPortlet.class);
47  	
48  	// Portlet init-Params
49  	public void init() throws PortletException {
50  		viewJSP = getInitParameter("view-jsp");
51  		editJSP = getInitParameter("edit-jsp");
52  		// helpJSP = getInitParameter("help-jsp");
53  	}
54  
55  	public void doView(RenderRequest req, RenderResponse res)
56  			throws IOException, PortletException {
57  
58  		res.setContentType("text/html");
59  
60  		PortletContext portletContext = getPortletContext();
61  
62  		String action = ParamUtil.getString(req, PARAM_ACTION);
63  		String errorMessage= "";
64  		
65  		PortletRequestDispatcher reqDispatcher = null;
66  		
67  		reqDispatcher = portletContext.getRequestDispatcher(viewJSP);
68  		int total= 0;
69  		
70  		// Check first if this is only a page event, not a new query.
71  		// In such cases we can get the cached data from the session.
72  		// Otherwise the portlets triggering a new query have removed the old session data.
73  		HttpServletRequest servletRequest= PortalUtil.getHttpServletRequest(req);
74  		HttpSession servletSession= servletRequest.getSession();
75  		List<ContentBean> contentList= (List<ContentBean>) servletSession.getAttribute(DEIQSER_CACHED_DATA);
76  		boolean noActionFound= true;
77  		if( action != null && action.startsWith("ACTION")) {
78  			noActionFound= false;
79  		}
80  		if(contentList != null && contentList.size() > 0 && noActionFound ) {
81  			SortedSet<String> allTypes= PortletIQserService.getAlltypes(contentList);
82  			// a page event or an event triggered elsewhere
83  			// it may be necessary to apply a filter
84  			Set<String> selectedTypes= (Set<String>) servletSession.getAttribute(DisplayPortlet.DEIQSER_SELECTED_TYPES);
85  			if( selectedTypes != null && selectedTypes.size() > 0) {
86  				// apply filter
87  				if( _ilog.isInfoEnabled()) {
88  					_ilog.info("A filter is applied after an event which is not a filter event");
89  				}
90  				if( !selectedTypes.contains(ALL_TYPES)) {
91  					// filter content list from session
92  					List<ContentBean> filteredList= new ArrayList<ContentBean>();
93  					for( int index= 0; index < contentList.size(); index++) {
94  						ContentBean contentBean= contentList.get(index);
95  						String type= contentBean.getType();
96  						if( selectedTypes.contains(type)) {
97  							filteredList.add(contentBean);
98  						}
99  					}
100 					total= PortletIQserService.total(filteredList);
101 					req.setAttribute(PARAM_CONTENT_LIST, filteredList);
102 				}
103 				else {
104 					// no filter, because the selected types contains string selecting all types
105 					total= PortletIQserService.total(contentList);
106 					req.setAttribute(PARAM_CONTENT_LIST, contentList);
107 				}
108 			}
109 			else {
110 				// no filter create a new default filter
111 				total= PortletIQserService.total(contentList);
112 				req.setAttribute(PARAM_CONTENT_LIST, contentList);
113 			}
114 			
115 			req.setAttribute(PARAM_CONTENT_TOTAL, new Integer(total));
116 			req.setAttribute(PARAM_CONTENT_TYPES, allTypes);
117 			// req.setAttribute(PARAM_SELECTED_TYPES, selectedTypes);	// not necessary, filter.jsp gets this from session
118 			reqDispatcher.include(req, res);
119 			return;	// stop, we are sure that no action was called
120 		}
121 		
122 		String searchInput= req.getParameter(IqserBasePortlet.PUBLIC_RENDER_PARAM_SEARCH_INPUT);
123 		if( searchInput != null) {
124 			searchInput= searchInput.trim();
125 		}
126 		else {
127 			searchInput= "";	// if we set empty string "" into the PUBLIC_RENDER_PARAM_SEARCH_INPUT, we get null here!
128 		}
129 		
130 		if( contentList == null && searchInput != null) {
131 			// new results are fetched in a service class
132 			if( searchInput.length() > 0) {			
133 				PortletPreferences prefs= req.getPreferences();
134 				String iqserWebserviceUrl= prefs.getValue(PREF_IQSER_WEBSERVICE, "");
135 				String maxResultsStr= prefs.getValue(PREF_MAX_RESULTS, "");
136 				contentList= PortletIQserService.searchIQSER(iqserWebserviceUrl, searchInput, maxResultsStr);
137 				if( contentList == null ) {
138 					errorMessage= "No connection to iQser Server!";
139 					req.setAttribute(PARAM_ERROR_MESSAGE, errorMessage);
140 					contentList= new ArrayList<ContentBean>();	// return empty list, because we cannot fetch data
141 				}
142 				else {
143 					errorMessage= "";
144 				}
145 			}
146 			else {
147 				errorMessage= "Search input must not be empty!";
148 				req.setAttribute(PARAM_ERROR_MESSAGE, errorMessage);
149 				req.setAttribute(PARAM_SEARCH_INPUT, "");
150 				contentList= new ArrayList<ContentBean>();	// return empty list, because we cannot fetch data
151 			}
152 			
153 			// store data in session for later reference
154 			servletSession.setAttribute(DEIQSER_CACHED_DATA, contentList); // contains a list without filter
155 			servletSession.setAttribute(DEIQSER_SEARCH_FIELD, searchInput);
156 		}
157 		total= PortletIQserService.total(contentList);
158 		if( searchInput == null ) {
159 			searchInput= (String) servletSession.getAttribute(DEIQSER_SEARCH_FIELD);
160 		}
161 		
162 		// we have the data, check if a filter was applied
163 		if( action != null && action.startsWith(ACTION_FILTER)) {
164 			Set<String> selectedTypes= new TreeSet<String>();
165 			String allTypesSelected= req.getParameter(PARAM_ALL_TYPES);
166 			// get selected types
167 			if( allTypesSelected != null && allTypesSelected.equals("true")) {
168 				// in the filter section the user has checked the check box for all types
169 				selectedTypes.add(ALL_TYPES);
170 				_ilog.info("Filter with all types");
171 			}
172 			else {
173 				// get selected types
174 				String[] selectedTypesArr= req.getParameterValues(PARAM_TYPES);
175 				if( selectedTypesArr == null ) {
176 					selectedTypesArr= new String[] { ALL_TYPES };	// should not happen
177 				}
178 				for( int index= 0; index < selectedTypesArr.length; index++) {
179 					String type= selectedTypesArr[index];
180 					selectedTypes.add(type);
181 					_ilog.info("Filter with type : " + type);
182 				}
183 			}
184 			// selectedTypes is filled as requested by the user
185 
186 			// store selected types in session to get them later in any case
187 			servletSession.setAttribute(DEIQSER_SELECTED_TYPES, selectedTypes);
188 			if( !selectedTypes.contains(ALL_TYPES)) {
189 				// filter content list from session
190 				List<ContentBean> filteredList= new ArrayList<ContentBean>();
191 				for( int index= 0; index < contentList.size(); index++) {
192 					ContentBean contentBean= contentList.get(index);
193 					String type= contentBean.getType();
194 					if( selectedTypes.contains(type)) {
195 						filteredList.add(contentBean);
196 					}
197 				}
198 				total= PortletIQserService.total(filteredList);
199 				req.setAttribute(PARAM_CONTENT_LIST, filteredList);
200 			}
201 			else {
202 				// no filter, because the selected types contains string selecting all types
203 				req.setAttribute(PARAM_CONTENT_LIST, contentList);
204 			}
205 		
206 			// get old search input from session
207 			searchInput= (String) servletSession.getAttribute(DEIQSER_SEARCH_FIELD);
208 		}	// if( action != null && action.startsWith(ACTION_FILTER
209 		else if( action!= null && action.startsWith(ACTION_SHOW_RELATED)) {
210 			// reset selectedTypes to all types
211 			Set<String> selectedTypes= (Set<String>) servletSession.getAttribute(DisplayPortlet.DEIQSER_SELECTED_TYPES);
212 			if( selectedTypes != null) {
213 				servletSession.removeAttribute(DEIQSER_SELECTED_TYPES);
214 			}
215 			// we need new data
216 			int contentId= ParamUtil.getInteger(req, PARAM_ID);
217 			String title= req.getParameter(PARAM_TITLE);
218 			PortletPreferences prefs= req.getPreferences();
219 			String iqserWebserviceUrl= prefs.getValue(PREF_IQSER_WEBSERVICE, "");
220 			String minScoreStr= prefs.getValue(PREF_MIN_SCORE, "");
221 			contentList= PortletIQserService.searchIQSER_Related(iqserWebserviceUrl, contentId, minScoreStr);
222 			servletSession.setAttribute(DEIQSER_CACHED_DATA, contentList);
223 			total= PortletIQserService.total(contentList);
224 			//searchInput="related content: id=" + contentId;
225 			req.setAttribute(PARAM_CONTENT_LIST, contentList);
226 			// store data
227 			List<BreadcrumbBean> relatedList= (List<BreadcrumbBean>) servletSession.getAttribute(DEIQSER_RELATED_LIST);
228 			if( relatedList == null) {
229 				relatedList= new ArrayList<BreadcrumbBean>();
230 			}
231 			if( title != null) {
232 				// add new selection to content list
233 				// if title is null, the PARAM_ID was set from the bread crumb => do not add a reference
234 				BreadcrumbBean bcBean= new BreadcrumbBean();
235 				bcBean.setId(""+ contentId);
236 				// if title is to large, use a substring
237 				if( title.length() > 20) {
238 					title= title.substring(0,20);
239 					title= title + "...";
240 				}
241 				// to avoid that the title is broken in the html: substitute blanks with &nbsp;
242 				title= title.replaceAll(" ", "&nbsp;");
243 				bcBean.setDisplayName(title);
244 				relatedList.add(bcBean);
245 				servletSession.setAttribute(DEIQSER_RELATED_LIST, relatedList);
246 			}
247 			req.setAttribute(PARAM_RELATED_LIST, relatedList);
248 			searchInput= (String) servletSession.getAttribute(DEIQSER_SEARCH_FIELD);
249 		}
250 		else if( action!= null && action.startsWith(ACTION_SHOW_BREADCRUMB)) {
251 			// reset selectedTypes to all types
252 			Set<String> selectedTypes= (Set<String>) servletSession.getAttribute(DisplayPortlet.DEIQSER_SELECTED_TYPES);
253 			if( selectedTypes != null) {
254 				servletSession.removeAttribute(DEIQSER_SELECTED_TYPES);
255 			}
256 			// we need new data
257 			BreadcrumbBean bcBean= null;
258 			int relatedLevel= ParamUtil.getInteger(req, PARAM_RELATED_LEVEL);
259 			List<BreadcrumbBean> relatedList= (List<BreadcrumbBean>) servletSession.getAttribute(DEIQSER_RELATED_LIST);
260 			if( relatedList == null ) {
261 				// possible after a refresh is performed when new  portlets are deployed
262 				relatedList= new ArrayList<BreadcrumbBean>();
263 				servletSession.setAttribute(DEIQSER_RELATED_LIST, relatedList);
264 			}
265 			else {
266 				// remove data > relatedLevel from stack
267 
268 				// list should be initialized by search or tree portlet
269 				List<BreadcrumbBean> newList= new ArrayList<BreadcrumbBean>();
270 				for( int index= 0; index <= relatedLevel; index++) {
271 					bcBean= relatedList.get(index);
272 					newList.add(bcBean);
273 				}
274 				servletSession.setAttribute(DEIQSER_RELATED_LIST, newList);
275 			}
276 			PortletPreferences prefs= req.getPreferences();
277 			String iqserWebserviceUrl= prefs.getValue(PREF_IQSER_WEBSERVICE, "");	
278 			if( relatedLevel == 0 && bcBean != null) {
279 				// user selected link identifying original search input
280 				searchInput= bcBean.getId();
281 				String maxResultsStr= prefs.getValue(PREF_MAX_RESULTS, "");
282 				contentList= PortletIQserService.searchIQSER(iqserWebserviceUrl, searchInput, maxResultsStr);
283 			}
284 			else if( bcBean != null) {
285 				// user selected a link containing related data ==> get id identifying the content
286 				String idStr= bcBean.getId();
287 				int id= -1;
288 				try {
289 					id= (new Integer(idStr)).intValue();
290 				}
291 				catch( NumberFormatException e) {
292 					_ilog.error("invalid related id " + idStr);
293 				}
294 				String minScoreStr= prefs.getValue(PREF_MIN_SCORE, "");
295 				contentList= PortletIQserService.searchIQSER_Related(iqserWebserviceUrl, id, minScoreStr);
296 			}
297 			else {
298 				// no valid bean
299 				contentList= new ArrayList<ContentBean>();
300 			}
301 			servletSession.setAttribute(DEIQSER_CACHED_DATA, contentList);
302 			total= PortletIQserService.total(contentList);
303 			//searchInput="related content: id=" + contentId;
304 			req.setAttribute(PARAM_CONTENT_LIST, contentList);			
305 
306 		}
307 		else {
308 			// no filter, return full list
309 			req.setAttribute(PARAM_CONTENT_LIST, contentList);
310 		}
311 		req.setAttribute(PARAM_SEARCH_INPUT, searchInput);
312 		req.setAttribute(PARAM_CONTENT_TOTAL, new Integer(total));
313 		SortedSet<String> allTypes= PortletIQserService.getAlltypes(contentList);
314 		req.setAttribute(PARAM_CONTENT_TYPES, allTypes);
315 		
316 		reqDispatcher.include(req, res);
317 	}
318 	
319 	// processAction is located in BasePortlet
320 	// If more is needed, this can override this method
321 	// the helper methods processActionUpdatePrefs and processActionInsertPref
322 	public void processAction(ActionRequest req,
323 			ActionResponse res) throws PortletException, IOException {
324 		super.processAction(req, res);
325 		String action = req.getParameter(PARAM_ACTION);
326 		if( action == null || !action.equals(ACTION_PREVIEW)) {
327 			return;
328 		}
329 		
330 		// we want a preview
331 		String contentId= req.getParameter(IqserBasePortlet.PARAM_ID);	// from action.jsp
332 		String contentType= req.getParameter(IqserBasePortlet.PARAM_CONTENT_TYPE);	// from action.jsp
333 		String contentProvider= req.getParameter(IqserBasePortlet.PARAM_CONTENT_PROVIDER);	// from action.jsp
334 		
335 		res.setRenderParameter(PUBLIC_RENDER_PARAM_CONTENT_ID, contentId);
336 		res.setRenderParameter(PUBLIC_RENDER_PARAM_CONTENT_TYPE, contentType);
337 		res.setRenderParameter(PUBLIC_RENDER_PARAM_CONTENT_PROVIDER, contentProvider);
338 	}
339 
340 }