Skip to main content
summaryrefslogtreecommitdiffstats
blob: 9eb460a8d71e739e9f19ec5fe38e96707ebf8e26 (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
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.osgi.framework.ServiceReference;

public abstract class MemberProvider {

	static class DictionaryMemberProvider extends MemberProvider {
		private final Dictionary<String, ? extends Object> dictionary;

		public DictionaryMemberProvider(Dictionary<String, ? extends Object> dictionary) {
			this.dictionary = dictionary;
		}

		@Override
		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;
		}

		@Override
		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;
		}

		@Override
		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 abstract Object getMember(String memberName);

	public static MemberProvider emptyProvider() {
		return emptyProvider;
	}
}

Back to the top