blob: 7bc8eeaf9423ff9f73c8b038737c0345934a9e18 [file] [log] [blame]
Marcel Offermans613a6202009-03-11 22:31:44 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19package org.apache.felix.das.util;
20
21
22import java.util.ArrayList;
23import java.util.Comparator;
24import java.util.List;
25import java.util.SortedMap;
26import java.util.TreeMap;
27
28import org.apache.felix.das.DriverAttributes;
29import org.apache.felix.das.Log;
30import org.osgi.framework.ServiceReference;
31import org.osgi.service.device.Constants;
32import org.osgi.service.device.DriverSelector;
33import org.osgi.service.device.Match;
34
35
36/**
37 * TODO: add javadoc
38 *
39 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
40 */
41public class DriverMatcher
42{
43
44 private final Log m_log;
45
46 SortedMap<Integer, List<DriverAttributes>> m_map = new TreeMap<Integer, List<DriverAttributes>>();
47
48 List<Match> m_matches = new ArrayList<Match>();
49
50
51 public DriverMatcher( Log log )
52 {
53 m_log = log;
54 }
55
56
57 // we keep track of the driver attributes in two
58 // lists, one to aid us if there is no driver selector, one
59 // if there is...
60 public void add( Integer match, DriverAttributes value )
61 {
62 List<DriverAttributes> da = get( match );
63 da.add( value );
64 m_matches.add( new MatchImpl( value.getReference(), match ) );
65 }
66
67
68 private List<DriverAttributes> get( Integer key )
69 {
70 List<DriverAttributes> da = m_map.get( key );
71 if ( da == null )
72 {
73 m_map.put( ( Integer ) key, new ArrayList<DriverAttributes>() );
74 }
75 return m_map.get( key );
76 }
77
78
79 public Match getBestMatch()
80 {
81 if ( m_map.isEmpty() )
82 {
83 return null;
84 }
85
86 int matchValue = m_map.lastKey();
87
88 // these are the matches that
89 // got the highest match value
90 List<DriverAttributes> das = m_map.get( matchValue );
91 if ( das.size() == 1 )
92 {
93 // a shortcut: there's only one with the highest match
94 return new MatchImpl( das.get( 0 ).getReference(), matchValue );
95 }
96
97 // get the highest ranking driver
98 final SortedMap<ServiceReference, Match> matches = new TreeMap<ServiceReference, Match>( new ServicePriority() );
99
100 for ( DriverAttributes da : das )
101 {
102 matches.put( da.getReference(), new MatchImpl( da.getReference(), matchValue ) );
103 }
104
105 ServiceReference last = matches.lastKey();
106 return matches.get( last );
107 }
108
109
110 public Match selectBestMatch( ServiceReference deviceRef, DriverSelector selector )
111 {
112 Match[] matches = m_matches.toArray( new Match[0] );
113 try
114 {
115 int index = selector.select( deviceRef, matches );
116 if ( index != DriverSelector.SELECT_NONE && index >= 0 && index < matches.length )
117 {
118 return matches[index];
119 }
120 }
121 catch ( Exception e )
122 {
123 m_log.error( "exception thrown in DriverSelector.select()", e );
124 }
125 return null;
126 }
127
128 private class MatchImpl implements Match
129 {
130
131 private final ServiceReference ref;
132 private final int match;
133
134
135 public MatchImpl( ServiceReference ref, int match )
136 {
137 this.ref = ref;
138 this.match = match;
139 }
140
141
142 public ServiceReference getDriver()
143 {
144 return ref;
145 }
146
147
148 public int getMatchValue()
149 {
150 return match;
151 }
152
153
154 public String toString()
155 {
156 return "[MatchImpl: DRIVER_ID=" + ref.getProperty( Constants.DRIVER_ID ) + ", match=" + match + "]";
157 }
158
159 }
160
161 private class ServicePriority implements Comparator<ServiceReference>
162 {
163
164 private int getValue( ServiceReference ref, String key, int defaultValue )
165 {
166 Object obj = ref.getProperty( key );
167 if ( obj == null )
168 {
169 return defaultValue;
170 }
171 try
172 {
173 return Integer.class.cast( obj );
174 }
175 catch ( Exception e )
176 {
177 return defaultValue;
178 }
179 }
180
181
182 public int compare( ServiceReference o1, ServiceReference o2 )
183 {
184 int serviceRanking1 = getValue( o1, org.osgi.framework.Constants.SERVICE_RANKING, 0 );
185 int serviceRanking2 = getValue( o2, org.osgi.framework.Constants.SERVICE_RANKING, 0 );
186
187 if ( serviceRanking1 != serviceRanking2 )
188 {
189 return ( serviceRanking1 - serviceRanking2 );
190 }
191 int serviceId1 = getValue( o1, org.osgi.framework.Constants.SERVICE_ID, Integer.MAX_VALUE );
192 int serviceId2 = getValue( o2, org.osgi.framework.Constants.SERVICE_ID, Integer.MAX_VALUE );
193
194 return ( serviceId2 - serviceId1 );
195 }
196 }
197}