blob: cc82db7d9124f9a3560bcbc4f837f3f9a7b4c570 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Cloudsmith Inc. 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:
* Cloudsmith Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.internal.p2.metadata.expression;
import java.util.*;
import java.util.Map.Entry;
import org.eclipse.equinox.internal.p2.core.helpers.CollectionUtils;
import org.eclipse.equinox.p2.metadata.expression.IMemberProvider;
import org.osgi.framework.ServiceReference;
public abstract class MemberProvider implements IMemberProvider {
static class DictionaryMemberProvider extends MemberProvider {
private final Dictionary<String, ? extends Object> dictionary;
public DictionaryMemberProvider(Dictionary<String, ? extends Object> dictionary) {
this.dictionary = dictionary;
}
public Object getMember(String memberName) {
return dictionary.get(memberName);
}
}
static class CIDictionaryMemberProvider extends DictionaryMemberProvider {
public CIDictionaryMemberProvider(Dictionary<String, ? extends Object> dictionary) {
super(lowerCaseKeys(dictionary));
}
@Override
public Object getMember(String memberName) {
return super.getMember(memberName == null ? null : memberName.toLowerCase());
}
private static Dictionary<String, ? extends Object> lowerCaseKeys(Dictionary<String, ? extends Object> dictionary) {
boolean hasUpperCase = false;
for (Enumeration<String> keys = dictionary.keys(); keys.hasMoreElements();) {
String key = keys.nextElement();
if (key.toLowerCase() != key) {
hasUpperCase = true;
break;
}
}
if (!hasUpperCase)
return dictionary;
Dictionary<String, Object> lcMap = new Hashtable<String, Object>(dictionary.size());
for (Enumeration<String> keys = dictionary.keys(); keys.hasMoreElements();) {
String key = keys.nextElement();
if (lcMap.put(key.toLowerCase(), dictionary.get(key)) != null)
throw new IllegalArgumentException("case variants of the same key name: '" + key + '\''); //$NON-NLS-1$
}
return lcMap;
}
}
static class MapMemberProvider extends MemberProvider {
private final Map<String, ? extends Object> map;
public MapMemberProvider(Map<String, ? extends Object> map) {
this.map = map;
}
public Object getMember(String memberName) {
return map.get(memberName);
}
}
static class CIMapMemberProvider extends MapMemberProvider {
public CIMapMemberProvider(Map<String, ? extends Object> map) {
super(lowerCaseKeys(map));
}
@Override
public Object getMember(String memberName) {
return super.getMember(memberName == null ? null : memberName.toLowerCase());
}
private static Map<String, ? extends Object> lowerCaseKeys(Map<String, ? extends Object> map) {
boolean hasUpperCase = false;
Set<? extends Entry<String, ? extends Object>> entrySet = map.entrySet();
for (Entry<String, ?> entry : entrySet) {
String key = entry.getKey();
String lowKey = key.toLowerCase();
if (key != lowKey) {
hasUpperCase = true;
break;
}
}
if (!hasUpperCase)
return map;
Map<String, Object> lcMap = new HashMap<String, Object>(map.size());
for (Entry<String, ?> entry : entrySet) {
if (lcMap.put(entry.getKey().toLowerCase(), entry.getValue()) != null)
throw new IllegalArgumentException("case variants of the same key name: '" + entry.getKey() + '\''); //$NON-NLS-1$
}
return lcMap;
}
}
static class ServiceRefMemberProvider extends MemberProvider {
private final ServiceReference<?> serviceRef;
public ServiceRefMemberProvider(ServiceReference<?> serviceRef) {
this.serviceRef = serviceRef;
}
public Object getMember(String memberName) {
return serviceRef.getProperty(memberName);
}
}
private static final MemberProvider emptyProvider = create(CollectionUtils.emptyMap(), false);
/**
* Create a new member provider on the given value. The value can be an instance of a {@link Map}, {@link Dictionary},
* or {@link ServiceReference}.
* @param value The value that provides the members
* @param caseInsensitive <code>true</code> if the members should be retrievable in a case insensitive way.
* @return A member provided that is backed by <code>value</code>.
*/
@SuppressWarnings("unchecked")
public static MemberProvider create(Object value, boolean caseInsensitive) {
if (value instanceof Map<?, ?>)
return caseInsensitive ? new CIMapMemberProvider((Map<String, ?>) value) : new MapMemberProvider((Map<String, ?>) value);
if (value instanceof Dictionary<?, ?>)
return caseInsensitive ? new CIDictionaryMemberProvider((Dictionary<String, ?>) value) : new DictionaryMemberProvider((Dictionary<String, ?>) value);
if (value instanceof ServiceReference)
return new ServiceRefMemberProvider((ServiceReference<?>) value);
throw new IllegalArgumentException();
}
public static MemberProvider emptyProvider() {
return emptyProvider;
}
}