Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: dccb003977807f681f22fae06c2517fbf0e0fa4a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*******************************************************************************
 * 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.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(Collections.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;
	}
}

Back to the top