/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Business Objects nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* ExecutionContextProperties.java
* Creation date: May 31, 2006.
* By: Joseph Wong
*/
package org.openquark.cal.runtime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import org.openquark.cal.services.LocaleUtilities;
/**
* This class encapsulates an <em>immutable</em> map of key-value pairs which are exposed in CAL as
* system properties. Only strings can be used as keys.
* <p>
* There are a number of keys whose values are constrained to be of a particular type, e.g.
* the value for the "cal.locale" property must be of type {@link java.util.Locale}. For these
* special keys, dedicated methods are available for accessing their values. These properties are
* known as <em>system properties</em>.
* <p>
* For other keys, their corresponding values can be objects of any type. It is up to the client
* code to coordinate the setting of the property on the Java side with the retrieval on the CAL side.
* <p>
* Note that instances of this class are immutable. In fact, the only way to build an instance is through
* the {@link ExecutionContextProperties.Builder} class, which contains methods for adding key-value pairs,
* and for finally building an instance of this class.
*
* @author Joseph Wong
*/
public final class ExecutionContextProperties {
/**
* An instance of this class can be used to gather up key-value pairs to turn into a
* {@link ExecutionContextProperties} instance.
*
* @author Joseph Wong
*/
public static final class Builder {
/**
* The map of string-valued keys to their values. Does not include cal.timezone.
*/
private final Map<String, Object> properties = new HashMap<String, Object>();
/**
* The value for the cal.timezone property. It will be null if the time zone is the default time zone and then
* lazily initialized. This is to speed up class loading on startup when time zones are not used.
*/
private TimeZone timeZone;
/**
* Constructs a Builder.
*/
public Builder() {
properties.put(ExecutionContextProperties.SYS_PROP_KEY_LOCALE, LocaleUtilities.INVARIANT_LOCALE);
//do not do this. We don't want to load the TimeZone related classes if they are not used.
//properties.put(ExecutionContextProperties.SYS_PROP_KEY_TIMEZONE, TimeZone.local());
}
/**
* Sets the current locale associated with the execution context.
* @param locale the locale.
*/
public void setLocale(Locale locale) {
if (locale == null) {
throw new NullPointerException("locale cannot be null.");
}
properties.put(ExecutionContextProperties.SYS_PROP_KEY_LOCALE, locale);
}
/**
* Sets the current time zone associated with the execution context.
* @param timeZone the time zone.
*/
public void setTimeZone(TimeZone timeZone) {
if (timeZone == null) {
throw new NullPointerException("timeZone cannot be null.");
}
this.timeZone = timeZone;
}
/**
* Sets the current time zone associated with the execution context.
* @param timeZoneID the time zone ID.
*/
public void setTimeZone(String timeZoneID) {
if (timeZoneID == null) {
throw new NullPointerException("timeZone cannot be null.");
}
this.timeZone = TimeZone.getTimeZone(timeZoneID);
}
/**
* Sets the value for a particular key. This method cannot be used for system properties - for these properties,
* use the dedicated set methods instead.
*
* @param key the key of the property.
* @param value the value of the property.
*/
public void setProperty(String key, Object value) {
if (ExecutionContextProperties.SYSTEM_PROPERTY_KEYS.contains(key)) {
throw new IllegalArgumentException("The property " + key + " is a system property. Set it via a dedicated setter method.");
}
properties.put(key, value);
}
/**
* Builds an {@link ExecutionContextProperties} instance based on the information gathered so far.
* @return a new instance of {@link ExecutionContextProperties}.
*/
public ExecutionContextProperties toProperties() {
return new ExecutionContextProperties(properties, timeZone);
}
}
/**
* A set of all the keys of the well-known system properties.
*/
private static final Set<String> SYSTEM_PROPERTY_KEYS = new HashSet<String>();
/**
* The system property key for the current locale associated with the execution context.
*/
public static final String SYS_PROP_KEY_LOCALE = makeSystemPropertyKey("cal.locale");
/**
* The system property key for the current time zone associated with the execution context.
*/
public static final String SYS_PROP_KEY_TIMEZONE = makeSystemPropertyKey("cal.timezone");
/**
* The map of string-valued keys to their values. Does not include the cal.timezone property.
*/
private final Map<String, Object> properties;
/**
* Value of the cal.timezone property. This is lazily initialized. Guarded by this.
*/
private TimeZone timeZone;
/**
* Helper for creating a system property key. The key is registered with {@link #SYSTEM_PROPERTY_KEYS}.
* @param key the system property key.
* @return the key itself.
*/
private static String makeSystemPropertyKey(String key) {
SYSTEM_PROPERTY_KEYS.add(key);
return key;
}
/**
* Private constructor meant to be called only by {@link ExecutionContextProperties.Builder#toProperties}.
* @param properties the map of string-valued keys to their values.
* @param timeZone timeZone
*/
private ExecutionContextProperties(Map<String, Object> properties, TimeZone timeZone) {
if (properties == null) {
throw new NullPointerException();
}
// make a copy of the map (since the Builder could still be around and modify its map)
this.properties = new HashMap<String, Object>(properties);
this.timeZone = timeZone;
}
/**
* Returns whether the specified property is defined.
* @param key the key for the property.
* @return true if the property is defined.
*/
public boolean hasProperty(String key) {
if (key.equals(SYS_PROP_KEY_TIMEZONE)) {
return true;
}
return properties.containsKey(key);
}
/**
* Returns the value of the specified property.
* @param key the key for the property.
* @return the value of the property, or null if there is no such property.
*/
public Object getProperty(String key) {
if (key.equals(SYS_PROP_KEY_TIMEZONE)) {
return getTimeZone();
}
return properties.get(key);
}
/**
* Returns the keys of all the defined properties.
* @return a List of the keys of all the defined properties.
*/
public List<String> getPropertyKeys() {
List<String> result = new ArrayList<String>(properties.keySet());
result.add(SYS_PROP_KEY_TIMEZONE);
Collections.sort(result);
return result;
}
/**
* @return the value of the system property for the current locale associated with the execution context.
*/
public Locale getLocale() {
return (Locale)getProperty(SYS_PROP_KEY_LOCALE);
}
/**
* @return the value of the system property for the current time zone associated with the execution context.
*/
public synchronized TimeZone getTimeZone() {
if (timeZone == null) {
timeZone = TimeZone.getDefault();
}
return timeZone;
}
}