| /******************************************************************************* |
| * 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; |
| } |
| } |