Java tutorial
/* * Copyright (C) NetStruxr, Inc. All rights reserved. * * This software is published under the terms of the NetStruxr * Public Software License version 0.5, a copy of which has been * included with this distribution in the LICENSE.NPL file. */ package er.corebusinesslogic; import java.util.Enumeration; import org.apache.commons.lang.ObjectUtils; import org.apache.log4j.Logger; import com.webobjects.eocontrol.EOEditingContext; import com.webobjects.eocontrol.EOEnterpriseObject; import com.webobjects.eocontrol.EOKeyValueArchiver; import com.webobjects.eocontrol.EOKeyValueUnarchiver; import com.webobjects.foundation.NSArray; import com.webobjects.foundation.NSDictionary; import com.webobjects.foundation.NSForwardException; import com.webobjects.foundation.NSKeyValueCoding; import com.webobjects.foundation.NSNotification; import com.webobjects.foundation.NSNotificationCenter; import com.webobjects.foundation.NSPropertyListSerialization; import com.webobjects.foundation.NSSelector; import er.extensions.batching.ERXBatchNavigationBar; import er.extensions.components.ERXSortOrder; import er.extensions.eof.ERXConstant; import er.extensions.eof.ERXEC; import er.extensions.eof.ERXEOControlUtilities; import er.extensions.foundation.ERXProperties; import er.extensions.foundation.ERXRetainer; import er.extensions.foundation.ERXValueUtilities; /** * * @property er.corebusinesslogic.ERCoreUserPreferences.handlerClassName */ public class ERCoreUserPreferences implements NSKeyValueCoding { // =========================================================================== // Class Constant(s) // --------------------------------------------------------------------------- /** Logging support */ public static final Logger log = Logger.getLogger(ERCoreUserPreferences.class); /** EOEncoding key */ private final static String VALUE = "_V"; /** Notification that is posted when preferences change */ public final static String PreferenceDidChangeNotification = "PreferenceChangedNotification"; // =========================================================================== // Class Variable(s) // --------------------------------------------------------------------------- /** caches the singleton user preference object */ private static ERCoreUserPreferences _userPreferences; // =========================================================================== // Class Method(s) // --------------------------------------------------------------------------- /** * Gets the singleton instance for interacting with * the user preference system. * @return single instance of the user preferences */ public static ERCoreUserPreferences userPreferences() { if (_userPreferences == null) { _userPreferences = new ERCoreUserPreferences(); } return _userPreferences; } // =========================================================================== // Instance Method(s) // --------------------------------------------------------------------------- /** * Registers notification handlers for user preference notifications. These * are mainly used within the context of D2W pages. */ public void registerHandlers() { log.debug("Registering preference handlers"); Object handler = null; String handlerClassName = ERXProperties .stringForKey("er.corebusinesslogic.ERCoreUserPreferences.handlerClassName"); if (handlerClassName != null) { try { handler = Class.forName(handlerClassName).newInstance(); } catch (Exception e) { throw NSForwardException._runtimeExceptionForThrowable(e); } } if (handler == null) { handler = new _UserPreferenceHandler(); } ERXRetainer.retain(handler); } protected NSArray preferences(EOEditingContext ec) { ERCoreUserInterface user = (ERCoreUserInterface) ERCoreBusinessLogic.actor(ec); return user != null ? user.preferences() : NSArray.EmptyArray; } protected EOEnterpriseObject preferenceRecordForKey(String key, EOEditingContext ec) { EOEnterpriseObject result = null; if (key != null) { if (log.isDebugEnabled()) log.debug("Preference value for Key = " + key); for (Enumeration e = preferences(ec).objectEnumerator(); e.hasMoreElements();) { EOEnterpriseObject pref = (EOEnterpriseObject) e.nextElement(); String prefKey = (String) pref.valueForKey("key"); if (log.isDebugEnabled()) { log.debug("prefKey \"" + prefKey + "\""); } if (prefKey != null && prefKey.equals(key)) { result = pref; break; } } } return result; } protected String encodedValue(Object value) { EOKeyValueArchiver archiver = new EOKeyValueArchiver(); archiver.encodeObject(value, VALUE); String encodedValue = NSPropertyListSerialization.stringFromPropertyList(archiver.dictionary()); return encodedValue; } protected Object decodedValue(String encodedValue) { NSDictionary d = (NSDictionary) NSPropertyListSerialization.propertyListFromString(encodedValue); EOKeyValueUnarchiver u = new EOKeyValueUnarchiver(d); return u.decodeObjectForKey(VALUE); } // =========================================================================== // Implementation of NSKeyValueCoding // --------------------------------------------------------------------------- // FIXME -- unarchiving - archiving probably could use optimization public Object valueForKey(String key) { Object result = null; EOEditingContext ec = ERXEC.newEditingContext(); ec.lock(); try { EOEnterpriseObject pref = preferenceRecordForKey(key, ec); if (pref != null) { String encodedValue = (String) pref.valueForKey("value"); if (encodedValue != null) { result = decodedValue(encodedValue); } } } catch (RuntimeException ex) { log.error("Error while getting preference " + key + ": " + ex); } finally { ec.unlock(); } ec.dispose(); if (log.isDebugEnabled()) log.debug("Prefs vfk " + key + " = " + result); return result; } public void takeValueForKey(Object value, String key) { // we first make sure there is no cruft left // !! locking is turned off on the value attribute of UserPreference // so that if a user opens two sessions they don't get locking failures // this is OK for display style prefs (how many items, how they are sorted) // but might not be for more behavior-style prefs!! EOEditingContext ec = ERXEC.newEditingContext(); ec.lock(); try { EOEnterpriseObject pref = preferenceRecordForKey(key, ec); ERCoreUserInterface u = (ERCoreUserInterface) ERCoreBusinessLogic.actor(ec); if (pref != null) { if (value != null) { String encodedValue = encodedValue(value); if (ObjectUtils.notEqual(encodedValue, pref.valueForKey("value"))) { if (log.isDebugEnabled()) log.debug("Updating preference " + u + ": " + key + "=" + encodedValue); pref.takeValueForKey(encodedValue, "value"); } } else { if (log.isDebugEnabled()) log.debug("Removing preference " + u + ": " + key); ec.deleteObject(pref); } } else if (value != null) { pref = ERXEOControlUtilities.createAndInsertObject(ec, "ERCPreference"); u.newPreference(pref); // done this way to not force you to sub-class our User entity pref.takeValueForKey(ERXEOControlUtilities.primaryKeyObjectForObject((EOEnterpriseObject) u), "userID"); pref.takeValueForKey(key, "key"); pref.takeValueForKey(encodedValue(value), "value"); if (log.isDebugEnabled()) log.debug( "Creating preference " + u + ": " + key + " - " + value + " -- " + encodedValue(value)); } if (ec.hasChanges()) { ec.saveChanges(); } } catch (RuntimeException ex) { log.error("Error while setting preference " + key + ": " + ex); } finally { ec.unlock(); } ec.dispose(); NSNotificationCenter.defaultCenter().postNotification(PreferenceDidChangeNotification, new NSDictionary(value, key)); } public boolean booleanValueForKey(String key) { return booleanValueForKeyWithDefault(key, false); } public boolean booleanValueForKeyWithDefault(String key, boolean def) { return ERXValueUtilities.booleanValueWithDefault(valueForKey(key), def); } public static class _UserPreferenceHandler { public _UserPreferenceHandler() { NSNotificationCenter.defaultCenter().addObserver(this, new NSSelector("handleBatchSizeChange", ERXConstant.NotificationClassArray), ERXBatchNavigationBar.BatchSizeChanged, null); NSNotificationCenter.defaultCenter().addObserver(this, new NSSelector("handleSortOrderingChange", ERXConstant.NotificationClassArray), ERXSortOrder.SortOrderingChanged, null); } public void handleBatchSizeChange(NSNotification n) { handleChange("batchSize", n); } public void handleSortOrderingChange(NSNotification n) { handleChange("sortOrdering", n); } public void handleChange(String prefName, NSNotification n) { if (ERCoreBusinessLogic.actor() != null) { NSKeyValueCoding context = (NSKeyValueCoding) n.userInfo().objectForKey("d2wContext"); if (context != null && context.valueForKey("pageConfiguration") != null) { userPreferences().takeValueForKey(n.object(), prefName + "." + (String) context.valueForKey("pageConfiguration")); } } } } }