blob: 593597ea7bcd869b6f8048923571ab2e41d569fc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2008 Oracle Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Oracle Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.jsf.designtime.internal.view.model.jsp.registry;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jst.jsf.common.internal.policy.OrderedListProvider;
import org.eclipse.jst.jsf.common.internal.policy.OrderedListProvider.OrderableObject;
import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
import org.eclipse.jst.jsf.designtime.internal.view.model.jsp.DefaultJSPTagResolver;
import org.eclipse.jst.jsf.designtime.internal.view.model.jsp.TagIntrospectingStrategy;
import org.eclipse.jst.jsf.designtime.internal.view.model.jsp.JSPTagResolvingStrategy.StrategyDescriptor;
import org.eclipse.jst.jsf.designtime.internal.view.model.jsp.persistence.PersistedDataTagStrategy;
/**
* Preferences model for the TLD registry. This class is not thread-safe and
* a single instance should only be used by one owner.
*
* @author cbateman
*
*/
public class TLDRegistryPreferences
{
private final static Map<String, StrategyDescriptor> ALL_KNOWN_STRATEGIES;
private final IPreferenceStore _prefStore;
private final CopyOnWriteArrayList<PropertyListener> _listeners;
private final AtomicBoolean _isDisposed = new AtomicBoolean(false);
private final static String KEY_STRATEGY_ID_ORDER = "org.eclipse.jst.jsf.designtime.jsp.registry.StrategyIDOrder"; //$NON-NLS-1$
private final static List<OrderableObject> DEFAULT_STRATEGY_ORDER;
static
{
final List<OrderableObject> list = new ArrayList<OrderableObject>();
// NOTE !!! this ordering is important and effects the default order
// in which strategies will be consulted !!!
list.add(new OrderableObject(new StrategyIdentifier(PersistedDataTagStrategy.createDescriptor()), true));
list.add(new OrderableObject(new StrategyIdentifier(DefaultJSPTagResolver.createDescriptor()), true));
list.add(new OrderableObject(new StrategyIdentifier(TagIntrospectingStrategy.createDescriptor()), true));
DEFAULT_STRATEGY_ORDER = Collections.unmodifiableList(list);
final Map<String, StrategyDescriptor> knownDescriptors = new HashMap<String, StrategyDescriptor>();
for (final OrderableObject object : DEFAULT_STRATEGY_ORDER)
{
StrategyIdentifier strategyId = (StrategyIdentifier) object.getObject();
knownDescriptors.put(strategyId.getId(), strategyId._descriptor);
}
ALL_KNOWN_STRATEGIES = Collections.unmodifiableMap(knownDescriptors);
}
private List<OrderableObject> _ids;
private List<OrderableObject> _originalIds;
private IPropertyChangeListener _propertyListener;
/**
* Constructor
*
* @param prefStore
*/
public TLDRegistryPreferences(final IPreferenceStore prefStore)
{
_prefStore = prefStore;
_ids = new ArrayList<OrderableObject>();
_listeners = new CopyOnWriteArrayList<PropertyListener>();
}
/**
* Dispose of this preferences object
*/
public void dispose()
{
if (_isDisposed.compareAndSet(false, true))
{
if (_propertyListener != null)
{
_prefStore.removePropertyChangeListener(_propertyListener);
}
}
}
void addListener(final PropertyListener propListener)
{
if (!assertNotDisposed())
{
return;
}
if (_propertyListener == null)
{
_propertyListener = new IPropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent event)
{
if (KEY_STRATEGY_ID_ORDER.equals(event.getProperty()))
{
fireStrategyOrderChanged();
}
}
};
_prefStore.addPropertyChangeListener(_propertyListener);
}
_listeners.addIfAbsent(propListener);
}
void removeListener(final PropertyListener propListener)
{
if (!assertNotDisposed())
{
return;
}
_listeners.remove(propListener);
if (_listeners.isEmpty())
{
_prefStore.removePropertyChangeListener(_propertyListener);
_propertyListener = null;
}
}
private void fireStrategyOrderChanged()
{
if (!assertNotDisposed())
{
return;
}
for (final PropertyListener listener : _listeners)
{
listener.strategyOrderChanged();
}
}
/**
* @return false if the assertion fails
*/
private boolean assertNotDisposed()
{
if (_isDisposed.get())
{
JSFCorePlugin.log(new Exception("Stack trace only"), "TLDRegistryPreferences is disposed"); //$NON-NLS-1$ //$NON-NLS-2$
return false;
}
return true;
}
/**
* IPreferenceStore The default preference loader
*/
public void load()
{
load(_prefStore);
}
/**
* @return the ordered list provider for the strategy id ordering
*/
public OrderedListProvider getOrderedListProvider()
{
return new MyOrderedListProvider();
}
/**
* @return the strategy id ordering
*/
public List<OrderableObject> getStrategyIdOrdering()
{
return _ids;
}
/**
* @param ids
*/
public void setStrategyIdOrdering(final List<OrderableObject> ids)
{
_ids = ids;
}
/**
* @return the list of strategy ids in the order they should be consulted
*/
public List<String> getEnabledIds()
{
final List<String> strategies = new ArrayList<String>();
for (final OrderableObject id : _ids)
{
if (id.isEnabled())
{
StrategyIdentifier strategyId = (StrategyIdentifier) id.getObject();
strategies.add(strategyId.getId());
}
}
return strategies;
}
/**
* Loads preferences from prefStore
*
* @param prefStore
*/
private void load(final IPreferenceStore prefStore)
{
if (!prefStore.contains(KEY_STRATEGY_ID_ORDER))
{
prefStore.setDefault(KEY_STRATEGY_ID_ORDER,
serialize(DEFAULT_STRATEGY_ORDER));
}
List<OrderableObject> ids = deserialize(prefStore
.getString(KEY_STRATEGY_ID_ORDER));
if (ids == null)
{
ids = deserialize(serialize(DEFAULT_STRATEGY_ORDER));
}
_ids = ids;
final List<OrderableObject> originalList = new ArrayList<OrderableObject>();
for (final OrderableObject id : _ids)
{
final OrderableObject copy = id.clone();
originalList.add(copy);
}
_originalIds = Collections.unmodifiableList(originalList);
}
private String serialize(final List<OrderableObject> ids)
{
final StringBuffer buffer = new StringBuffer();
for (final OrderableObject id : ids)
{
StrategyIdentifier strategyId = (StrategyIdentifier) id.getObject();
buffer.append("dummyValue"); //$NON-NLS-1$
buffer.append(","); //$NON-NLS-1$
buffer.append(strategyId.getId());
buffer.append(","); //$NON-NLS-1$
buffer.append(id.isEnabled());
buffer.append(","); //$NON-NLS-1$
}
return buffer.toString();
}
private List<OrderableObject> deserialize(final String serializedList)
{
final List<OrderableObject> list = new ArrayList<OrderableObject>();
final String[] ids = serializedList.split(","); //$NON-NLS-1$
if ((ids.length % 3) != 0)
{
return null;
}
for (int i = 0; i < ids.length; i += 3)
{
/// ingore the dummy value: final String displayName = ids[i];
String id = ids[i + 1];
final String enabled = ids[i + 2];
// fix old id for meta-data resolver
if ("org.eclipse.jst.jsf.THISISTEMPORARY".equals(id)) //$NON-NLS-1$
{
id = DefaultJSPTagResolver.ID;
}
final StrategyDescriptor desc = ALL_KNOWN_STRATEGIES.get(id);
if (desc == null)
{
JSFCorePlugin.log(new Exception("Stack trace only"), "Error: unknown strategy id: "+id); //$NON-NLS-1$ //$NON-NLS-2$
}
else
{
final StrategyIdentifier strategyIdentifier = new StrategyIdentifier(desc);
list.add(new OrderableObject(strategyIdentifier
, Boolean.valueOf(enabled).booleanValue()));
}
}
return list;
}
/**
* Commits but does not store the preferences
*
* @param prefStore
*/
public void commit(final IPreferenceStore prefStore)
{
prefStore.setValue(KEY_STRATEGY_ID_ORDER,
serialize(getStrategyIdOrdering()));
// refresh local copy of preferences
load();
}
/**
* Reverts the model to it's defaults. Does not commit to pref store.
*/
public void setDefaults()
{
setStrategyIdOrdering(new ArrayList<OrderableObject>(
DEFAULT_STRATEGY_ORDER));
}
/**
* @return true if this preference object's properties have
* changed since load() was last called.
*/
public boolean isDirty()
{
// dirty if the current list is not equal to the original list
// generated at load time.
return !(_ids.equals(_originalIds));
}
/**
* Used as the model for sorting and enabling strategy identifiers.
*
*/
public static class StrategyIdentifier
{
private final StrategyDescriptor _descriptor;
StrategyIdentifier(final StrategyDescriptor descriptor)
{
_descriptor = descriptor;
}
/**
* @return the id
*/
public String getId()
{
return _descriptor.getId();
}
@Override
public boolean equals(Object obj)
{
if (obj instanceof StrategyIdentifier)
{
return getId().equals(((StrategyIdentifier)obj).getId());
}
return false;
}
@Override
public int hashCode()
{
return getId().hashCode();
}
/**
* @return the display name of the strategy
*/
public String getDisplayName()
{
return _descriptor.getDisplayName();
}
}
private class MyOrderedListProvider extends OrderedListProvider
{
@Override
protected List<OrderableObject> createAndPopulateOrderedObjects()
{
return _ids;
}
}
static abstract class PropertyListener
{
public abstract void strategyOrderChanged();
}
}