View Javadoc
1   /**
2    * Copyright (C) 2010-14 pvmanager developers. See COPYRIGHT.TXT
3    * All rights reserved. Use is subject to license terms. See LICENSE.TXT
4    */
5   /*
6    * To change this template, choose Tools | Templates
7    * and open the template in the editor.
8    */
9   package org.epics.pvmanager;
10  
11  import java.util.ArrayList;
12  import java.util.Collection;
13  import java.util.List;
14  
15  /**
16   * The type support for a datasource. This optional class is provided to help
17   * create a more flexible type support in a datasource, so that support
18   * for individual types is done through runtime configuration. It provides
19   * default implementation for matching typeAdapters from the desired cache
20   * and connection payload.
21   *
22   * @author carcassi
23   */
24  public class DataSourceTypeSupport {
25      
26      /**
27       * Given a collection of type datapters, finds the one that can store
28       * data in the cache given the channel information described in the
29       * connection payload. If there isn't a unique match, an exception
30       * is thrown.
31       * 
32       * @param <C> type of connection payload
33       * @param <T> datasource specific type adapter type
34       * @param typeAdapters a collection of type adapters
35       * @param cache the cache where to store the data
36       * @param connection the connection payload
37       * @return 0 if the type was not matched
38       */
39      protected <C, T extends DataSourceTypeAdapter<? super C,?>> T find(Collection<T> typeAdapters, ValueCache<?> cache, C connection) {
40          int matched = 0;
41          List<T> matchedConverters = new ArrayList<T>();
42          for (T converter : typeAdapters) {
43              int match = converter.match(cache, connection);
44              if (match != 0) {
45                  if (match < matched) {
46                      matchedConverters.clear();
47                  }
48                  matchedConverters.add(converter);
49              }
50          }
51          
52          if (matchedConverters.size() != 1) {
53              throw new IllegalStateException(formatMessage(cache, connection, matched, matchedConverters));
54          }
55          
56          return matchedConverters.get(0);
57      }
58      
59      /**
60       * Formats the error message in case of not unique match. This
61       * allows data sources to give more specific error messages.
62       * 
63       * @param cache the cache used for the match
64       * @param connection the connection payload used for the match
65       * @param match the result of the match
66       * @param matchedConverters the matched converters; will either be 0 (no match)
67       * or more than 1 (non unique match)
68       * @return the message to be passed with the exception
69       */
70      protected String formatMessage(ValueCache<?> cache, Object connection, int match, List<? extends DataSourceTypeAdapter<?, ?>> matchedConverters) {
71          if (matchedConverters.isEmpty()) {
72              return "DataSource misconfiguration: no match found to convert payload to type. ("
73                      + cache.getType() + " - " + connection + ")";
74          } else {
75              return "DataSource misconfiguration: multiple matches found to convert payload to type. ("
76                      + cache.getType() + " - " + connection + ": " + matchedConverters + ")";
77          }
78      }
79  }