/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/calendar/trunk/calendar-summary-tool/tool/src/java/org/sakaiproject/tool/summarycalendar/ui/PrefsBean.java $
* $Id: PrefsBean.java 105078 2012-02-24 23:00:38Z ottenhoff@longsight.com $
***********************************************************************************
*
* Copyright (c) 2006, 2007, 2008 The Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**********************************************************************************/
package org.sakaiproject.tool.summarycalendar.ui;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Map.Entry;
import javax.faces.application.FacesMessage;
import javax.faces.application.FacesMessage.Severity;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.model.SelectItem;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.component.api.ServerConfigurationService;
import org.sakaiproject.component.cover.ComponentManager;
import org.sakaiproject.entity.api.ResourceProperties;
import org.sakaiproject.entity.api.ResourcePropertiesEdit;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.tool.api.SessionManager;
import org.sakaiproject.user.api.Preferences;
import org.sakaiproject.user.api.PreferencesEdit;
import org.sakaiproject.user.api.PreferencesService;
import org.sakaiproject.util.ResourceLoader;
public class PrefsBean {
/** Preferences properties */
public static String PREFS_KEY = "sakai:calendar:calendar-summary";
public static String PREFS_LAST_MODIFIED = "lastModified";
public static String PREFS_VIEW_MODE = "viewMode";
public static String PREFS_HIGHPRIORITY_COLOR = "highPriorityColor";
public static String PREFS_MEDIUMPRIORITY_COLOR = "mediumPriorityColor";
public static String PREFS_LOWPRIORITY_COLOR = "lowPriorityColor";
public static String PREFS_HIGHPRIORITY_EVENTS = "highPriorityEvents";
public static String PREFS_MEDIUMPRIORITY_EVENTS = "mediumPriorityEvents";
public static String PREFS_LOWPRIORITY_EVENTS = "lowPriorityEvents";
/** sakai.properties default values */
public static String SAKPROP_BASE = "calendarSummary.";
/** Our log (commons). */
private static Log LOG = LogFactory.getLog(PrefsBean.class);
/** Resource bundle */
private transient ResourceLoader msgs = new ResourceLoader("calendar");
/** Bean members */
private List viewModes = null;
private String selectedViewMode = null;
private String selectedHighPrColor = null;
private String selectedMediumPrColor = null;
private String selectedLowPrColor = null;
//private static List eventTypes = null;
private Collection highPriorityEvents = null;
private Collection mediumPriorityEvents = null;
private Collection lowPriorityEvents = null;
/** Private members */
private String message = null;
private Severity messageSeverity = null;
private Map priorityColorsMap = null;
private Map priorityEventsMap = null;
/** Sakai Services */
private static transient PreferencesService M_ps = (PreferencesService) ComponentManager.get(PreferencesService.class.getName());
private static transient SessionManager M_sm = (SessionManager) ComponentManager.get(SessionManager.class.getName());
private static transient ServerConfigurationService M_cfg = (ServerConfigurationService) ComponentManager.get(ServerConfigurationService.class.getName());
// ######################################################################################
// Main methods
// ######################################################################################
public PrefsBean(){
}
public String getInitValues() {
// reload localized event types
EventTypes.reloadLocalization();
return "";
}
// ######################################################################################
// Action/ActionListener methods
// ######################################################################################
public boolean isMessageToBeDisplayed() {
if(message != null){
FacesContext fc = FacesContext.getCurrentInstance();
fc.addMessage("msg", new FacesMessage(messageSeverity, message, null));
message = null;
return true;
}
return false;
}
public String update() {
try{
// read from FacesContext
setSelectedViewMode(getValueFromFacesContext("prefsForm:selectViewMode"));
setSelectedHighPriorityColor(getValueFromFacesContext("prefsForm:highPriorityColor"));
setSelectedMediumPriorityColor(getValueFromFacesContext("prefsForm:mediumPriorityColor"));
setSelectedLowPriorityColor(getValueFromFacesContext("prefsForm:lowPriorityColor"));
setSelectedHighPriorityEvents(getValuesFromFacesContext("prefsForm:highPriorityEvents"));
setSelectedMediumPriorityEvents(getValuesFromFacesContext("prefsForm:mediumPriorityEvents"));
setSelectedLowPriorityEvents(getValuesFromFacesContext("prefsForm:lowPriorityEvents"));
// update User Preferences
setPreferenceString(PREFS_VIEW_MODE, selectedViewMode);
setPreferenceString(PREFS_HIGHPRIORITY_COLOR, selectedHighPrColor);
setPreferenceString(PREFS_MEDIUMPRIORITY_COLOR, selectedMediumPrColor);
setPreferenceString(PREFS_LOWPRIORITY_COLOR, selectedLowPrColor);
clearPreferenceList(PREFS_HIGHPRIORITY_EVENTS);
clearPreferenceList(PREFS_MEDIUMPRIORITY_EVENTS);
clearPreferenceList(PREFS_LOWPRIORITY_EVENTS);
setPreferenceList(PREFS_HIGHPRIORITY_EVENTS, highPriorityEvents);
setPreferenceList(PREFS_MEDIUMPRIORITY_EVENTS, mediumPriorityEvents);
setPreferenceList(PREFS_LOWPRIORITY_EVENTS, lowPriorityEvents);
setPreferenceString(PREFS_LAST_MODIFIED, Long.toString(System.currentTimeMillis()));
priorityColorsMap = null;
priorityEventsMap = null;
}catch(Exception e){
// error occurred
message = msgs.getString("prefs_not_updated");
messageSeverity = FacesMessage.SEVERITY_FATAL;
LOG.error("Calendar Summary: "+message, e);
return "prefs";
}
// all ok
return "calendar";
}
public String cancel() {
message = null;
priorityColorsMap = null;
priorityEventsMap = null;
return "calendar";
}
// ######################################################################################
// Generic get/set methods
// ######################################################################################
private void readPriorityColorsMap() {
// priority colors (CSS properties)
priorityColorsMap = getPreferencePriorityColors();
selectedHighPrColor = (String) priorityColorsMap.get(PREFS_HIGHPRIORITY_COLOR);
selectedMediumPrColor = (String) priorityColorsMap.get(PREFS_MEDIUMPRIORITY_COLOR);
selectedLowPrColor = (String) priorityColorsMap.get(PREFS_LOWPRIORITY_COLOR);
}
private void readPriorityEventsMap() {
// priority events
priorityEventsMap = getPreferencePriorityEvents();
highPriorityEvents = (List) priorityEventsMap.get(PREFS_HIGHPRIORITY_EVENTS);
mediumPriorityEvents = (List) priorityEventsMap.get(PREFS_MEDIUMPRIORITY_EVENTS);
lowPriorityEvents = (List) priorityEventsMap.get(PREFS_LOWPRIORITY_EVENTS);
}
public String getSelectedViewMode() {
selectedViewMode = getPreferenceViewMode();
return selectedViewMode;
}
public void setSelectedViewMode(String selectedViewMode) {
this.selectedViewMode = selectedViewMode;
}
public List getViewModes() {
viewModes = new ArrayList();
viewModes.add(new SelectItem(CalendarBean.MODE_MONTHVIEW, msgs.getString("month_view")));
viewModes.add(new SelectItem(CalendarBean.MODE_WEEKVIEW, msgs.getString("week_view")));
return viewModes;
}
public String getSelectedHighPriorityColor() {
if(priorityColorsMap == null)
readPriorityColorsMap();
return selectedHighPrColor;
}
public void setSelectedHighPriorityColor(String color) {
this.selectedHighPrColor = color;
}
public String getSelectedMediumPriorityColor() {
if(priorityColorsMap == null)
readPriorityColorsMap();
return selectedMediumPrColor;
}
public void setSelectedMediumPriorityColor(String color) {
this.selectedMediumPrColor = color;
}
public String getSelectedLowPriorityColor() {
if(priorityColorsMap == null)
readPriorityColorsMap();
return selectedLowPrColor;
}
public void setSelectedLowPriorityColor(String color) {
this.selectedLowPrColor = color;
}
public List<SelectItem> getHighPriorityEvents(){
if(priorityEventsMap == null)
readPriorityEventsMap();
return listOfEventTypesToLocalizedList(highPriorityEvents);
}
public void setHighPriorityEvents(List<SelectItem> events){
this.highPriorityEvents = new ArrayList<String>();
Iterator<SelectItem> i = events.iterator();
while(i.hasNext()){
SelectItem e = i.next();
highPriorityEvents.add(e.getValue());
}
}
public List<String> getSelectedHighPriorityEvents(){
return new ArrayList<String>();
}
public void setSelectedHighPriorityEvents(List<String> events){
this.highPriorityEvents = events;
}
public void setSelectedHighPriorityEvents(Collection<String> events){
this.highPriorityEvents = events;
}
public List<SelectItem> getMediumPriorityEvents(){
if(priorityEventsMap == null)
readPriorityEventsMap();
return listOfEventTypesToLocalizedList(mediumPriorityEvents);
}
public void setMediumPriorityEvents(List<SelectItem> events){
this.mediumPriorityEvents = new ArrayList<String>();
Iterator<SelectItem> i = events.iterator();
while(i.hasNext()){
SelectItem e = i.next();
mediumPriorityEvents.add(e.getValue());
}
}
public List<String> getSelectedMediumPriorityEvents(){
return new ArrayList<String>();
}
public void setSelectedMediumPriorityEvents(List<String> events){
this.mediumPriorityEvents = events;
}
public void setSelectedMediumPriorityEvents(Collection<String> events){
this.mediumPriorityEvents = events;
}
public List<SelectItem> getLowPriorityEvents(){
if(priorityEventsMap == null)
readPriorityEventsMap();
return listOfEventTypesToLocalizedList(lowPriorityEvents);
}
public void setLowPriorityEvents(List<SelectItem> events){
this.lowPriorityEvents = new ArrayList<String>();
Iterator<SelectItem> i = events.iterator();
while(i.hasNext()){
SelectItem e = i.next();
lowPriorityEvents.add(e.getValue());
}
}
public List<String> getSelectedLowPriorityEvents(){
return new ArrayList<String>();
}
public void setSelectedLowPriorityEvents(List<String> events){
this.lowPriorityEvents = events;
}
public void setSelectedLowPriorityEvents(Collection<String> events){
this.lowPriorityEvents = events;
}
// ######################################################################################
// Preferences methods
// ######################################################################################
public static long getPreferenceLastModified() {
Long lastModified = 0l;
String value = getPreferenceString(PREFS_LAST_MODIFIED);
if(value != null){
try{
lastModified = Long.parseLong(value);
}catch(NumberFormatException e){
lastModified = 0l;
}
}
return lastModified;
}
public static String getPreferenceViewMode() {
String value = getPreferenceString(PREFS_VIEW_MODE);
// preferences not set, read from sakai.properties
if(value == null){
value = getDefaultStringFromSakaiProperties(PREFS_VIEW_MODE);
}
// sakai.properties default not set, using 'month'
if(value == null){
return CalendarBean.MODE_MONTHVIEW;
}else
return value;
}
public static Map getPreferencePriorityColors() {
HashMap map = new HashMap();
String h = getPreferenceString(PREFS_HIGHPRIORITY_COLOR);
String m = getPreferenceString(PREFS_MEDIUMPRIORITY_COLOR);
String l = getPreferenceString(PREFS_LOWPRIORITY_COLOR);
// preferences not set, read from sakai.properties
if(h == null && m == null && l == null){
h = getDefaultStringFromSakaiProperties(PREFS_HIGHPRIORITY_COLOR);
m = getDefaultStringFromSakaiProperties(PREFS_MEDIUMPRIORITY_COLOR);
l = getDefaultStringFromSakaiProperties(PREFS_LOWPRIORITY_COLOR);
}
map.put(PREFS_HIGHPRIORITY_COLOR, h);
map.put(PREFS_MEDIUMPRIORITY_COLOR, m);
map.put(PREFS_LOWPRIORITY_COLOR, l);
return map;
}
public static Map getPreferencePriorityEvents() {
HashMap map = new HashMap();
List h = getPreferenceList(PREFS_HIGHPRIORITY_EVENTS);
List m = getPreferenceList(PREFS_MEDIUMPRIORITY_EVENTS);
List l = getPreferenceList(PREFS_LOWPRIORITY_EVENTS);
// preferences not set, read from sakai.properties
if(h == null && m == null && l == null){
h = getDefaultListFromSakaiProperties(PREFS_HIGHPRIORITY_EVENTS);
m = getDefaultListFromSakaiProperties(PREFS_MEDIUMPRIORITY_EVENTS);
l = getDefaultListFromSakaiProperties(PREFS_LOWPRIORITY_EVENTS);
}
if(h == null) h = new ArrayList();
if(m == null) m = new ArrayList();
if(l == null) l = new ArrayList();
// make sure all available events are listed
// no pass-by-reference in java, must use a work-around...
List temp = new ArrayList();
temp.addAll(EventTypes.getEventTypes());
PairList lists = new PairList(h, temp);
lists = validateEventList(lists);
h = lists.dataList;
lists.dataList = m;
lists = validateEventList(lists);
m = lists.dataList;
lists.dataList = l;
lists = validateEventList(lists);
l = lists.dataList;
// add all non-specified events to low priority list
l.addAll(lists.tempList);
// sort lists
//Collections.sort(h);
//Collections.sort(m);
//Collections.sort(l);
map.put(PREFS_HIGHPRIORITY_EVENTS, h);
map.put(PREFS_MEDIUMPRIORITY_EVENTS, m);
map.put(PREFS_LOWPRIORITY_EVENTS, l);
return map;
}
/**
* Get the current user preference value. First attempt Preferences, then defaults from sakai.properties.
* @param name The property name.
* @return The preference value or null if not set.
*/
private static String getPreferenceString(String name) {
Preferences prefs = M_ps.getPreferences(M_sm.getCurrentSessionUserId());
ResourceProperties rp = prefs.getProperties(PREFS_KEY);
String value = rp.getProperty(name);
return value;
}
/**
* Get the current user preference list value. First attempt Preferences, then defaults from sakai.properties.
* @param name The property name.
* @return The preference list value or null if not set.
*/
private static List getPreferenceList(String name) {
Preferences prefs = M_ps.getPreferences(M_sm.getCurrentSessionUserId());
ResourceProperties rp = prefs.getProperties(PREFS_KEY);
List l = rp.getPropertyList(name);
return l;
}
private static void setPreferenceString(String name, String value) throws Exception {
PreferencesEdit prefsEdit = null;
String userId = M_sm.getCurrentSessionUserId();
try{
prefsEdit = M_ps.edit(userId);
}catch(IdUnusedException e){
prefsEdit = M_ps.add(userId);
}
try{
ResourcePropertiesEdit props = prefsEdit.getPropertiesEdit(PREFS_KEY);
if(value == null){
props.removeProperty(name);
}else{
props.addProperty(name, value.toString());
}
}catch(Exception e){
if(prefsEdit != null)
M_ps.cancel(prefsEdit);
throw e;
}
M_ps.commit(prefsEdit);
}
private static void setPreferenceList(String name, Collection values) throws Exception {
PreferencesEdit prefsEdit = null;
String userId = M_sm.getCurrentSessionUserId();
try{
prefsEdit = M_ps.edit(userId);
}catch(IdUnusedException e){
prefsEdit = M_ps.add(userId);
}
try{
ResourcePropertiesEdit props = prefsEdit.getPropertiesEdit(PREFS_KEY);
if(values == null){
props.removeProperty(name);
}else{
List existing = props.getPropertyList(name);
Iterator it = values.iterator();
while(it.hasNext()){
String value = (String) it.next();
if(existing == null || !existing.contains(value))
props.addPropertyToList(name, value.toString());
}
}
}catch(Exception e){
if(prefsEdit != null)
M_ps.cancel(prefsEdit);
M_ps.cancel(prefsEdit);
throw e;
}
M_ps.commit(prefsEdit);
}
private static void clearPreferenceList(String name) throws Exception {
PreferencesEdit prefsEdit = null;
try{
prefsEdit = M_ps.edit(M_sm.getCurrentSessionUserId());
ResourcePropertiesEdit props = prefsEdit.getPropertiesEdit(PREFS_KEY);
props.removeProperty(name);
}catch(Exception e){
M_ps.cancel(prefsEdit);
throw e;
}
M_ps.commit(prefsEdit);
}
private static String getDefaultStringFromSakaiProperties(String name) {
String value = M_cfg.getString(SAKPROP_BASE + name);
return value;
}
private static List getDefaultListFromSakaiProperties(String name) {
List l = new ArrayList();
String[] valuesStr = M_cfg.getStrings(SAKPROP_BASE + name);
if(valuesStr == null)
return l;
else{
for(int i=0; i<valuesStr.length; i++){
l.add(valuesStr[i]);
}
}
return l;
}
// ######################################################################################
// Util methods
// ######################################################################################
protected Set getValuesFromFacesContext(String componentId) {
Set values = new HashSet();
String[] str = (String[]) FacesContext.getCurrentInstance().getExternalContext().getRequestParameterValuesMap().get(componentId);
if(str != null){
for(int i = 0; i < str.length; i++){
values.add(str[i]);
}
}
return values;
}
protected String getValueFromFacesContext(String componentId) {
String[] str = (String[]) FacesContext.getCurrentInstance().getExternalContext().getRequestParameterValuesMap().get(componentId);
return str[0];
}
private List<SelectItem> listOfEventTypesToLocalizedList(Collection<String> l) {
List<SelectItem> list = new ArrayList<SelectItem>();
if(l == null)
return list;
Iterator<String> lI = l.iterator();
while(lI.hasNext()){
String eventType = lI.next();
SelectItem item = new SelectItem(eventType, EventTypes.getLocalizedEventType(eventType));
list.add(item);
}
return list;
}
/**
* Foreach 'list' entry A, remove it from 'temp'. If A doesn't exist in 'temp', remove it from 'list'.
* @param list A event priority List.
* @param temp A List with all events.
*/
private static PairList validateEventList(PairList lists) {
List temp = lists.tempList;
List list = lists.dataList;
if(list == null){
return lists;
}
List toRemoveFromList = new ArrayList();
Iterator iL = list.iterator();
while(iL.hasNext()){
Object e = iL.next();
if(temp.contains(e))
temp.remove(e);
else
toRemoveFromList.add(e);
}
Iterator iR = toRemoveFromList.iterator();
while(iR.hasNext()){
Object e = iR.next();
list.remove(e);
}
lists.dataList = list;
lists.tempList = temp;
return lists;
}
}
/** Pair of lists */
class PairList {
public List dataList;
public List tempList;
public PairList(List dataList, List tempList) {
this.dataList = dataList;
this.tempList = tempList;
}
}